Programatically Accessing Netflix in C#

When I lived with a few roommates, we all shared  my Netflix account and pretty much exclusively used it to add movies to instant which were then streamed using the Netflix app for my Xbox 360.  Since there were 3 of us, this meant that we had a ton of random movies constantly being shoveled into the queue and as a result, my queue got really messy… like 300 movies in no particular order messy … which made it particularly difficult to find a movie that one of us added.

To solve this dilemma, one of my roommates would painstakingly reorder our entire Netflix queue one item at a time to alphabetize them.  He didn’t mind doing it while commercials were on TV and he was an auditor by trade so there weren’t any errors in the ordering. However, this seemed like about the worst possible way to do this, so I checked the Netflix site and discovered,  ”Hey, there’s an API.”  Even more awesomely, there is a C# library for Netflix that some generous developer decided to share on CodePlex which greatly simplifies development.

Library in hand, I eagerly produced a simple C# Netflix app that lets you sort your Netflix queue.  This is probably the least optimal implementation, but it works!

The application works only in 3 steps:

  1. Authenticate
  2. Clear the instant queue
  3. Add entries to the queue in the order you want them in

The following code shows how authentication works.

        /* The following came straight from the Netflix signup / API page
         * and are used by OAUTH
         *
         * Key: <removed>
         * Application:<removed>
         * Key: <removed>
         * Shared Secret: <removed>
         * Status: active Registered: 2 seconds ago Rate Limits
         * 4 Queries per second
         * 5,000 Queries per day
         *
         * Update your app.config with:
         *     ConsumerKey as a string set to the "Key" field
         *     ConsumerSecret as a string set to the "Shared Secret" field
         *     UserId should be created as a string, but not set
         *     UserAccessToken should be created as a string, but not set
         *     UserAccessTokenSecret should be created as a string, but not set
         */
        NetflixConnection netflixConnection;
        AccessToken userAccessToken;
        User user;
        String NetflixAccessToken = "";
        int attempts    = 0;
        int maxAttempts = 5;

        private void authenticate()
        {
            attempts++;

            netflixConnection = new NetflixConnection(Properties.Settings.Default.ConsumerKey, Properties.Settings.Default.ConsumerSecret);
            try
            {
                if (String.IsNullOrEmpty(NetflixAccessToken))
                {
                    RequestToken currentRequestToken = netflixConnection.GenerateRequestToken();
                    Process.Start(currentRequestToken.PermissionUrl);

                    // Race condition:  If you call ConvertToAccessToken() before the previous process finishes,
                    //                  the token is invalidated.  Blocking using a messagebox.
                    //
                    // TODO:            Figure out better way to solve this issue
                    MessageBox.Show("After you have enabled permissions from Netflix, click OK.");
                    userAccessToken = currentRequestToken.ConvertToAccessToken();

                    Properties.Settings.Default.UserId = userAccessToken.UserId;
                    Properties.Settings.Default.UserAccessToken = userAccessToken.Token;
                    Properties.Settings.Default.UserAccessTokenSecret = userAccessToken.TokenSecret;
                    Properties.Settings.Default.Save();
                    // TODO:  Persist the UserId / UserAccessToken / UserAccessTokenSecret
                    //        so the user doesn't need to do this every time

                    // Turn off auth button, turn on sort buttons
                    authenticateButton.IsEnabled = false;
                    sortAZ.IsEnabled             = true;
                    sortZA.IsEnabled             = true;
                }
            }
            catch (Exception e)
            {
                MessageBox.Show("Something went wrong, trying again." + e.InnerException.ToString());
                if (attempts < maxAttempts)
                {
                    authenticate();
                }
            }

            user = new User(userAccessToken, netflixConnection);
        }

The following code shows how I retrieve the instant queue which will then be removed one entry at a time.

        private void sortAZ_Click(object sender, RoutedEventArgs e)
        {
            user.InstantQueue.Refresh();

            QueueItem[] instantQueue = user.InstantQueue.ToArray();

            Console.WriteLine("Unsorted Queue");
            for (int i = 0; i < instantQueue.Length; i++)
            {
                Console.WriteLine(instantQueue[i].Title);
            }

            Array.Sort(instantQueue,sortTitleAZ());

            Console.WriteLine("-- Sorted A-Z");
            for (int i = 0; i < instantQueue.Length; i++)
            {
                user.InstantQueue.Remove(instantQueue[i]);
                Console.WriteLine(instantQueue[i].Title);
            }

The following code shows how the entries are then added back into the instant queue in order.

            // Add all entries in order
            Console.WriteLine("Adding entries in order");
            for (int i = 0; i < instantQueue.Length; i++)
            {
                user.InstantQueue.Add(instantQueue[i].Id);
                // 250 ms / query = 4 queries / second
                // limit is 4 queries / second
                // using 300 for good measure
                Console.WriteLine(instantQueue[i].Title);
            }
        }

A rather simple application, but a true time saver for my poor roommate.  If you’re interested in hacking up my application, feel free to grab it from my fileshare.  The only thing you need to do to get it working is get a developer key/secret from Netflix, double click the “Settings.settings” file in the project from CodePlex, and update the ConsumerKey and ConsumerSecret before compiling.

Windows Touch resources from around the Web

Szymon Kobalczyk’s Blog has an interesting entry on Windows Touch resources. It might be interesting to see where he has gotten with his projects such as this Windows Touch WPF project.

The forums for unmanaged tablet content are a great community for general Tablet discussion.

The WPF forums have some interesting details on Windows Touch for managed developers.

Interpreting the WM_GESTURE message

In the Tablet / Touch forums, there has been some confusion about interpreting the WM_GESTURE message, the GID_PRESSANDTAP gesture, specifically.  The gist of getting to the message is:

  • Turn the lParam into a GestureInfo structure.
  • Grab the POINT value from the ptsLocation member
  • Convert the lower 32 bits of the ullArgument member into a POINT structure

The following code shows how to get a GESTUREINFO from the LPARAM


// Create a structure to populate and retrieve the extra
// message info.
GESTUREINFO gi;
double d;
ZeroMemory(&gi, sizeof(GESTUREINFO));
gi.cbSize = sizeof(GESTUREINFO);
BOOL bResult = GetGestureInfo((HGESTUREINFO)lParam, &gi);
// Create a structure to populate and retrieve the extra
// message info.
GESTUREINFO gi;
ZeroMemory(&gi, sizeof(GESTUREINFO));
gi.cbSize = sizeof(GESTUREINFO);
BOOL bResult = GetGestureInfo((HGESTUREINFO)lParam, &gi);

The following code shows how the first touch point (x/y) and delta values (x/y) can be interpreted from the ullArguments / ptsLocation values from the GESTUREINFO structure.

case GID_PRESSANDTAP:
// Code for pressandtap goes here
pt = _localizePoint(gi.ptsLocation);

temp = gi.ullArguments;

if (temp > 0){

Log << "touch x: ["<< pt.x << "]\n";
Log << "touch y: ["<< pt.y << "]\n";
Log << endl;

pt = MAKEPOINTS(temp);
POINTSTOPOINT(delta, pt);

Log << "delta x: ["<< pt.x << "]\n";
Log << "delta y: ["<< pt.y << "]\n";
Log << endl;

}
bHandled = TRUE;
break;

This code uses a utility function, _localizePoint, which simply calls ScreenToClient on a POINT struct.


POINTS
_localizePoint(const POINTS& pt)
{
POINT point;
point.x = pt.x;
point.y = pt.y;

BOOL bResult = ScreenToClient(m_hwnd, &point);

POINTS pts;
pts.x = (SHORT)point.x;
pts.y = (SHORT)point.y;

return pts;
}


// Create a structure to populate and retrieve the extra

Hit me on Twitter!

Just a reminder, my twitter username is gguuss, I make a few posts there that don’t quite cut it to the blog.  Also, if you’re interested in Windows 7 Touch announcements, follow Windows7Touch.

Windows 7 “GodMode” Folders

Here’s an interesting hack that I ran into on Gizmodo via CNET.

By creating a new folder in Windows 7 and renaming it with a certain text string at the end, users are able to have a single place to do everything from changing the look of the mouse pointer to making a new hard-drive partition.
The trick is also said to work in Windows Vista, although some are warning that although it works fine in 32-bit versions of Vista, it can cause 64-bit versions of that operating system to crash.
To enter “GodMode,” one need only create a new folder and then rename the folder to the following:
GodMode.{ED7BA470-8E54-465E-825C-99712043E01C}

I’m not sure exactly how this works…  but it’s pretty darn cool.  A commenter on the CNET site pointed out that you can search this folder to quickly find all of the settings for a particular term (e.g. Display).  Also of note, it’s the extension (ED7BA470-8E54-465E-825C-99712043E01C) that causes the folder to function in the strange way it does so you can label the folder CPanel.{ED7BA470-8E54-465E-825C-99712043E01C} and it would work the same.

Windows Touch in Visio 2010

The Office team has posted a video and some screenshots from Visio 2010 that show off the Windows Touch features. It will be very exciting to see more applications enable support for Windows Touch and I hope that everyone implementing these features makes sure to address all of the challenges associated with developing Windows Touch applications.

Wacom Bamboo Pen & Touch Impressions

First things first, the Wacom Bamboo is a great and inexpensive way to start prototype UI, but unfortunately it is not a true Windows Touch input device.

I had heard a rumor that this device supported Windows Touch, which I discovered wasn’t the case when I got the latest Wacom Bamboo Drivers from Wacom, traced some messages in a WndProc function, and didn’t see the WM_TOUCH message :-(

The Bamboo is a cool device still, however, and it’s still a pen input device which will enable Tablet features on Windows.

Windows 7 Ship Award

I came into my office this morning and I have now received my new Windows 7 Ship Award, a special copy of Windows 7.

Inside, it’s just a retail box of Windows 7 Ultimate, which I won’t be opening because I’m a nerd :-D

One picture shows the Windows 7 ship box next to my Vista ship box.

Magazine Article on Mobile Considerations for Windows Touch

My new magazine article is now online for MSDN magazine! http://bit.ly/5XI2H0

Multitouch Talks from PDC 2009

I have a received a number of questions about the difference between multitouch on Windows 7 and Surface. The following presentation covers the differences and some frequently asked questions about Windows Touch. Reed’s talk is oriented to unmanaged while the talk by Anson and Robert’s talk is more focused to managed development.

Anson and Robert’s talk, Multitouch on Microsoft Surface and Windows 7, covers the differences between Windows Touch and Surface input.

Multi-touch is going mainstream as part of Microsoft Surface and Windows 7. Come to this session to learn about how to create innovative new user experiences with touch – and how .NET developers can share code between both of these platforms. You’ll get a deep dive on the new touch capabilities in WPF 4 and the subset in Silverlight 3. You will also see how the unique capabilities of Microsoft Surface take multi-touch to a whole new level.

Also worth checking out from PDC 2009 is Reed Townsend’s presentation, the Windows Touch Deep Dive.

Windows provides applications a default experience for gestures and touch interaction. Applications that want to go beyond that basic experience have a powerful platform to build on top of. This session is targeted at developers interested in building touch-optimized experiences. We look closely at some of the more powerful portions of the Touch platform, like manipulation and inertia processors, as well as cover real-world problems that developers have encountered and overcome. Come help build the next generation of user experiences!