From: user Date: Mon, 27 Jun 2011 14:38:22 +0000 (+0300) Subject: init commit X-Git-Url: http://git.maemo.org/git/?p=profile-appoint;a=commitdiff_plain;h=c0b4e4bd7424ac8e2eccce0203a9b7b2bb6cb57a;ds=sidebyside init commit --- diff --git a/debug.py b/debug.py new file mode 100755 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 index 0000000..d392f45 --- /dev/null +++ b/makeprofile-appointments.py @@ -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 index 0000000..0cc3850 --- /dev/null +++ b/profile-appointments.desktop @@ -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 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 index 0000000..ecdc076 --- /dev/null +++ b/profile-appointments.py @@ -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 index 0000000..c24201c --- /dev/null +++ b/profile-appointments.sudoers @@ -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 index 0000000..0e63b4b --- /dev/null +++ b/profile-appointments_0.0.1-1.changes @@ -0,0 +1,18 @@ +Maintainer: Niv Waizer +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 +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 index 0000000..72c8dd5 --- /dev/null +++ b/profile-appointments_0.0.1-1.dsc @@ -0,0 +1,10 @@ +Source: profile-appointments +Version: 0.0.1-1 +Maintainer: Niv Waizer +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 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 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 index 0000000..9a54242 --- /dev/null +++ b/switch_backend @@ -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 index 0000000..3b73fe0 --- /dev/null +++ b/switch_backend.py @@ -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()