Thursday, July 31, 2008

Microsoft Sphere

There's been lots of rumors lately about a cool new spherical Surface computer.

The original Surface is a multi-touch table-top PC designed mainly for commercial use in bars and restaurants. It's really too early to tell how it will be used, and the potential is enormous, but for now this is how it is conceived:



Last week Microsoft unveiled the Sphere during their annual Research Faculty Summit in Redmond. It's an amazing device that seems to be geared towards interactive exhibits in science museums, but again, only time will tell what the true killer app for the Sphere will be.
Here's a link to a Gizmodo hands-on:
http://gizmodo.com/5030603/hands-on-with-the-microsoft-surface-sphere-prototype

And a YouTube video:

Read more...

Wednesday, July 30, 2008

Claiming My Blog

Technorati wants me to claim my blog for them, so here goes:

Technorati Profile

Lets release the spiders and see what happens...

Read more...

Monday, July 28, 2008

Merging Flickr Accounts

How to Use the FlickrNet API to Merge Flickr Accounts

A few months ago, my wife finally convinced me that it doesn't make any sense to manage two separate pro Flickr accounts, and that we should transfer all the photos to one account and drop the other.

So, I looked online for tools that merge Flickr accounts, and couldn't find any. Not even on CodePlex. Don't get me wrong, I found a gazzillion mass downloaders, and uploaders and a bunch of other very cool stuff. But not a merge tool. I even contacted Flickr support, but they were totally useless.

What I really wanted was a way to download the photos from the source account, and keep all the metadata I have meticulously added to the photos over the years - titles, descriptions, sets, tags, geo tags, etc. Then, upload to the target account without disrupting the flow on my photostream. I didn't want a bunch of old photos clogging it up.

Being a developer, I decided to write my own Flickr app using the FlickrNet API library, which turned out to be fun and quite enjoyable.

I don't want to bore you with all the details of my implementation. I'd just like to point out some interesting aspects and potential pitfalls.

Getting an API Key


To get started, you'll need an API key from Flickr. Go to the Services page and click on the "Apply for an API Key" link.

The FlickrNet Library


Download the FlickrNet library from CodePlex. You can download the binaries and reference the DLL from your code. I opted for the more geeky option, and downloaded the source code, and added the FlickrNet project to my solution. This way I could step through the code and better understand how it works.

Authorizing


If you want your app to do more than merely download public photos, your users will need to authorize it. The process is quite simple, but not that obvious. You need to launch a web browser and navigate to a Url. Here's what you do to get the Url.

FlickrNet.Flickr flickr = new FlickrNet.Flickr(ApiKey, SharedSecret);
string frob = flickr.AuthGetFrob();
string url = flickr.AuthCalcUrl(frob, FlickrNet.AuthLevel.Write);


AuthLevel can be one of the following values:
  • Read
  • Write
  • Delete
  • None

Once you have the Url, launch the default web browser.

System.Diagnostics.Process.Start(url);


At this point, the user needs to login to her account and authorize the application. Now you can retrieve the authorization token from Flickr.

FlickrNet.Flickr flickr = new FlickrNet.Flickr(ApiKey, SharedSecret);
FlickrNet.Auth auth = flickr.AuthGetToken(frob);
string token = auth.Token;
string userName = auth.User.Username;


Downloading Photos Metadata


This is a relatively simple process. Use the PhotoSearchOptions object to define the photos you are interested in (this could be based on a user, tag, etc.). The PhotosSearch method doesn't return all the photos it finds in one call, rather it returns "pages" of photos. You use the same PhotoSearchOptions to move to the next page and bring the next batch of results.

// Get the user Id based on the user name
FlickrNet.Flickr flickr = new FlickrNet.Flickr(ApiKey, SharedSecret);
FlickrNet.FoundUser user = flickr.PeopleFindByUsername(UserName);
string userId = user.UserId;

// Create a PhotoSearchOptions object
FlickrNet.PhotoSearchOptions options = new FlickrNet.PhotoSearchOptions();
options.UserId = userId;

// Retrieve the user's photos
FlickrNet.Photos photos = flickr.PhotosSearch(options);


Downloading Sets Metadata



// Get all the photosets for the user
FlickrNet.Photosets sets = flickr.PhotosetsGetList(userId);


Linking Photos to Photosets


This is where it gets a little tricky. See, Flickr allows photos to belong to 0-n sets. So, in theory I had to account for photos that are not part of any set, photos that belong to a single set, and for photos that belong to multiple sets. Since almost all of my photos belong to just one set, I've decided to cut myself some slack, and only deal with 0-1 sets per photo.

foreach (FlickrNet.Photoset set in sets.PhotosetCollection)
{
...
... //Save photoset metadata
...

// Get the photoset's photos
FlickrNet.Photoset set1 = flickr.PhotosetsGetPhotos(set.PhotosetId);
FlickrNet.Photo[] setPhotos = set1.PhotoCollection;
foreach (FlickrNet.Photo photo in setPhotos)
{
...
... // Link photo to photoset
...
}
}


Downloading Photos


The one thing to keep in mind here is that Flickr stores multiple versions of each photo (with different resolutions), so you want to make sure you download the largest one.

FlickrNet.Sizes sizes = flickr.PhotosGetSizes(photo.PhotoId);
FlickrNet.Size size = sizes.SizeCollection[sizes.SizeCollection.Length - 1];
string sourceUrl = size.Source;
string fileName = size.Source.Substring(size.Source.LastIndexOf("/") + 1);

WebClient client = new WebClient();
client.DownloadFile(sourceUrl, fileName);


Uploading Photos


Uploading the photos is easy. I just had to change the dates on the photo after the upload to make sure it shows up in the correct place in my photostream based on the upload date, and add the GEO tags, if they existed in the original metadata.

FlickrNet.Flickr flickr = new FlickrNet.Flickr(ApiKey, SharedSecret, AuthToken);
string photoId = flickr.UploadPicture(fileName, title, description, tags, true, false, false);
flickr.PhotosSetDates(photoId, datePosted, dateTaken, FlickrNet.DateGranularity.FullDate);
flickr.PhotosGeoSetLocation(photoId, latitude, longitude);


Creating Photosets


Creating a Photoset is a breeze. Just remember to assign a primary photo to the set, and make sure the photo id is the new photo id (from the target account) not the old one.

FlickrNet.Flickr flickr = new FlickrNet.Flickr(ApiKey, SharedSecret, AuthToken);
FlickrNet.Photoset set = flickr.PhotosetsCreate(title, description, primaryPhotoId);


Now you can add the photos (already uploaded) to the newly created set.

flickr.PhotosetsAddPhoto(photosetId, photoId);


Conclusion


Working with the FlickrNet API is both easy and fun. I'm personally happy I've decided to write my own app, I think I've learned a lot from it. If you are like me, and believe that reading code makes you a better developer, I recommend downloading the source code version and using is in your solution.

Related Links


Coding4Fun
Flickr Explorer
Flickr API

Read more...

Monday, July 14, 2008

A New Beginning

New beginnings are hard. Starting something new - a new job, start-up, or even a blog - is not a simple task. It takes effort. It's against our nature, really. Newton, with his first law of motion explains it well (I'm paraphrasing):





"An object at rest tends to stay at rest and an object in motion tends to stay in motion with the same speed and in the same direction..."


We are conditioned to do what we know, what we're good at. Stay the course. Most of us are afraid of change, of the unknown. It's natural.

But Newton realized that things are not that simple, so he added:

"unless acted upon by an external, unbalanced force."

Several weeks ago I started a new job as a developer at SAP Labs in Israel (a definite "unbalanced force"). This new job involves quite a bit of research around the latest Microsoft technologies (WCF, WPF, MOSS, OBA, VSTO, etc.). So I figured, I might as well share my experiences with other developers in the community, and what better way than an online blog.




With everything I have to learn these days (a new company, a new product, new technologies) I know I'll be drinking from the fire hose for a while, but I honestly believe that writing will actually help me make sense and keep track of it all.

So, hang on, and enjoy the ride.

Read more...