private void InitialiseServer() { errors = PluginError.Initialising; try { server = new DAAP.Server(settings.serverName, db, revisionManager); server.Port = settings.serverPort; server.Collision += (o, args) => { if (server.Name.Length > settings.serverName.Length) { int next = int.Parse(server.Name.Substring(server.Name.Length + 1)) + 1; server.Name = settings.serverName + " " + next.ToString(); } else { server.Name += " 2"; } }; server.TrackRequested += OnTrackRequest; server.DatabaseRequested += OnDatabaseRequest; server.UserLogin += revisionManager.OnLogin; server.UserLogout += revisionManager.OnLogout; server.Start(); errors = PluginError.None; } catch (SocketException) { errors = PluginError.PortTaken; } catch (Mono.Zeroconf.Providers.Bonjour.ServiceErrorException) { errors = PluginError.BonjourNotFound; } catch (Exception) { // Fatal. StopPlugin(); mbApi.MB_SendNotification(CallbackType.DisablePlugin); } configForm?.SetMessages(errors); }
// flags has bit indicators whether 2 way rating and/or playcount is requested (only set if enabled in the device properties) // for files(): // Key - the SynchronisationCategory the file should be sychronised to if appropriate for the device // Value is 3 strings // (0) - source file or playlist to be synchronised - use to query MusicBee for file tags, or files in a playlist // (1) - the filename extension of the file to be synchronised - normally the same as the extension for (0) but if the file would need to be re-encoded to meet the user's synch preferences then the extension for the encoded file // (2) - if SyncOrganisedFolders is enabled, filename as formatted by a naming template otherwise null // for each file that is synchronised, call Sync_FileStart(filename(0)) // MusicBee will determine if the file needs to be re-encoded depending on the user synch settings and if so the returned filename will be the temporary encoded filename // call Sync_FileEnd(filename(0), success, errorMessage) when that file has been synched or not // return true if all files synchronised ok public bool Synchronise(SynchronisationSettings flags, KeyValuePair <int, string[]>[] syncItems) { while (ReadyForSync == null) { ; // Wait if still opening iTunes } try { if (SynchronizationInProgress) { lastEx = null; return(false); } SynchronizationInProgress = true; var playlistKeys = new Dictionary <long, string>(); var trackKeys = new Dictionary <long, MusicBeeFile>(); foreach (var item in syncItems) { if (AbortSynchronization) { SynchronizationInProgress = false; AbortSynchronization = false; lastEx = null; return(true); } if (item.Key == (int)SynchronisationCategory.Playlist) { // Create or verify playlist. Populate after all files have been processed. var name = Regex.Replace(item.Value[0], "^.*\\\\(.*)(\\..*)", "$1"); var playlist = iTunes.GetPlaylist(name) ?? iTunes.CreatePlaylist(name); var key = iTunes.GetPersistentId(playlist); Marshal.ReleaseComObject(playlist); playlistKeys[key] = item.Value[0]; } else { // item.Value[0] is the URL to a MusicBee file to be sync'ed // item.Value[1] is the extension of the file // indicate to MusicBee that you want to synch the file // the returned filename is either the same as the supplied filename or // if re-encoding/forced embedding artwork, a temporary filename is returned var filename = Plugin.MbApiInterface.Sync_FileStart(item.Value[0]); // if filename is returned as null, that means MusicBee wasnt able to encode the file and it should be skipped from synchronisation if (filename == null) { continue; } bool success = false; string errorMessage = null; try { var mbFile = new MusicBeeFile(item.Value[0]); IITTrack itTrack = null; string itTrackPath = null; if (mbFile.WebFile) { itTrackPath = mbFile.Url; } else if (!File.Exists(filename)) { throw new IOException(Text.L("Track source file not found: {0}", filename)); } else if (mbFile.Url == filename) { itTrackPath = filename; } else { // Track was converted to a format that iTunes accepts... // Create a unique name for the converted file and store it in the MB file record var trackGUID = mbFile.ReencodingFileName; if (string.IsNullOrEmpty(trackGUID)) { trackGUID = Guid.NewGuid().ToString(); mbFile.ReencodingFileName = trackGUID; mbFile.CommitChanges(); } itTrackPath = Path.Combine(ReencodedFilesStorage, trackGUID + item.Value[1]); File.Copy(filename, itTrackPath, true); } var itKey = mbFile.ITunesKey; // Track was synced before if (itKey != 0) { itTrack = iTunes.GetTrackByPersistentId(itKey); if (itTrack == null) { Trace.WriteLine("A file in MusicBee appears to have been sync'ed to iTunes before but is not found in iTunes: " + mbFile.Url); itKey = 0; } else if (!mbFile.WebFile) { //Local or local network file ((IITFileOrCDTrack)itTrack).UpdateInfoFromFile(); } } // Track was never synced before or was deleted from iTunes library if (itTrack == null) { if (mbFile.WebFile) { itTrack = iTunes.LibraryPlaylist.AddURL(itTrackPath); } else { var operation = iTunes.LibraryPlaylist.AddFile(itTrackPath).Await(); var tracks = operation.Tracks; itTrack = tracks[1]; Marshal.ReleaseComObject(tracks); Marshal.ReleaseComObject(operation); itKey = iTunes.GetPersistentId(itTrack); mbFile.ITunesKey = itKey; mbFile.CommitChanges(); } } // Sync ratings & play counts to iTunes itTrack.SyncMusicBeeHistoryToITunes(mbFile); mbFile.SyncFileTimestamp(itTrackPath); Marshal.ReleaseComObject(itTrack); trackKeys[itKey] = mbFile; success = true; errorMessage = null; } catch (Exception ex) { Trace.WriteLine(ex); lastEx = ex; if (errorMessage == null) { errorMessage = ex.Message; } } finally { Plugin.MbApiInterface.Sync_FileEnd(item.Value[0], success, errorMessage); } } } // Remove non-sync'ed tracks foreach (var track in iTunes.GetAllTracks()) { var key = iTunes.GetPersistentId(track); if (!trackKeys.ContainsKey(key)) { Plugin.MbApiInterface.MB_SetBackgroundTaskMessage(Text.L("Removing track: \"{0}\"", track.Name)); track.Delete(); } Marshal.ReleaseComObject(track); } // Remove non-sync'ed playlists and populate the remaining ones foreach (var playlist in iTunes.GetPlaylists()) { var key = iTunes.GetPersistentId(playlist); if (playlistKeys.ContainsKey(key)) { Plugin.MbApiInterface.MB_SetBackgroundTaskMessage(Text.L("Clearing playlist: \"{0}\"", playlist.Name)); playlist.DeleteAllTracks(); var m = 0; var playlistFiles = MusicBeeFile.GetPlaylistFiles(playlistKeys[key]).ToArray(); foreach (var playlistFile in playlistFiles) { m++; Plugin.MbApiInterface.MB_SetBackgroundTaskMessage(Text.L("Adding track {0} of {1} to playlist: \"{2}\"", m, playlistFiles.Length, playlist.Name)); iTunes.AddTrackToPlaylistByPersistentId(playlist, playlistFile.ITunesKey); } } else { Plugin.MbApiInterface.MB_SetBackgroundTaskMessage(Text.L("Removing playlist: \"{0}\"", playlist.Name)); playlist.Delete(); } Marshal.ReleaseComObject(playlist); } return(lastEx == null); } catch (Exception ex) { Trace.WriteLine(ex); MbApiInterface.MB_SendNotification(CallbackType.StorageFailed); lastEx = ex; return(false); } finally { Plugin.MbApiInterface.MB_SetBackgroundTaskMessage(""); SynchronizationInProgress = false; } }