X-Git-Url: http://git.maemo.org/git/?p=watersofshiloah;a=blobdiff_plain;f=src%2Fmormonchannel_gtk.py;h=fb7749df5a40ebe943caa7c1f33ef9ffda2a2fe0;hp=1b020b37052802820763495b0602c6e44def8b8f;hb=38a0379289645cae29c5522ffdca16fd557369dd;hpb=ef6503021e57ba2e8da4e0eefc5c080fbee2a5cb diff --git a/src/mormonchannel_gtk.py b/src/mormonchannel_gtk.py index 1b020b3..fb7749d 100755 --- a/src/mormonchannel_gtk.py +++ b/src/mormonchannel_gtk.py @@ -2,34 +2,46 @@ # -*- coding: utf-8 -*- """ +@bug For some reason, the back/close button doesn't work when I nest multiple levels +@bug When switching from conference to magazines, it randomly jumps around and duplicates windows +@bug fullscreen does not propgate + +@todo Re-use windows for better performance +@todo Make radio program updates only happen when the app has focus to reduce CPU wakes +@todo Need to confirm id's are persistent (not just for todos but broken behavior on transition) + @todo Track recent + @todo Persisted Pause + @todo Favorites +@todo Sleep timer @todo Reverse order option. Toggle between playing ascending/descending chronological order -@todo Track recent +@todo Podcast integration + @todo Default with BYU Devotionals, http://speeches.byu.edu/?act=help&page=podcast """ from __future__ import with_statement +import os import gc import logging import ConfigParser +import gobject +import dbus +import dbus.mainloop.glib import gtk try: - import hildon -except ImportError: - hildon = None - -try: import osso except ImportError: osso = None import constants import hildonize -import gtk_toolbox +import util.misc as misc_utils import imagestore import player +import stream_index import windows @@ -41,134 +53,52 @@ class MormonChannelProgram(hildonize.get_app_class()): def __init__(self): super(MormonChannelProgram, self).__init__() - self._clipboard = gtk.clipboard_get() - self._player = player.Player() - self._store = imagestore.ImageStore("../data", "../data") - - self._window_in_fullscreen = False #The window isn't in full screen mode initially. - - #Create GUI main vbox - vbox = gtk.VBox(homogeneous = False, spacing = 0) - - if hildonize.GTK_MENU_USED: - #Create Menu and apply it for hildon - filemenu = gtk.Menu() - - menu_items = gtk.MenuItem("Quit") - filemenu.append(menu_items) - menu_items.connect("activate", self._on_destroy, None) - - file_menu = gtk.MenuItem("File") - file_menu.show() - file_menu.set_submenu(filemenu) - - categorymenu = gtk.Menu() - - menu_items = gtk.MenuItem("Search") - categorymenu.append(menu_items) - menu_items.connect("activate", self._on_toggle_search) - - helpmenu = gtk.Menu() - - menu_items = gtk.MenuItem("About") - helpmenu.append(menu_items) - menu_items.connect("activate", self._on_show_about, None) - - help_menu = gtk.MenuItem("Help") - help_menu.show() - help_menu.set_submenu(helpmenu) - - menuBar = gtk.MenuBar() - menuBar.show() - menuBar.append (file_menu) - menuBar.append (help_menu) - - vbox.pack_start(menuBar, False, False, 0) - else: - menuBar = gtk.MenuBar() - menuBar.show() - vbox.pack_start(menuBar, False, False, 0) - - #Get the Main Window, and connect the "destroy" event - self._window = gtk.Window() - self._window.add(vbox) - - self._window = hildonize.hildonize_window(self, self._window) - hildonize.set_application_title(self._window, "%s" % constants.__pretty_app_name__) - self._window.set_icon(self._store.get_pixbuf_from_store(self._store.STORE_LOOKUP["icon"])) - menuBar = hildonize.hildonize_menu( - self._window, - menuBar, - ) - if hildonize.IS_FREMANTLE_SUPPORTED: - searchButton= gtk.Button("Search") - searchButton.connect("clicked", self._on_toggle_search) - menuBar.append(searchButton) - - menuBar.show_all() - - if not hildonize.IS_HILDON_SUPPORTED: - _moduleLogger.info("No hildonization support") - - if osso is not None: - self._osso_c = osso.Context(constants.__app_name__, constants.__version__, False) - self._deviceState = osso.DeviceState(self._osso_c) - self._deviceState.set_device_state_callback(self._on_device_state_change, 0) - else: - _moduleLogger.info("No osso support") - self._osso_c = None - self._deviceState = None - - self._window.connect("delete-event", self._on_delete_event) - self._window.connect("destroy", self._on_destroy) - self._window.connect("key-press-event", self._on_key_press) - self._window.connect("window-state-event", self._on_window_state_change) - - self._window.show_all() - - self._windowStack = [windows.SourceSelector(self._player, self._store)] - vbox.pack_start(self._windowStack[0].toplevel, True, True) + currentPath = os.path.abspath(__file__) + storePath = os.path.join(os.path.split(os.path.dirname(currentPath))[0], "data") + self._store = imagestore.ImageStore(storePath, constants._cache_path_) + self._index = stream_index.AudioIndex() + self._player = player.Player(self._index) + + self._store.start() + self._index.start() + try: + if not hildonize.IS_HILDON_SUPPORTED: + _moduleLogger.info("No hildonization support") - self._load_settings() + if osso is not None: + self._osso_c = osso.Context(constants.__app_name__, constants.__version__, False) + self._deviceState = osso.DeviceState(self._osso_c) + self._deviceState.set_device_state_callback(self._on_device_state_change, 0) + else: + _moduleLogger.info("No osso support") + self._osso_c = None + self._deviceState = None + + self._sourceSelector = windows.source.SourceSelector(self, self._player, self._store, self._index) + self._sourceSelector.window.connect("destroy", self._on_destroy) + self._sourceSelector.window.set_default_size(400, 800) + self._sourceSelector.show() + self._load_settings() + except: + self._index.stop() + self._store.stop() + raise def _save_settings(self): config = ConfigParser.SafeConfigParser() - self.save_settings(config) + + self._sourceSelector.save_settings(config, "Windows") + with open(constants._user_settings_, "wb") as configFile: config.write(configFile) - def save_settings(self, config): - config.add_section(constants.__pretty_app_name__) - config.set(constants.__pretty_app_name__, "fullscreen", str(self._window_in_fullscreen)) - def _load_settings(self): config = ConfigParser.SafeConfigParser() config.read(constants._user_settings_) - self.load_settings(config) - def load_settings(self, config): - try: - self._window_in_fullscreen = config.getboolean(constants.__pretty_app_name__, "fullscreen") - except ConfigParser.NoSectionError, e: - _moduleLogger.info( - "Settings file %s is missing section %s" % ( - constants._user_settings_, - e.section, - ) - ) - - if self._window_in_fullscreen: - self._window.fullscreen() - else: - self._window.unfullscreen() - - def _toggle_search(self): - if self._search.get_property("visible"): - self._search.hide() - else: - self._search.show() - - @gtk_toolbox.log_exception(_moduleLogger) + self._sourceSelector.load_settings(config, "Windows") + + @misc_utils.log_exception(_moduleLogger) def _on_device_state_change(self, shutdown, save_unsaved_data, memory_low, system_inactivity, message, userData): """ For system_inactivity, we have no background tasks to pause @@ -181,67 +111,30 @@ class MormonChannelProgram(hildonize.get_app_class()): if save_unsaved_data or shutdown: self._save_settings() - @gtk_toolbox.log_exception(_moduleLogger) - def _on_window_state_change(self, widget, event, *args): - if event.new_window_state & gtk.gdk.WINDOW_STATE_FULLSCREEN: - self._window_in_fullscreen = True - else: - self._window_in_fullscreen = False - - @gtk_toolbox.log_exception(_moduleLogger) - def _on_key_press(self, widget, event, *args): - RETURN_TYPES = (gtk.keysyms.Return, gtk.keysyms.ISO_Enter, gtk.keysyms.KP_Enter) - isCtrl = bool(event.get_state() & gtk.gdk.CONTROL_MASK) - if ( - event.keyval == gtk.keysyms.F6 or - event.keyval in RETURN_TYPES and isCtrl - ): - # The "Full screen" hardware key has been pressed - if self._window_in_fullscreen: - self._window.unfullscreen () - else: - self._window.fullscreen () - return True - elif event.keyval == gtk.keysyms.f and isCtrl: - self._toggle_search() - return True - elif ( - event.keyval in (gtk.keysyms.w, gtk.keysyms.q) and - event.get_state() & gtk.gdk.CONTROL_MASK - ): - self._window.destroy() - elif event.keyval == gtk.keysyms.l and event.get_state() & gtk.gdk.CONTROL_MASK: - with open(constants._user_logpath_, "r") as f: - logLines = f.xreadlines() - log = "".join(logLines) - self._clipboard.set_text(str(log)) - return True - - @gtk_toolbox.log_exception(_moduleLogger) - def _on_toggle_search(self, *args): - self._toggle_search() - - @gtk_toolbox.log_exception(_moduleLogger) - def _on_delete_event(self, widget, event, data = None): - return False - - @gtk_toolbox.log_exception(_moduleLogger) + @misc_utils.log_exception(_moduleLogger) def _on_destroy(self, widget = None, data = None): try: - self._save_settings() - - try: - self._deviceState.close() - except AttributeError: - pass # Either None or close was removed (in Fremantle) - try: - self._osso_c.close() - except AttributeError: - pass # Either None or close was removed (in Fremantle) + self.quit() finally: gtk.main_quit() - @gtk_toolbox.log_exception(_moduleLogger) + def quit(self): + self._save_settings() + + self._player.stop() + self._index.stop() + self._store.stop() + + try: + self._deviceState.close() + except AttributeError: + pass # Either None or close was removed (in Fremantle) + try: + self._osso_c.close() + except AttributeError: + pass # Either None or close was removed (in Fremantle) + + @misc_utils.log_exception(_moduleLogger) def _on_show_about(self, widget = None, data = None): dialog = gtk.AboutDialog() dialog.set_position(gtk.WIN_POS_CENTER) @@ -257,11 +150,20 @@ class MormonChannelProgram(hildonize.get_app_class()): def run(): - if hildonize.IS_HILDON_SUPPORTED: - gtk.set_application_name(constants.__pretty_app_name__) + gobject.threads_init() + gtk.gdk.threads_init() + l = dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) + + hildonize.set_application_name("FMRadio") # Playback while silent on Maemo 5 app = MormonChannelProgram() if not PROFILE_STARTUP: - gtk.main() + try: + gtk.main() + except KeyboardInterrupt: + app.quit() + raise + else: + app.quit() if __name__ == "__main__":