]> code.delx.au - notipod/blobdiff - notipod_gui.py
Ignore tracks not in the library
[notipod] / notipod_gui.py
index 52b4456faa633bb910a0a68b0f9b6835fd39857c..11c6880a86604a493a22d27dca616e220d228ce6 100644 (file)
@@ -5,6 +5,7 @@
 import logging
 import os
 import sys
+import time
 import traceback
 import uuid
 
@@ -122,6 +123,10 @@ class NotiPodController(NSObject):
        loadingLabel = objc.IBOutlet()
        loadingIndicator = objc.IBOutlet()
 
+       advancedSheet = objc.IBOutlet()
+       advancedSyncFolder = objc.IBOutlet()
+       advancedPathPrefix = objc.IBOutlet()
+
        previewWindow = objc.IBOutlet()
        previewText = objc.IBOutlet()
 
@@ -143,13 +148,9 @@ class NotiPodController(NSObject):
                for target in self.targets:
                        folders.append(target["folder"])
                self.folderModel.loadFolders_(folders)
-               
+
                self.library = libnotipod.ITunesLibrary.alloc().init()
-               def finish():
-                       self.playlistModel.setPlaylists(self.library.get_playlists())
-               def fail():
-                       sys.exit(0)
-               self.runGenerator(lambda: self.library.load_(None), finish, fail)
+               self.loadLibrary_(self)
 
        def applicationWillTerminate_(self, _):
                self.prefs().synchronize()
@@ -157,6 +158,10 @@ class NotiPodController(NSObject):
        def applicationShouldTerminateAfterLastWindowClosed_(self, _):
                return True
 
+       def windowDidBecomeKey_(self, _):
+               if self.library.needs_reload():
+                       self.loadLibrary_(self)
+
 
        # Utility methods
        def runGenerator(self, func, finish, fail):
@@ -169,12 +174,15 @@ class NotiPodController(NSObject):
 
        def runGeneratorThread(self, (gen, finish, fail)):
                pool = NSAutoreleasePool.alloc().init()
+               last_time = 0
                try:
                        for msg in gen:
                                if not self.runningGenerator:
                                        break
-                               self.loadingLabel.performSelectorOnMainThread_withObject_waitUntilDone_(
-                                       self.loadingLabel.setStringValue_, msg, True)
+                               now = time.time()
+                               if now - last_time > 0.1:
+                                       self.loadingLabel.performSelectorOnMainThread_withObject_waitUntilDone_(
+                                               self.loadingLabel.setStringValue_, msg, True)
                except Exception, e:
                        NSRunAlertPanel("Error!", str(e), "Ok", None, None)
                        traceback.print_exc()
@@ -191,26 +199,64 @@ class NotiPodController(NSObject):
                if finish:
                        finish()
 
+
+       @objc.IBAction
+       def loadLibrary_(self, sender):
+               if self.runningGenerator:
+                       return
+
+               def finish():
+                       self.playlistModel.setPlaylists(self.library.get_playlists())
+               def fail():
+                       NSRunAlertPanel("Error!", "Unable to load iTunes library! Exiting...", "Ok", None, None)
+                       os._exit(0)
+               self.runGenerator(lambda: self.library.load_(None), finish, fail)
+
+       @objc.IBAction
+       def showAdvancedOptions_(self, sender):
+               if self.runningGenerator:
+                       return
+               target = self.getCurrentTarget()
+               self.advancedSyncFolder.setStringValue_(target["folder"])
+               self.advancedPathPrefix.setStringValue_(target["path_prefix"])
+               NSApp.beginSheet_modalForWindow_modalDelegate_didEndSelector_contextInfo_(self.advancedSheet, self.window, None, None, None)
+
+       @objc.IBAction
+       def finishAdvancedOptions_(self, sender):
+               target = self.getCurrentTarget()
+               target["folder"] = self.advancedSyncFolder.stringValue()
+               target["path_prefix"] = self.advancedPathPrefix.stringValue()
+               self._savePrefs()
+               NSApp.endSheet_(self.advancedSheet)
+               self.advancedSheet.orderOut_(self)
+
        @objc.IBAction
        def doCancel_(self, sender):
                self.runningGenerator = False
 
-       def getDestFolder(self):
+       def getCheckTarget(self):
                target = self.getCurrentTarget()
                if not target:
                        NSRunAlertPanel("Error!", "You must choose a folder first!", "Ok", None, None)
                        return
                folder = target["folder"]
+
                if not os.path.isdir(folder.encode("utf-8")):
                        NSRunAlertPanel("Error!", "Destination " + folder + " does not exist, try mounting it first?", "Ok", None, None)
                        return
-               return folder
+
+               folder_contents = [f for f in os.listdir(folder) if not f.startswith(".")]
+               if len(folder_contents) > 0 and "-Playlists-" not in folder_contents:
+                       NSRunAlertPanel("Error!", "Refusing to clobber files in non-empty folder: " + folder, "Ok", None, None)
+                       return
+
+               return target
 
        def doPreviewThread(self):
                yield "Calculating changes..."
 
-               folder = self.getDestFolder()
-               if not folder:
+               target = self.getCheckTarget()
+               if not target:
                        return
 
                all_tracks = set()
@@ -221,12 +267,14 @@ class NotiPodController(NSObject):
 
                all_filenames = []
                for trackID in all_tracks:
-                       all_filenames.append(self.library.get_track_filename(trackID))
+                       f = self.library.get_track_filename(trackID)
+                       if f:
+                               all_filenames.append(f)
 
                gen = libnotipod.sync(
                        dry_run=True,
                        source=self.library.folder,
-                       dest=folder, 
+                       dest=target["folder"],
                        files_to_copy=all_filenames,
                )
                self.previewResult = "\n".join(gen)
@@ -245,8 +293,8 @@ class NotiPodController(NSObject):
 
        @objc.IBAction
        def doSync_(self, sender):
-               folder = self.getDestFolder()
-               if not folder:
+               target = self.getCheckTarget()
+               if not target:
                        return
 
                all_tracks = set()
@@ -262,21 +310,33 @@ class NotiPodController(NSObject):
 
                all_filenames = []
                for trackID in all_tracks:
-                       all_filenames.append(self.library.get_track_filename(trackID))
+                       f = self.library.get_track_filename(trackID)
+                       if f:
+                               all_filenames.append(f)
                        all_playlists.update(self.library.get_track_playlists(trackID))
 
+               libnotipod.delete_playlists(dry_run=False, dest=target["folder"])
+
                for playlist_id in all_playlists:
                        playlist = self.library.get_playlist_pid(playlist_id)
                        if playlist is None:
                                continue
                        tracks = []
                        for trackID in playlist.tracks:
-                               if trackID in all_tracks:
-                                       tracks.append(self.library.get_track_filename(trackID))
+                               if trackID not in all_tracks:
+                                       continue
+                               f = self.library.get_track_filename(trackID)
+                               if f:
+                                       tracks.append(f)
                        if playlist_id not in orig_playlists and len(tracks) < 10:
                                continue
-                       libnotipod.export_m3u(dry_run=False, dest=folder, path_prefix="",
-                                       playlist_name=playlist.name, files=tracks)
+                       libnotipod.export_m3u(
+                               dry_run=False,
+                               dest=target["folder"],
+                               path_prefix=target["path_prefix"],
+                               playlist_name=playlist.name,
+                               files=tracks
+                       )
 
                def finish():
                        NSRunAlertPanel("Complete!", "Synchronisation is complete", "Ok", None, None)
@@ -285,7 +345,7 @@ class NotiPodController(NSObject):
                                libnotipod.sync(
                                        dry_run=False,
                                        source=self.library.folder,
-                                       dest=folder, 
+                                       dest=target["folder"],
                                        files_to_copy=all_filenames,
                                )
                        ,
@@ -301,7 +361,7 @@ class NotiPodController(NSObject):
 
        def _migratePrefs(self):
                p = self.prefs()
-               
+
                playlists = p.stringArrayForKey_("playlists")
                if playlists is not None:
                        p.removeObjectForKey_("playlists")
@@ -318,7 +378,8 @@ class NotiPodController(NSObject):
                        target = {}
                        target["folder"] = f
                        target["playlists"] = list(playlists)
-                       target["uuid"] = uuid.uuid1().get_hex()
+                       target["uuid"] = uuid.uuid4().get_hex()
+                       target["path_prefix"] = "../"
                        if first:
                                first = False
                                self.setCurrentTarget_(target["uuid"])
@@ -329,8 +390,8 @@ class NotiPodController(NSObject):
        def _loadPrefs(self):
                p = self.prefs()
 
-               self.current_target = None
-               self.setCurrentTarget_(p.stringForKey_("current_target"))
+               self.currentTarget = None
+               self.setCurrentTarget_(p.stringForKey_("currentTarget"))
 
                self.targets = self.prefs().arrayForKey_("targets")
                if self.targets is None:
@@ -343,22 +404,22 @@ class NotiPodController(NSObject):
 
        def _savePrefs(self):
                p = self.prefs()
-               p.setObject_forKey_(self.current_target, "current_target")
+               p.setObject_forKey_(self.currentTarget, "currentTarget")
                p.setObject_forKey_(self.targets, "targets")
                p.synchronize()
 
        def getCurrentTarget(self):
                for target in self.targets:
-                       if target["uuid"] == self.current_target:
+                       if target["uuid"] == self.currentTarget:
                                return target
                return None
-       
-       def setCurrentTarget_(self, target_uuid):
-               old_uuid = self.current_target
-               self.current_target = target_uuid
-               if old_uuid is None and target_uuid is not None:
+
+       def setCurrentTarget_(self, targetUuid):
+               oldUuid = self.currentTarget
+               self.currentTarget = targetUuid
+               if oldUuid is None and targetUuid is not None:
                        self.playlistModel.outlineView.setEnabled_(True)
-               if old_uuid != target_uuid:
+               if oldUuid != targetUuid:
                        self.playlistModel.outlineView.reloadItem_reloadChildren_(None, True)
 
        def playlists(self):
@@ -377,7 +438,8 @@ class NotiPodController(NSObject):
                        target = {}
                        target["folder"] = folder
                        target["playlists"] = self.playlists()
-                       target["uuid"] = uuid.uuid1().get_hex()
+                       target["uuid"] = uuid.uuid4().get_hex()
+                       target["path_prefix"] = "../"
                        self.targets.insertObject_atIndex_(target, 0)
 
                self.setCurrentTarget_(target["uuid"])