init commit master
authoruser <user@mishmish.(none)>
Mon, 27 Jun 2011 14:38:22 +0000 (17:38 +0300)
committeruser <user@mishmish.(none)>
Mon, 27 Jun 2011 14:38:22 +0000 (17:38 +0300)
12 files changed:
debug.py [new file with mode: 0755]
makeprofile-appointments.py [new file with mode: 0755]
profile-appointments.desktop [new file with mode: 0644]
profile-appointments.png [new file with mode: 0644]
profile-appointments.py [new file with mode: 0755]
profile-appointments.sudoers [new file with mode: 0644]
profile-appointments_0.0.1-1.changes [new file with mode: 0644]
profile-appointments_0.0.1-1.dsc [new file with mode: 0644]
profile-appointments_0.0.1-1.tar.gz [new file with mode: 0644]
profile-appointments_0.0.1-1_all.deb [new file with mode: 0644]
switch_backend [new file with mode: 0755]
switch_backend.py [new file with mode: 0755]

diff --git a/debug.py b/debug.py
new file mode 100755 (executable)
index 0000000..16c7db2
--- /dev/null
+++ b/debug.py
@@ -0,0 +1,20 @@
+import os,time
+
+if os.path.exists("/tmp/switch.debug"):
+if True:
+    enable_logging = True
+else:
+    enable_logging = False
+
+if enable_logging and not 'fd' in locals():
+    fd = open('/tmp/switch.log','w+')
+else:
+    fd = None
+
+def debug(*input):
+    if enable_logging:
+               now = str(time.time())
+               print now+str(input)
+               print >>fd,now+str(input)
+               fd.flush()
+
diff --git a/makeprofile-appointments.py b/makeprofile-appointments.py
new file mode 100755 (executable)
index 0000000..d392f45
--- /dev/null
@@ -0,0 +1,75 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+## 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; version 2 only.
+##
+## 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.
+##
+import pypackager
+import os
+
+if __name__ == "__main__":
+    try:
+        os.chdir(os.path.dirname(sys.argv[0]))
+    except:
+        pass
+
+    p=pypackager.PyPackager("profile-appointments")
+    p.version='0.0.1'
+    p.buildversion='1'
+    p.display_name='profile-appointments'
+    p.description="widget to switch profile to silent when a meeting is in progress , and switch back to general afterward"
+    p.author="Niv Waizer"
+    p.maintainer="Niv Waizer"
+    p.email="nivwiz@gmail.com"
+    p.depends = "python-hildon (>= 0.9.0-1maemo15), python-hildondesktop (>= 0.1.0-1maemo3), python-gtk2 (>= 2.12.1-6maemo10), python-gobject (>= 2.16), hildon-desktop-python-loader (>= 0.1.0-1maemo3), python-dbus, sudo, python, python-support (>= 0.90.0), python2.5, python-dbus, python-mafw"
+    p.section="user/development"
+    p.arch="all"
+    p.urgency="extra"
+    p.bugtracker='http://unknown'
+    p.distribution="fremantle"
+    p.repository="extras-devel"
+    p.icon='profile-appointments.png'
+    p["/etc/init.d"] = ["switch_backend",]
+    p["/usr/lib/hildon-desktop"] = ["profile-appointments.py",]
+    p["/usr/lib/switchProfByMeeting"] = ["debug.py", "switch_backend.py",]
+    p["/usr/share/icons/hicolor/32x32/hildon"] = ["profile-appointments.png",]
+    p["/etc/sudoers.d"] = ["profile-appointments.sudoers",]
+    p["/usr/share/applications/hildon-status-menu"] = ["profile-appointments.desktop",]
+    
+    p.postinstall = """#!/bin/sh
+update-sudoers || true
+
+gtk-update-icon-cache /usr/share/icons/hicolor/
+
+#chmod 755".join(p['/usr/...']
+for file in /etc/init.d/switch_backend /usr/lib/switchProfByMeeting/switch_backend.py ; do
+chmod 755 $file
+done
+for file in /usr/share/applications/hildon-status-menu/profile-appointments.desktop /usr/lib/hildon-desktop/profile-appointments.py ; do
+chmod 644 $file
+chown root:root $file
+done
+#Force applet reloading to get the icon
+  echo "Reloading switchByProfile"
+  TMPFILE=`mktemp /tmp/temp.XXXXXX`
+  mv /usr/share/applications/hildon-status-menu/profile-appointments.desktop $TMPFILE
+  sleep 2
+  mv $TMPFILE /usr/share/applications/hildon-status-menu/profile-appointments.desktop
+  rm -f $TMPFILE
+
+# Automatically added by dh_pysupport
+#if which update-python-modules >/dev/null 2>&1; then
+#        update-python-modules  openvpn-applet.private
+#fi
+exit 0
+"""
+
+    p.changelog="""First Release
+"""
+
+print p.generate(build_binary=True,build_src=True)
diff --git a/profile-appointments.desktop b/profile-appointments.desktop
new file mode 100644 (file)
index 0000000..0cc3850
--- /dev/null
@@ -0,0 +1,5 @@
+[Desktop Entry]
+Name=switch profile by meeting
+#Comment=Example Status Menu Python plugin
+Type=python
+X-Path=profile-appointments.py
diff --git a/profile-appointments.png b/profile-appointments.png
new file mode 100644 (file)
index 0000000..68f39af
Binary files /dev/null and b/profile-appointments.png differ
diff --git a/profile-appointments.py b/profile-appointments.py
new file mode 100755 (executable)
index 0000000..ecdc076
--- /dev/null
@@ -0,0 +1,71 @@
+#!/usr/bin/env python
+
+import hildon, gtk
+import hildondesktop
+import commands
+
+class ExampleStatusPlugin(hildondesktop.StatusMenuItem):
+       def __init__(self):
+               hildondesktop.StatusMenuItem.__init__(self)
+
+               self.backend_started =  self.status_backend()
+
+               self.button_title_text = "profile-appointments"
+               self.button = hildon.Button(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
+               self.button.set_style(hildon.BUTTON_STYLE_PICKER)
+               self.button.set_alignment(0.2,0.5,1,1)
+               image = gtk.image_new_from_icon_name("profile-appointments", gtk.ICON_SIZE_BUTTON)
+               self.button.set_image(image)
+               self.button.set_image_position(gtk.POS_LEFT)
+               self.button.connect("clicked", self.button_clicked_event)
+
+               icon_theme = gtk.icon_theme_get_default()
+               self.pixbuf = icon_theme.load_icon("profile-appointments", 22, gtk.ICON_LOOKUP_NO_SVG)
+
+               self.add(self.button)
+               self.show_all()
+               self.update_button()
+
+       def status_backend(self):
+               """is backend running?"""
+               return commands.getoutput('pgrep switch_backend')
+
+       def button_clicked_event(self,*args):
+               if self.backend_started:
+                       self.stop_backend()
+               else:
+                       self.start_backend()
+               self.update_button()
+
+       def update_button(self):
+               """Update the start/stop button to reflect current state"""
+               if self.backend_started:
+                       self.button.set_text(self.button_title_text,'Stop')
+                       self.set_status_area_icon(self.pixbuf)
+               else:
+                       self.button.set_text(self.button_title_text,'Start')
+                       self.set_status_area_icon(None)
+       
+       def start_backend(self):
+               """calls backend start"""
+               (exitstatus, outtext) = commands.getstatusoutput("""/etc/init.d/switch_backend start""")
+               if exitstatus <> 0:
+                       print "DEBUG: backend start exit code " + str(status) + ", output: \n"
+                       note = hildon.hildon_note_new_information(self.mainwindow, 'profile-appointments failed to start')
+                       response = gtk.Dialog.run(note)
+                       note.destroy()
+                       return
+               self.backend_started = True
+
+       def stop_backend(self):
+               """kills backend"""
+               (exitstatus, outtext) = commands.getstatusoutput("""/etc/init.d/switch_backend stop""")
+               if exitstatus <> 0:
+                       print "DEBUG: backend start exit code " + str(status) + ", output: \n"
+                       note = hildon.hildon_note_new_information(self.mainwindow, 'profile-appointments failed to start')
+                       response = gtk.Dialog.run(note)
+                       note.destroy()
+                       return
+               self.backend_started = False
+
+hd_plugin_type = ExampleStatusPlugin
diff --git a/profile-appointments.sudoers b/profile-appointments.sudoers
new file mode 100644 (file)
index 0000000..c24201c
--- /dev/null
@@ -0,0 +1 @@
+user ALL = NOPASSWD: /etc/init.d/switch_backend
diff --git a/profile-appointments_0.0.1-1.changes b/profile-appointments_0.0.1-1.changes
new file mode 100644 (file)
index 0000000..0e63b4b
--- /dev/null
@@ -0,0 +1,18 @@
+Maintainer: Niv Waizer <nivwiz@gmail.com>
+Format: 1.7
+Source: profile-appointments
+Version: 0.0.1-1
+Architecture: all
+Date: Mon, 27 Jun 2011 04:33:49 +0000
+Distribution: fremantle
+Urgency: extra
+Description: 
+ widget to switch profile to silent when a meeting is in progress , and switch back to general afterward
+Changes: 
+   First Release
+Changed-By: Niv Waizer <nivwiz@gmail.com>
+Files:
+ 9da9e14fd9c6b4780bd0a7e9f60fc18a 10792 user/development extras-devel profile-appointments_0.0.1-1.tar.gz
+ 08ab4b189d654976ce09cc3334113ddd 520 user/development extras-devel profile-appointments_0.0.1-1.dsc
+
diff --git a/profile-appointments_0.0.1-1.dsc b/profile-appointments_0.0.1-1.dsc
new file mode 100644 (file)
index 0000000..72c8dd5
--- /dev/null
@@ -0,0 +1,10 @@
+Source: profile-appointments
+Version: 0.0.1-1
+Maintainer: Niv Waizer <nivwiz@gmail.com>
+Architecture: all
+Format: 1.0
+Build-Depends: python-hildon (>= 0.9.0-1maemo15), python-hildondesktop (>= 0.1.0-1maemo3), python-gtk2 (>= 2.12.1-6maemo10), python-gobject (>= 2.16), hildon-desktop-python-loader (>= 0.1.0-1maemo3), python-dbus, sudo, python, python-support (>= 0.90.0), python2.5, python-dbus, python-mafw
+Standards-Version: 0.0.1-1
+Files:
+ 9da9e14fd9c6b4780bd0a7e9f60fc18a 10792 profile-appointments_0.0.1-1.tar.gz
+
diff --git a/profile-appointments_0.0.1-1.tar.gz b/profile-appointments_0.0.1-1.tar.gz
new file mode 100644 (file)
index 0000000..857f1f0
Binary files /dev/null and b/profile-appointments_0.0.1-1.tar.gz differ
diff --git a/profile-appointments_0.0.1-1_all.deb b/profile-appointments_0.0.1-1_all.deb
new file mode 100644 (file)
index 0000000..2add4af
Binary files /dev/null and b/profile-appointments_0.0.1-1_all.deb differ
diff --git a/switch_backend b/switch_backend
new file mode 100755 (executable)
index 0000000..9a54242
--- /dev/null
@@ -0,0 +1,63 @@
+#!/bin/sh
+# 
+#set -x
+prefix=/usr/lib/switchProfByMeeting
+PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/bin/X11:$prefix
+#exec_prefix=${prefix}
+#sbindir=${exec_prefix}/sbin
+NAME=switch_backend
+DAEMON=${prefix}/switch_backend.py
+USER=user
+DESC="switch profile by meeting"
+unset USE_UPSTART
+#INITCTL=/sbin/initctl
+ACTION=$1
+test -x $DAEMON || exit 0
+
+kill_deamon()
+{
+ps ax |grep $NAME |grep -v grep|grep -v init|awk '{print $1}'|while read pid 
+do kill $pid 
+done 
+}
+
+case "$ACTION" in
+  start)
+       echo "before"
+       kill_deamon
+       echo "after"
+       echo -n "Starting $DESC: "
+       start-stop-daemon --start --quiet -c $USER \
+               --background --exec "$DAEMON"
+       if test $? == 0
+       then
+           echo "$NAME"
+       fi
+       ;;
+  stop)
+       echo -n "Stopping $DESC: "
+               start-stop-daemon --stop --quiet --oknodo --user $USER \
+               --exec "$DAEMON"
+       if test $? == 0
+       then
+           echo "$NAME"
+       fi
+       kill_deamon
+       ;;
+  reload|restart|force-reload)
+       #
+       #       If the "reload" option is implemented, move the "force-reload"
+       #       option to the "reload" entry above. If not, "force-reload" is
+       #       just the same as "restart".
+       #
+       "$0" stop
+       "$0" start
+       ;;
+  *)
+       N=/etc/init.d/$NAME
+       echo "Usage: $N {start|stop|restart|force-reload}" >&2
+       exit 1
+       ;;
+esac
+
+exit 0
diff --git a/switch_backend.py b/switch_backend.py
new file mode 100755 (executable)
index 0000000..3b73fe0
--- /dev/null
@@ -0,0 +1,159 @@
+#!/usr/bin/run-standalone.sh python2.5
+
+# Import global modules
+import sys, traceback, gobject, dbus, dbus.mainloop.glib ,os , subprocess 
+import time, sqlite3,mafw
+sys.path.insert(0, '/usr/lib/switchProfByMeeting')
+import debug
+debug = debug.debug
+
+sys.path.insert(0, '/home/user')
+dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+
+class backend:
+       def __init__( self ):
+               #debug( 'init' )
+               self.bus = dbus.SessionBus()
+               self.sleep_duration = 10000
+               self.timeout_id = None
+               self.loop = None
+               
+               try:
+                       self.profiled_object = self.bus.get_object( 'com.nokia.profiled', '/com/nokia/profiled' )
+                       self.calender_object = self.bus.get_object( 'com.nokia.calendar', '/com/nokia/calendar' )
+                       self.calender_object.connect_to_signal( 'dbChange', \
+                       self.calender_changed, dbus_interface = 'com.nokia.calendar' )
+                       self.mafw_object = self.bus.get_object( \
+                       'com.nokia.mafw.renderer.Mafw-Gst-Renderer-Plugin.gstrenderer' \
+                       ,'/com/nokia/mafw/renderer/gstrenderer' )
+               except dbus.DBusException:
+                       traceback.print_exc()
+                       sys.exit(1)
+
+               self.start()
+
+       def set_profile( self, prof ):
+               debug ('in set_profile with '+prof)
+               #save speaker volume as profile change effects it
+               volume_level = self.mafw_object.get_extension_property( 'volume' \
+               , dbus_interface = 'com.nokia.mafw.extension')[1]
+               self.profiled_object.set_profile(prof, dbus_interface='com.nokia.profiled')
+               #restore volume level due to profile change
+               retcode = subprocess.call("dbus-send --type=method_call \
+               --dest=com.nokia.mafw.renderer.Mafw-Gst-Renderer-Plugin.gstrenderer \
+               /com/nokia/mafw/renderer/gstrenderer \
+               com.nokia.mafw.extension.set_extension_property \
+               string:volume variant:uint32:%d"%volume_level, shell=True)
+               if retcode != 0:
+                       raise SystemExit('got error code '+str(retcode)+' when setting volume')
+
+       def is_meeting_now( self ):
+               cal_db = sqlite3.connect(os.path.expanduser("~/.calendar/calendardb"))
+               query = "SELECT Summary FROM Components WHERE ComponentType='1' \
+               AND AllDay='0' AND strftime('%s','now') >= DateStart AND \
+               strftime('%s','now') < DateEnd limit 1"
+               ans = cal_db.execute(query).fetchone()
+               debug( 'is_meeting_now returns: '+str(ans) )
+               return ans
+
+       def when_next_meeting( self ):
+               cal_db = sqlite3.connect(os.path.expanduser("~/.calendar/calendardb"))  
+               query = "SELECT DateStart FROM Components WHERE ComponentType='1' \
+               and AllDay='0' and strftime('%s','now') < DateStart AND \
+               DateStart < DateEnd ORDER BY DateStart limit 1"
+       #here is the place to make sure the meeting is leagal non zero duration and event 
+               ans = cal_db.execute(query).fetchone()
+               if ans != None:
+                       next_timeout = ans [0]
+               else:
+                       next_timeout = None
+               debug( 'when_next_meeting returns: '+str(next_timeout) )
+               return next_timeout
+               
+       def when_end_of_meeting( self ):
+               cal_db = sqlite3.connect(os.path.expanduser("~/.calendar/calendardb"))  
+               query = "SELECT DateEnd FROM Components WHERE ComponentType='1' \
+               and AllDay='0' and strftime('%s','now') < DateEnd and \
+               DateStart < DateEnd ORDER BY DateEnd limit 1"
+               #I also need to adress overlapping meetings that the other finishes later
+               next_timeout = cal_db.execute(query).fetchone() [0]
+               debug( 'when_end_of_meeting returns: ' +str(next_timeout) )
+               return next_timeout
+               
+       def calc_next_duration( self, next_meeting_time ):
+               if next_meeting_time != None:
+                       self.sleep_duration = int ((next_meeting_time - time.time())*1000)
+               else:
+                       self.sleep_duration = 5000
+               debug("calc_next_duration returns: "+str(self.sleep_duration))
+                       
+       def set_timer( self, current_profile ):
+               if current_profile == 'general' :
+                       self.calc_next_duration( self.when_next_meeting() )
+               else :
+                       self.calc_next_duration( self.when_end_of_meeting() )
+                       
+       def calender_changed( self, arg1 , arg2 ):
+               debug('calender_changed called with arg1: '+arg1+' arg2: '+arg2 )
+               self.remove_timeout()
+               self.update_profile()
+               self.mainloop()
+               debug ('end of calender_changed')
+               
+       def timer_callback( self ):
+               debug('timer_callback timeout_id: '+str(self.timeout_id))
+               self.remove_timeout()
+               self.update_profile()
+               self.mainloop()
+               #commented by merlin 1991 advice self.mainloop()
+               debug('end of timer_callback')
+                       
+       def remove_timeout( self ):
+               debug ( 'remove timeout called' )
+               if self.timeout_id != None:
+                       gobject.source_remove(self.timeout_id)
+                       debug( 'removed timeout: '+str(self.timeout_id) )
+
+       def update_profile( self ):
+               debug ( 'begining of update_profile' )
+               if self.is_meeting_now() :
+                       self.set_profile( 'silent' )
+                       self.set_timer( 'silent' )
+               else:
+                       self.set_profile( 'general' )
+                       self.set_timer( 'general' )
+                       
+       def mainloop( self ):
+               debug('going to run loop with sleep_duration: '+str(self.sleep_duration))
+               self.timeout_id = gobject.timeout_add(self.sleep_duration, self.timer_callback )
+               debug( ' new timeou_id is: '+str(self.timeout_id) )
+
+               if self.loop == None :
+                       self.loop = gobject.MainLoop()
+                       self.loop.run()
+                       debug('new loop started')
+               debug ('end of mainloop')
+               
+       def start ( self ):
+               ''' update the profile and set a timer loop'''
+               debug( 'starting' )
+               self.update_profile()
+               self.mainloop()
+               
+       def stop_mainloop( self ):
+               ''' stop nain loop'''
+               debug( 'stopping main loop' )
+               if self.loop != None and self.loop.is_running():
+                       self.loop.quit()
+               
+       def status( self ):
+               '''check the status of the switch backend'''
+               if self.loop != None:
+                       status = self.loop.is_running()
+               else:
+                       status = None
+               debug( 'status is: '+status)
+               return status
+
+if __name__ == "__main__":
+       backend = backend()