clementine-player / Clementine

:tangerine: Clementine Music Player
https://www.clementine-player.org/
GNU General Public License v3.0
3.74k stars 675 forks source link

Clementine not updating "Now playing" applications #1497

Closed Clementine-Issue-Importer closed 10 years ago

Clementine-Issue-Importer commented 10 years ago

From legion1978 on February 23, 2011 00:10:20

What steps will reproduce the problem? 1. Just start Clementine

  1. Some "now playing" related applications wont reflect Clementine status
    • What is the expected output? What do you see instead? Apps should communicate with Clementine and reflect the player status
    • What version of the product are you using? On what operating system? 0.6 r2864 - Please provide any additional information below. A bit ago i sent this through the mail list, in hope dev team could tell if there was something wrong with the code, meaning it wasnt Clementines fault. This code is from the Cover Gloobus Now Playing desktop app:

8<- - -- - - - - - - - - - - - -- - - import dbus

from common import _ from players import MPRISPlayer

class Clementine(MPRISPlayer):

__title__ = 'Clementine'
__version__ = '0.1'
__authors__ = 'Alexandr Grigorcea <cahr.gr@gmail.com>'
__desc__ = _('Clementine music player plugin')

DBUS_NAME   = 'org.mpris.clementine'

def connect(self):
    session_bus = dbus.SessionBus()
    obj = session_bus.get_object(self.DBUS_NAME, self.DBUS_OBJECT)
    self.iface = dbus.Interface(obj,'org.freedesktop.MediaPlayer')
    if not self.connected:
        session_bus.add_signal_receiver(self.playing_changed_handler,
            "StatusChange", 'org.freedesktop.MediaPlayer',
            self.DBUS_NAME, '/TrackList')
        session_bus.add_signal_receiver(self.song_changed_handler,
            "TrackChange", 'org.freedesktop.MediaPlayer',
            self.DBUS_NAME, '/TrackList')
        self.connected = True
    return True

def disconnect(self):
    if self.connected:
        session_bus = dbus.SessionBus()
        session_bus.remove_signal_receiver(self.playing_changed_handler,
            "StatusChange", 'org.freedesktop.MediaPlayer',
            self.DBUS_NAME, self.DBUS_OBJECT)
        session_bus.remove_signal_receiver(self.song_changed_handler,
            "TrackChange", 'org.freedesktop.MediaPlayer',
            self.DBUS_NAME, '/TrackList')
        self.connected = False

8<- - -- - - - - - - - - - - - -- - -

now, I updated to latest revision and, suddenly, no apps are updating with Clementine status.

Applications are:

So i believe something was definitely broken in this area.

Original issue: http://code.google.com/p/clementine-player/issues/detail?id=1497

Clementine-Issue-Importer commented 10 years ago

From klingasteri on February 22, 2011 22:42:26

I can confirm this problem.

I've been using ConkyClementine ( http://ubuntuforums.org/showthread.php?t=1645481 ) which worked really fine before, but stopped working when updated to newest revision (can't remember which one, unfortunately).

Clementine-Issue-Importer commented 10 years ago

From john.maguire on February 23, 2011 03:11:21

This issue was closed by revision r2866 .

Status: Fixed

Clementine-Issue-Importer commented 10 years ago

From legion1978 on February 23, 2011 17:26:57

Yes its been fixed. TY However, the cover gloobus app is still faulty. Can u guys please tell me if the code above is ok so I can go nag the gloobus guys? =)

ty guys u rock.

Clementine-Issue-Importer commented 10 years ago

From keirangtp on February 24, 2011 08:41:00

This isn't the whole code right? Because it's using a 'self.DBUS_OBJECT' variable which isn't defined anywhere.

Clementine-Issue-Importer commented 10 years ago

From legion1978 on February 24, 2011 09:26:00

well., i digged in the application folder and its got one named "players" and theres a .py file for each one of the supported players: the code is from the corresponding clementine.py file... and i think it is the whole code.. im also posting the common.py code below. thanks for your help =)

Copyright (C) 2009-2010 Gloobus Developers

#

This program is free software; you can redistribute it and/or

modify it under the terms of the GNU General Public License

as published by the Free Software Foundation; either version 2

of the License, or (at your option) any later version.

#

This program is distributed in the hope that it will be useful,

but WITHOUT ANY WARRANTY; without even the implied warranty of

MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

GNU General Public License for more details.

#

You should have received a copy of the GNU General Public License

along with this program; if not, write to the Free Software

Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA

02110-1301, USA.

import dbus

from common import _ from players import MPRISPlayer

class Clementine(MPRISPlayer):

 __title__ = 'Clementine'
 __version__ = '0.1'
 __authors__ = 'Alexandr Grigorcea <cahr.gr@gmail.com>'
 __desc__ = _('Clementine music player plugin')

 DBUS_NAME   = 'org.mpris.clementine'

 def connect(self):
     session_bus = dbus.SessionBus()
     obj = session_bus.get_object(self.DBUS_NAME, self.DBUS_OBJECT)
     self.iface = dbus.Interface(obj,'org.freedesktop.MediaPlayer')
     if not self.connected:
         session_bus.add_signal_receiver(self.playing_changed_handler,
             "StatusChange", 'org.freedesktop.MediaPlayer',
             self.DBUS_NAME, '/TrackList')
         session_bus.add_signal_receiver(self.song_changed_handler,
             "TrackChange", 'org.freedesktop.MediaPlayer',
             self.DBUS_NAME, '/TrackList')
         self.connected = True
     return True

 def disconnect(self):
     if self.connected:
         session_bus = dbus.SessionBus()

session_bus.remove_signal_receiver(self.playing_changed_handler, "StatusChange", 'org.freedesktop.MediaPlayer', self.DBUS_NAME, self.DBUS_OBJECT) session_bus.remove_signal_receiver(self.song_changed_handler, "TrackChange", 'org.freedesktop.MediaPlayer', self.DBUS_NAME, '/TrackList') self.connected = False

////////////////////

from common.py -----------------------------////////////////////////////////////////////////////////////////////////////

Copyright (C) 2009-2010 Gloobus Developers

#

This program is free software; you can redistribute it and/or

modify it under the terms of the GNU General Public License

as published by the Free Software Foundation; either version 2

of the License, or (at your option) any later version.

#

This program is distributed in the hope that it will be useful,

but WITHOUT ANY WARRANTY; without even the implied warranty of

MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

GNU General Public License for more details.

#

You should have received a copy of the GNU General Public License

along with this program; if not, write to the Free Software

Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA

02110-1301, USA.

import gettext import htmlentitydefs import os import string import sys import re

from ConfigParser import SafeConfigParser from urllib2 import urlopen

from config import prefix as PREFIX

from glob import glob

class Notifier: _debug = False

colors = {

"reset" : "\x1b[0m",

"bold" : "\x1b[01m",

"teal" : "\x1b[36;06m",

"turquoise" : "\x1b[36;01m",

"fucsia" : "\x1b[35;01m",

"purple" : "\x1b[35;06m",

"blue" : "\x1b[34;01m",

"darkblue" : "\x1b[34;06m",

"green" : "\x1b[32;01m",

"darkgreen" : "\x1b[32;06m",

"yellow" : "\x1b[33;01m",

"brown" : "\x1b[33;06m",

"red" : "\x1b[31;01m",

"darkred" : "\x1b[31;06m"

}

 def set_debug(self, debug):
     self._debug = debug

 def debug(self, message): #blue
     if self._debug:
         print '\x1b[34;01m[DEBUG]\x1b[0m', message

 def info(self, message, notify=False): #bold
     print '\x1b[01m[INFO]\x1b[0m', message
     if notify:
         self.notify(message)

 def warning(self, message, notify=False): #red
     print '\x1b[31;01m[WARNING]\x1b[0m', message
     if notify:
         self.notify(message)

 def error(self, message, notify=False): #darkred
     print '\x1b[31;06m[ERROR]\x1b[0m', message
     if notify:
         self.notify(message)

 def notify(self, message):
     os.system('notify-send --icon=covergloobus CoverGloobus "' + 

message + '"')

class Config(SafeConfigParser): def init(self, default=False): SafeConfigParser.init(self)

     self.load_default()

     if not default and os.path.isfile(CONFIG_PATH):
         self.read(CONFIG_PATH)
     else:
         c.warning(_("Using default configuration"))

 def load_default(self):
     self.add_section('General')
     self.set('General', 'start_at_login', '0')
     self.set('General', 'hide_if_inactive', '0')
     self.set('General', 'show_status_icon', '1')
     self.set('General', 'player', 'Rhythmbox')

     self.add_section('Lyrics')
     self.set('Lyrics', 'lyrics_source', 'lyricswikia')
     self.set('Lyrics', 'tabs_source', 'ultimateguitar')
     self.set('Lyrics', 'widget', '0')
     self.set('Lyrics', 'window', 'new')
     self.set('Lyrics', 'refresh', '0')
     self.set('Lyrics', 'try_all', '0')
     self.set('Lyrics', 'cache', '0')
     self.set('Lyrics', 'lyricsfly_key', 

'1c0736f65ac693cbd-temporary.API.access')

     self.add_section('Covers')
     self.set('Covers', 'search_engines', 'Location,Amazon')
     self.set('Covers', 'search_pattern', '')
     self.set('Covers', 'location_filenames', 

'folder,cover,front,album,albumart') self.set('Covers', 'location_extentions', 'jpg,jpeg,png,gif')

     self.add_section('Docky')
     self.set('Docky', 'show', '0')
     self.set('Docky', 'time', '1')

     self.add_section('MPD')
     self.set('MPD', 'host', 'localhost')
     self.set('MPD', 'port', '6600')
     self.set('MPD', 'password', '')
     self.set('MPD', 'path', HOME_PATH + '/Music')

     self.add_section('Window')
     self.set('Window', 'theme', ABS_PATH + '/themes/BadChoice')
     self.set('Window', 'resize', '100')
     self.set('Window', 'stick', '0')
     self.set('Window', 'ontop', '...
Clementine-Issue-Importer commented 10 years ago

From legion1978 on February 24, 2011 09:26:00

...0') self.set('Window', 'x', '20') self.set('Window', 'y', '20') self.set('Window', 'hide_inactive', '0') self.set('Window', 'show_background', '0') self.set('Window', 'background_opacity', '0.5') self.set('Window', 'background_color', '#000') self.set('Window', 'long_text', 'theme')

 def load(self):
     self.read(CONFIG_PATH)

 def save(self):
     if not os.path.isfile(CONFIG_PATH):
         path = os.path.dirname(CONFIG_PATH)
         if not os.path.exists(path):
             c.warning(_("Creating configuration directory"))
             os.makedirs(path)

     with open(CONFIG_PATH, 'wb') as f:
         self.write(f)
         c.debug('Configuration saved')

def get_themes(): themes = [] for path in (ABS_PATH+'/themes/' , THEME_PATH): for folder in os.listdir(path): if os.path.exists(os.path.join(path, folder, 'skin.xml')): themes.append(os.path.join(path, folder)) return themes

class Track(object): def init(self, title='', album='',artist='',rating='0',cover='', genre='', year='0', tracknumber='0', location='', length=''): self.title = title self.album = album self.artist = artist

     self.cover = cover
     self.genre = genre
     self.location = location

     try:
         self.rating = int(rating)
     except:
         self.rating = 0
     try:
         self.year = int(year)
     except:
         self.year = 0
     try:
         self.tracknumber = int(tracknumber)
     except:
         self.tracknumber = 0
     try:
         self.length = int(length)
     except:
         self.length = 0

 def __str__(self):
     return self.artist + ', ' + self.title + ', ' + self.album + ', 

' + str(self.rating) + ', ' + self.cover + ', ' + self.genre

class State: PLAYING = 1 PAUSED = 2 STOPPED = 3 STARTED = 4 CLOSED = 5

 @staticmethod
 def get(string):
     if string == 'playing':
         return State.PLAYING
     elif string == 'paused':
         return State.PAUSED
     elif string == 'stopped':
         return State.STOPPED
     elif string == 'started':
         return State.STARTED
     elif string == 'closed':
         return State.CLOSED
     else:
         raise Exception()

class Observer(object): def init(self, target, callback, *args): super(Observer, self).init() self.target = target self.callback = callback self.args = args

 def __call__(self, *args):
     if not self.callback is None:
         args += self.args
         self.callback(*args)

def draw_background(context, width, height, opacity=0.8, r=12):

"""

This function draws a nice semiblack background using cairo.

@param context: Cairo context

@param width: width of the rectangle to draw

@param height: height of the rectangle to draw

@param opacity: background opacity

@param r: background roundness

@return: None

"""

context.set_operator(cairo.OPERATOR_OVER);

context.set_source_rgba (0, 0, 0, opacity)

context.move_to (r, 0)

context.line_to (width - r, 0)

context.curve_to(width - r, 0, width, 0, width, r )

context.line_to (width, height - r )

context.curve_to(width, height - r, width , height, width - r, height)

context.line_to (r, height)

context.curve_to(r, height, 0, height, 0, height - r)

context.line_to (0, r)

context.curve_to(0, r, 0, 0, r, 0)

context.fill ()

def check_command(command): p = '/proc' for f in os.listdir(p): path = os.path.join(p, f, 'comm') if os.path.exists(path): c = open(path).read().strip() if c == command: return f return None

def html_unescape(text): """ Removes HTML or XML character references and entities from a text string. from Fredrik Lundh http://effbot.org/zone/re-sub.htm#unescape-html @param text The HTML (or XML) source text. @return The plain text, as a Unicode string, if necessary. """ def fixup(m): text = m.group(0) if text[:2] == "&#":

character reference

         try:
             if text[:3] == "&#x":
                 return unichr(int(text[3:-1], 16))
             else:
                 return unichr(int(text[2:-1]))
         except ValueError:
             pass
     else:
         # named entity
         try:
             text = unichr(htmlentitydefs.name2codepoint[text[1:-1]])
         except KeyError:
             pass
     return text # leave as is
 return re.sub("&#?\w+;", fixup, text)

def wikilyrics_getalbum(artist, title): artist = urllib2.quote(artist.replace(" ","").encode('utf-8')) title = urllib2.quote(title.replace(" ","_").encode('utf-8'))

 url = " http://lyrics.wikia.com/ " + artist + ":" + title
 c.debug("Getting Album: " + URL)
 try:
     webcode = urlopen(URL).read()
     #        appears on the album         //First string
     #        (.*?)                        //Match the title the 

first time (the ? adds a nongreedy search)

(._/> //What is afeter the

title (its non-greedy so it will return the first one) regexp = re.compile ("appears on the album (._?)(.*/>",re.DOTALL) m = re.search(regexp, webcode) return m.group(1) except: return ""

def name_hash(s, artist=False): """ Prepares song title or artist name for cache file name.

     @param str: string - title or artist
     @param artist: boolean - True if str is artist name
     @return: string - prepared artist or title name
 """
 s = s.decode('utf-8').lower()
 if artist:
     s = re.sub('^the\s*', '', s)
 else:
     s = re.sub('[\[\(]\s*(live|bonus|feat|ft).*?[\]\)]', '', s)
 s = s.encode('utf-8')
 s = s.translate(string.maketrans('',''), string.punctuation + ' -')
 return s

#

GLOOBUS_URL = ' http://gloobus.net/' DBUS_NAME = 'net.gloobus.covergloobus' DBUS_PATH = '/net/gloobus/covergloobus'

DBUS_IFACE =

ABS_PATH = os.path.abspath(os.path.dirname(sys.argv[0])) ICON_PATH = ABS_PATH + '/images/covergloobus.png' HOME_PATH = os.path.expanduser("~")

if not os.path.exists(HOME_PATH + '/.CoverGloobus/'): os.mkdir(HOME_PATH+'/.CoverGloobus/')

LOCK_PATH = HOME_PATH + '/.CoverGloobus/CoverGloobus.lock' CONFIG_PATH = HOME_PATH + '/.config/CoverGloobus/CoverGloobus.cfg'

CACHE_PATH = HOME_PATH + '/.cache/CoverGloobus/' if not os.path.exists(CACHE_PATH): os.mkdi...

Clementine-Issue-Importer commented 10 years ago

From legion1978 on February 24, 2011 09:26:00

...r(CACHE_PATH)

THEME_PATH = HOME_PATH+'/.CoverGloobus/themes/' if not os.path.exists(THEME_PATH): os.mkdir(THEME_PATH)

THREAD_COUNTER = 0

COVER, STATE, TIME, TRACK = range(4)

gettext.bindtextdomain('covergloobus', PREFIX + '/share/locale/') gettext.textdomain('covergloobus') _ = gettext.gettext

c = Notifier()

config = None

for a in sys.argv: if a == '--debug': c.set_debug(True) c.debug('Installed themes:') for theme in get_themes(): print ' * ', theme, ',' c.debug('Installed players:') import players for player in players.get_players(): print ' * ', player elif a == '--default-config': config = Config(True)

if not config: config = Config()

c.debug("Prefix: " + PREFIX) c.debug("ABS_PATH: " + ABS_PATH)

clementine-player@googlecode.com escribió:

Clementine-Issue-Importer commented 10 years ago

From keirangtp on February 25, 2011 09:22:57

There's too much of this for us to scan - call the guys from CoverGlobus and if they have any questions - we'll answer.

Clementine-Issue-Importer commented 10 years ago

From legion1978 on February 26, 2011 07:11:02

ok it is fixed in the [obscure :)] bzr version of CG. Thanx for your help!