From 77c080ef748f67f229486ffdf9c5736823409686 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Pali=20Roh=C3=A1r?= Date: Fri, 22 Jun 2012 15:10:58 +0200 Subject: [PATCH] Import patched yrannadx version from http://talk.maemo.org/showpost.php?p=1164866&postcount=465 Changes: - It uses playbin2 for playing sounds for missed calls and sms, and this means any sound file can be used instead of default one /usr/share/CallNotify/missed.wav - If you want to use separate sound files for missed call, sms and both, you need to copy the attached sound.txt file to /home/user/.config/CallNotify/ directory. The file contain in order: first line is for missed call sound, second line is for missed sms sound and third line is for missed both call and sms sound. Of course you need to change the lines with your own sound files. Last line is volume in the range 0.1-1.0. --- src/usr/lib/hildon-desktop/CallNotify.py | 436 ++++++++++++------------------ 1 file changed, 175 insertions(+), 261 deletions(-) mode change 100755 => 100644 src/usr/lib/hildon-desktop/CallNotify.py diff --git a/src/usr/lib/hildon-desktop/CallNotify.py b/src/usr/lib/hildon-desktop/CallNotify.py old mode 100755 new mode 100644 index 4552a8b..6f81c18 --- a/src/usr/lib/hildon-desktop/CallNotify.py +++ b/src/usr/lib/hildon-desktop/CallNotify.py @@ -1,4 +1,4 @@ -import gtk +import gtk, gst import gobject import hildon, hildondesktop import sqlite3 @@ -8,73 +8,112 @@ 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) # Set members self.configDir = "/home/user/.config/CallNotify/" self.configFile = "conf.txt" - self.Debug = False + self.configSoundFile = "sound.txt" + self.Debug = WriteLog self.dbg("debugging started") - self.readConfigurationFile() - self.msgType = "" + self.msgType = "" self.toShow = True self.stop = False - self.path = "/home/user/.rtcom-eventlogger/el-v1.db" - self.missed = self.getMissedCallsCount(False) - self.missedSMS = self.getMissedCallsCount(True) - self.missedLastCall = self.missed - self.missedLastSMS = self.missedSMS - self.mainLoop = None + 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() - + # Register to handle screen off/on events osso_c = osso.Context("osso_test_device_on", "0.0.1", False) device = osso.DeviceState(osso_c) - #device.set_display_event_cb(self.state_cb) - # Check missed calls notification - self.tmr_main = gobject.timeout_add(5000, self.handleMissedCall) - self.tmrset = True # 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) - #atexit.register(self.cleanup) - # add GUI buttons - # self.addGUI() + if self.Debug: + hildon.hildon_play_system_sound(self.soundFile) self.dbg('constructor end') - def addGUI(self): - # add GUI buttons - label = gtk.Label("Call Notify") - button = gtk.Button() - button.add(label) - button.connect("clicked", self.openSettingsDialog) - self.add(button) - self.show_all() - self.dbg('addGUI end') - - def checkForConfigFile(self): + def checkForConfigFile(self): self.dbg('checkForConfigFile started') os.umask(0) if not os.path.exists(self.configDir): - os.mkdir(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() + 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): + + def readConfigurationFile(self): try: self.dbg('readConfigurationFile started') self.checkForConfigFile() @@ -85,127 +124,44 @@ class CallNotify(hildondesktop.StatusMenuItem): 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 saveConfigurationFile(self): - self.dbg('saveConfigurationFile started') - f = open(self.configDir+self.configFile, "w") - conf = '' - if self.visual: - conf += 'y;' - else: - conf += 'n;' - - if self.sound: - conf += 'y;' - else: - conf +='n;' - - if self.vibration: - conf += 'y;' - else: - conf += 'n;' - - conf += str(self.interval) - - f.write(conf) - f.close() - - def openSettingsDialog(self, widget, data=None): - self.dbg('openSettingsDialog started') - self.dialog = gtk.Dialog(title="Call Notify Settings") - self.dialog.set_size_request(800,300) - #self.dialog.connect("response", self.dialogClosed) - self.readConfigurationFile() - # Visual - - b2 = gtk.CheckButton(label="Visual Notification On") - b2.connect("clicked", self.notificationActivate) - b2.set_active(self.visual) - self.dialog.vbox.add(b2) - - # Sound - - b3 = gtk.CheckButton(label="Sound Notification On") - b3.connect("clicked", self.soundActivate) - b3.set_active(self.sound) - self.dialog.vbox.add(b3) - - # Vibration - - b4 = gtk.CheckButton(label="Vibrate Notification On") - b4.connect("clicked", self.vibrateActivate) - b4.set_active(self.vibration) - self.dialog.vbox.add(b4) - - # Slider - - Adj = gtk.Adjustment(self.interval, lower=0, upper=60, step_incr=5, page_incr=5) - Adj.connect("value_changed", self.intervalChanged) - Adj.set_value(self.interval) - - Slider = gtk.HScale(adjustment=Adj) - self.dialog.vbox.add(Slider) - - # Manual reset - - b5 = gtk.Button(label="Manually reset notification") - b5.connect("clicked", self.resetNotification) - self.dialog.vbox.add(b5) - - # Save Button - - bSave = gtk.Button(label="Save") - bSave.connect("clicked", self.saveSettings) - self.dialog.action_area.add(bSave) - - # Cancel Button - - bCancel = gtk.Button(label="Cancel") - bCancel.connect("clicked", self.cancelDialog) - self.dialog.vbox.add(bCancel) - - self.dialog.show_all() - - def intervalChanged(self, adj): - self.dbg('intervalChanged started') - self.interval = adj.value - - def saveSettings(self, widget, data=None): - self.dbg('saveSettings started') - self.saveConfigurationFile() - - def dialogClosed(self, dialog, response_id): - self.dbg('dialogClosed started') - - def cancelDialog(self, widget, data=None): - self.dbg('cancelDialog started') - self.dialog.destroy() - - def resetNotification(self, widget, data=None): - self.dbg('resetNotification started') - self.stop_notification(self) - - def soundActivate(self, widget, data=None): - self.dbg('soundActivate started') - self.sound = widget.get_active() #not(self.sound) - - def notificationActivate(self,widget, data=None): - self.dbg('notificationActivate started') - self.visual = widget.get_active() #not(self.visual) - - def vibrateActivate(self, widget, data=None): - self.dbg('vibrateActivate started') - self.vibration = widget.get_active() #not(self.vibrate) - - - def playSound(self): + def playSound(self): self.dbg('playSound started') if self.sound: - hildon.hildon_play_system_sound(self.soundFile) - #pygame.time.delay(1000) + # 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) + 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) @@ -216,27 +172,14 @@ class CallNotify(hildondesktop.StatusMenuItem): b.close() return True - - def cleanup(self): - self.dbg('cleanup started') - gobject.source_remove(self.tmr_main) - gobject.source_remove(self.tmr_ptr) - gobject.source_remove(self.tmr_ptr2) - - self.mainLoop.quit() - - def loadImages(self): + def loadImages(self): self.dbg('loadImages started') - # Load phone image - #self.pixbuf = gtk.gdk.pixbuf_new_from_file_at_size("/home/user/phone.png",18,18) icon_theme = gtk.icon_theme_get_default() self.callPicture = gtk.gdk.pixbuf_new_from_file_at_size("/usr/share/CallNotify/call.png",18,18) - #icon_theme.load_icon("general_call", 18, gtk.ICON_LOOKUP_NO_SVG) 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)) @@ -244,112 +187,85 @@ 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)) - # Screen off event-handler - def state_cb(self, state, a): - self.dbg('state_cb started') - if state == osso.device_state.OSSO_DISPLAY_OFF: - try: - #gobject.source_remove(self.tmr_main) - self.tmrset = False - #gobject.source_remove(self.tmr_ptr) - - #gobject.source_remove(self.tmr_ptr2) - except: - pass - elif state == osso.device_state.OSSO_DISPLAY_ON: - if not tmrset: - pass - #self.tmr_main = gobject.timeout_add(5000, self.handleMissedCall) - #self.handleMissedCall() - return False - - # Method to define the way to add dbus signal receiver - - def smsRead2(self, a): - self.dbg('smsrec started') - self.stop_notification(self) - - def startDbusListeners(self): + def startDbusListeners(self): self.dbg('startDbusListeners started') - 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, "MessageReceived", None, None, None) - bus.add_signal_receiver(self.smsRead, "NotificationClosed", "org.freedesktop.Notifications", None, "/org/freedesktop/Notifications") - bus.add_signal_receiver(self.smsRead2, "PendingMessagesRemoved", None, None, None) + DBusGMainLoop(set_as_default=True) + bus = dbus.SessionBus() - self.mainLoop = gobject.MainLoop() - self.mainLoop.run() + 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): - self.dbg('snsReceived started') - if a[0].has_key('message-type'): - 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.dbg('smsRead started') + + 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 handleMissedCall(self): - self.dbg('handleMissedCall started') - #self.dbg('self.missedLastCall: ' + self.missedLastCall) - #self.dbg('self.getMissedCallsCount(False): ' + self.getMissedCallsCount(False)) - if self.missedLastCall != self.getMissedCallsCount(False): - if self.msgType == "SMS": - self.msgType = "Both" - else: - self.msgType = "Call" + def pendingMessagesRemoved(self, a): + self.dbg('pendingMessagesRemoved started') + self.stop_notification(self) + + 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 = self.getMissedCallsCount(False) - return True - - def stop_notification(self, a): + + # 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.missed = self.getMissedCallsCount(False) - self.missedSMS = self.getMissedCallsCount(True) - self.missedLastCall = self.missed - self.missedLastSMS = self.missedSMS 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): + conn = sqlite3.connect(self.path) + cur = conn.cursor() + 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 theLoop(self): - self.dbg('theLoop started') - missedCalls = self.getMissedCallsCount(False) - if self.missedLastCall != missedCalls: - self.show() - self.missedLastCall = missedCalls - return True - - def getMissedCallsCount(self, isSms): - self.dbg('getMissedCallsCount started. agrs: ' + str(isSms)) - conn = sqlite3.connect(self.path) - cur = conn.cursor() - if isSms: - #Nokia changed the event number from 7 to 11 and also combined the incomming and outgoing sms's - cur.execute("select count(id) from Events where event_type_id = 7 and outgoing = 0") - else: - #Nokia changed the event from 3 to 2 - cur.execute("select count(id) from Events where event_type_id = 3 and outgoing = 0") - return cur.fetchone()[0] + #if isSms: + #self.dbg('get missed SMSs: ' + str(missed)) + #else: + #self.dbg('get missed Calls: ' + str(missed)) + + return missed - def show(self): + def show(self): self.dbg('show started') # blink the icon every 1 second if not(self.stop): @@ -359,8 +275,8 @@ class CallNotify(hildondesktop.StatusMenuItem): 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): - self.dbg('blinkIcon started') + def blinkIcon(self): + # self.dbg('blinkIcon started') if self.toShow: self.toShow = False img = self.callPicture @@ -371,22 +287,20 @@ 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): + def dbg(self, txt): if self.Debug: f = open(self.configDir+'log.txt', 'a') f.write(str(datetime.datetime.now()) + ': '+ txt) -- 1.7.9.5