def __update_now_playing(self): try: track = library[self.__uri] except KeyError: return if (not track[ARTIST] or not track[TITLE] or track[LENGTH] < 30 or not blacfg.getboolean("lastfm", "scrobble") or not blacfg.getboolean("lastfm", "now.playing")): return session_key = self.get_session_key() if not session_key: return method = "track.updateNowPlaying" params = [ ("method", method), ("api_key", blaconst.LASTFM_APIKEY), ("artist", track[ARTIST]), ("track", track[TITLE]), ("sk", session_key) ] if track[ALBUM]: params.append(("album", track[ALBUM])) if track[ALBUM_ARTIST]: params.append(("album_artist", track[ALBUM_ARTIST])) # Sign API call. api_signature = sign_api_call(params) params.append(("api_sig", api_signature)) response = post_message(params) if isinstance(response, ResponseError): print_d("Failed to update nowplaying: %s" % response)
def __init__(self): super(BlaPreferences.GeneralSettings, self).__init__("General") # Tray tray_frame = gtk.Frame("Tray") tray_table = gtk.Table(rows=2, columns=2, homogeneous=False) tray_table.set_border_width(10) tray_frame.add(tray_table) def tray_changed(checkbutton, key): blacfg.setboolean("general", key, checkbutton.get_active()) options = [ ("Always display tray icon", "always.show.tray", [0, 1, 0, 1]), ("Close to tray", "close.to.tray", [0, 1, 1, 2]), ("Show tooltip", "tray.show.tooltip", [1, 2, 0, 1]) ] for label, key, coords in options: b = gtk.CheckButton(label) b.set_active(blacfg.getboolean("general", key)) b.connect("toggled", tray_changed, key) tray_table.attach(b, *coords) # Miscellaneous misc_frame = gtk.Frame("Miscellaneous") misc_table = gtk.Table(rows=1, columns=2, homogeneous=False) misc_table.set_border_width(10) misc_frame.add(misc_table) cb = gtk.CheckButton("Cursor follows playback") cb.set_active( blacfg.getboolean("general", "cursor.follows.playback")) cb.connect("toggled", self.__follow_playback) misc_table.attach(cb, 0, 1, 0, 1) cb = gtk.CheckButton( "Remove track from queue on double-click or return") cb.set_active(blacfg.getboolean( "general", "queue.remove.when.activated")) cb.connect("toggled", self.__queue_remove) misc_table.attach(cb, 1, 2, 0, 1, xpadding=10) cb = gtk.CheckButton("Search after timeout") cb.set_active( blacfg.getboolean("general", "search.after.timeout")) cb.connect("toggled", self.__search_after_timeout) misc_table.attach(cb, 0, 2, 1, 2) self.pack_start(tray_frame, expand=False) self.pack_start(misc_frame, expand=False)
def __update_title(self): track = player.get_track() state = player.get_state() if state == blaconst.STATE_STOPPED or not track: title = "%s %s" % (blaconst.APPNAME, blaconst.VERSION) tooltip = "Stopped" else: if player.radio: title = track[TITLE] or "%s - %s" % ( blaconst.APPNAME, track["organization"]) else: artist = track[ARTIST] title = track[TITLE] or "?" if artist and title: title = "%s - %s" % (artist, title) else: title = track.basename tooltip = title self.set_title(title) self.__tray.set_tooltip(tooltip) if not blacfg.getboolean("general", "tray.show.tooltip"): self.__tray.set_has_tooltip(False)
def play_item(self, treeview, path, column=None): model = treeview.get_model() iterator = model.get_iter(path) model[iterator][0].play() if blacfg.getboolean("general", "queue.remove.when.activated"): model.remove(iterator) self.update_queue_positions()
def __restore_state(self): if self.__is_main_window: self.__maximized = self.__was_maximized = blacfg.getboolean( "general", "maximized") if self.__maximized: self.maximize() else: self.unmaximize()
def __filter_parameters_changed(self, entry): filter_string = self.__filter_entry.get_text() if (blacfg.getboolean("general", "search.after.timeout") or not filter_string): gobject.source_remove(self.__fid) def activate(): self.__filt.refilter() return False self.__fid = gobject.timeout_add(500, activate)
def __button_release_event(self, scale, event): if blacfg.getboolean("player", "muted"): return True if hasattr(event, "button"): event.button = 2 self.__volume = self.__scale.get_value() player.set_volume(self.__volume) return False
def __volume_changed(self, scale): state = blacfg.getboolean("player", "muted") if state: volume = self.__volume else: volume = scale.get_value() blacfg.set("player", "volume", volume / 100.0) player.set_volume(scale.get_value()) self.__update_icon(state)
def __query_tooltip(self, *args): volume = self.__scale.get_value() if blacfg.getboolean("player", "logarithmic.volume.scale"): if volume == 0: tooltip = "-Inf dB" else: tooltip = "%.1f dB" % (50 * (volume / 100.0 - 1)) else: tooltip = "%d%%" % volume self.__scale.set_tooltip_text(tooltip) return False
def __init__(self): super(BlaPreferences.LastfmSettings, self).__init__("last.fm") self.connect("destroy", self.__save) scrobble = gtk.CheckButton("Enable scrobbling") scrobble.set_active(blacfg.getboolean("lastfm", "scrobble")) scrobble.connect("toggled", self.__scrobble_changed) self.__user_entry = gtk.Entry() self.__user_entry.set_text(blacfg.getstring("lastfm", "user")) self.__ignore_entry = gtk.Entry() self.__ignore_entry.set_text( blacfg.getstring("lastfm", "ignore.pattern")) self.__ignore_entry.set_tooltip_text("Comma-separated list") nowplaying = gtk.CheckButton("Submit \"Listening now\" messages") nowplaying.set_active(blacfg.getboolean("lastfm", "now.playing")) nowplaying.connect("toggled", self.__nowplaying_changed) count = 0 pairs = [ ("Username", self.__user_entry), ("Ignore pattern", self.__ignore_entry) ] table = gtk.Table(rows=len(pairs), columns=2, homogeneous=False) count = 0 for label, widget in pairs: label = gtk.Label("%s:" % label) label.set_alignment(xalign=0.0, yalign=0.5) table.attach(label, 0, 1, count, count+1, xoptions=gtk.FILL, xpadding=5) table.attach(widget, 1, 2, count, count+1) count += 1 self.pack_start(scrobble, expand=False) self.pack_start(table, expand=False) self.pack_start(nowplaying, expand=False)
def __init__(self): # TODO: Add support for scroll-events. super(BlaTray, self).__init__() self.set_from_icon_name(blaconst.APPNAME) self.set_visible( blacfg.getboolean("general", "always.show.tray")) self.set_tooltip_text("Stopped") self.set_has_tooltip( blacfg.getboolean("general", "tray.show.tooltip")) def config_changed(cfg, section, key): if section == "general": if key == "always.show.tray": self.set_visible(blacfg.getboolean(section, key)) elif key == "tray.show.tooltip": self.set_has_tooltip(blacfg.getboolean(section, key)) blacfg.connect("changed", config_changed) def activate(status_icon): blaplay.bla.window.toggle_hide() self.connect("activate", activate) self.connect("popup_menu", self.__tray_menu)
def update_treeview_style(self): column = self.__treeview.get_column(0) column.clear() if blacfg.getboolean("library", "custom.browser"): renderer = BlaCellRenderer() else: renderer = gtk.CellRendererText() def cdf(column, renderer, model, iterator): n_children = model.iter_n_children(iterator) if n_children > 0: text = "%s (%d)" % (model[iterator][1], n_children) else: text = model[iterator][1] renderer.set_property("text", text) column.pack_start(renderer) column.set_cell_data_func(renderer, cdf)
def set_volume(self, volume): volume /= 100. if blacfg.getboolean("player", "logarithmic.volume.scale"): volume_db = 50 * (volume - 1.0) if volume_db == -50: volume = 0 else: volume = pow(10, volume_db / 20.0) if volume > 1.0: volume = 1.0 elif volume < 0.0: volume = 0.0 try: self.__volume.set_property("volume", volume) except AttributeError: pass
def __submit_last_track(self, shutdown=False): if self.__uri: try: track = library[self.__uri] except KeyError: return # According to the last.fm API docs, only tracks longer than 30 # seconds should be submitted, and only if min(len[s]/2, 240) # seconds of the track elapsed. Submission should be performed once # a track stops, e.g. on track changes or playback stops (and not # in paused states). if (track[LENGTH] > 30 and track[ARTIST] and track[TITLE] and blacfg.getboolean("lastfm", "scrobble") and (self.__elapsed > track[LENGTH] / 2 or self.__elapsed > 240)): print_d("Submitting track to scrobbler queue") self.__queue.put_nowait((self.__uri, self.__start_time)) self.__uri = None if shutdown: print_i("Saving scrobbler queue") self.__queue.save()
def __init__(self): super(VolumeControl, self).__init__(spacing=5) self.__volume = int(blacfg.getfloat("player", "volume") * 100) state = blacfg.getboolean("player", "muted") if not state: volume = self.__volume else: volume = 0.0 # The mute button self.__image = gtk.Image() mute = gtk.ToggleButton() mute.add(self.__image) mute.set_relief(gtk.RELIEF_NONE) mute.set_active(state) mute.connect("toggled", self.__mute_toggled) # The volume scale self.__scale = gtk.HScale() self.__scale.set_range(0, 100) self.__scale.set_increments(-1, -10) self.__scale.set_size_request(120, 20) self.__scale.set_update_policy(gtk.UPDATE_CONTINUOUS) self.__scale.set_draw_value(False) self.__scale.set_value(volume) self.__scale.connect("value_changed", self.__volume_changed) self.__scale.connect("button_press_event", self.__button_press_event) self.__scale.connect( "button_release_event", self.__button_release_event) self.__scale.connect("scroll_event", self.__scroll_event) self.__scale.connect("key_press_event", lambda *x: True) self.__scale.connect("query_tooltip", self.__query_tooltip) self.__scale.set_has_tooltip(True) self.__update_icon(state) self.pack_start(mute, expand=False) self.pack_start(self.__scale, expand=True)
def __accept_button_event(self, column, path, event, check_expander): # TODO: get rid of this method and implement it only where necessary # (i.e. the library browser) if (not blacfg.getboolean("library", "custom.browser") or self.__multicol or self.__renderer is None): return True renderer = column.get_cell_renderers()[self.__renderer] model = self.get_model() iterator = model.get_iter(path) layout = renderer.get_layout( self, model.get_value(iterator, self.__text_column)) width = layout.get_pixel_size()[0] cell_area = self.get_cell_area(path, column) expander_size = self.style_get_property("expander_size") # check vertical position of click event if not (event.y >= cell_area.y+PADDING_Y and event.y <= cell_area.y+cell_area.height): return False # check for click on expander and if the row has children if (check_expander and event.x >= cell_area.x+PADDING_X-expander_size and event.x <= cell_area.x+PADDING_X and model.iter_has_child(iterator) and event.type not in [gtk.gdk._2BUTTON_PRESS, gtk.gdk._3BUTTON_PRESS]): return True # check for click in the highlighted area if (event.x >= cell_area.x+PADDING_X and event.x <= cell_area.x+width): return True return False
def __init__(self): super(BlaStatusbar, self).__init__(rows=1, columns=3, homogeneous=True) type(self).__instance = self self.__pb = gtk.ProgressBar() self.__pb_label = gtk.Label("Scanning library:") self.__track_info = gtk.Label(self.__state_string) hbox = gtk.HBox(spacing=10) hbox.pack_start(self.__pb_label, expand=False) hbox.pack_start(self.__pb, expand=False, fill=True) hbox.pack_start(self.__track_info, expand=True) self.__view_info = gtk.Label("") # Playback order self.__order = gtk.combo_box_new_text() map(self.__order.append_text, blaconst.ORDER_LITERALS) self.__order.set_active(blacfg.getint("general", "play.order")) def order_changed(cb): order = cb.get_active() states = [False] * len(blaconst.ORDER_LITERALS) states[order] = True ui_manager = blaplay.bla.ui_manager for idx, order in enumerate(blaconst.MENU_ORDER): action = ui_manager.get_widget(order) action.set_active(states[idx]) self.__order.connect("changed", order_changed) table = gtk.Table(rows=1, columns=3) table.attach(gtk.Label("Order:"), 0, 1, 0, 1, xpadding=10) table.attach(self.__order, 1, 2, 0, 1) button = gtk.Button() button.set_tooltip_text("Clear queue") from blaqueue import queue button.connect("clicked", lambda *x: queue.clear()) queue.connect("count_changed", lambda *x: button.set_sensitive(x[-1] > 0)) button.add(gtk.image_new_from_stock(gtk.STOCK_CLEAR, gtk.ICON_SIZE_SMALL_TOOLBAR)) button.set_relief(gtk.RELIEF_NONE) button.set_sensitive(False) table.attach(button, 2, 3, 0, 1), count = 0 for widget, xalign in [(hbox, 0.0), (self.__view_info, 0.5), (table, 1.0)]: alignment = gtk.Alignment(xalign, 0.5, 0.0, 0.5) alignment.add(widget) self.attach(alignment, count, count+1, 0, 1) count += 1 player.connect("state_changed", self.__changed) library.connect("progress", self.update_progress) self.show_all() # TODO: group these two self.__pb.set_visible(False) self.__pb_label.set_visible(False) self.set_visible(blacfg.getboolean("general", "statusbar"))
def __init__(self): super(BlaPreferences.LibraryBrowsersSettings, self).__init__( "Library/Browsers") restrict_string = blacfg.getstring("library", "restrict.to") exclude_string = blacfg.getstring("library", "exclude") def destroy(*args): if (restrict_string != blacfg.getstring("library", "restrict.to") or exclude_string != blacfg.getstring("library", "exclude")): library.sync() self.connect("destroy", destroy) hbox = gtk.HBox(spacing=10) model = gtk.ListStore(gobject.TYPE_STRING) treeview = gtk.TreeView(model) treeview.set_property("rules_hint", True) r = gtk.CellRendererText() treeview.insert_column_with_attributes( -1, "Directories", r, text=0) sw = BlaScrolledWindow() sw.set_shadow_type(gtk.SHADOW_IN) sw.set_size_request(-1, 140) sw.add(treeview) directories = blacfg.getdotliststr("library", "directories") for f in directories: model.append([f]) table = gtk.Table(rows=2, columns=1) items = [ ("Add...", self.__add_directory), ("Remove", self.__remove_directory), ("Rescan all", self.__rescan_all) ] for idx, (label, callback) in enumerate(items): button = gtk.Button(label) button.connect("clicked", callback, treeview) table.attach(button, 0, 1, idx, idx+1, yoptions=not gtk.EXPAND) hbox.pack_start(sw, expand=True) hbox.pack_start(table, expand=False, fill=False) # Update library checkbutton update_library = gtk.CheckButton("Update library on startup") update_library.set_active( blacfg.getboolean("library", "update.on.startup")) update_library.connect( "toggled", lambda cb: blacfg.setboolean("library", "update.on.startup", cb.get_active())) # The file types restrict_to_entry = gtk.Entry() restrict_to_entry.set_tooltip_text( "Comma-separated list, works on filenames") restrict_to_entry.set_text( blacfg.getstring("library", "restrict.to")) restrict_to_entry.connect( "changed", lambda entry: blacfg.set("library", "restrict.to", entry.get_text())) exclude_entry = gtk.Entry() exclude_entry.set_tooltip_text( "Comma-separated list, works on filenames") exclude_entry.set_text( blacfg.getstring("library", "exclude")) exclude_entry.connect( "changed", lambda entry: blacfg.set("library", "exclude", entry.get_text())) pairs = [ (blaconst.ACTION_SEND_TO_CURRENT, "send to current playlist"), (blaconst.ACTION_ADD_TO_CURRENT, "add to current playlist"), (blaconst.ACTION_SEND_TO_NEW, "send to new playlist"), (blaconst.ACTION_EXPAND_COLLAPSE, "expand/collapse") ] # FIXME: Ugly!! actions = [""] * 4 for idx, label in pairs: actions[idx] = label comboboxes = [] def cb_changed(combobox, key): blacfg.set("library", "%s.action" % key, combobox.get_active()) for key in ["doubleclick", "middleclick", "return"]: cb = gtk.combo_box_new_text() map(cb.append_text, actions) if key == "return": cb.remove_text(3) cb.set_active(blacfg.getint("library", "%s.action" % key)) cb.connect("changed", cb_changed, key) comboboxes.append(cb) widgets = [restrict_to_entry, exclude_entry] + comboboxes labels = ["Restrict to", "Exclude", "Double-click", "Middle-click", "Return"] action_table = gtk.Table(rows=len(labels), columns=2, homogeneous=False) count = 0 for label, widget in zip(labels, widgets): label = gtk.Label("%s:" % label) label.set_alignment(xalign=0.0, yalign=0.5) action_table.attach(label, 0, 1, count, count+1, xoptions=gtk.FILL, xpadding=5) action_table.attach(widget, 1, 2, count, count+1) count += 1 hbox2 = gtk.HBox(spacing=10) draw_tree_lines = gtk.CheckButton("Draw tree lines in browsers") draw_tree_lines.set_active( blacfg.getboolean("library", "draw.tree.lines")) draw_tree_lines.connect("toggled", self.__tree_lines_changed) custom_library_browser = gtk.CheckButton( "Use custom treeview as library browser") custom_library_browser.set_active( blacfg.getboolean("library", "custom.browser")) custom_library_browser.connect( "toggled", self.__custom_library_browser_changed) hbox2.pack_start(draw_tree_lines) hbox2.pack_start(custom_library_browser) self.pack_start(hbox, expand=False) self.pack_start(update_library, expand=False) self.pack_start(action_table, expand=False) self.pack_start(hbox2, expand=False)
def __init_pipeline(self): if not gstreamer_is_working: self.stop() from blaplay.blagui import blaguiutils blaguiutils.error_dialog( "Error", "Failed to construct GStreamer pipeline. Make sure " "GStreamer 0.10, its Python bindings, and gst-plugins-base " "and gst-plugins-good are installed.") return False audio_sink = gst.Bin() filt = gst.element_factory_make("capsfilter") filt.set_property( "caps", gst.caps_from_string("audio/x-raw-float," "rate=(int)44100," "channels=(int)2," "width=(int)32," "depth=(int)32," "endianness=(int)1234")) self.__equalizer = gst.element_factory_make("equalizer-10bands") tee = gst.element_factory_make("tee") queue = gst.element_factory_make("queue") queue.set_property("silent", True) def new_buffer(sink): self.emit("new_buffer", sink.emit("pull_buffer")) appsink = gst.element_factory_make("appsink") appsink.set_property("drop", True) appsink.set_property("sync", True) appsink.set_property("emit_signals", True) appsink.connect("new_buffer", new_buffer) sink = gst.element_factory_make("autoaudiosink") self.__volume = gst.element_factory_make("volume") elements = [filt, self.__equalizer, tee, queue, appsink, self.__volume, sink] map(audio_sink.add, elements) pad = elements[0].get_static_pad("sink") audio_sink.add_pad(gst.GhostPad("sink", pad)) gst.element_link_many(filt, self.__equalizer, tee) gst.element_link_many(tee, self.__volume, sink) gst.element_link_many(tee, queue, appsink) video_sink = gst.element_factory_make("xvimagesink") video_sink.set_property("force_aspect_ratio", True) self.__bin = gst.element_factory_make("playbin2") self.__bin.set_property("audio_sink", audio_sink) self.__bin.set_property("buffer_duration", 500 * gst.MSECOND) self.__bin.set_property("video_sink", video_sink) self.__bin.connect("about_to_finish", self.__about_to_finish) self.__bin.set_state(gst.STATE_READY) bus = self.__bin.get_bus() bus.add_signal_watch() bus.enable_sync_message_emission() self.__message_id = bus.connect("message", self.__message) self.__sync_message_id = bus.connect( "sync-message::element", self.__sync_message) if blacfg.getboolean("player", "muted"): volume = 0 else: volume = blacfg.getfloat("player", "volume") * 100 self.set_volume(volume) self.enable_equalizer(blacfg.getboolean("player", "use.equalizer")) return True
def set_equalizer_value(self, band, value): if blacfg.getboolean("player", "use.equalizer"): try: self.__equalizer.set_property("band%d" % band, value) except AttributeError: pass
def config_changed(cfg, section, key): if section == "general": if key == "always.show.tray": self.set_visible(blacfg.getboolean(section, key)) elif key == "tray.show.tooltip": self.set_has_tooltip(blacfg.getboolean(section, key))
def __init__(self): super(BlaPreferences.PlayerSettings, self).__init__("Player") logarithmic_volume_scale = gtk.CheckButton( "Use logarithmic volume scale") logarithmic_volume_scale.set_active( blacfg.getboolean("player", "logarithmic.volume.scale")) logarithmic_volume_scale.connect( "toggled", self.__volume_scale_changed) state = blacfg.getboolean("player", "use.equalizer") self.__scales = [] use_equalizer = gtk.CheckButton("Use equalizer") use_equalizer.set_active(state) use_equalizer.connect("toggled", self.__use_equalizer_changed) self.__profiles_box = gtk.combo_box_new_text() self.__profiles_box.connect("changed", self.__profile_changed) old_profile = blacfg.getstring("player", "equalizer.profile") profiles = blacfg.get_keys("equalizer.profiles") for idx, profile in enumerate(profiles): self.__profiles_box.append_text(profile[0]) if profile[0] == old_profile: self.__profiles_box.set_active(idx) button_table = gtk.Table(rows=1, columns=3, homogeneous=True) new_profile_button = gtk.Button("New") new_profile_button.connect( "clicked", self.__new_profile, self.__profiles_box) delete_profile_button = gtk.Button("Delete") delete_profile_button.connect( "clicked", self.__delete_profile, self.__profiles_box) reset_profile_button = gtk.Button("Reset") reset_profile_button.connect_object( "clicked", BlaPreferences.PlayerSettings.__reset_profile, self) button_table.attach(new_profile_button, 0, 1, 0, 1, xpadding=2) button_table.attach(delete_profile_button, 1, 2, 0, 1, xpadding=2) button_table.attach(reset_profile_button, 2, 3, 0, 1, xpadding=2) self.__button_box = gtk.HBox() self.__button_box.pack_start( gtk.Label("Profiles:"), expand=False, padding=10) self.__button_box.pack_start(self.__profiles_box, expand=False) self.__button_box.pack_start( button_table, expand=False, padding=16) table = gtk.Table(rows=2, columns=2, homogeneous=False) table.set_row_spacings(2) table.attach(logarithmic_volume_scale, 0, 2, 0, 1, xpadding=2) table.attach(use_equalizer, 0, 1, 1, 2, xpadding=2) table.attach(self.__button_box, 1, 2, 1, 2, xpadding=2) self.__scale_box = gtk.HBox(homogeneous=True) bands = [29, 59, 119, 237, 474, 947, 1889, 3770, 7523, 15011] values = blacfg.getlistfloat("equalizer.profiles", old_profile) if not values: values = [0] * blaconst.EQUALIZER_BANDS for idx, val in enumerate(values): box = gtk.VBox(spacing=10) scale = gtk.VScale(gtk.Adjustment(val, -24., 12., 0.1)) scale.set_inverted(True) scale.set_update_policy(gtk.UPDATE_DISCONTINUOUS) scale.set_value(values[idx]) scale.set_digits(1) scale.set_draw_value(True) scale.set_value_pos(gtk.POS_BOTTOM) scale.connect("value_changed", self.__equalizer_value_changed, idx, self.__profiles_box) scale.connect("format_value", lambda *x: "%.1f dB" % x[-1]) self.__scales.append(scale) label = gtk.Label("%d Hz" % bands[idx]) box.pack_start(label, expand=False) box.pack_start(scale, expand=True) self.__scale_box.pack_start(box) self.pack_start(table, expand=False, padding=10) self.pack_start(self.__scale_box, expand=True) self.__use_equalizer_changed(use_equalizer)
def __delete_event(self, window, event): if blacfg.getboolean("general", "close.to.tray"): self.toggle_hide() return True blaplay.shutdown() return False
def raise_window(self): self.present() if not blacfg.getboolean("general", "always.show.tray"): self.__tray.set_visible(False) self.__visualization.flush_buffers()
def update_tree_lines(self): self.__treeview.set_enable_tree_lines( blacfg.getboolean("library", "draw.tree.lines"))
def __button_press_event(self, scale, event): if blacfg.getboolean("player", "muted"): return True if hasattr(event, "button"): event.button = 2 return False
def __init__(self): super(BlaMainWindow, self).__init__(gtk.WINDOW_TOPLEVEL) self.set_resizable(True) self.connect("delete_event", self.__delete_event) self.enable_tracking(is_main_window=True) # Set up the fullscreen window. self.__fullscreen_window = gtk.Window() def map_(window): pass self.__fullscreen_window.connect("map", map_) self.__fullscreen_window.set_modal(True) self.__fullscreen_window.set_transient_for(self) self.__fullscreen_window.connect_object( "window_state_event", BlaMainWindow.__window_state_event, self) def key_press_event(window, event): if blagui.is_accel(event, "Escape"): window.child.emit("toggle_fullscreen") elif blagui.is_accel(event, "space"): player.play_pause() elif blagui.is_accel(event, "<Ctrl>Q"): blaplay.shutdown() self.__fullscreen_window.connect_object( "key_press_event", key_press_event, self.__fullscreen_window) # Realize the fullscreen window. If we don't do this here and reparent # the drawingarea to it later that in turn will get unrealized again, # causing bad X window errors. self.__fullscreen_window.realize() # Install a global mouse hook. If connected callbacks don't consume the # event by returning True this hook gets called for every widget in the # hierarchy that re-emits the event. We therefore cache the event's # timestamp to detect and ignore signal re-emissions. def button_press_hook(receiver, event): event_time = event.get_time() if event_time != self.__previous_event_time: self.__previous_event_time = event_time if event.button == 8: player.previous() elif event.button == 9: player.next() # This behaves like gobject.{timeout|idle}_add: if the callback # doesn't return True it's only called once. It does NOT prevent # signal callbacks from executing. return True self.__previous_event_time = -1 gobject.add_emission_hook(self, "button_press_event", button_press_hook) # Main menu ui_manager = blaplay.bla.ui_manager self.add_accel_group(ui_manager.get_accel_group()) actions = [ # Menus and submenus ("File", None, "_File"), ("Edit", None, "_Edit"), ("Select", None, "S_elect"), ("Selection", None, "Se_lection"), ("NewPlaylistFrom", None, "_New playlist from"), ("PlayOrder", None, "_Order"), ("View", None, "_View"), ("Help", None, "_Help"), # Menu items ("OpenPlaylist", None, "Open playlist...", None, "", self.__open_playlist), ("AddFiles", None, "Add _files...", None, "", lambda *x: self.__add_tracks()), ("AddDirectories", None, "_Add directories...", None, "", lambda *x: self.__add_tracks(files=False)), ("SavePlaylist", None, "_Save playlist...", None, "", self.__save_playlist), ("Quit", gtk.STOCK_QUIT, "_Quit", "<Ctrl>Q", "", lambda *x: blaplay.shutdown()), ("Preferences", None, "Pre_ferences...", None, "", BlaPreferences), ("About", None, "_About...", None, "", BlaAbout) ] ui_manager.add_actions(actions) toggle_actions = [ ("Statusbar", None, "St_atusbar", None, "", self.__toggle_statusbar, blacfg.getboolean("general", "statusbar")), ("Visualization", None, "Visualization", None, "", self.__toggle_visualization, blacfg.getboolean("general", "show.visualization")) ] ui_manager.add_toggle_actions(toggle_actions) radio_actions = [ ("OrderNormal", None, "_Normal", None, "", blaconst.ORDER_NORMAL), ("OrderRepeat", None, "_Repeat", None, "", blaconst.ORDER_REPEAT), ("OrderShuffle", None, "_Shuffle", None, "", blaconst.ORDER_SHUFFLE) ] # TODO: Emit "order_changed" signal in the on_change handler instead # and let interested widgets handle this instead. ui_manager.add_radio_actions( radio_actions, value=blacfg.getint("general", "play.order"), on_change=BlaStatusbar.set_order) # This is the topmost box that holds all the other components. self.add(gtk.VBox()) # Create instances of the main parts of the GUI. self.__toolbar = BlaToolbar() self.__browsers = BlaBrowsers() self.__visualization = BlaVisualization() self.__view = BlaView() self.__statusbar = BlaStatusbar() # Group browsers and visualization widget. self.__vbox_left = gtk.VBox(spacing=blaconst.WIDGET_SPACING) self.__vbox_left.pack_start(self.__browsers, expand=True) self.__vbox_left.pack_start(self.__visualization, expand=False) self.__vbox_left.show() # Pack the browser + view-widget into a gtk.HPane instance. hpane = gtk.HPaned() hpane.pack1(self.__vbox_left, resize=False, shrink=False) hpane.pack2(self.__view, resize=True, shrink=True) hpane.show() # Restore pane positions. def notify(pane, propspec, key): blacfg.set("general", key, str(pane.get_position())) for pane, side in [(hpane, "left"), (self.__view, "right")]: key = "pane.pos.%s" % side try: pane.set_position(blacfg.getint("general", key)) except TypeError: pass pane.connect("notify", notify, key) # Create a vbox hpane and the statusbar. This allows for setting a # border around those items which excludes the menubar and the toolbar. vbox = gtk.VBox(spacing=blaconst.BORDER_PADDING) vbox.set_border_width(blaconst.BORDER_PADDING) vbox.pack_start(hpane) vbox.pack_start(self.__statusbar, expand=False) vbox.show() self.child.pack_start(ui_manager.get_widget("/Menu"), expand=False) self.child.pack_start(self.__toolbar, expand=False) self.child.pack_start(vbox) self.child.show() self.__tray = BlaTray() def update_title(*args): self.__update_title() player.connect("state_changed", update_title) library.connect("library_updated", update_title) self.__update_title()
def __scroll_event(self, scale, event): if blacfg.getboolean("player", "muted"): return True
def startup_complete(*args): self.set_visible( blacfg.getboolean("general", "show.visualization"))