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:
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.
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.
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:
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.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
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.
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.
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.
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.
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
One picture shows the Windows 7 ship box next to my Vista ship box.
My new magazine article is now online for MSDN magazine! http://bit.ly/5XI2H0