#!/usr/bin/env python import sys, locale import pygtk pygtk.require("2.0") import gtk import Moosic TRUE = 1 FALSE = 0 # Set the locale locale.setlocale(locale.LC_ALL, '') # Instantiate a Moosic client object for controlling the Moosic server. moosic = Moosic.MoosicClient() # Create the main window. window = gtk.Window(gtk.WINDOW_TOPLEVEL) window.connect("destroy", gtk.mainquit) # quit the event loop on destruction window.set_border_width(3) window.set_default_size(500, 300) window.set_title("Moosic Song Queue") # Create a horizontal box to hold most of the app's widgets. vbox = gtk.VBox(FALSE, 3) window.add(vbox) # Create a menu bar. accel_group = gtk.AccelGroup() menu_items = ( # path, accel, callback, param, type ("/_File", None, None, 0, ""), ("/File/_Quit", "Q", gtk.mainquit, 0, None), ) menu_factory = gtk.ItemFactory(gtk.MenuBar, "
", accel_group) menu_factory.create_items(menu_items) vbox.pack_start(menu_factory.get_widget("
"), FALSE, TRUE, 0) window.add_accel_group(accel_group) # Create a label to display the currently playing song. current_song_frame = gtk.Frame("Currently playing song") current_song_label = gtk.Entry() current_song_label.set_text(moosic.current()) current_song_label.set_editable(FALSE) current_song_frame.add(current_song_label) vbox.pack_start(current_song_frame, FALSE) # Create a frame and a scrolled window to contain the song list. songlist_frame = gtk.Frame("Contents of the song queue") vbox.pack_start(songlist_frame) scrolled_window = gtk.ScrolledWindow() scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) songlist_frame.add(scrolled_window) # Create a list to display the songs that are currently in the Moosic queue. clist = gtk.CList(2) clist.set_selection_mode(gtk.SELECTION_EXTENDED) scrolled_window.add_with_viewport(clist) # Create a button to print the current list selection to stdout for debugging # purposes. #selection_button = gtk.Button("Print Selection") #def show_selection(widget, clist): # print "The current selection:", clist.selection #selection_button.connect("clicked", show_selection, clist) #vbox.pack_start(selection_button, FALSE) # Refresh the data display every 0.5 seconds. def refresh(clist, song_label): try: moosic.no_op() except: print "The Moosic server is not running!" # TODO: pop up a warning dialog box return FALSE def utf8(something): '''Converts something into a UTF8-encoded Unicode string.''' return unicode(something, locale.getlocale()[1]).encode('utf-8') current_song = utf8(moosic.current()) # Don't bother refreshing the song label if it hasn't actually changed. if current_song != song_label.get_text(): song_label.set_text(current_song) songlist = [utf8(x) for x in moosic.list()] # Don't bother refreshing the list if it hasn't actually changed. if songlist != [clist.get_text(row, 1) for row in range(clist.rows)]: clist.freeze() clist.clear() num = 0 for item in songlist: clist.append([str(num), item]) num += 1 clist.set_column_width(0, clist.optimal_column_width(0)) clist.set_column_width(1, clist.optimal_column_width(1)) clist.thaw() return TRUE gtk.timeout_add(500, refresh, clist, current_song_label) # TODO: create a toolbar for commonly-used actions: skip, delete, # TODO: add more entries to the menu # - File # - Save playlist... # - Load playlist... # - Quit # - Queue # - Skip to the next song # - Stop # - (Un)Pause # - Kill/Start the server # - Add # - Add file or directory... # - Add playlist... # - Add literal string... # - Remove # - Remove all items # - Remove selected items # - Remove by regexp... # - Rearrange # - Sort # - Shuffle # - Reverse # - Configuration # - Show config # - Reload config # - Edit config # - Help (of course) # - Show version info (about) # TODO: add drag'n'drop # TODO: allow editing of an individual list item by double-clicking on it # TODO: handle the case where the Moosic server isn't running. # TODO (maybe, way in the future): add a slider for adjusting the soundcard's # volume. window.show_all() gtk.main()