# Licensed for distribution under the GPL version 2, check COPYING for details
import logging
+import os
+import sys
+import traceback
import objc
from Foundation import *
return len(playlist.children)
def outlineView_objectValueForTableColumn_byItem_(self, _, col, playlist):
- col = col.identifier() if col else "playlist"
+ if not col:
+ return
+ col = col.identifier()
if col == "selected":
selected = NSApp.delegate().playlists()
return playlist.pid in selected
- if col == None or col == "playlist":
+ if col == "icon":
+ return NSImage.imageNamed_("playlist-" + playlist.ptype)
+ if col == "playlist":
return playlist.name
def outlineView_setObjectValue_forTableColumn_byItem_(self, _, v, col, playlist):
- col = col.identifier() if col else "playlist"
+ if not col:
+ return
+ col = col.identifier()
+
if col != "selected":
return
class NotiPodController(NSObject):
window = objc.IBOutlet()
- playlistModel = objc.IBOutlet()
- folderModel = objc.IBOutlet()
+
loadingSheet = objc.IBOutlet()
loadingLabel = objc.IBOutlet()
+ loadingIndicator = objc.IBOutlet()
+
+ previewWindow = objc.IBOutlet()
+ previewText = objc.IBOutlet()
+
+ playlistModel = objc.IBOutlet()
+ folderModel = objc.IBOutlet()
+
def awakeFromNib(self):
- self.gen = None
+ self.runningGenerator = False
+ self.previewWindow.setReleasedWhenClosed_(False)
# Delegate methods
def applicationWillFinishLaunching_(self, _):
self.library = libnotipod.ITunesLibrary.alloc().init()
def finish():
self.playlistModel.setPlaylists(self.library.get_playlists())
- self.runGenerator(lambda: self.library.load_(None), finish)
+ def fail():
+ sys.exit(0)
+ self.runGenerator(lambda: self.library.load_(None), finish, fail)
def applicationWillTerminate_(self, _):
self.prefs().synchronize()
# Utility methods
- def runGenerator(self, func, finish):
+ def runGenerator(self, func, finish, fail):
+ assert not self.runningGenerator
+ self.runningGenerator = True
+ self.loadingIndicator.startAnimation_(self)
NSApp.beginSheet_modalForWindow_modalDelegate_didEndSelector_contextInfo_(self.loadingSheet, self.window, None, None, None)
- arg = (func(), finish)
+ arg = (func(), finish, fail)
self.performSelectorInBackground_withObject_(self.runGeneratorThread, arg)
- def runGeneratorThread(self, (gen, finish)):
+ def runGeneratorThread(self, (gen, finish, fail)):
pool = NSAutoreleasePool.alloc().init()
- for msg in gen:
- self.loadingLabel.performSelectorOnMainThread_withObject_waitUntilDone_(
- self.loadingLabel.setStringValue_, msg, True)
+ try:
+ for msg in gen:
+ if not self.runningGenerator:
+ break
+ self.loadingLabel.performSelectorOnMainThread_withObject_waitUntilDone_(
+ self.loadingLabel.setStringValue_, msg, True)
+ except Exception, e:
+ NSRunAlertPanel("Error!", str(e), "Ok", None, None)
+ traceback.print_exc()
+ finish = fail
self.performSelectorOnMainThread_withObject_waitUntilDone_(
self.stopGenerator, finish, True)
- del pool
-
+ self.runningGenerator = False
+
def stopGenerator(self, finish):
+ self.runningGenerator = False
NSApp.endSheet_(self.loadingSheet)
self.loadingSheet.orderOut_(self)
+ self.loadingIndicator.stopAnimation_(self)
if finish:
finish()
@objc.IBAction
def doCancel_(self, sender):
- self.stopGenerator(None)
+ self.runningGenerator = False
+
+ def doPreviewThread(self):
+ yield "Calculating changes..."
+
+ folder = self.folders()[0]
+ if not os.path.isdir(folder.encode("utf-8")):
+ NSRunAlertPanel("Error!", "Destination " + folder + " does not exist, try mounting it first?", "Ok", None, None)
+ return
+
+ all_tracks = []
+ for playlist_id in self.playlists():
+ playlist = self.library.get_playlist_pid(playlist_id)
+ if playlist is not None:
+ all_tracks.extend(playlist.tracks)
+
+ gen = libnotipod.sync(
+ dry_run=True,
+ source=self.library.folder,
+ dest=folder,
+ files_to_copy=all_tracks
+ )
+ self.previewResult = "\n".join(gen)
+
+ @objc.IBAction
+ def doPreview_(self, sender):
+ self.previewResult = ""
+ self.previewWindow.orderOut_(self)
+
+ def finish():
+ self.previewText.textStorage().mutableString().setString_(self.previewResult)
+ self.previewWindow.center()
+ self.previewWindow.makeKeyAndOrderFront_(self)
+
+ self.runGenerator(self.doPreviewThread, finish, None)
@objc.IBAction
def doSync_(self, sender):
folder = self.folders()[0]
- playlists = [self.library.get_playlist_pid(pid) for pid in self.playlists()]
+ if not os.path.isdir(folder.encode("utf-8")):
+ NSRunAlertPanel("Error!", "Destination " + folder + " does not exist, try mounting it first?", "Ok", None, None)
+ return
all_tracks = []
- for playlist in playlists:
+ for playlist_id in self.playlists():
+ playlist = self.library.get_playlist_pid(playlist_id)
+ if playlist is None:
+ print "Forgetting unknown playlist:", playlist_id
+ self.setPlaylist_selected_(playlist_id, False)
+ continue
all_tracks.extend(playlist.tracks)
libnotipod.export_m3u(dry_run=False, dest=folder, path_prefix="",
playlist_name=playlist.name, files=playlist.tracks)
files_to_copy=all_tracks
)
,
- finish
+ finish,
+ None
)