Syncing YouTube Videos to iTunes and Zune

iTunes and Zune provide different mechanisms for syncing videos, but we will build one interface that we can use for both videos, to keep a standard mechanism for syncing files (see Example 4-35 and Example 4-36). This interface will sync files for a given device based on the file path.

Example 4-35.  C# interface for syncing to iTunes and Zune

interface IVideoService
{
  void Sync(string filePath);
}

Example 4-36.  Visual Basic interface for syncing with iTunes and Zune

Friend Interface IVideoService
  Sub Sync(ByVal filePath As String)
End Interface

Syncing Videos to iTunes

To sync YouTube videos to iTunes, we'll use the iTunes COM interop library. This library is automatically included when you install iTunes, and you can add it to your Visual Studio project by clicking in the Solution Explorer and selecting Add Reference.... Then, click the COM tab and select the iTunes 1.11 Type Library, which is a COM wrapper class that simplifies automating iTunes with .NET code.

As you can see in Example 4-37 and Example 4-38, we import the iTunesLib namespace and create a private member named iTunes.

Example 4-37.  C# class declaration for iTunes class

using iTunesLib;
public class iTunesSync : IVideoService
{
  iTunesApp iTunes = new iTunesApp();
...

Example 4-38.  Visual Basic class declaration for iTunes class

Imports iTunesLib
Public Class iTunesSync
Implements IVideoService
  Private iTunes As New iTunesApp()
...

The next step is to implement the IVideoService Sync interface, as shown in Example 4-39 and Example 4-40. To do this, we filter the list of files in the filePath variable to only those files with an MP4 file extension. Once we've filtered the list of videos, we then loop through each video and add it to the iTunes Library. When the Sync() method is called, iTunes will open (if it's not already open) and will begin adding videos to your library. As iTunes builds a thumbnail for each video, it may take 1–3 seconds for each video to be added to your library, depending on your machine's performance.

Example 4-39.  C# code for implementing the Sync interface

#region IVideoService Members
public void Sync(string filePath)
{
  //only get MP4 files
  string[] fileList = Directory.GetFiles(filePath, "*.mp4",
    SearchOption.TopDirectoryOnly);
  try
  {
    foreach (var f in fileList)
    {
      //Add file
      iTunes.LibraryPlaylist.AddFile(f);
    }
  }
  catch (Exception ex)
  {
    System.Diagnostics.Debug.WriteLine("iTunes error: " + ex.Message);
  }
  finally
  {
    this.iTunes = null;
  }
}
#endregion

Example 4-40.  Visual Basic code for implementing the Sync interface

#Region "IVideoService Members"
Public Sub Sync(ByVal filePath As String) Implements IVideoService.Sync
  'only get MP4 files
  Dim fileList() As String = Directory.GetFiles(filePath, "*.mp4", _
    SearchOption.TopDirectoryOnly)
  Try
    For Each f In fileList
      'Add file
      iTunes.LibraryPlaylist.AddFile(f)
    Next f
  Catch ex As Exception
    System.Diagnostics.Debug.WriteLine("iTunes error: " & ex.Message)
  Finally
    Me.iTunes = Nothing
  End Try
 End Sub
#End Region

Note

The reason we filter the list of files instead of looping through all the files in the directory is that per the iTunes COM SDK, the AddFile method will fail if you add a file that is not supported by iTunes (for example, a Windows Media Video file). The SDK suggests using the iTunes ConvertFile method, which will convert the file to a format iTunes understands. Although ConvertFile is one option for developers, ffmpeg.exe supports more file formats and has easy programmatic access.

We can, with one line of code, tell iTunes to update an iPod (if it's connected), as shown in Example 4-41 and Example 4-42. Finally, as this is COM and since the iTunesApp class doesn't implement Dispose, make sure to clean up the memory by setting the variable to null.

Example 4-41.  C# code to update an iPod and cleanup memory

public void UpdateIPod()
{
  iTunes.UpdateIPod();
}

˜iTunesSync()
{
  if (this.iTunes != null)
  {
    //cleanup
    this.iTunes = null;
  }
}

Example 4-42.  Visual Basic to update an iPod and cleanup memory

Public Sub UpdateIPod()
  iTunes.UpdateIPod()
 End Sub

Protected Overrides Sub Finalize()
If Me.iTunes IsNot Nothing Then
  'cleanup
  Me.iTunes = Nothing
 End If

 End Sub

Syncing Videos to Zune

The process for syncing videos to Zune is quite different than syncing videos to iTunes. Although the Zune team doesn't provide an API we can call programmatically, Zune does make it very easy to add files to its library by simply copying the files to directories that Zune monitors.

Note

Underneath the covers, Zune continuously runs a process called Zune-Launcher.exe. Conceptually, ZuneLauncher implements the same functionality that a .NET FileSystemWatcher class, as it monitors changes to a set of folders for audio and video files.

Zune monitored folders

To pull the list of folders that Zune is monitoring, we will need to go spelunking into the Windows registry. Specifically, we will need to open the HKEY_CURRENT_USER\Software\Microsoft\Zune\Groveler registry key, as shown in Figure 4-9.

Zune monitored folders are stored in the registry

Figure 4-9. Zune monitored folders are stored in the registry

To do the same thing programmatically, we'll create an enum named ZuneMonitoredFolders that will represent each monitored folder registry key. We can then call GetZuneMonitoredFolders to get a string array of folders by calling the GetValue method for the Groveler subkey using the Registry class, as shown in Example 4-43 and Example 4-44.

Example 4-43.  C# code to programmatically extract Zune monitored folders from the registry

public enum ZuneMonitoredFolders
{
  MonitoredAudioFolders,
  MonitoredVideoFolders,
  MonitoredPhotoFolders,
  MonitoredPodcastFolders
}

public class ZuneSync : IVideoService
{
  public static string[] GetZuneMonitoredFolders(ZuneMonitoredFolders folder)
  {
    //Pull registry
    string hive = @"Software\Microsoft\Zune\Groveler\";
    string[] values =
       (string[])Registry.CurrentUser.OpenSubKey(hive).GetValue(folder.ToString());
    return values;
}
...

Example 4-44.  Visual Basic code to programmatically extract Zune monitored folders from the registry

Public Enum ZuneMonitoredFolders
  MonitoredAudioFolders
  MonitoredVideoFolders
  MonitoredPhotoFolders
  MonitoredPodcastFolders
End Enum

Public Class ZuneSync
  Implements IVideoService

  Public Shared Function GetZuneMonitoredFolders(ByVal folder As _
    ZuneMonitoredFolders) As String()
    'Pull registry
    Dim hive As String = "Software\Microsoft\Zune\Groveler\"
    Dim values() As String = _
    CType(My.Computer.Registry.CurrentUser.OpenSubKey(hive). _
      GetValue(folder.ToString()), String())

    Return values
  End Function
...

Like we did with the iTunes wrapper, we will implement the IVideoService.Sync interface for Zune, as shown in Example 4-45 and Example 4-46. In the implementation of the Sync method, we first get the list of video folders that are being monitored. If the passed-in folder is already being monitored, then we are done because new videos being added will automatically show up in Zune. If it's not in the list of monitored folders, we're going to pick the first monitored folder, currentFolders[0], and similar to the iTunes code, we filter just those files with the .wmv extension and copy them to the first monitored folder.

Example 4-45.  C# code for implementing the Sync interface

#region VideoService Members
public void Sync(string filePath)
{
  string[] currentFolders = ZuneSync.GetZuneMonitoredFolders(
    ZuneMonitoredFolders.MonitoredVideoFolders);
  bool found = currentFolders.Contains(filePath);
  //check if we are already added the files to the folder
  if (!found)
  {
    //copy the files to the first specified directory
    if (currentFolders.Length >0)
    {
      string destinationPath = currentFolders[0];
      string[] Files = Directory.GetFiles(filePath, "*.wmv",
        SearchOption.TopDirectoryOnly);
      foreach (var f in Files)
      {
        File.Copy(f, destinationPath, true);
      }
    }
    else
    {
      throw new ArgumentException("Zune is not configured to monitor *any* " +
        "folders, to fix this, open zune.exe, click settings, " +
        "and add a video folder");
    }
  }
}
#endregion

Example 4-46.  Visual Basic code for implementing the Sync interface

#Region "VideoService Members"
Public Sub Sync(ByVal filePath As String) Implements IVideoService.Sync
  Dim currentFolders() As String = ZuneSync.GetZuneMonitoredFolders( _
    ZuneMonitoredFolders.MonitoredVideoFolders)
  Dim found As Boolean = currentFolders.Contains(filePath)
  'check if we are already adding the files to the folder
  If (Not found) Then
  'copy the files to the first specified directory
    If currentFolders.Length >0 Then
      Dim destinationPath As String = currentFolders(0)
      Dim Files() As String = Directory.GetFiles(filePath, "*.wmv", _
        SearchOption.TopDirectoryOnly)
      For Each f In Files
        File.Copy(f, destinationPath, True)
      Next f
    Else
      Throw New ArgumentException("Zune is not configured to monitor *any* " & _
      "folders,to fix this, open zune.exe, click settings, and add a video folder")
    End If
  End If
 End Sub
#End Region

Get Coding4Fun now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.