Moving iTunes Library in two steps using COM interface

Several years ago I migrated from storing my data on on server to another. I had all of my music stored in an hierarchy under the UNC sharename of \\Via\Music and moved it to a different server with the sharename of \\FortMeade\Music.

My music collection is around 60 gigabytes, and my experience with apple software in windows has not been very good. Telling the itunes application itself to do the moving did not seem like the best of plans if I wanted to be able to use my computer any time soon.

I decided that the most reliable method of transfering the files was to use the robocopy command and the windows command prompt. This took several hours over gigabit ethernet but got the data copied over.

I wanted to maintain as much of the data as possible about the individual tracks, and decided I could write a program using the COM interface to control iTunes and copy the entries from the old tracks and put them in for the new location.

I wrote a program in C++ using Microsoft Visual Studio, and successfully maintained the last played date and the number of plays. Unfortunately the location data of a track seems to be read only, otherwise I’d simply have changed that and been able to maintain all of the data.

Several years later, and I want to move to another server. Now when I modify my program and attempt to run it with the new names, it adds the tracks in the new location, but when it tries to modify the PlayedCount value, it traps a COM error (0xA0040203), and the error doesn’t seem to have a description.


// iManipulate.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "iManipulate.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif

#undef GetFreeSpace /* macros are evil */
#import "C:/Program Files (x86)/iTunes/iTunes.exe"
using namespace iTunesLib;

// The one and only application object
CWinApp theApp;

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
 int nRetCode = 0;

// initialize MFC and print and error on failure
 if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
 {
 _tprintf(_T("Fatal Error: MFC initialization failed\n"));
 nRetCode = 1;
 }
 else
 {
 // initialize COM libraries
 HRESULT hr = CoInitialize(NULL);
 if (SUCCEEDED(hr))
 {
 CComPtr<IiTunes> iTunes;
 if (S_OK == iTunes.CoCreateInstance(__uuidof(iTunesApp)))
 {
 CComPtr<IITLibraryPlaylist> MyLibrary = iTunes->LibraryPlaylist;
 CComPtr<IITTrackCollection> MyTrackCollection = MyLibrary->Tracks;
 for (long index = 1; index <= MyTrackCollection->Count ; index++)
 {
 CComPtr<IITTrack> MyTrack = MyTrackCollection->Item[index];
 if (MyTrack->Kind == ITTrackKindFile)
 {
 CComPtr<IITFileOrCDTrack> MyFileOrCDTrack;
 if (S_OK == MyTrack->QueryInterface(&MyFileOrCDTrack))
 {
 _tprintf(_T("%d"), index);
 BSTR MyTrackLocation = MyFileOrCDTrack->Location;
 _tprintf(_T("\t%s"), MyTrackLocation);
 CString NewLocation(MyTrackLocation);
 CString NewLocationAllLowerCase(NewLocation);
 NewLocationAllLowerCase.MakeLower();
 CString TextToReplace(_T("\\\\fortmeade\\music"));
 CString NewText(_T("\\\\Acid\\Music"));
 int ReplaceStart = NewLocationAllLowerCase.Find(TextToReplace);
 if (ReplaceStart >= 0)
 {
 NewLocation.Delete(ReplaceStart,TextToReplace.GetLength());
 NewLocation.Insert(0,NewText);
 if (-1 != _taccess(NewLocation,0))
 {
 try
 {
 CComBSTR FileToAdd(NewLocation);
 CComPtr<IITOperationStatus> MyOperationStatus = MyLibrary->AddFile(FileToAdd.m_str);
 while ( VARIANT_TRUE == MyOperationStatus->GetInProgress())
 Sleep(100);
 CComPtr<IITTrackCollection> MyAddedTrackCollection = MyOperationStatus->GetTracks();
 if (1 == MyAddedTrackCollection->Count)
 {
 CComPtr<IITTrack> MyAddedTrack = MyAddedTrackCollection->GetItem(1);
 //MyAddedTrack->DateAdded = MyFileOrCDTrack->DateAdded;
 if (MyFileOrCDTrack->Rating > 0)
 MyAddedTrack->PutRating(MyFileOrCDTrack->Rating);
 if (MyFileOrCDTrack->PlayedCount > 0)
 {
MyAddedTrack->PutPlayedCount(MyFileOrCDTrack->GetPlayedCount());
 MyAddedTrack->PutPlayedDate(MyFileOrCDTrack->GetPlayedDate());
 }
 MyFileOrCDTrack->Delete();
 _tprintf(_T("\t%s\n"), FileToAdd);
 }
 }
 catch(_com_error &e)
 {
 _tprintf(_T("\t(COM ERROR:%#lx %s, %s)\n"), e.Error(), e.Source(), e.Description());
 }
 }
 }
 else
 _tprintf(_T("\r"));
 }
 }
 }
 }
 }
 CoUninitialize();
 }
 return nRetCode;
}

Advertisements
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s