X-Git-Url: http://git.maemo.org/git/?a=blobdiff_plain;f=src%2Fusr%2Flib%2Fhildon-desktop%2FCallNotify.py;h=6f81c18aba30f382f52aafb2e299ca6af99adc77;hb=77c080ef748f67f229486ffdf9c5736823409686;hp=d05e5d66e32d3aa303cac3f258f61591808ea7ac;hpb=a02a5ee77a3dbf64f041ac5a7a8b94f3234ee2c4;p=callnotify diff --git a/src/usr/lib/hildon-desktop/CallNotify.py b/src/usr/lib/hildon-desktop/CallNotify.py index d05e5d6..6f81c18 100644 --- a/src/usr/lib/hildon-desktop/CallNotify.py +++ b/src/usr/lib/hildon-desktop/CallNotify.py @@ -1,45 +1,185 @@ -import gtk +import gtk, gst import gobject -import hildondesktop +import hildon, hildondesktop import sqlite3 import time import dbus +import osso +import atexit, os, datetime from dbus.mainloop.glib import DBusGMainLoop +WriteLog = False +class Playbin2: + def __init__(self): + self.idle = True # not playing at the moment + self.configDir = "/home/user/.config/CallNotify/" + self.Debug = WriteLog + # create a playbin2 pipe + self.player = gst.element_factory_make("playbin2", "player") + # connect a signal handler to it's bus + bus = self.player.get_bus() + bus.add_signal_watch() + bus.connect("message", self.on_message) + + def on_message(self, bus, message): + t = message.type + if t == gst.MESSAGE_EOS: + self.player.set_state(gst.STATE_NULL) + self.idle = True + self.dbg('Playbin2: EOS: STATE_NULL') + elif t == gst.MESSAGE_ERROR: + #err, debug = message.parse_error() + #print >> sys.stderr, "Error: {0} {1}".format(err, debug) + self.player.set_state(gst.STATE_NULL) + self.idle = True + self.dbg('Playbin2: ERROR: STATE_NULL') + return self.idle + + def play(self, file, volume): + # abort previous play if still busy + if not self.idle: + #print >> sys.stderr, 'audio truncated' + self.player.set_state(gst.STATE_NULL) + self.player.set_property("uri", "file://" + file) + if volume > 0.0: + self.player.set_property("volume", min(volume, 1.0)) + self.dbg('Volume:' + str(self.player.get_property("volume"))) + self.player.set_state(gst.STATE_PLAYING) + self.idle = False # now playing + + def dbg(self, txt): + if self.Debug: + f = open(self.configDir+'log.txt', 'a') + f.write(str(datetime.datetime.now()) + ': '+ txt) + f.write('\n') + + f.close() + class CallNotify(hildondesktop.StatusMenuItem): - def __init__(self): + def __init__(self): hildondesktop.StatusMenuItem.__init__(self) - - self.path = "/home/user/.rtcom-eventlogger/el.db" - - # Prevent multiple timers to refresh the status icon + # Set members + self.configDir = "/home/user/.config/CallNotify/" + self.configFile = "conf.txt" + self.configSoundFile = "sound.txt" + self.Debug = WriteLog + self.dbg("debugging started") + self.msgType = "" + self.toShow = True self.stop = False - + self.path = "/home/user/.config/hildon-desktop/notifications.db" + self.mainLoop = None + self.soundFile = "/usr/share/CallNotify/missed.wav" + self.soundCall = self.soundFile + self.soundSMS = self.soundFile + self.soundBoth = self.soundFile + self.volume = 0.0 + self.readConfigurationFile() + + self.dbg('constructor') + # Load images self.loadImages() - self.msgType = "" - self.toShow = True - self.missed = self.getMissedCallsCount(False) - self.missedSMS = self.getMissedCallsCount(True) - self.missedLastCall = self.missed - self.missedLastSMS = self.missedSMS - gobject.timeout_add(5000, self.handleMissedCall) + + # Register to handle screen off/on events + osso_c = osso.Context("osso_test_device_on", "0.0.1", False) + device = osso.DeviceState(osso_c) # add d-bus listener for removing notification after viewing missed call # Doing timeout_add with return False instead of explicitly raising a thread gobject.timeout_add(500, self.startDbusListeners) + + if self.Debug: + hildon.hildon_play_system_sound(self.soundFile) + self.dbg('constructor end') + + def checkForConfigFile(self): + self.dbg('checkForConfigFile started') + os.umask(0) + if not os.path.exists(self.configDir): + os.mkdir(self.configDir) + if not os.path.exists(self.configDir+self.configFile): + a = open(self.configDir+self.configFile,'w+') + a.write('y;y;y;5.0\n') + a.close() + if not os.path.exists(self.configDir+self.configSoundFile): + a = open(self.configDir+self.configSoundFile,'w+') + a.write('\n') + a.close() + # set proper permissions + os.system("chmod 766 " + self.configDir) + os.system("chmod 766" + self.configDir+self.configFile) + os.system("chmod 766" + self.configDir+self.configSoundFile) + + + def readConfigurationFile(self): + try: + self.dbg('readConfigurationFile started') + self.checkForConfigFile() + f = open(self.configDir+self.configFile, 'r') + raw_set = f.readline().rsplit(';') + self.visual = raw_set[0] in ('y') + self.sound = raw_set[1] in ('y') + self.vibration = raw_set[2] in ('y') + self.interval = float(raw_set[3].replace(',','.')) + f.close() + + # read sound config file + f = open(self.configDir+self.configSoundFile, 'r') + line = f.readline() + # check if specific missed call, SMS or common sound was defined in config file + if line: + self.soundCall = line.rstrip() + line = f.readline() + if line: + self.soundSMS = line.rstrip() + line = f.readline() + if line: + self.soundBoth = line.rstrip() + line = f.readline() + if line: + self.volume = float(line.rstrip()) + f.close() + except: + os.remove(self.configDir+self.configFile) + os.remove(self.configDir+self.configSoundFile) + self.checkForConfigFile() + + def playSound(self): + self.dbg('playSound started') + if self.sound: + # Create the player_name sink + if self.msgType == "Call": + self.dbg('play soundCall:' + self.soundCall) + Playbin2().play(self.soundCall, self.volume) + elif self.msgType == "SMS": + self.dbg('play soundSMS:' + self.soundSMS) + Playbin2().play(self.soundSMS, self.volume) + elif self.msgType == "Both": + self.dbg('play soundBoth:' + self.soundBoth) + Playbin2().play(self.soundBoth, self.volume) + else: + Playbin2().play(self.soundFile, self.volume) - def loadImages(self): - # Load phone image - #self.pixbuf = gtk.gdk.pixbuf_new_from_file_at_size("/home/user/phone.png",18,18) + if self.vibration: + bb = 'run-standalone.sh dbus-send --print-reply --system --dest=com.nokia.mce /com/nokia/mce/request com.nokia.mce.request.req_vibrator_pattern_activate string:' + "\'PatternIncomingCall\'" + bb = str(bb) + b = os.popen(bb) + b.close() + bb = 'run-standalone.sh dbus-send --print-reply --system --dest=com.nokia.mce /com/nokia/mce/request com.nokia.mce.request.req_vibrator_pattern_deactivate string:' + "\'PatternIncomingCall\'" + b = os.popen(bb) + b.close() + return True + + def loadImages(self): + self.dbg('loadImages started') icon_theme = gtk.icon_theme_get_default() - self.callPicture = icon_theme.load_icon("general_call", 18, gtk.ICON_LOOKUP_NO_SVG) + self.callPicture = gtk.gdk.pixbuf_new_from_file_at_size("/usr/share/CallNotify/call.png",18,18) self.smsPicture = gtk.gdk.pixbuf_new_from_file_at_size("/usr/share/CallNotify/sms.png",18,18) # Load 5 numbers and the "+5" self.imgList = [] - #self.imgList.append(gtk.gdk.pixbuf_new_from_file_at_size("/home/user/1.png",18,18)) self.imgList.append(gtk.gdk.pixbuf_new_from_file_at_size("/usr/share/CallNotify/1.png",18,18)) self.imgList.append(gtk.gdk.pixbuf_new_from_file_at_size("/usr/share/CallNotify/2.png",18,18)) self.imgList.append(gtk.gdk.pixbuf_new_from_file_at_size("/usr/share/CallNotify/3.png",18,18)) @@ -47,75 +187,96 @@ class CallNotify(hildondesktop.StatusMenuItem): self.imgList.append(gtk.gdk.pixbuf_new_from_file_at_size("/usr/share/CallNotify/5.png",18,18)) self.imgList.append(gtk.gdk.pixbuf_new_from_file_at_size("/usr/share/CallNotify/more.png",18,18)) - # Method to define the way to add dbus signal receiver - def startDbusListeners(self): - DBusGMainLoop(set_as_default=True) - bus = dbus.SessionBus() - #bus.add_signal_receiver(self.stop_notification, "NotificationClosed", "org.freedesktop.Notifications", "org.freedesktop.Notifications", "/org/freedesktop/Notifications") - #bus.add_signal_receiver(self.handleMissedCall, "Notify", None, None, None) - #bus.add_signal_receiver(self.handleMissedCall, "MembersChanged", None, None, None) - bus.add_signal_receiver(self.smsReceived, "Received", "org.freedesktop.Telepathy.Channel.Type.Text", None, None) - bus.add_signal_receiver(self.smsRead, "NotificationClosed", "org.freedesktop.Notifications", None, "/org/freedesktop/Notifications") - gobject.MainLoop().run() + def startDbusListeners(self): + self.dbg('startDbusListeners started') + DBusGMainLoop(set_as_default=True) + bus = dbus.SessionBus() + + bus.add_signal_receiver(self.notificationClosed, "NotificationClosed", "org.freedesktop.Notifications", None, "/org/freedesktop/Notifications") + bus.add_signal_receiver(self.pendingMessagesRemoved, "PendingMessagesRemoved", None, None, None) + bus.add_signal_receiver(self.newEvent, "NewEvent", None, None, None) + + self.mainLoop = gobject.MainLoop() + self.mainLoop.run() return False - - def smsReceived(self, a, b, c, d, e, f): - if self.missedLastSMS == self.getMissedCallsCount(True): - if self.msgType == "Call": - self.msgType = "Both" - else: - self.msgType = "SMS" - self.show() - self.missedLastSMS = self.getMissedCallsCount(True) - - def smsRead(self, a): - self.stop_notification(a) - - def handleMissedCall(self): - if self.missedLastCall != self.getMissedCallsCount(False): - if self.msgType == "SMS": - self.msgType = "Both" - else: - self.msgType = "Call" - self.show() - self.missedLastCall = self.getMissedCallsCount(False) + + def newEvent(self, a, b, c, d, e, f): + self.dbg('newEvent started') + # On NewEvent the notifications.db is not immediately filled, thus check the event after one minute waiting + self.tmr_main = gobject.timeout_add(60000, self.handleMissed) return True + + def notificationClosed(self, a): + self.dbg('notificationClosed started') + self.stop_notification(a) - def stop_notification(self, a): - self.set_status_area_icon(None) - gobject.source_remove(self.tmr_ptr) - self.set_status_area_icon(None) - # Reset the notification (get recent missed call count) - self.missed = self.getMissedCallsCount(False) - self.missedSMS = self.getMissedCallsCount(True) - self.missedLastCall = self.missed - self.missedLastSMS = self.missedSMS - self.stop = False - self.msgType = "" + def pendingMessagesRemoved(self, a): + self.dbg('pendingMessagesRemoved started') + self.stop_notification(self) - def theLoop(self): - missedCalls = self.getMissedCallsCount(False) - if self.missedLastCall != missedCalls: + def handleMissed(self): + missedCall = self.getMissedCallsCount(False) + missedSMS = self.getMissedCallsCount(True) + self.dbg('Missed CALL: ' + str(missedCall)) + self.dbg('Missed SMS: ' + str(missedSMS)) + + if missedCall and missedSMS: + self.msgType = "Both" + self.dbg('***********handleMissed BOTH started***********: ' + str(missedCall) + str(missedSMS)) + elif missedCall and not missedSMS: + self.msgType = "Call" + self.dbg('***********handleMissed CALL started***********: ' + str(missedCall)) + elif missedSMS and not missedCall: + self.msgType = "SMS" + self.dbg('***********handleMissed SMS started***********: ' + str(missedSMS)) + + if missedCall or missedSMS: self.show() - self.missedLastCall = missedCalls - return True + + # Execute the function only once on NewEvent + return False + + def stop_notification(self, a): + self.dbg('stop_notification started') + try: + self.set_status_area_icon(None) + # Reset the notification (get recent missed call count) + self.stop = False + self.msgType = "" + gobject.source_remove(self.tmr_ptr) + gobject.source_remove(self.tmr_ptr2) + gobject.source_remove(self.tmr_main) + except: + pass - def getMissedCallsCount(self, isSms): - eType = 3 - if isSms: - eType=7 + def getMissedCallsCount(self, isSms): conn = sqlite3.connect(self.path) cur = conn.cursor() - cur.execute("select count(id) from Events where event_type_id = " + str(eType)) - return cur.fetchone()[0] + if isSms: + cur.execute("select count(id) from notifications where icon_name='general_sms'") + else: + cur.execute("select count(id) from notifications where icon_name='general_missed'") + missed = cur.fetchone()[0] - def show(self): + #if isSms: + #self.dbg('get missed SMSs: ' + str(missed)) + #else: + #self.dbg('get missed Calls: ' + str(missed)) + + return missed + + def show(self): + self.dbg('show started') # blink the icon every 1 second if not(self.stop): - self.tmr_ptr = gobject.timeout_add(1000, self.blinkIcon) + self.readConfigurationFile() self.stop = True + if self.visual: + self.tmr_ptr = gobject.timeout_add(1000, self.blinkIcon) + self.tmr_ptr2 = gobject.timeout_add(int(self.interval*1000*60), self.playSound) - def blinkIcon(self): + def blinkIcon(self): + # self.dbg('blinkIcon started') if self.toShow: self.toShow = False img = self.callPicture @@ -126,20 +287,36 @@ class CallNotify(hildondesktop.StatusMenuItem): else: img = self.smsPicture isSMS = False - counter = self.missed if self.msgType == "SMS": - counter = self.missedSMS isSMS = True - index = self.getMissedCallsCount(isSMS) - counter - 1 + index = self.getMissedCallsCount(isSMS) - 1 if index >= 5: index = 5 - if index < 0 - index = 0 + if index < 0: + index = 0 if self.msgType != "Both": img = self.imgList[index] self.toShow = True self.set_status_area_icon(img) return True + + def dbg(self, txt): + if self.Debug: + f = open(self.configDir+'log.txt', 'a') + f.write(str(datetime.datetime.now()) + ': '+ txt) + f.write('\n') + + f.close() hd_plugin_type = CallNotify + +# Uncomment from "if __name__..." to "gtk.main()" if running from CLI as: +# "run-standalone.sh python CallNotify.py" + +#if __name__=="__main__": +# gobject.type_register(hd_plugin_type) +# obj = gobject.new(hd_plugin_type, plugin_id="plugid_id") +# obj.show_all() +# gtk.main() +