# 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
import cairo
import gtk
import gtk.gdk
import gettext
import config
import sys

_ = gettext.gettext

class docky:

    DBUS_NAME = 'org.gnome.Docky'
    DBUS_OBJECT = '/org/gnome/Docky'
    FILE_PATH = "/usr/share/applications/covergloobus.desktop"

    launcher_dbus = None
    connected = False
    
    #Menu Items
    playpause = 0
    next = 0
    prev = 0
    config = 0
    lyrics = 0
    tabs = 0
    about = 0
    
    #Main Items
    cg = None                #The main object to launch common functions such as next prev pause stop...
    g = None

    def __init__(self,cg,g):
        self.cg = cg
        self.g = g
        self.g.debug("Creating Docky")

    def is_active(self):
        if self.DBUS_NAME in self.cg.dbus_iface.ListNames():
            return True
        else:
            return False

    def connect(self):
        self.g.debug("Docky: Connect DBUS")
        if not self.connected:
            session_bus = dbus.SessionBus()
            dbus_object = session_bus.get_object(self.DBUS_NAME, self.DBUS_OBJECT)
            self.dbus_iface = dbus.Interface (dbus_object, self.DBUS_NAME)
            self.launcher_path = None
            c = 0
            while not self.launcher_path:
                self.launcher_path  = self.dbus_iface.DockItemPathForDesktopFile(self.FILE_PATH)
                c = c+1
                if c == 10:
                    self.g.error("Docky: something gone wrong with docky :(")
                    sys.exit(1)
            self.launcher_dbus = session_bus.get_object(self.DBUS_NAME, self.launcher_path)
            self.connected = True
        self.g.debug("Docky: Connection to DBUS done")

    def disconnect(self):
        if self.connected:
            self.g.debug("Docky: disconnecting")
            session_bus = dbus.SessionBus()
            session_bus.remove_signal_receiver(self.signal_handler,
                "MenuItemActivated", 'org.gnome.Docky.Item',
                self.DBUS_NAME, self.launcher_path)
            session_bus.remove_signal_receiver(self.item_confirmation,
                "ItemConfirmationNeeded", 'org.gnome.Docky.Item',
                self.DBUS_NAME, self.launcher_path)
            self.connected = False

    # ================================= CREATE MENU ================================ #
    def create_menu(self):
        if self.connected:
            self.playpause     = self.launcher_dbus.AddMenuItem(_("Play/Pause"),"",    _("Controls"))
            self.next         = self.launcher_dbus.AddMenuItem(_("Next"),"",            _("Controls"))
            self.prev         = self.launcher_dbus.AddMenuItem(_("Previous"),"",        _("Controls"))
            self.lyrics     = self.launcher_dbus.AddMenuItem(_("Show Lyrics"),"",    _("Song"))
            self.tabs         = self.launcher_dbus.AddMenuItem(_("Show Tabs"),"",        _("Song"))
            self.config     = self.launcher_dbus.AddMenuItem(_("Settings"),"",        "")
            self.about         = self.launcher_dbus.AddMenuItem(_("About"),"",            "")
            self.g.debug("Docky: Create Menu" + str(self.playpause))

    # =============================== BIND SIGNALS ================================= #
    def bind_signals(self):
        self.g.debug("Docky: Bind Menu Signals")
        bus = dbus.SessionBus()
        bus.add_signal_receiver (self.item_confirmation,
                "ItemConfirmationNeeded", 'org.gnome.Docky.Item',
                self.DBUS_NAME, self.launcher_path)
        bus.add_signal_receiver (self.signal_handler,
                "MenuItemActivated", 'org.gnome.Docky.Item',
                self.DBUS_NAME, self.launcher_path)

    def set_title(self, artist, song):
        self.g.debug("Docky: Set Title")
        if self.connected:
            if artist == '' and song == '':
                self.launcher_dbus.SetText('CoverGloobus')
            else:
                self.launcher_dbus.SetText(artist + " - " + song)

    def set_waiting(self):
        self.g.debug("Docky: Set Waiting")
        if self.connected:
            self.launcher_dbus.SetWaiting()
        
    def unset_waiting(self):
        self.g.debug("Docky: Unset Waiting")
        if self.connected:
            self.launcher_dbus.UnsetWaiting()

    def set_cover(self, path):
        self.g.debug("Docky: Set Cover: " + path)
        if self.connected:
            try:
                self.round_image(path)
                self.launcher_dbus.SetIcon("/tmp/cover.png")
            except:
                self.launcher_dbus.SetIcon(config.prefix + "/share/covergloobus/images/nocover.png")
        else:
            self.g.warning("DOCKY: Docky Not connected")
        
    def round_image(self,filename):
        pixbuf = gtk.gdk.pixbuf_new_from_file(filename)
        w = pixbuf.get_width()
        h = pixbuf.get_height()

        surface = cairo.ImageSurface(0,w,h)        #Create a new cairo surface to place the image on
        #nostar    = cairo.ImageSurface.create_from_png("/home/jordi/Escriptori/star.png")

        ct = cairo.Context(surface)                #Create a context to the new surface
        self.roundedrec(ct,0,0,w,h,40)                #Rounded Rectangle
        ct.clip()                                #Clip the out of the rectangle

        ct.new_path()                            #Path not afected by clip

        ct2 = gtk.gdk.CairoContext(ct)            #Create GDK formated cairo contex
        ct2.set_source_pixbuf(pixbuf,0,0)        #Draw pixbuf to the new surface
        ct2.paint()                                #Paint
    
        ct2.new_path()
        ct2.set_source_rgba(1,1,1,1)
        ct2.set_line_width(10)
        self.roundedrec(ct2,0,0,w,h,40)
        ct2.stroke()

        #ct2.move_to(10,10)
        #ct2.set_source_surface(nostar)
        #ct2.scale(0.1,0.1)
        #ct2.paint()


        surface.write_to_png("/tmp/cover.png")


    def roundedrec(self,context,x,y,w,h,r = 10):
        "Draw a rounded rectangle"
        #   A****BQ
        #  H      C
        #  *      *
        #  G      D
        #   F****E

        context.move_to(x+r,y)                      # Move to A
        context.line_to(x+w-r,y)                    # Straight line to B
        context.curve_to(x+w,y,x+w,y,x+w,y+r)       # Curve to C, Control points are both at Q
        context.line_to(x+w,y+h-r)                  # Move to D
        context.curve_to(x+w,y+h,x+w,y+h,x+w-r,y+h) # Curve to E
        context.line_to(x+r,y+h)                    # Line to F
        context.curve_to(x,y+h,x,y+h,x,y+h-r)       # Curve to G
        context.line_to(x,y+r)                      # Line to H
        context.curve_to(x,y,x,y,x+r,y)             # Curve to A
        return

    #====================== DOCKY MENU SIGNAL HANDLER ================#
    def signal_handler(self,args):
        self.g.debug("Docky: an item was pressed - " + str(args))
        if args == self.playpause:
            self.cg.player.play(None,None)
        if args == self.next:
            self.cg.player.next(None,None)
        if args == self.prev:
            self.cg.player.previous(None,None)
        if args == self.config:
            self.cg.menu_option_config(None,None)
        if args == self.lyrics:
            self.cg.menu_option_lyrics(None,None)
        if args == self.tabs:
            self.cg.menu_option_tabs(None,None)
        if args == self.about:
            self.cg.menu_option_about(None,None)

    #== Docky ask for confirmations every 2 min or so, we listen to its signal and send confirmation
    def item_confirmation(self):
        self.g.debug("Docky: Menu items confirmation required")
        self.launcher_dbus.ConfirmItem(self.playpause)
        self.launcher_dbus.ConfirmItem(self.next)
        self.launcher_dbus.ConfirmItem(self.prev)
        self.launcher_dbus.ConfirmItem(self.config)
        self.launcher_dbus.ConfirmItem(self.lyrics)
        self.launcher_dbus.ConfirmItem(self.tabs)
        self.launcher_dbus.ConfirmItem(self.about)

