# 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
import common
from common import Track

class SongbirdPlayer(GenericPlayer):
    """
        Songbird player plugin
        Songbird requires MPRIS plugin
    """
    __name__ = 'Songbird'
    __version__ = '0.1'
    __author__ = 'Jaap Broekhuizen <jaapz.b@gmail.com>, Alexandr Grigorcea <cahr.gr@gmail.com>'
    __desc__ = 'API to Songbird'
    
    DBUS_NAME   = 'org.mpris.songbird'
    DBUS_OBJECT = '/Player'
    
    dbus_object = None
    _artwork_path = 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
        """
        self.session_bus = dbus.SessionBus()
        self.dbus_object = self.session_bus.get_object(self.DBUS_NAME, 
            self.DBUS_OBJECT)
        if not self.connected:
            self.session_bus.add_signal_receiver(self.playing_changed_handler, 
                "StatusChange", 'org.freedesktop.MediaPlayer', 
                self.DBUS_NAME, self.DBUS_OBJECT)
            self.session_bus.add_signal_receiver(self.song_changed_handler, 
                "TrackChange", 'org.freedesktop.MediaPlayer', 
                self.DBUS_NAME, self.DBUS_OBJECT)
            self.connected = True
        return True
            
    def disconnect(self):
        """
            Disconnects player
        """
        if self.connected:
            self.session_bus.remove_signal_receiver(self.playing_changed_handler, 
                "StatusChange", 'org.freedesktop.MediaPlayer', 
                self.DBUS_NAME, self.DBUS_OBJECT)
            self.session_bus.remove_signal_receiver(self.song_changed_handler, 
                "TrackChange", 'org.freedesktop.MediaPlayer', 
                self.DBUS_NAME, self.DBUS_OBJECT)
            self.connected = False

    def get_title(self):
        """
            @return: string, title of current playing song
        """
        try: 
            return self.dbus_object.GetMetadata()['title']
        except:
            return ""

    def get_album(self):
        """
            @return: string, album name of current playing song
        """
        try: 
            return self.dbus_object.GetMetadata()['album']
        except:
            return ""
        
    def get_artist(self):
        """
            @return: string, artist name of current playing song
        """
        try: 
            return self.dbus_object.GetMetadata()['artist']
        except:
            return ""

    def get_rating(self):
        """
            @return: integer, [0-5] value, representing rating of current
                playing song
        """
        try: 
            return self.dbus_object.GetMetadata()['rating']
        except:
            return 0
    
    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.dbus_object.GetMetadata()
            cover = self.search_cover(data['location'],data)
            if cover:
                return cover
            cover = data['arturl']
            if cover[:21] == 'resource://sb-artwork':
                cover = self._get_artwork_path() + cover[21:]
                return cover
        except:
            pass
        return ''

    def get_state(self,data=None):
        """
            Returns players actual state.
            @return: string - playing, paused, stopped
        """
        if not data:
            data = self.dbus_object.GetStatus()
        if data[0] == 0:
            return 'playing'
        if data[0] == 1:
            return 'paused'
        if data[0] == 2:
            return 'stopped'

    def is_playing(self):
        """
            @return: boolean, True if player is playing, False if not
        """
        data = self.dbus_object.GetStatus()
        if data[0] == 0:
            return True
        else:
            return False

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

    def play(self, widget, event):
        """
            Plays or pauses the player
        """
        if self.active:
            self.dbus_object.Pause()

    def next(self, widget, event):
        """
            Changes song to next
        """
        if self.active:
            self.dbus_object.Next()
        
    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
        """
        try:
            if not data:
                data = self.dbus_object.GetMetadata()
        
            track = Track(
                title = data['title'],
                album = data['album'],
                artist= data['artist'],
                genre = data['genre'],
                year  = data['year'],
                tracknumber = data['tracknumber'],
                cover = self.get_cover_path(data)
            )
            return track
        except:
            return Track()

    def _get_artwork_path(self):
        if self._artwork_path:
            return self._artwork_path
            
        profile = open(common.HOME_PATH + '/.songbird2/profiles.ini')

        found = False
        relative = False
        name = None
        for line in profile:
            line = line.strip()
            data = line.split('=',1)
            if len(data) == 2:
                key = data[0].strip()
                val = data[1].strip()
                if key == 'Name' and val == 'default':
                    found = True
                if found and key == 'Path':
                    name = val
                if found and key == 'IsRelative':
                    if val == '1':
                        relative = True
        if name:
            if relative:
                self._artwork_path = common.HOME_PATH + '/.songbird2/' + name + '/artwork'
            else:
                if self._artwork_path[1:] == '/':
                    self._artwork_path = self._artwork_path[:-1]
                self._artwork_path = name + '/artwork/'
            return self._artwork_path
        
# ================================= HANDLERS ================================= #

    def playing_changed_handler(self, message):
        """
            Handles StatusChanged dbus signal, calls state_handler()
            
            @param message: list
        """
        self.state_handler(state=self.get_state(message))
            
    def song_changed_handler(self, message):
        """
            Handles TrackChanged dbus signal, calls state_handler()
            
            @param message: dictionary with current playing song stats
        """
        track = self.get_track(message)
        self.state_handler(track=track)
