def cb_call_action(self, widget, data = None):
     log("Quicklist showing conversation", INFO)
     id = widget.property_get("id")
     action = widget.property_get("action")
 
     if not id in self.calls:
         return
 
     if action == 'HOLD':
         self.calls[id].Hold()
     if action == 'FINISH':
         self.calls[id].Finish()
     if action == 'ANSWER':
         self.calls[id].Answer()
     if action == 'RESUME':
         self.calls[id].Resume()
     if action == 'VIDEOOUT':
         self.calls[id].StartVideoSend()
     if action == 'VIDEOIN':
         self.calls[id].StartVideoReceive()
     if action == 'ENDVIDEOOUT':
         self.calls[id].StopVideoSend()
     if action == 'ENDVIDEOIN':
         self.calls[id].StopVideoReceive()
     if action == 'MUTE':
         self.skype._SetMute(True)
     if action == 'UNMUTE':
         self.skype._SetMute(False)
     if helpers.isUnityRunning():             
         unitylauncher.createCallsQuickList(self.calls, self.cb_call_action)
         unitylauncher.redrawQuicklist()  
    def new_message(self, conversation):
        if not settings.get_notify_on_messagerecieve() or self.skype.skype_presence == Skype4Py.cusDoNotDisturb:
            return
        #conversation.skypereturn.Chat.Type == Skype4Py.chatTypeMultiChat and  
        conversation.display_name = conversation.skypereturn.Chat.Topic or conversation.display_name
        name = conversation.skypereturn.Sender.DisplayName or conversation.skypereturn.Sender.FullName or conversation.skypereturn.Sender.Handle

        if len(conversation.skypereturn.Chat.Members) > 2:
            group_chat_title = unicode(name + " ► " + conversation.display_name)
        else:
            group_chat_title = unicode(conversation.display_name)
        
        icon = ""
        if settings.get_display_notification_avatars():
            avatar = SkypeAvatar(conversation.skypereturn.Sender.Handle)
            if avatar.filename:
                icon = avatar.filename
            else:
                icon = wrapperPath + "/icons/skype-wrapper-48.svg"
    
        if helpers.isUnityRunning():
            unitylauncher.count(len(self.indicators) + self.skype.incomingfilecount)
            unitylauncher.createUnreadMessageQuickList(self.skype.unread_conversations, self.show_conversation_quicklist)
            unitylauncher.redrawQuicklist()  
            unitylauncher.count(len(self.indicators) + self.skype.incomingfilecount)
    
        helpers.notify(group_chat_title, conversation.skypereturn.Body, icon, group_chat_title, False, False, conversation.skypereturn.Chat.Topic)  
 def calls_ringing(self) :
     self.calls_ringing_started = True
     if self.call_ringing > 0:
         if helpers.isUnityRunning():
             unitylauncher.urgent()
     else :
         self.calls_ringing_started = False
     return self.call_ringing > 0
 def reset_indicators(self) :
     del self.indicators
     self.indicators = {}
     for _id in self.skype.unread_conversations:
         self.show_indicator(self.skype.unread_conversations[int(_id)])
     if helpers.isUnityRunning():
         unitylauncher.count(len(self.indicators) + self.skype.incomingfilecount)
         unitylauncher.createUnreadMessageQuickList(self.skype.unread_conversations, self.show_conversation_quicklist)
         unitylauncher.redrawQuicklist()  
         unitylauncher.count(len(self.indicators) + self.skype.incomingfilecount)
 def CallStatus(self, call, status):
     global active_player, player_paused, volume_level
     if status == "RINGING":
         if settings.get_control_music_player() and active_player == "unknown" and player_paused == False:
             controlMusicPlayer()
         if settings.get_restore_volume():
             SaveRestore_Volume()
         self.call_ringing = self.call_ringing + 1
         self.calls[call.PartnerHandle] = call
     else:
         self.call_ringing = self.call_ringing - 1
 
     #if status == "INPROGRESS":LOCALHOLD
 
     if (status == "MISSED" or status == "FINISHED" or status == "REFUSED" or status == "CANCELLED") and call.PartnerHandle in self.calls:
         if settings.get_restore_volume():
             SaveRestore_Volume()
             volume_level = "unknown"
         if settings.get_control_music_player():
             controlMusicPlayer()
             active_player = "unknown"
             player_paused = False
         del self.calls[call.PartnerHandle]
     if helper.isUnityRunning():    
         unitylauncher.createCallsQuickList(self.calls, self.cb_call_action)
         unitylauncher.redrawQuicklist()  
 
     # wiggle the launcher
     if self.call_ringing > 0 and not self.calls_ringing_started:
         if helpers.isUnityRunning():
             unitylauncher.urgent()
         GObject.timeout_add(1000, self.calls_ringing)
     
     icon = ""
     if settings.get_display_notification_avatars():
         avatar = SkypeAvatar(call.PartnerHandle)
         if avatar.filename:
             icon = avatar.filename
         else:
             icon = wrapperPath + "/icons/skype-wrapper-48.svg"
 
     partner = call.PartnerDisplayName or call.PartnerHandle
     notification = ""
     if status == "RINGING" and (call.Type == "INCOMING_P2P" or call.Type == "INCOMING_PSTN"):
         notification = "* Incoming call";
     if status == "INPROGRESS":
         notification = "* Call started";
     if status == "MISSED":
         notification = "* Missed call";
     if status == "FINISHED":
         notification = "* Call ended";
     if status == "REMOTEHOLD":
         notification = "* Call put on hold";
     if notification:
         helpers.notify(partner, notification, icon, "call://"+call.PartnerHandle, True, True)  
 def checkUnreadMessages(self):
     if not self.messageupdatepending:
         return AppletRunning
     self.messageupdatepending = False
 
     try :
         log("Checking unread messages", INFO)
         missedmessages = []
         if self.skype.MissedMessages:
             for mesg in self.skype.MissedMessages:
                 missedmessages.append(mesg)
             
         unread = self.unread_conversations
         self.unread_conversations = {}
         logged = False
         if missedmessages and self.cb_show_indicator:
             for mesg in reversed(missedmessages):
                 try:
                     id = mesg.Id
                     if self.skype.Friends:
                         for friend in self.skype.Friends:
                             if mesg.Chat.DialogPartner == friend.Handle:
                                 display_name = friend.DisplayName or friend.FullName or friend.Handle
                                 break                    
                 except:
                     log("Couldn't get missed message Chat object", ERROR)
                     continue
                 if not id in self.unread_conversations:
                     conversation = Conversation(display_name, mesg.Timestamp, mesg.Sender.Handle, mesg)
                     self.name_mappings[id] = mesg.Sender.Handle
                     self.unread_conversations[id] = conversation
                 else:
                     self.unread_conversations[id].add_timestamp(mesg.Timestamp)
             
                 if helpers.isUserBlacklisted(mesg.Sender.Handle):
                     self.unread_conversations[id].Read = True
                 
                 if not self.unread_conversations[id].Read:
                     self.logMessage(self.unread_conversations[id])
                     self.cb_show_indicator(self.unread_conversations[id]) 
     
         if len(unread) != len(self.unread_conversations):
         
             if self.cb_read_within_skype:
                 self.cb_read_within_skype()
             
             if helpers.isUnityRunning():
                 unitylauncher.urgent(True)
                 unitylauncher.urgent(False)
         
     except Exception, e:
         log("Checking unread messages failed: "+str(e), WARNING)
    def checkFileTransfers(self) :
        if not self.filetransferupdatepending:
            return AppletRunning
        self.filetransferupdatepending = False
        try : 
            log("Checking file transfers", INFO)
            for transfer in self.skype.ActiveFileTransfers:
                if not transfer.Id in self.filetransfers:
                    self.filetransfers[transfer.Id] = FileTransfer(transfer)
        
            for transfer in self.skype.FileTransfers:
                if transfer.Id in self.filetransfers:
                    self.filetransfers[transfer.Id].update(transfer)
             
            oldincoming = self.incomingfilecount
            self.incomingfilecount = 0
            self.filetransfer = {
                "total" : -1,
                "current" : 0    
            }
            # should we send out notifications
            for k in self.filetransfers:
                v = self.filetransfers[k]
                if str(v.type) == "INCOMING":
                    if "NEW" in str(v.status):
                        self.incomingfilecount = self.incomingfilecount + 1
                        if helpers.isUnityRunning():
                            unitylauncher.urgent(True)
                    else:
                        if helpers.isUnityRunning():
                            unitylauncher.urgent(False)
                
                    if settings.get_show_incoming_filetransfer_progress():
                        if "TRANSFERRING" in str(v.status) or "PAUSED" in str(v.status):
                            self.filetransfer['total'] = self.filetransfer['total'] + v.skype_transfer.FileSize
                            self.filetransfer['current'] = self.filetransfer['current'] + v.skype_transfer.BytesTransferred
                            self.incomingfilecount = self.incomingfilecount + 1
                            self.filetransferupdatepending = True
                      
                    if not str(v.status) in v.notifications:
                        if "NEW" in v.status:
                            self.filetransfers[k].notifications[str(v.status)] = str(v.status)
                            if self.cb_log_transfer:
                                self.cb_log_transfer(v, "* " + v.partner+ " wants to send you a file")
                        if "TRANSFERRING" in v.status:
                            self.filetransfers[k].notifications[str(v.status)] = str(v.status)
                            if self.cb_log_transfer:
                                self.cb_log_transfer(v, "* " + v.partner+ " is busy sending you a file")
                            self.filetransferupdatepending = True
                        if "CANCELLED" in v.status:
                            self.filetransfers[k].notifications[str(v.status)] = str(v.status)
                            if self.cb_log_transfer:
                                self.cb_log_transfer(v, "* file transfer with " + v.partner+ " has been cancelled")
                        if "COMPLETED" in v.status:
                            self.filetransfers[k].notifications[str(v.status)] = str(v.status)
                            if self.cb_log_transfer:
                                self.cb_log_transfer(v, "* " + v.partner+ " finished sending you a file")
                            if helpers.isUnityRunning():
                                unitylauncher.urgent(True)
                        if "FAILED" in v.status:
                            self.filetransfers[k].notifications[str(v.status)] = str(v.status)
                            if self.cb_log_transfer:
                                self.cb_log_transfer(v, "* " + v.partner+ " failed to send you a file")
                    else:
                        if "COMPLETED" in v.status:
                            if helpers.isUnityRunning():
                                unitylauncher.urgent(False)
                        
                if str(v.type) == "OUTGOING":                
                    if settings.get_show_outgoing_filetransfer_progress():
                        if "TRANSFERRING" in str(v.status) or "PAUSED" in str(v.status) or "REMOTELY_PAUSED" in str(v.status):
                            self.filetransfer['total'] = self.filetransfer['total'] + v.skype_transfer.FileSize
                            self.filetransfer['current'] = self.filetransfer['current'] + v.skype_transfer.BytesTransferred
                            self.incomingfilecount = self.incomingfilecount + 1
                            self.filetransferupdatepending = True
                        
                    if not str(v.status) in v.notifications:
                        if "TRANSFERRING" in v.status:
                            self.filetransfers[k].notifications[str(v.status)] = str(v.status)
                            if self.cb_log_transfer:
                                self.cb_log_transfer(v, "* " + v.partner+ " is busy receiving your file")
                            self.filetransferupdatepending = True
                        if "CANCELLED" in v.status:
                            self.filetransfers[k].notifications[str(v.status)] = str(v.status)
                            if self.cb_log_transfer:
                                self.cb_log_transfer(v, "* file transfer with " + v.partner+ " has been cancelled")
                        if "COMPLETED" in v.status:
                            self.filetransfers[k].notifications[str(v.status)] = str(v.status)
                            if self.cb_log_transfer:
                                self.cb_log_transfer(v, "* " + v.partner+ " has received your file")                        
                        if "FAILED" in v.status:
                            self.filetransfers[k].notifications[str(v.status)] = str(v.status)
                            if self.cb_log_transfer:
                                self.cb_log_transfer(v, "* " + v.partner+ " failed to receive your file")
               
            if self.filetransfer['total'] > -1:
                currentprogress = float(self.filetransfer['current']) / float(self.filetransfer['total'])
                if helpers.isUnityRunning():
                    unitylauncher.progress(currentprogress)
            else:
                if helpers.isUnityRunning():
                    unitylauncher.progress(-1)
            
            if oldincoming != self.incomingfilecount and self.cb_read_within_skype:
                self.cb_read_within_skype()  

        except Exception, e:
            log("Checking file transfers failed ("+str(e)+")", WARNING)
            raise
    def __init__(self):
        log("Initializing Skype API", INFO)
        self.skype = Skype4Py.Skype(None, Transport='x11')
        self.call_ringing = 0
        self.calls_ringing_started = False
    
        #register events
        self.skype.RegisterEventHandler('MessageStatus', self.MessageStatus)
        self.skype.RegisterEventHandler('OnlineStatus', self.OnlineStatus)
        self.skype.RegisterEventHandler('FileTransferStatusChanged', self.FileTransferStatusChanged)
        self.skype.RegisterEventHandler('CallStatus', self.CallStatus)
    
        self.skype.Timeout = 500
    
        if not isSkypeRunning():
            if settings.get_start_skype_cmd_params():
                log("Starting Skype with extra params", INFO)
                subprocess.Popen(shlex.split("skype "+settings.get_start_skype_cmd_params()))
            else:
                if not helpers.isSkypeWrapperDesktopOnUnityLauncher():
                    log("Starting Skype process", INFO)
                    subprocess.Popen(shlex.split("skype"))
                else:
                    log("Starting Skype", INFO)
                    self.skype.Client.Start(Minimized=True)

        log("Waiting for Skype Process", INFO)
        while True:
            if isSkypeRunning():
                break

        log("Attaching skype-wrapper to Skype process", INFO)
        while True:
            try:
                # don't know if its our authorization request but we will wait our turn
                if not helpers.isAuthorizationRequestOpen():
                    self.skype.Attach(Wait=True)
                    break
                else:
                    log("Authorization dialog still open", INFO)
                    sys.exit(2)
            except:
                # we tell the parent process that the skype couldn't attached
                log("Failed to attach skype-wrapper to Skype process", WARNING)
                sys.exit(2) 
                        
        log("Attached complete", INFO)
    
        #self.skype.Timeout = 30000
        if helpers.isUnityRunning():
            unitylauncher.launcher.SkypeAgent = self.skype.Client
            unitylauncher.launcher.skype = self.skype
            unitylauncher.launcher.redrawQuicklist()
        
        self.skype.Client.Minimize()
        self.name_mappings = {}
        self.unread_conversations = {}
    
        # we will store all outdated messages here, anything not here will get net notified
        self.conversations = {}
    
        # store all the users online for notifying if they're on
        self.usersonline = {}
    
        # stor all file transfers
        self.filetransfers = {}
        self.incomingfilecount = 0
    
        # store all calls current
        self.calls = {}
    
        self.cb_show_conversation = None
        self.cb_show_indicator = None
        self.cb_user_status_change = None
        self.cb_log_message = None
        self.cb_read_within_skype = None
        self.cb_log_transfer = None

        self.initSkypeFirstStart()    
        
        self.messageupdatepending = True
        GObject.timeout_add(CB_INTERVALS, self.checkUnreadMessages)
    
        self.onlineuserupdatepending = True
        GObject.timeout_add(CB_INTERVALS, self.checkOnlineUsers)
    
        self.onlinepresenceupdatepending = True
        GObject.timeout_add(CB_INTERVALS, self.checkOnlineStatus)
    
        self.filetransferupdatepending = True
        GObject.timeout_add(CB_INTERVALS, self.checkFileTransfers)
# WITHOUT ANY WARRANTY; without even the implied warranties of 
# MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR 
# PURPOSE.  See the applicable version of the GNU Lesser General Public 
# License for more details.
#
# You should have received a copy of both the GNU Lesser General Public 
# License version 3 and version 2.1 along with this program.  If not, see 
# <http://www.gnu.org/licenses/>
#

# Documentation:
# just start it

import helpers

if helpers.isUnityRunning():
    import unitylauncher
    
from gi.repository import GObject
import indicate
import Skype4Py
import shared
import settings

import os
import sys
import commands
import time
import subprocess
import shlex