Category Archives: 7721

MIX09 Session Videos – How I Did It

On my last post I introduced the feeds I created to subscribe to Mix09 session videos.

In case someone is interested on how I did it, here it is:

<%@ WebHandler Language="C#" Class="mix09" %>

using System;
using System.IO;
using System.Web;
using System.Linq;
using System.Xml.Linq;
using System.Net;
using System.Xml;

public class mix09 : IHttpHandler, IHttpAsyncHandler
{
    class WebClientOpenReadAsyncResult : IAsyncResult
    {
        private AsyncCallback callback;

        public WebClientOpenReadAsyncResult()
        {
            this.IsCompleted = true;
            this.CompletedSynchronously = true;
        }

        public WebClientOpenReadAsyncResult(AsyncCallback callback)
        {
            this.callback = callback;
            this.IsCompleted = false;
            this.CompletedSynchronously = false;
        }

        public object AsyncState
        {
            get { return null; }
        }

        public bool CompletedSynchronously { get; private set; }

        public System.Threading.WaitHandle AsyncWaitHandle
        {
            get { throw new InvalidOperationException("ASP.NET should not use this property ."); }
        }

        public bool IsCompleted { get; private set; }

        public Stream Stream { get; private set; }

        public void Completed(object sender, OpenReadCompletedEventArgs e)
        {
            this.IsCompleted = true;
            this.Stream = e.Result;
            if (this.callback != null)
            {
                this.callback(this);
            }
        }

    }

    private static Uri mixSessionsUri = new Uri("http://sessions.visitmix.com/RSS");

    private HttpContext context;

    private string type;

    #region IHttpHandler Members

    public bool IsReusable
    {
        get { return true; }
    }

    public void ProcessRequest(HttpContext context)
    {
        WebClient wc = InitializeRequest(context);

        if (wc == null)
        {
            return;
        }

        OutputFeed(wc.OpenRead(mixSessionsUri));
    }

    #endregion

    #region IHttpAsyncHandler Members

    public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
    {
        WebClient wc = InitializeRequest(context);

        if (wc == null)
        {
            return new WebClientOpenReadAsyncResult();
        }

        WebClientOpenReadAsyncResult ar = new WebClientOpenReadAsyncResult(cb);

        wc.OpenReadCompleted += ar.Completed;

        wc.OpenReadAsync(mixSessionsUri, extraData);

        return ar;
    }

    public void EndProcessRequest(IAsyncResult result)
    {
        Stream stream = (result as WebClientOpenReadAsyncResult).Stream;

        if (stream != null)
        {
            OutputFeed(stream);
        }
    }

    #endregion

    private WebClient InitializeRequest(HttpContext context)
    {
        this.context = context;
        this.type = context.Request.QueryString["type"];

        if (string.IsNullOrEmpty(this.type))
        {
            return null;
        }

        WebClient wc = new WebClient();
        wc.Headers[HttpRequestHeader.UserAgent] = "Required User Agent";
        return wc;
    }

    private void OutputFeed(Stream source)
    {
        XmlReader feedReader = XmlReader.Create(source);

        XDocument feed = XDocument.Load(feedReader);

        var rss = feed.Element("rss");
        var channel = rss.Element("channel");
        var title = channel.Element("title");

        title.Value = string.Format("{0} ({1})", title.Value, this.type.ToUpper());
        channel.Element("link").Value = "http://cli.gs/Mix09Sessions";

        foreach (var item in channel.Elements("item"))
        {
            string link = item.Element("link").Value;
            string session = link.Substring(link.LastIndexOf('/') + 1).ToLower();
            string enclosureUrl = string.Format("http://mschannel9.vo.msecnd.net/o9/mix/09/{0}/{1}.wmv", this.type.ToLower(), session);

            item.Add(
                new XElement("enclosure",
                    new XAttribute("url", enclosureUrl)));
        }

        this.context.Response.Write(feed.ToString());

        this.context.Response.ContentType = "application/rss+xml";

        HttpCachePolicy cache = this.context.Response.Cache;
        cache.SetCacheability(HttpCacheability.ServerAndPrivate);
        cache.SetExpires(DateTime.Now.AddHours(1));
        cache.VaryByParams["type"] = true;
        cache.SetValidUntilExpires(true);
    }
}

MIX09 Session Videos

Updated (2009Mar25): Added MP4 feed. 


Mix09 is over and I would like to watch some sessions.


I like to watch these kind of videos by subscribing them using the Zune Software as a podcast. I like the Zune Software because it downloads the “episodes” and I can watch them in any order and it never forgets where I was – even if I was watching it in the Zune.


Unfortunately, the only feed available (http://sessions.visitmix.com/RSS) does not include the videos.


Fortunately, the address of the videos is very predictable and I was able to build my own feeds:



The session videos are not available in all formats for every session (at least, not now) but, if you subscribe to all, you’ll get videos for all the sessions.


Subscribe and enjoy.

My Shared Podcasts

I used to share my podcast watching through a feed created using FeedDemon, NewsGator and FeedBurner.

It was very easy. All it took was to adding he post to a clipping folder created to that purpose. That folder was shared as an RSS feed and I ran it through FeedBurner to get some statistics and a more friendly URL. For downloading the webcast/pocast, I used FeedBurner’s companion: FeedStation.

Because I listen to a fair amount of podcasts, I got myself an 8GB Zune. The Zune uses it’s own software to load content and that software is capable handling podcast subscriptions, so I won’t be needing FeedDemon and FeedStation for subscribing downloading podcasts.

Because I have a few subscribers to my feed, I wanted to keep it. Then I found PodShow [^][^] a created my onw profile and changed the source of the feed.

So, if you already are one of my followers you don’t need to do anything. If you aren’t and would like to be, go ahead and subscribe it.

subscribe to my shared podcast's feed My mevieo