Ejemplo n.º 1
0
 def activate(self, shell):
     self.shell = shell
     sp = shell.get_player()
     self.player_cb_ids = (sp.connect('playing-song-changed',
                                      self.playing_entry_changed),
                           sp.connect('playing-changed',
                                      self.playing_changed))
     db = shell.get_property("db")
     self.db_cb_ids = (
         db.connect_after('entry-extra-metadata-request::rb:coverArt',
                          self.cover_art_request),
         db.connect_after('entry-extra-metadata-notify::rb:coverArt',
                          self.cover_art_notify),
         db.connect_after('entry-extra-metadata-request::rb:coverArt-uri',
                          self.cover_art_uri_request),
         db.connect_after('entry-extra-metadata-notify::rb:coverArt-uri',
                          self.cover_art_uri_notify),
         db.connect_after('entry-extra-metadata-gather',
                          self.cover_art_uri_gather),
     )
     self.art_widget = ArtDisplayWidget(
         self.find_file(ART_MISSING_ICON + ".svg"))
     self.art_widget.connect('pixbuf-dropped', self.on_set_pixbuf)
     self.art_widget.connect('uri-dropped', self.on_set_uri)
     self.art_widget.connect('get-max-size', self.get_max_art_size)
     self.art_widget.connect('button-press-event', self.on_button_press)
     self.art_container = gtk.VBox()
     self.art_container.pack_start(self.art_widget, padding=6)
     shell.add_widget(self.art_container, rb.SHELL_UI_LOCATION_SIDEBAR)
     self.art_db = CoverArtDatabase()
     self.current_entry, self.current_pixbuf = None, None
     self.playing_entry_changed(sp, sp.get_playing_entry())
Ejemplo n.º 2
0
 def do_activate(self):
     shell = self.object
     sp = shell.props.shell_player
     self.player_cb_ids = (sp.connect('playing-song-changed',
                                      self.playing_entry_changed),
                           sp.connect('playing-changed',
                                      self.playing_changed))
     self.emitting_uri_notify = False
     db = shell.props.db
     self.db_cb_ids = (
         db.connect_after('entry-extra-metadata-request::rb:coverArt',
                          self.cover_art_request),
         db.connect_after('entry-extra-metadata-notify::rb:coverArt',
                          self.cover_art_notify),
         db.connect_after('entry-extra-metadata-request::rb:coverArt-uri',
                          self.cover_art_uri_request),
         db.connect_after('entry-extra-metadata-notify::rb:coverArt-uri',
                          self.cover_art_uri_notify),
         db.connect_after('entry-extra-metadata-gather',
                          self.cover_art_uri_gather),
     )
     self.art_widget = ArtDisplayWidget(
         rb.find_plugin_file(self, ART_MISSING_ICON + ".svg"))
     self.art_widget.connect('pixbuf-dropped', self.on_set_pixbuf)
     self.art_widget.connect('uri-dropped', self.on_set_uri)
     self.art_widget.connect('get-max-size', self.get_max_art_size)
     self.art_widget.connect('button-press-event', self.on_button_press)
     self.art_container = Gtk.VBox()
     self.art_container.pack_start(self.art_widget, True, True, 6)
     shell.add_widget(self.art_container, RB.ShellUILocation.SIDEBAR, False,
                      True)
     self.art_db = CoverArtDatabase()
     self.current_entry, self.current_pixbuf = None, None
     self.playing_entry_changed(sp, sp.get_playing_entry())
Ejemplo n.º 3
0
	def do_activate (self):
		shell = self.object
		sp = shell.props.shell_player
		self.player_cb_ids = (
			sp.connect ('playing-song-changed', self.playing_entry_changed),
			sp.connect ('playing-changed', self.playing_changed)
		)
		self.emitting_uri_notify = False
		db = shell.props.db
		self.db_cb_ids = (
			db.connect_after ('entry-extra-metadata-request::rb:coverArt', self.cover_art_request),
			db.connect_after ('entry-extra-metadata-notify::rb:coverArt', self.cover_art_notify),
			db.connect_after ('entry-extra-metadata-request::rb:coverArt-uri', self.cover_art_uri_request),
			db.connect_after ('entry-extra-metadata-notify::rb:coverArt-uri', self.cover_art_uri_notify),
			db.connect_after ('entry-extra-metadata-gather', self.cover_art_uri_gather),
		)
		self.art_widget = ArtDisplayWidget (rb.find_plugin_file (self, ART_MISSING_ICON + ".svg"))
		self.art_widget.connect ('pixbuf-dropped', self.on_set_pixbuf)
		self.art_widget.connect ('uri-dropped', self.on_set_uri)
		self.art_widget.connect ('get-max-size', self.get_max_art_size)
		self.art_widget.connect ('button-press-event', self.on_button_press)
		self.art_container = Gtk.VBox ()
		self.art_container.pack_start (self.art_widget, True, True, 6)
		shell.add_widget (self.art_container, RB.ShellUILocation.SIDEBAR, False, True)
		self.art_db = CoverArtDatabase ()
		self.current_entry, self.current_pixbuf = None, None
		self.playing_entry_changed (sp, sp.get_playing_entry ())
Ejemplo n.º 4
0
	def activate (self, shell):
		self.shell = shell
		sp = shell.get_player ()
		self.player_cb_ids = (
			sp.connect ('playing-song-changed', self.playing_entry_changed),
			sp.connect ('playing-changed', self.playing_changed)
		)
		db = shell.get_property ("db")
		self.db_cb_ids = (
			db.connect_after ('entry-extra-metadata-request::rb:coverArt', self.cover_art_request),
			db.connect_after ('entry-extra-metadata-notify::rb:coverArt', self.cover_art_notify),
			db.connect_after ('entry-extra-metadata-request::rb:coverArt-uri', self.cover_art_uri_request),
			db.connect_after ('entry-extra-metadata-notify::rb:coverArt-uri', self.cover_art_uri_notify),
			db.connect_after ('entry-extra-metadata-gather', self.cover_art_uri_gather),
		)
		self.art_widget = ArtDisplayWidget (self.find_file (ART_MISSING_ICON + ".svg"))
		self.art_widget.connect ('pixbuf-dropped', self.on_set_pixbuf)
		self.art_widget.connect ('uri-dropped', self.on_set_uri)
		self.art_widget.connect ('get-max-size', self.get_max_art_size)
		self.art_widget.connect ('button-press-event', self.on_button_press)
		self.art_container = gtk.VBox ()
		self.art_container.pack_start (self.art_widget, padding=6)
		shell.add_widget (self.art_container, rb.SHELL_UI_LOCATION_SIDEBAR)
		self.art_db = CoverArtDatabase ()
		self.current_entry, self.current_pixbuf = None, None
		self.playing_entry_changed (sp, sp.get_playing_entry ())
Ejemplo n.º 5
0
	def activate (self, shell):
		self.shell = shell
		sp = shell.get_player ()
		self.pec_id = sp.connect ('playing-song-changed', self.playing_entry_changed)
		self.pc_id = sp.connect ('playing-changed', self.playing_changed)
		self.art_widget = gtk.Image ()
		self.art_widget.set_padding (0, 5)
		shell.add_widget (self.art_widget, rb.SHELL_UI_LOCATION_SIDEBAR)
		self.sa_id = self.art_widget.connect ('size-allocate', self.size_allocated)
		self.current_pixbuf = None
		self.art_db = CoverArtDatabase ()
		self.resize_id = 0
		self.resize_in_progress = False
		self.old_width = 0
		self.fade_step = 0
		self.fade_id = 0
		self.current_entry = None
		entry = sp.get_playing_entry ()
		self.playing_entry_changed (sp, entry)

		#dbus stuff
		self.bus = dbus.SessionBus()
		self.awn_obj = self.bus.get_object(BUS_NAME, OBJ_PATH)
Ejemplo n.º 6
0
    def activate(self, shell):
        self.shell = shell
        sp = shell.get_player()
        self.pec_id = sp.connect("playing-song-changed", self.playing_entry_changed)
        self.pc_id = sp.connect("playing-changed", self.playing_changed)
        self.art_widget = gtk.Image()
        self.art_widget.set_padding(0, 5)
        shell.add_widget(self.art_widget, rb.SHELL_UI_LOCATION_SIDEBAR)
        self.sa_id = self.art_widget.connect("size-allocate", self.size_allocated)
        self.current_pixbuf = None
        self.art_db = CoverArtDatabase()
        self.resize_id = 0
        self.resize_in_progress = False
        self.old_width = 0
        self.fade_step = 0
        self.fade_id = 0
        self.current_entry = None
        entry = sp.get_playing_entry()
        self.playing_entry_changed(sp, entry)

        # dbus stuff
        self.bus = dbus.SessionBus()
        self.awn_obj = self.bus.get_object(BUS_NAME, OBJ_PATH)
Ejemplo n.º 7
0
class ArtDisplayPlugin (gobject.GObject, Peas.Activatable):
	__gtype_name__ = 'ArtDisplayPlugin'
	object = gobject.property(type=gobject.GObject)

	def __init__ (self):
		gobject.GObject.__init__ (self)

	def do_activate (self):
		shell = self.object
		sp = shell.props.shell_player
		self.player_cb_ids = (
			sp.connect ('playing-song-changed', self.playing_entry_changed),
			sp.connect ('playing-changed', self.playing_changed)
		)
		self.emitting_uri_notify = False
		db = shell.props.db
		self.db_cb_ids = (
			db.connect_after ('entry-extra-metadata-request::rb:coverArt', self.cover_art_request),
			db.connect_after ('entry-extra-metadata-notify::rb:coverArt', self.cover_art_notify),
			db.connect_after ('entry-extra-metadata-request::rb:coverArt-uri', self.cover_art_uri_request),
			db.connect_after ('entry-extra-metadata-notify::rb:coverArt-uri', self.cover_art_uri_notify),
			db.connect_after ('entry-extra-metadata-gather', self.cover_art_uri_gather),
		)
		self.art_widget = ArtDisplayWidget (rb.find_plugin_file (self, ART_MISSING_ICON + ".svg"))
		self.art_widget.connect ('pixbuf-dropped', self.on_set_pixbuf)
		self.art_widget.connect ('uri-dropped', self.on_set_uri)
		self.art_widget.connect ('get-max-size', self.get_max_art_size)
		self.art_widget.connect ('button-press-event', self.on_button_press)
		self.art_container = Gtk.VBox ()
		self.art_container.pack_start (self.art_widget, True, True, 6)
		shell.add_widget (self.art_container, RB.ShellUILocation.SIDEBAR, False, True)
		self.art_db = CoverArtDatabase ()
		self.current_entry, self.current_pixbuf = None, None
		self.playing_entry_changed (sp, sp.get_playing_entry ())

	def do_deactivate (self):

		shell = self.object
		sp = shell.props.shell_player
		for id in self.player_cb_ids:
			sp.disconnect (id)
		self.player_cb_ids = ()

		db = shell.props.db
		for id in self.db_cb_ids:
			db.disconnect (id)
		self.db_cb_ids = ()

		shell.remove_widget (self.art_container, RB.ShellUILocation.SIDEBAR)
		self.art_widget.disconnect_handlers ()
		self.art_widget = None
		self.art_container = None
		self.art_db = None

	def playing_changed (self, sp, playing):
		self.set_entry(sp.get_playing_entry ())

	def playing_entry_changed (self, sp, entry):
		self.set_entry(entry)

	def set_entry (self, entry):
		if rb.entry_equal(entry, self.current_entry):
			return

		self.art_widget.set (entry, None, None, None, None, True)
		self.art_container.show_all ()
		# Intitates search in the database (which checks art cache, internet etc.)
		self.current_entry = entry
		self.current_pixbuf = None

		shell = self.object
		db = shell.props.db
		self.art_db.get_pixbuf(db, entry, True, self.on_get_pixbuf_completed)

	def on_get_pixbuf_completed(self, entry, pixbuf, uri, tooltip_image, tooltip_text):
		# Set the pixbuf for the entry returned from the art db
		if rb.entry_equal(entry, self.current_entry):
			self.current_pixbuf = pixbuf

			if tooltip_image is None:
				pb = None
			elif tooltip_image.startswith("/"):
				pb = GdkPixbuf.Pixbuf.new_from_file(tooltip_image)
			else:
				f = rb.find_plugin_file (self, tooltip_image)
				pb = GdkPixbuf.Pixbuf.new_from_file(f)
			self.art_widget.set (entry, pixbuf, uri, pb, tooltip_text, False)

		if pixbuf:
			# This might be from a playing-changed signal,
			# in which case consumers won't be ready yet.
			def idle_emit_art():
				shell = self.object
				db = shell.props.db
				db.emit_entry_extra_metadata_notify (entry, "rb:coverArt", pixbuf)
				if uri:
					self.emitting_uri_notify = True
					db.emit_entry_extra_metadata_notify (entry, "rb:coverArt-uri", uri)
					self.emitting_uri_notify = False
				return False
			gobject.idle_add(idle_emit_art)

	def cover_art_request (self, db, entry):
		a = [None]
		def callback(entry, pixbuf, uri, tooltip_image, tooltip_text):
			a[0] = pixbuf
			self.on_get_pixbuf_completed(entry, pixbuf, uri, tooltip_image, tooltip_text)

		playing = rb.entry_equal(entry, self.current_entry)
		self.art_db.get_pixbuf(db, entry, playing, callback)

		# If callback was called synchronously we can return a pixmap
		return a[0]

	def cover_art_notify (self, db, entry, field, metadata):
		if entry != self.current_entry:
			return
		if not isinstance (metadata, GdkPixbuf.Pixbuf):
			return
		self.art_db.cancel_get_pixbuf (entry)
		if self.current_pixbuf == metadata:
			return

		# cache the pixbuf so we can provide a url
		uri = self.art_db.cache_pixbuf (db, entry, metadata)
		self.art_widget.set (entry, metadata, uri, None, None, False)
		self.emitting_uri_notify = True
		db.emit_entry_extra_metadata_notify (entry, "rb:coverArt-uri", uri)
		self.emitting_uri_notify = False

	def cover_art_uri_notify (self, db, entry, field, metadata):
		if entry != self.current_entry:
			return

		if self.emitting_uri_notify:
			return

		if not metadata:
			print "got no-cover-art notification"
			self.art_widget.set (entry, None, None, False)
			db.emit_entry_extra_metadata_notify (entry, "rb:coverArt", None)
			return

		uri = str (metadata)
		def loader_cb_busted (data):
			if data and len (data) >= 1000:
				pbl = GdkPixbuf.PixbufLoader ()
				try:
					if pbl.write (data, len(data)) and pbl.close ():
						pixbuf = pbl.get_pixbuf ()
						if pixbuf:
							self.art_db.cancel_get_pixbuf (entry)
							self.on_get_pixbuf_completed (entry, pixbuf, uri, None, None)
				except GError:
					pass

		def loader_cb (data):
			if data and len(data) >= 1000:
				l = GdkPixbuf.PixbufLoader()
				l.write(data)
				l.close()
				pixbuf = l.get_pixbuf()
			else:
				pixbuf = None

			self.art_db.cancel_get_pixbuf (entry)
			self.on_get_pixbuf_completed (entry, pixbuf, uri, None, None)

		print "got cover art URI notification: %s" % (uri)

		# TODO use GdkPixbuf.new_from_stream_async()
		l = rb.Loader()
		l.get_url (uri, loader_cb)


	def cover_art_uri_request (self, db, entry):
		if rb.entry_equal(entry, self.current_entry):
			return self.art_widget.current_uri

	def cover_art_uri_gather (self, db, entry, metadata):
		if rb.entry_equal(entry, self.current_entry) and self.art_widget.current_uri:
			metadata ['rb:coverArt-uri'] = self.art_widget.current_uri

	def on_set_pixbuf (self, widget, entry, pixbuf):
		shell = self.object
		db = shell.props.db
		self.art_db.set_pixbuf (db, entry, pixbuf, self.on_get_pixbuf_completed)

	def on_set_uri (self, widget, entry, uri):
		shell = self.object
		db = shell.props.db
		self.art_db.set_pixbuf_from_uri (db, entry, uri, self.on_get_pixbuf_completed)

	def get_max_art_size (self, widget):
		# limit the art image to a third of the window height to prevent it from
		# forcing the window to resize, obscuring everything else, and so on.
		shell = self.object
		(width, height) = shell.props.window.get_size()
		return height / 3

	def on_button_press (self, widget, event):
		# on double clicks, open the cover image (if there is one) in the default
		# image viewer

		doubleclick = Gdk.EventType._2BUTTON_PRESS
		if event.type != doubleclick or event.button != 1:
			return

		if self.art_widget.current_uri is None:
			return

		f = Gio.file_new_for_uri(self.art_widget.current_uri)
		shell = self.object
		Gtk.show_uri(shell.props.window.get_screen(), f.get_uri(), event.time)
Ejemplo n.º 8
0
class ArtDisplayPlugin(rb.Plugin):
    def __init__(self):
        rb.Plugin.__init__(self)

    def activate(self, shell):
        self.shell = shell
        sp = shell.get_player()
        self.player_cb_ids = (sp.connect('playing-song-changed',
                                         self.playing_entry_changed),
                              sp.connect('playing-changed',
                                         self.playing_changed))
        db = shell.get_property("db")
        self.db_cb_ids = (
            db.connect_after('entry-extra-metadata-request::rb:coverArt',
                             self.cover_art_request),
            db.connect_after('entry-extra-metadata-notify::rb:coverArt',
                             self.cover_art_notify),
            db.connect_after('entry-extra-metadata-request::rb:coverArt-uri',
                             self.cover_art_uri_request),
            db.connect_after('entry-extra-metadata-notify::rb:coverArt-uri',
                             self.cover_art_uri_notify),
            db.connect_after('entry-extra-metadata-gather',
                             self.cover_art_uri_gather),
        )
        self.art_widget = ArtDisplayWidget(
            self.find_file(ART_MISSING_ICON + ".svg"))
        self.art_widget.connect('pixbuf-dropped', self.on_set_pixbuf)
        self.art_widget.connect('uri-dropped', self.on_set_uri)
        self.art_widget.connect('get-max-size', self.get_max_art_size)
        self.art_widget.connect('button-press-event', self.on_button_press)
        self.art_container = gtk.VBox()
        self.art_container.pack_start(self.art_widget, padding=6)
        shell.add_widget(self.art_container, rb.SHELL_UI_LOCATION_SIDEBAR)
        self.art_db = CoverArtDatabase()
        self.current_entry, self.current_pixbuf = None, None
        self.playing_entry_changed(sp, sp.get_playing_entry())

    def deactivate(self, shell):
        self.shell = None

        sp = shell.get_player()
        for id in self.player_cb_ids:
            sp.disconnect(id)
        self.player_cb_ids = ()

        db = shell.get_property("db")
        for id in self.db_cb_ids:
            db.disconnect(id)
        self.db_cb_ids = ()

        shell.remove_widget(self.art_container, rb.SHELL_UI_LOCATION_SIDEBAR)
        self.art_widget.disconnect_handlers()
        self.art_widget = None
        self.art_db = None

    def playing_changed(self, sp, playing):
        self.set_entry(sp.get_playing_entry())

    def playing_entry_changed(self, sp, entry):
        self.set_entry(entry)

    def set_entry(self, entry):
        if entry == self.current_entry:
            return
        db = self.shell.get_property("db")

        self.art_widget.set(entry, None, None, None, None, True)
        self.art_container.show_all()
        # Intitates search in the database (which checks art cache, internet etc.)
        self.current_entry = entry
        self.current_pixbuf = None
        self.art_db.get_pixbuf(db, entry, True, self.on_get_pixbuf_completed)

    def on_get_pixbuf_completed(self, entry, pixbuf, uri, tooltip_image,
                                tooltip_text):
        # Set the pixbuf for the entry returned from the art db
        if entry == self.current_entry:
            self.current_pixbuf = pixbuf

            if tooltip_image is None:
                pb = None
            elif tooltip_image.startswith("/"):
                pb = gtk.gdk.pixbuf_new_from_file(tooltip_image)
            else:
                f = self.find_file(tooltip_image)
                pb = gtk.gdk.pixbuf_new_from_file(f)
            self.art_widget.set(entry, pixbuf, uri, pb, tooltip_text, False)

        if pixbuf:
            db = self.shell.get_property("db")

            # This might be from a playing-changed signal,
            # in which case consumers won't be ready yet.
            def idle_emit_art():
                db.emit_entry_extra_metadata_notify(entry, "rb:coverArt",
                                                    pixbuf)
                return False

            gobject.idle_add(idle_emit_art)

    def cover_art_request(self, db, entry):
        a = [None]

        def callback(entry, pixbuf, uri, tooltip_image, tooltip_text):
            a[0] = pixbuf
            self.on_get_pixbuf_completed(entry, pixbuf, uri, tooltip_image,
                                         tooltip_text)

        playing = (entry == self.current_entry)
        self.art_db.get_pixbuf(db, entry, playing, callback)

        # If callback was called synchronously we can return a pixmap
        return a[0]

    def cover_art_notify(self, db, entry, field, metadata):
        if entry != self.current_entry:
            return
        if not isinstance(metadata, gtk.gdk.Pixbuf):
            return
        self.art_db.cancel_get_pixbuf(entry)
        if self.current_pixbuf == metadata:
            return
        self.art_widget.set(entry, metadata, None, None, None, False)

    def cover_art_uri_notify(self, db, entry, field, metadata):
        if entry != self.current_entry:
            return

        if not metadata:
            print "got no-cover-art notification"
            self.art_widget.set(entry, None, None, False)
            db.emit_entry_extra_metadata_notify(entry, "rb:coverArt", None)
            return

        uri = str(metadata)

        def loader_cb(data):
            if data and len(data) >= 1000:
                pbl = gtk.gdk.PixbufLoader()
                try:
                    if pbl.write(data) and pbl.close():
                        pixbuf = pbl.get_pixbuf()
                        if pixbuf:
                            self.art_db.cancel_get_pixbuf(entry)
                            self.on_get_pixbuf_completed(
                                entry, pixbuf, uri, None, None)
                except GError:
                    pass

        print "got cover art URI notification: %s" % (uri)
        l = rb.Loader()
        l.get_url(uri, loader_cb)

    def cover_art_uri_request(self, db, entry):
        if entry == self.current_entry:
            return self.art_widget.current_uri

    def cover_art_uri_gather(self, db, entry, metadata):
        if entry == self.current_entry and self.art_widget.current_uri:
            metadata['rb:coverArt-uri'] = self.art_widget.current_uri

    def on_set_pixbuf(self, widget, entry, pixbuf):
        db = self.shell.get_property("db")
        self.art_db.set_pixbuf(db, entry, pixbuf, self.on_get_pixbuf_completed)

    def on_set_uri(self, widget, entry, uri):
        db = self.shell.get_property("db")
        self.art_db.set_pixbuf_from_uri(db, entry, uri,
                                        self.on_get_pixbuf_completed)

    def get_max_art_size(self, widget):
        # limit the art image to a third of the window height to prevent it from
        # forcing the window to resize, obscuring everything else, and so on.
        (width, height) = self.shell.props.window.get_size()
        return height / 3

    def on_button_press(self, widget, event):
        # on double clicks, open the cover image (if there is one) in the default
        # image viewer
        if event.type != gtk.gdk._2BUTTON_PRESS or event.button != 1:
            return

        if self.art_widget.current_uri is None:
            return

        f = gio.File(self.art_widget.current_uri)
        gtk.show_uri(self.shell.props.window.get_screen(), f.get_uri(),
                     event.time)
Ejemplo n.º 9
0
class ArtDisplayPlugin(rb.Plugin):
    def __init__(self):
        rb.Plugin.__init__(self)

    def activate(self, shell):
        self.shell = shell
        sp = shell.get_player()
        self.pec_id = sp.connect("playing-song-changed", self.playing_entry_changed)
        self.pc_id = sp.connect("playing-changed", self.playing_changed)
        self.art_widget = gtk.Image()
        self.art_widget.set_padding(0, 5)
        shell.add_widget(self.art_widget, rb.SHELL_UI_LOCATION_SIDEBAR)
        self.sa_id = self.art_widget.connect("size-allocate", self.size_allocated)
        self.current_pixbuf = None
        self.art_db = CoverArtDatabase()
        self.resize_id = 0
        self.resize_in_progress = False
        self.old_width = 0
        self.fade_step = 0
        self.fade_id = 0
        self.current_entry = None
        entry = sp.get_playing_entry()
        self.playing_entry_changed(sp, entry)

        # dbus stuff
        self.bus = dbus.SessionBus()
        self.awn_obj = self.bus.get_object(BUS_NAME, OBJ_PATH)

    def deactivate(self, shell):
        self.shell = None
        sp = shell.get_player()
        sp.disconnect(self.pec_id)
        sp.disconnect(self.pc_id)
        shell.remove_widget(self.art_widget, rb.SHELL_UI_LOCATION_SIDEBAR)
        self.art_widget.disconnect(self.sa_id)
        self.art_widget = None
        self.current_pixbuf = None
        self.art_db = None
        self.action = None
        self.action_group = None

        if self.resize_id != 0:
            gobject.source_remove(self.resize_id)
        if self.fade_id != 0:
            gobject.source_remove(self.fade_id)

    def playing_changed(self, sp, playing):
        self.set_entry(sp.get_playing_entry())

    def playing_entry_changed(self, sp, entry):
        self.set_entry(entry)

    def size_allocated(self, widget, allocation):
        if self.old_width == allocation.width:
            return
        if self.resize_id == 0:
            self.resize_id = gobject.idle_add(self.do_resize)
        self.resize_in_progress = True
        self.old_width = allocation.width

    def do_resize(self):
        if self.resize_in_progress:
            self.resize_in_progress = False
            self.update_displayed_art(True)
            ret = True
        else:
            self.update_displayed_art(False)
            self.resize_id = 0
            ret = False
        return ret

    def set_entry(self, entry):
        if entry != self.current_entry:
            db = self.shell.get_property("db")

            # Intitates search in the database (which checks art cache, internet etc.)
            self.current_entry = entry
            self.art_db.get_pixbuf(db, entry, self.on_get_pixbuf_completed)

    def on_get_pixbuf_completed(self, entry, pixbuf):
        # Set the pixbuf for the entry returned from the art db
        if entry == self.current_entry:
            self.set_current_art(pixbuf)

    def fade_art(self, old_pixbuf, new_pixbuf):
        self.fade_step += 1.0 / FADE_STEPS

        if self.fade_step <= 0.999:
            # get pixbuf size
            ow = old_pixbuf.get_width()
            nw = new_pixbuf.get_width()
            oh = old_pixbuf.get_height()
            nh = new_pixbuf.get_height()

            # find scale, widget size and alpha
            ww = self.art_widget.parent.allocation.width
            wh = ww * (self.fade_step * (float(nh) / nw) + (1 - self.fade_step) * (float(oh) / ow))
            sw = float(ww) / nw
            sh = float(wh) / nh
            alpha = int(self.fade_step * 255)

            self.current_pixbuf = old_pixbuf.scale_simple(int(ww), int(wh), gtk.gdk.INTERP_BILINEAR)
            new_pixbuf.composite(
                self.current_pixbuf, 0, 0, int(ww), int(wh), 0, 0, sw, sh, gtk.gdk.INTERP_BILINEAR, alpha
            )
            self.art_widget.set_from_pixbuf(self.current_pixbuf)
            self.art_widget.show()
            return True
        else:
            self.current_pixbuf = new_pixbuf
            self.update_displayed_art(False)
            self.fade_id = 0
            return False

    def set_current_art(self, pixbuf):
        current_pb = self.art_widget.get_pixbuf()
        if self.fade_id != 0:
            gobject.source_remove(self.fade_id)
            self.fade_id = 0

        if current_pb is not None and pixbuf is not None:
            self.fade_step = 0.0
            self.fade_art(current_pb, pixbuf)
            self.fade_id = gobject.timeout_add((FADE_TOTAL_TIME / FADE_STEPS), self.fade_art, current_pb, pixbuf)
        else:
            self.current_pixbuf = pixbuf
            self.update_displayed_art(False)

    def update_displayed_art(self, quick):
        if self.current_pixbuf is None:
            # don't use  Image.clear(), not pygtk 2.6-compatible
            self.art_widget.set_from_pixbuf(None)
            self.art_widget.hide()
            try:
                self.awn_obj.UnsetTaskIconByName("rhythmbox")
            except:
                pass
        else:
            width = self.art_widget.parent.allocation.width
            height = self.current_pixbuf.get_height() * width / self.current_pixbuf.get_width()
            if quick:
                mode = gtk.gdk.INTERP_BILINEAR
            else:
                mode = gtk.gdk.INTERP_HYPER
            self.art_widget.set_from_pixbuf(self.current_pixbuf.scale_simple(width, height, mode))
            self.art_widget.show()

            try:
                self.current_pixbuf.save(SAVE_PATH, "png")
                self.awn_obj.SetTaskIconByName("rhythmbox", "/tmp/rhythmbox.png")
            except:
                pass
Ejemplo n.º 10
0
class ArtDisplayPlugin (rb.Plugin):
	def __init__ (self):
		rb.Plugin.__init__ (self)

	def activate (self, shell):
		self.shell = shell
		sp = shell.get_player ()
		self.player_cb_ids = (
			sp.connect ('playing-song-changed', self.playing_entry_changed),
			sp.connect ('playing-changed', self.playing_changed)
		)
		db = shell.get_property ("db")
		self.db_cb_ids = (
			db.connect_after ('entry-extra-metadata-request::rb:coverArt', self.cover_art_request),
			db.connect_after ('entry-extra-metadata-notify::rb:coverArt', self.cover_art_notify),
			db.connect_after ('entry-extra-metadata-request::rb:coverArt-uri', self.cover_art_uri_request),
			db.connect_after ('entry-extra-metadata-notify::rb:coverArt-uri', self.cover_art_uri_notify),
			db.connect_after ('entry-extra-metadata-gather', self.cover_art_uri_gather),
		)
		self.art_widget = ArtDisplayWidget (self.find_file (ART_MISSING_ICON + ".svg"))
		self.art_widget.connect ('pixbuf-dropped', self.on_set_pixbuf)
		self.art_widget.connect ('uri-dropped', self.on_set_uri)
		self.art_widget.connect ('get-max-size', self.get_max_art_size)
		self.art_widget.connect ('button-press-event', self.on_button_press)
		self.art_container = gtk.VBox ()
		self.art_container.pack_start (self.art_widget, padding=6)
		shell.add_widget (self.art_container, rb.SHELL_UI_LOCATION_SIDEBAR)
		self.art_db = CoverArtDatabase ()
		self.current_entry, self.current_pixbuf = None, None
		self.playing_entry_changed (sp, sp.get_playing_entry ())

	def deactivate (self, shell):
		self.shell = None

		sp = shell.get_player ()
		for id in self.player_cb_ids:
			sp.disconnect (id)
		self.player_cb_ids = ()

		db = shell.get_property ("db")
		for id in self.db_cb_ids:
			db.disconnect (id)
		self.db_cb_ids = ()

		shell.remove_widget (self.art_container, rb.SHELL_UI_LOCATION_SIDEBAR)
		self.art_widget.disconnect_handlers ()
		self.art_widget = None
		self.art_db = None

	def playing_changed (self, sp, playing):
		self.set_entry(sp.get_playing_entry ())

	def playing_entry_changed (self, sp, entry):
		self.set_entry(entry)

	def set_entry (self, entry):
		if entry == self.current_entry:
			return
		db = self.shell.get_property ("db")

		self.art_widget.set (entry, None, None, None, None, True)
		self.art_container.show_all ()
		# Intitates search in the database (which checks art cache, internet etc.)
		self.current_entry = entry
		self.current_pixbuf = None
		self.art_db.get_pixbuf(db, entry, True, self.on_get_pixbuf_completed)

	def on_get_pixbuf_completed(self, entry, pixbuf, uri, tooltip_image, tooltip_text):
		# Set the pixbuf for the entry returned from the art db
		if entry == self.current_entry:
			self.current_pixbuf = pixbuf

			if tooltip_image is None:
				pb = None
			elif tooltip_image.startswith("/"):
				pb = gtk.gdk.pixbuf_new_from_file(tooltip_image)
			else:
				f = self.find_file(tooltip_image)
				pb = gtk.gdk.pixbuf_new_from_file(f)
			self.art_widget.set (entry, pixbuf, uri, pb, tooltip_text, False)

		if pixbuf:
			db = self.shell.get_property ("db")
			# This might be from a playing-changed signal,
			# in which case consumers won't be ready yet.
			def idle_emit_art():
				db.emit_entry_extra_metadata_notify (entry, "rb:coverArt", pixbuf)
				return False
			gobject.idle_add(idle_emit_art)

	def cover_art_request (self, db, entry):
		a = [None]
		def callback(entry, pixbuf, uri, tooltip_image, tooltip_text):
			a[0] = pixbuf
			self.on_get_pixbuf_completed(entry, pixbuf, uri, tooltip_image, tooltip_text)

		playing = (entry == self.current_entry)
		self.art_db.get_pixbuf(db, entry, playing, callback)

		# If callback was called synchronously we can return a pixmap
		return a[0]

	def cover_art_notify (self, db, entry, field, metadata):
		if entry != self.current_entry:
			return
		if not isinstance (metadata, gtk.gdk.Pixbuf):
			return
		self.art_db.cancel_get_pixbuf (entry)
		if self.current_pixbuf == metadata:
			return
		self.art_widget.set (entry, metadata, None, None, None, False)

	def cover_art_uri_notify (self, db, entry, field, metadata):
		if entry != self.current_entry:
			return

		if not metadata:
			print "got no-cover-art notification"
			self.art_widget.set (entry, None, None, False)
			db.emit_entry_extra_metadata_notify (entry, "rb:coverArt", None)
			return

		uri = str (metadata)
		def loader_cb (data):
			if data and len (data) >= 1000:
				pbl = gtk.gdk.PixbufLoader ()
				try:
					if pbl.write (data) and pbl.close ():
						pixbuf = pbl.get_pixbuf ()
						if pixbuf:
							self.art_db.cancel_get_pixbuf (entry)
							self.on_get_pixbuf_completed (entry, pixbuf, uri, None, None)
				except GError:
					pass

		print "got cover art URI notification: %s" % (uri)
		l = rb.Loader()
		l.get_url (uri, loader_cb)

	def cover_art_uri_request (self, db, entry):
		if entry == self.current_entry:
			return self.art_widget.current_uri

	def cover_art_uri_gather (self, db, entry, metadata):
		if entry == self.current_entry and self.art_widget.current_uri:
			metadata ['rb:coverArt-uri'] = self.art_widget.current_uri

	def on_set_pixbuf (self, widget, entry, pixbuf):
		db = self.shell.get_property ("db")
		self.art_db.set_pixbuf (db, entry, pixbuf, self.on_get_pixbuf_completed)

	def on_set_uri (self, widget, entry, uri):
		db = self.shell.get_property ("db")
		self.art_db.set_pixbuf_from_uri (db, entry, uri, self.on_get_pixbuf_completed)

	def get_max_art_size (self, widget):
		# limit the art image to a third of the window height to prevent it from
		# forcing the window to resize, obscuring everything else, and so on.
		(width, height) = self.shell.props.window.get_size()
		return height / 3

	def on_button_press (self, widget, event):
		# on double clicks, open the cover image (if there is one) in the default
		# image viewer
		if event.type != gtk.gdk._2BUTTON_PRESS or event.button != 1:
			return

		if self.art_widget.current_uri is None:
			return

		f = gio.File(self.art_widget.current_uri)
		gtk.show_uri(self.shell.props.window.get_screen(), f.get_uri(), event.time)
Ejemplo n.º 11
0
class ArtDisplayPlugin(gobject.GObject, Peas.Activatable):
    __gtype_name__ = 'ArtDisplayPlugin'
    object = gobject.property(type=gobject.GObject)

    def __init__(self):
        gobject.GObject.__init__(self)

    def do_activate(self):
        shell = self.object
        sp = shell.props.shell_player
        self.player_cb_ids = (sp.connect('playing-song-changed',
                                         self.playing_entry_changed),
                              sp.connect('playing-changed',
                                         self.playing_changed))
        self.emitting_uri_notify = False
        db = shell.props.db
        self.db_cb_ids = (
            db.connect_after('entry-extra-metadata-request::rb:coverArt',
                             self.cover_art_request),
            db.connect_after('entry-extra-metadata-notify::rb:coverArt',
                             self.cover_art_notify),
            db.connect_after('entry-extra-metadata-request::rb:coverArt-uri',
                             self.cover_art_uri_request),
            db.connect_after('entry-extra-metadata-notify::rb:coverArt-uri',
                             self.cover_art_uri_notify),
            db.connect_after('entry-extra-metadata-gather',
                             self.cover_art_uri_gather),
        )
        self.art_widget = ArtDisplayWidget(
            rb.find_plugin_file(self, ART_MISSING_ICON + ".svg"))
        self.art_widget.connect('pixbuf-dropped', self.on_set_pixbuf)
        self.art_widget.connect('uri-dropped', self.on_set_uri)
        self.art_widget.connect('get-max-size', self.get_max_art_size)
        self.art_widget.connect('button-press-event', self.on_button_press)
        self.art_container = Gtk.VBox()
        self.art_container.pack_start(self.art_widget, True, True, 6)
        shell.add_widget(self.art_container, RB.ShellUILocation.SIDEBAR, False,
                         True)
        self.art_db = CoverArtDatabase()
        self.current_entry, self.current_pixbuf = None, None
        self.playing_entry_changed(sp, sp.get_playing_entry())

    def do_deactivate(self):

        shell = self.object
        sp = shell.props.shell_player
        for id in self.player_cb_ids:
            sp.disconnect(id)
        self.player_cb_ids = ()

        db = shell.props.db
        for id in self.db_cb_ids:
            db.disconnect(id)
        self.db_cb_ids = ()

        shell.remove_widget(self.art_container, RB.ShellUILocation.SIDEBAR)
        self.art_widget.disconnect_handlers()
        self.art_widget = None
        self.art_container = None
        self.art_db = None

    def playing_changed(self, sp, playing):
        self.set_entry(sp.get_playing_entry())

    def playing_entry_changed(self, sp, entry):
        self.set_entry(entry)

    def set_entry(self, entry):
        if rb.entry_equal(entry, self.current_entry):
            return

        self.art_widget.set(entry, None, None, None, None, True)
        self.art_container.show_all()
        # Intitates search in the database (which checks art cache, internet etc.)
        self.current_entry = entry
        self.current_pixbuf = None

        shell = self.object
        db = shell.props.db
        self.art_db.get_pixbuf(db, entry, True, self.on_get_pixbuf_completed)

    def on_get_pixbuf_completed(self, entry, pixbuf, uri, tooltip_image,
                                tooltip_text):
        # Set the pixbuf for the entry returned from the art db
        if rb.entry_equal(entry, self.current_entry):
            self.current_pixbuf = pixbuf

            if tooltip_image is None:
                pb = None
            elif tooltip_image.startswith("/"):
                pb = GdkPixbuf.Pixbuf.new_from_file(tooltip_image)
            else:
                f = rb.find_plugin_file(self, tooltip_image)
                pb = GdkPixbuf.Pixbuf.new_from_file(f)
            self.art_widget.set(entry, pixbuf, uri, pb, tooltip_text, False)

        if pixbuf:
            # This might be from a playing-changed signal,
            # in which case consumers won't be ready yet.
            def idle_emit_art():
                shell = self.object
                db = shell.props.db
                db.emit_entry_extra_metadata_notify(entry, "rb:coverArt",
                                                    pixbuf)
                if uri:
                    self.emitting_uri_notify = True
                    db.emit_entry_extra_metadata_notify(
                        entry, "rb:coverArt-uri", uri)
                    self.emitting_uri_notify = False
                return False

            gobject.idle_add(idle_emit_art)

    def cover_art_request(self, db, entry):
        a = [None]

        def callback(entry, pixbuf, uri, tooltip_image, tooltip_text):
            a[0] = pixbuf
            self.on_get_pixbuf_completed(entry, pixbuf, uri, tooltip_image,
                                         tooltip_text)

        playing = rb.entry_equal(entry, self.current_entry)
        self.art_db.get_pixbuf(db, entry, playing, callback)

        # If callback was called synchronously we can return a pixmap
        return a[0]

    def cover_art_notify(self, db, entry, field, metadata):
        if entry != self.current_entry:
            return
        if not isinstance(metadata, GdkPixbuf.Pixbuf):
            return
        self.art_db.cancel_get_pixbuf(entry)
        if self.current_pixbuf == metadata:
            return

        # cache the pixbuf so we can provide a url
        uri = self.art_db.cache_pixbuf(db, entry, metadata)
        self.art_widget.set(entry, metadata, uri, None, None, False)
        self.emitting_uri_notify = True
        db.emit_entry_extra_metadata_notify(entry, "rb:coverArt-uri", uri)
        self.emitting_uri_notify = False

    def cover_art_uri_notify(self, db, entry, field, metadata):
        if entry != self.current_entry:
            return

        if self.emitting_uri_notify:
            return

        if not metadata:
            print "got no-cover-art notification"
            self.art_widget.set(entry, None, None, False)
            db.emit_entry_extra_metadata_notify(entry, "rb:coverArt", None)
            return

        uri = str(metadata)

        def loader_cb_busted(data):
            if data and len(data) >= 1000:
                pbl = GdkPixbuf.PixbufLoader()
                try:
                    if pbl.write(data, len(data)) and pbl.close():
                        pixbuf = pbl.get_pixbuf()
                        if pixbuf:
                            self.art_db.cancel_get_pixbuf(entry)
                            self.on_get_pixbuf_completed(
                                entry, pixbuf, uri, None, None)
                except GError:
                    pass

        def loader_cb(data):
            if data and len(data) >= 1000:
                l = GdkPixbuf.PixbufLoader()
                l.write(data)
                l.close()
                pixbuf = l.get_pixbuf()
            else:
                pixbuf = None

            self.art_db.cancel_get_pixbuf(entry)
            self.on_get_pixbuf_completed(entry, pixbuf, uri, None, None)

        print "got cover art URI notification: %s" % (uri)

        # TODO use GdkPixbuf.new_from_stream_async()
        l = rb.Loader()
        l.get_url(uri, loader_cb)

    def cover_art_uri_request(self, db, entry):
        if rb.entry_equal(entry, self.current_entry):
            return self.art_widget.current_uri

    def cover_art_uri_gather(self, db, entry, metadata):
        if rb.entry_equal(entry,
                          self.current_entry) and self.art_widget.current_uri:
            metadata['rb:coverArt-uri'] = self.art_widget.current_uri

    def on_set_pixbuf(self, widget, entry, pixbuf):
        shell = self.object
        db = shell.props.db
        self.art_db.set_pixbuf(db, entry, pixbuf, self.on_get_pixbuf_completed)

    def on_set_uri(self, widget, entry, uri):
        shell = self.object
        db = shell.props.db
        self.art_db.set_pixbuf_from_uri(db, entry, uri,
                                        self.on_get_pixbuf_completed)

    def get_max_art_size(self, widget):
        # limit the art image to a third of the window height to prevent it from
        # forcing the window to resize, obscuring everything else, and so on.
        shell = self.object
        (width, height) = shell.props.window.get_size()
        return height / 3

    def on_button_press(self, widget, event):
        # on double clicks, open the cover image (if there is one) in the default
        # image viewer

        doubleclick = Gdk.EventType._2BUTTON_PRESS
        if event.type != doubleclick or event.button != 1:
            return

        if self.art_widget.current_uri is None:
            return

        f = Gio.file_new_for_uri(self.art_widget.current_uri)
        shell = self.object
        Gtk.show_uri(shell.props.window.get_screen(), f.get_uri(), event.time)
Ejemplo n.º 12
0
class ArtDisplayPlugin (rb.Plugin):
	def __init__ (self):
		rb.Plugin.__init__ (self)

	def activate (self, shell):
		self.shell = shell
		sp = shell.get_player ()
		self.pec_id = sp.connect ('playing-song-changed', self.playing_entry_changed)
		self.pc_id = sp.connect ('playing-changed', self.playing_changed)
		self.art_widget = gtk.Image ()
		self.art_widget.set_padding (0, 5)
		shell.add_widget (self.art_widget, rb.SHELL_UI_LOCATION_SIDEBAR)
		self.sa_id = self.art_widget.connect ('size-allocate', self.size_allocated)
		self.current_pixbuf = None
		self.art_db = CoverArtDatabase ()
		self.resize_id = 0
		self.resize_in_progress = False
		self.old_width = 0
		self.fade_step = 0
		self.fade_id = 0
		self.current_entry = None
		entry = sp.get_playing_entry ()
		self.playing_entry_changed (sp, entry)

		#dbus stuff
		self.bus = dbus.SessionBus()
		self.awn_obj = self.bus.get_object(BUS_NAME, OBJ_PATH)

	def deactivate (self, shell):
		self.shell = None
		sp = shell.get_player ()
		sp.disconnect (self.pec_id)
		sp.disconnect (self.pc_id)
		shell.remove_widget (self.art_widget, rb.SHELL_UI_LOCATION_SIDEBAR)
		self.art_widget.disconnect(self.sa_id)
		self.art_widget = None
		self.current_pixbuf = None
		self.art_db = None
		self.action = None
		self.action_group = None

		if self.resize_id != 0:
			gobject.source_remove (self.resize_id)
		if self.fade_id != 0:
			gobject.source_remove (self.fade_id)

	def playing_changed (self, sp, playing):
		self.set_entry(sp.get_playing_entry ())

	def playing_entry_changed (self, sp, entry):
		self.set_entry(entry)

	def size_allocated (self, widget, allocation):
		if self.old_width == allocation.width:
			return
		if self.resize_id == 0:
			self.resize_id = gobject.idle_add (self.do_resize)
		self.resize_in_progress = True
		self.old_width = allocation.width

	def do_resize(self):
		if self.resize_in_progress:
			self.resize_in_progress = False
			self.update_displayed_art (True)
			ret = True
		else:
			self.update_displayed_art (False)
			self.resize_id = 0
			ret = False
		return ret

	def set_entry (self, entry):
		if entry != self.current_entry:
			db = self.shell.get_property ("db")

			# Intitates search in the database (which checks art cache, internet etc.)
			self.current_entry = entry
			self.art_db.get_pixbuf(db, entry, self.on_get_pixbuf_completed)

	def on_get_pixbuf_completed(self, entry, pixbuf):
		# Set the pixbuf for the entry returned from the art db
		if entry == self.current_entry:
			self.set_current_art (pixbuf)

	def fade_art (self, old_pixbuf, new_pixbuf):
		self.fade_step += 1.0 / FADE_STEPS

		if self.fade_step <= 0.999:
			# get pixbuf size
			ow = old_pixbuf.get_width ()
			nw = new_pixbuf.get_width ()
			oh = old_pixbuf.get_height ()
			nh = new_pixbuf.get_height ()

			# find scale, widget size and alpha
			ww = self.art_widget.parent.allocation.width
			wh = ww * (self.fade_step * (float(nh)/nw) + (1 - self.fade_step) * (float(oh)/ow))
			sw = float(ww)/nw
			sh = float(wh)/nh
			alpha = int (self.fade_step * 255)

			self.current_pixbuf = old_pixbuf.scale_simple (int(ww), int(wh), gtk.gdk.INTERP_BILINEAR)
			new_pixbuf.composite (self.current_pixbuf, 0, 0, int(ww), int(wh), 0, 0, sw, sh, gtk.gdk.INTERP_BILINEAR, alpha)
			self.art_widget.set_from_pixbuf (self.current_pixbuf)
			self.art_widget.show ()
			return True
		else:
			self.current_pixbuf = new_pixbuf
			self.update_displayed_art (False);
			self.fade_id = 0
			return False

	def set_current_art (self, pixbuf):
		current_pb = self.art_widget.get_pixbuf ()
		if self.fade_id != 0:
			gobject.source_remove (self.fade_id)
			self.fade_id = 0

		if current_pb is not None and pixbuf is not None:
			self.fade_step = 0.0
			self.fade_art (current_pb, pixbuf)
			self.fade_id = gobject.timeout_add ((FADE_TOTAL_TIME / FADE_STEPS), self.fade_art, current_pb, pixbuf)
		else:
			self.current_pixbuf = pixbuf;
			self.update_displayed_art (False);

	def update_displayed_art (self, quick):
		if self.current_pixbuf is None:
			# don't use  Image.clear(), not pygtk 2.6-compatible
			self.art_widget.set_from_pixbuf (None)
			self.art_widget.hide ()
			try:
				self.awn_obj.UnsetTaskIconByName ("rhythmbox")
			except:
				pass
		else:
			width = self.art_widget.parent.allocation.width
			height = self.current_pixbuf.get_height () * width / self.current_pixbuf.get_width ()
			if quick:
				mode = gtk.gdk.INTERP_BILINEAR
			else:
				mode = gtk.gdk.INTERP_HYPER
			self.art_widget.set_from_pixbuf (self.current_pixbuf.scale_simple (width, height, mode))
			self.art_widget.show ()

			try:
				self.current_pixbuf.save (SAVE_PATH, "png")
				self.awn_obj.SetTaskIconByName("rhythmbox", "/tmp/rhythmbox.png")
			except:
				pass