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;
}

Posted in Uncategorized | Leave a comment

As usual, I’m late to the party.

I’m finally setting up a basic blog to post random thoughts about anything that comes to mind.

Mostly I’ll probably post ideas that I’ve been wrestling with from a programming perspective, but I may also post travelogues or anything else that comes up.

Posted in Uncategorized | Leave a comment

Hello world!

Welcome to WordPress.com. After you read this, you should delete and write your own post, with a new title above. Or hit Add New on the left (of the admin dashboard) to start a fresh post.

Here are some suggestions for your first post.

  1. You can find new ideas for what to blog about by reading the Daily Post.
  2. Add PressThis to your browser. It creates a new blog post for you about any interesting  page you read on the web.
  3. Make some changes to this page, and then hit preview on the right. You can always preview any post or edit it before you share it to the world.
Posted in Uncategorized | 1 Comment