# 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 os
import dbus
import urllib
from GenericPlayer import GenericPlayer
from common import Track

class RhythmboxPlayer(GenericPlayer):
    """
        Rhythmbox player plugin
    """
    __name__ = 'Rhythmbox'
    __version__ = '0.1'
    __author__ = 'BadChoice <guitarboy000@gmail.com>, Alexandr Grigorcea <cahr.gr@gmail.com>'
    __desc__ = 'API to the Rythmbox Music Player'
    
    DBUS_NAME   = 'org.gnome.Rhythmbox'
    DBUS_OBJECT = '/org/gnome/Rhythmbox/Player'
    playerAPI = None
    shellAPI  = None

    def is_active(self):
        """
            Initializes class, begins dbus listening if DBUS_NAME is provided
            @param d: dbus.Interface
        """
        if self.DBUS_NAME in self.dbus.ListNames():
            return True
        else:
            return False

    def connect(self):
        """
            Connects player
            @return: boolean, True if successful, False if not
        """
        proxy_obj1 = dbus.SessionBus().get_object(self.DBUS_NAME, 
            '/org/gnome/Rhythmbox/Player')
        proxy_obj2 = dbus.SessionBus().get_object(self.DBUS_NAME, 
            '/org/gnome/Rhythmbox/Shell')
        self.playerAPI = dbus.Interface(proxy_obj1, self.DBUS_NAME+".Player")
        self.shellAPI = dbus.Interface(proxy_obj2, self.DBUS_NAME+".Shell")
        if not self.connected:
            dbus.SessionBus().add_signal_receiver(self.playing_changed_handler, 
                "playingChanged", 'org.gnome.Rhythmbox.Player', 
                'org.gnome.Rhythmbox', '/org/gnome/Rhythmbox/Player')
            dbus.SessionBus().add_signal_receiver(self.song_changed_handler, 
                "playingUriChanged", 'org.gnome.Rhythmbox.Player', 
                'org.gnome.Rhythmbox', '/org/gnome/Rhythmbox/Player')
            self.connected = True
        return True
            
    def disconnect(self):
        """
            Disconnects player
        """
        if self.connected:
            dbus.SessionBus().remove_signal_receiver(self.playing_changed_handler, 
                "playingChanged", 'org.gnome.Rhythmbox.Player', 
                'org.gnome.Rhythmbox', '/org/gnome/Rhythmbox/Player')
            dbus.SessionBus().remove_signal_receiver(self.song_changed_handler, 
                "playingUriChanged", 'org.gnome.Rhythmbox.Player', 
                'org.gnome.Rhythmbox', '/org/gnome/Rhythmbox/Player')
            self.connected = False
    
    def get_title(self):
        """
            @return: string, title of current playing song
        """
        try:
            return self.getProperty('title')
        except:
            return ""
    
    def get_album(self):
        """
            @return: string, album name of current playing song
        """
        try:
            return self.getProperty('album')
        except:
            return ""
        
    def get_artist(self):
        """
            @return: string, artist name of current playing song
        """
        try:
            return self.getProperty('artist')
        except:
            return ""
        
    def get_rating(self):
        """
            @return: integer, [0-5] value, representing rating of current
                playing song
        """
        try:
            return int(self.getProperty('rating'))
        except:
            return ""

    def get_cover_path(self, data=None):
        """
            @param data: dictionary, contains info about current playing song.
                optional
            @return: string, path to the album art image of current playing
                songm, (not URI)
        """
        try:
            if not data:
                data = self.shellAPI.getSongProperties(self.playerAPI.getPlayingUri())
            cover = self.search_cover(data['location'],data)
            if cover:
                return cover
            filename = os.path.expanduser('~/.cache/rhythmbox/covers/{0} - {1}.jpg'.format(data['artist'],data['album']))
            if os.path.exists(filename):
                return filename
        except:
            pass
        return ''

    def get_state(self):
        """
            Returns players actual state.
            @return: string - playing, paused, stopped
        """
        if self.playerAPI.getPlaying():
            return 'playing'
        else:
            if self.playerAPI.getPlayingUri() == '':
                return 'stopped'
            else:
                return 'paused'

    def is_playing(self):
        """
            @return: boolean, True if player is playing, False if not
        """
        return self.playerAPI.getPlaying()

    def previous(self ,widget, event):
        """
            Changes song to previous
        """
        if self.active:
            self.playerAPI.previous()

    def play(self ,widget, event):
        """
            Plays or pauses the player
        """
        if self.active:
            self.playerAPI.playPause(True)
 

    def next(self ,widget, event):
        """
            Changes song to next
        """
        if self.active:
            self.playerAPI.next()
    
    def getProperty(self, name):
        try:
            val = self.shellAPI.getSongProperties(self.playerAPI.getPlayingUri())[name]
            return val
        except:
            return None
    
    def get_track(self, data=None):
        """
            Prepares a Track object with current playing song data
            
            @param data: dictionary, contains info about current playing song.
                optional
            @return: Track, object with current playing song data
        """
        if not data:
            try:
                path = self.playerAPI.getPlayingUri()
                data = self.shellAPI.getSongProperties(path)
            except dbus.DBusException:
                if self.is_active():
                    self.connect()
                    path = self.playerAPI.getPlayingUri()
                    data = self.shellAPI.getSongProperties(path)
                else:
                    self.state_handler(state='closed')
                    return
        track = Track(
            title  = data['title'],
            album  = data['album'],
            artist = data['artist'],
            rating = data['rating'],
            genre  = data['genre'],
            year   = data['year'],
            tracknumber = data['track-number'],
            cover  = self.get_cover_path(data))
        return track
            
# ================================= HANDLERS ================================= #

    def playing_changed_handler(self, message):
        """
            Handles StatusChanged dbus signal, calls state_handler()
            
            @param message: boolean
        """
        if message:
            self.state_handler(state='playing')
        else:
            self.state_handler(state='paused')
            
    def song_changed_handler(self, message):
        """
            Handles TrackChanged dbus signal, calls state_handler()
            
            @param message: string, URI of current playing song
        """
        track = self.get_track()
        self.state_handler(track=track)
