import logging
import os
import sys
+import time
import traceback
import uuid
loadingLabel = objc.IBOutlet()
loadingIndicator = objc.IBOutlet()
+ advancedSheet = objc.IBOutlet()
+ advancedSyncFolder = objc.IBOutlet()
+ advancedPathPrefix = objc.IBOutlet()
+
previewWindow = objc.IBOutlet()
previewText = objc.IBOutlet()
self.folderModel.loadFolders_(folders)
self.library = libnotipod.ITunesLibrary.alloc().init()
- self.loadLibrary()
+ self.loadLibrary_(self)
def applicationWillTerminate_(self, _):
self.prefs().synchronize()
def windowDidBecomeKey_(self, _):
if self.library.needs_reload():
- print "needs reload!"
- self.loadLibrary()
- else:
- print "no reloading this time"
+ self.loadLibrary_(self)
# Utility methods
- def loadLibrary(self):
- 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)
- sys.exit(0)
- self.runGenerator(lambda: self.library.load_(None), finish, fail)
-
def runGenerator(self, func, finish, fail):
assert not self.runningGenerator
self.runningGenerator = True
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()
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()
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)
@objc.IBAction
def doSync_(self, sender):
- folder = self.getDestFolder()
- if not folder:
+ target = self.getCheckTarget()
+ if not target:
return
all_tracks = set()
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)
libnotipod.sync(
dry_run=False,
source=self.library.folder,
- dest=folder,
+ dest=target["folder"],
files_to_copy=all_filenames,
)
,
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"])
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"])