[gnome-clocks] Import a copy of pycanberra and use it



commit eb420bb7c15b44230913c270c355271bfddbc054
Author: Paolo Borelli <pborelli gnome org>
Date:   Wed Aug 22 18:28:58 2012 +0200

    Import a copy of pycanberra and use it
    
    Import a copy if pycanberra (https://github.com/psykoyiko/pycanberra)
    in the repository and use it to play the alert sound.
    I do not particularly like this solution, but canberra is not
    introspectable and the alternatives are even worse (e.g. spawining
    canberra-gtk-play in the background or writing our own C module).

 gnomeclocks/clocks.py     |    2 +-
 gnomeclocks/pycanberra.py |  614 +++++++++++++++++++++++++++++++++++++++++++++
 gnomeclocks/utils.py      |   13 +-
 3 files changed, 621 insertions(+), 8 deletions(-)
---
diff --git a/gnomeclocks/clocks.py b/gnomeclocks/clocks.py
index 0fb02ac..17e3308 100644
--- a/gnomeclocks/clocks.py
+++ b/gnomeclocks/clocks.py
@@ -465,7 +465,7 @@ class Timer(Clock):
         self.timer_screen.timerLabel.set_markup(TIMER_LABEL_MARKUP %
                                                 (hours, minutes, seconds))
         if hours == 00 and minutes == 00 and seconds == 00:
-            self.alert.do_alert("Ta Da !")
+            self.alert.do_alert("Ta Da !", "complete")
             self.state = Timer.State.STOPPED
             self.timerbox.remove(self.timer_screen)
             self.show_timer_welcome_screen()
diff --git a/gnomeclocks/pycanberra.py b/gnomeclocks/pycanberra.py
new file mode 100644
index 0000000..36a0245
--- /dev/null
+++ b/gnomeclocks/pycanberra.py
@@ -0,0 +1,614 @@
+from ctypes import *
+import exceptions
+import time
+
+# /**
+#  * CA_PROP_MEDIA_NAME:
+#  *
+#  * A name describing the media being played. Localized if possible and applicable.
+#  */
+CA_PROP_MEDIA_NAME = "media.name"
+
+# /**
+#  * CA_PROP_MEDIA_TITLE:
+#  *
+#  * A (song) title describing the media being played. Localized if possible and applicable.
+#  */
+CA_PROP_MEDIA_TITLE = "media.title"
+
+# /**
+#  * CA_PROP_MEDIA_ARTIST:
+#  *
+#  * The artist of this media. Localized if possible and applicable.
+#  */
+CA_PROP_MEDIA_ARTIST = "media.artist"
+
+# /**
+#  * CA_PROP_MEDIA_LANGUAGE:
+#  *
+#  * The language this media is in, in some standard POSIX locale string, such as "de_DE".
+#  */
+CA_PROP_MEDIA_LANGUAGE = "media.language"
+
+# /**
+#  * CA_PROP_MEDIA_FILENAME:
+#  *
+#  * The file name this media was or can be loaded from.
+#  */
+CA_PROP_MEDIA_FILENAME = "media.filename"
+
+# /**
+#  * CA_PROP_MEDIA_ICON:
+#  *
+#  * An icon for this media in binary PNG format.
+#  */
+CA_PROP_MEDIA_ICON = "media.icon"
+
+# /**
+#  * CA_PROP_MEDIA_ICON_NAME:
+#  *
+#  * An icon name as defined in the XDG icon naming specifcation.
+#  */
+CA_PROP_MEDIA_ICON_NAME = "media.icon_name"
+
+# /**
+#  * CA_PROP_MEDIA_ROLE:
+#  *
+#  * The "role" this media is played in. For event sounds the string
+#  * "event". For other cases strings like "music", "video", "game", ...
+#  */
+CA_PROP_MEDIA_ROLE = "media.role"
+
+# /**
+#  * CA_PROP_EVENT_ID:
+#  *
+#  * A textual id for an event sound, as mandated by the XDG sound naming specification.
+#  */
+CA_PROP_EVENT_ID = "event.id"
+
+# /**
+#  * CA_PROP_EVENT_DESCRIPTION:
+#  *
+#  * A descriptive string for the sound event. Localized if possible and applicable.
+#  */
+CA_PROP_EVENT_DESCRIPTION = "event.description"
+ 
+# /**
+#  * CA_PROP_EVENT_MOUSE_X:
+#  *
+#  * If this sound event was triggered by a mouse input event, the X
+#  * position of the mouse cursor on the screen, formatted as string.
+#  */
+CA_PROP_EVENT_MOUSE_X = "event.mouse.x"
+ 
+# /**
+#  * CA_PROP_EVENT_MOUSE_Y:
+#  *
+#  * If this sound event was triggered by a mouse input event, the Y
+#  * position of the mouse cursor on the screen, formatted as string.
+#  */
+CA_PROP_EVENT_MOUSE_Y = "event.mouse.y"
+ 
+# /**
+#  * CA_PROP_EVENT_MOUSE_HPOS:
+#  *
+#  * If this sound event was triggered by a mouse input event, the X
+#  * position of the mouse cursor as fractional value between 0 and 1,
+#  * formatted as string, 0 reflecting the left side of the screen, 1
+#  * the right side.
+#  */
+CA_PROP_EVENT_MOUSE_HPOS = "event.mouse.hpos"
+ 
+# /**
+#  * CA_PROP_EVENT_MOUSE_VPOS:
+#  *
+#  * If this sound event was triggered by a mouse input event, the Y
+#  * position of the mouse cursor as fractional value between 0 and 1,
+#  * formatted as string, 0 reflecting the top end of the screen, 1
+#  * the bottom end.
+#  */
+CA_PROP_EVENT_MOUSE_VPOS = "event.mouse.vpos"
+ 
+# /**
+#  * CA_PROP_EVENT_MOUSE_BUTTON:
+#  *
+#  * If this sound event was triggered by a mouse input event, the
+#  * number of the mouse button that triggered it, formatted as string. 1
+#  * for left mouse button, 3 for right, 2 for middle.
+#  */
+CA_PROP_EVENT_MOUSE_BUTTON = "event.mouse.button"
+ 
+# /**
+#  * CA_PROP_WINDOW_NAME:
+#  *
+#  * If this sound event was triggered by a window on the screen, the
+#  * name of this window as human readable string.
+#  */
+CA_PROP_WINDOW_NAME = "window.name"
+ 
+# /**
+#  * CA_PROP_WINDOW_ID:
+#  *
+#  * If this sound event was triggered by a window on the screen, some
+#  * identification string for this window, so that the sound system can
+#  * recognize specific windows.
+#  */
+CA_PROP_WINDOW_ID = "window.id"
+ 
+# /**
+#  * CA_PROP_WINDOW_ICON:
+#  *
+#  * If this sound event was triggered by a window on the screen, binary
+#  * icon data in PNG format for this window.
+#  */
+CA_PROP_WINDOW_ICON = "window.icon"
+ 
+# /**
+#  * CA_PROP_WINDOW_ICON_NAME:
+#  *
+#  * If this sound event was triggered by a window on the screen, an
+#  * icon name for this window, as defined in the XDG icon naming
+#  * specification.
+#  */
+CA_PROP_WINDOW_ICON_NAME = "window.icon_name"
+ 
+# /**
+#  * CA_PROP_WINDOW_X:
+#  *
+#  * If this sound event was triggered by a window on the screen, the X
+#  * position of the window measured from the top left corner of the
+#  * screen to the top left corner of the window.
+#  *
+#  * Since: 0.17
+#  */
+CA_PROP_WINDOW_X = "window.x"
+ 
+# /**
+#  * CA_PROP_WINDOW_Y:
+#  *
+#  * If this sound event was triggered by a window on the screen, the y
+#  * position of the window measured from the top left corner of the
+#  * screen to the top left corner of the window.
+#  *
+#  * Since: 0.17
+#  */
+CA_PROP_WINDOW_Y = "window.y"
+ 
+# /**
+#  * CA_PROP_WINDOW_WIDTH:
+#  *
+#  * If this sound event was triggered by a window on the screen, the
+#  * pixel width of the window.
+#  *
+#  * Since: 0.17
+#  */
+CA_PROP_WINDOW_WIDTH = "window.width"
+ 
+# /**
+#  * CA_PROP_WINDOW_HEIGHT:
+#  *
+#  * If this sound event was triggered by a window on the screen, the
+#  * pixel height of the window.
+#  *
+#  * Since: 0.17
+#  */
+CA_PROP_WINDOW_HEIGHT = "window.height"
+ 
+# /**
+#  * CA_PROP_WINDOW_HPOS:
+#  *
+#  * If this sound event was triggered by a window on the screen, the X
+#  * position of the center of the window as fractional value between 0
+#  * and 1, formatted as string, 0 reflecting the left side of the
+#  * screen, 1 the right side.
+#  *
+#  * Since: 0.17
+#  */
+CA_PROP_WINDOW_HPOS = "window.hpos"
+ 
+# /**
+#  * CA_PROP_WINDOW_VPOS:
+#  *
+#  * If this sound event was triggered by a window on the screen, the Y
+#  * position of the center of the window as fractional value between 0
+#  * and 1, formatted as string, 0 reflecting the top side of the
+#  * screen, 1 the bottom side.
+#  *
+#  * Since: 0.17
+#  */
+CA_PROP_WINDOW_VPOS = "window.vpos"
+ 
+# /**
+#  * CA_PROP_WINDOW_DESKTOP:
+#  *
+#  * If this sound event was triggered by a window on the screen and the
+#  * windowing system supports multiple desktops, a comma seperated list
+#  * of indexes of the desktops this window is visible on. If this
+#  * property is an empty string, it is visible on all desktops
+#  * (i.e. 'sticky'). The first desktop is 0. (e.g. "0,2,3")
+#  *
+#  * Since: 0.18
+#  */
+CA_PROP_WINDOW_DESKTOP = "window.desktop"
+ 
+# /**
+#  * CA_PROP_WINDOW_X11_DISPLAY:
+#  *
+#  * If this sound event was triggered by a window on the screen and the
+#  * windowing system is X11, the X display name of the window (e.g. ":0").
+#  */
+CA_PROP_WINDOW_X11_DISPLAY = "window.x11.display"
+ 
+# /**
+#  * CA_PROP_WINDOW_X11_SCREEN:
+#  *
+#  * If this sound event was triggered by a window on the screen and the
+#  * windowing system is X11, the X screen id of the window formatted as
+#  * string (e.g. "0").
+#  */
+CA_PROP_WINDOW_X11_SCREEN = "window.x11.screen"
+ 
+# /**
+#  * CA_PROP_WINDOW_X11_MONITOR:
+#  *
+#  * If this sound event was triggered by a window on the screen and the
+#  * windowing system is X11, the X monitor id of the window formatted as
+#  * string (e.g. "0").
+#  */
+CA_PROP_WINDOW_X11_MONITOR = "window.x11.monitor"
+ 
+# /**
+#  * CA_PROP_WINDOW_X11_XID:
+#  *
+#  * If this sound event was triggered by a window on the screen and the
+#  * windowing system is X11, the XID of the window formatted as string.
+#  */
+CA_PROP_WINDOW_X11_XID = "window.x11.xid"
+ 
+# /**
+#  * CA_PROP_APPLICATION_NAME:
+#  *
+#  * The name of the application this sound event was triggered by as
+#  * human readable string. (e.g. "GNU Emacs") Localized if possible and
+#  * applicable.
+#  */
+CA_PROP_APPLICATION_NAME = "application.name"
+ 
+# /**
+#  * CA_PROP_APPLICATION_ID:
+#  *
+#  * An identifier for the program this sound event was triggered
+#  * by. (e.g. "org.gnu.emacs").
+#  */
+CA_PROP_APPLICATION_ID = "application.id"
+ 
+# /**
+#  * CA_PROP_APPLICATION_VERSION:
+#  *
+#  * A version number for the program this sound event was triggered
+#  * by. (e.g. "22.2")
+#  */
+CA_PROP_APPLICATION_VERSION = "application.version"
+ 
+# /**
+#  * CA_PROP_APPLICATION_ICON:
+#  *
+#  * Binary icon data in PNG format for the application this sound event
+#  * is triggered by.
+#  */
+CA_PROP_APPLICATION_ICON = "application.icon"
+ 
+# /**
+#  * CA_PROP_APPLICATION_ICON_NAME:
+#  *
+#  * An icon name for the application this sound event is triggered by,
+#  * as defined in the XDG icon naming specification.
+#  */
+CA_PROP_APPLICATION_ICON_NAME = "application.icon_name"
+ 
+# /**
+#  * CA_PROP_APPLICATION_LANGUAGE:
+#  *
+#  * The locale string the application that is triggering this sound
+#  * event is running in. A POSIX locale string such as de_DE euro 
+#  */
+CA_PROP_APPLICATION_LANGUAGE = "application.language"
+ 
+# /**
+#  * CA_PROP_APPLICATION_PROCESS_ID:
+#  *
+#  * The unix PID of the process that is triggering this sound event, formatted as string.
+#  */
+CA_PROP_APPLICATION_PROCESS_ID = "application.process.id"
+ 
+# /**
+#  * CA_PROP_APPLICATION_PROCESS_BINARY:
+#  *
+#  * The path to the process binary of the process that is triggering this sound event.
+#  */
+CA_PROP_APPLICATION_PROCESS_BINARY = "application.process.binary"
+ 
+# /**
+#  * CA_PROP_APPLICATION_PROCESS_USER:
+#  *
+#  * The user that owns the process that is triggering this sound event.
+#  */
+CA_PROP_APPLICATION_PROCESS_USER = "application.process.user"
+ 
+# /**
+#  * CA_PROP_APPLICATION_PROCESS_HOST:
+#  *
+#  * The host name of the host the process that is triggering this sound event runs on.
+#  */
+CA_PROP_APPLICATION_PROCESS_HOST = "application.process.host"
+ 
+# /**
+#  * CA_PROP_CANBERRA_CACHE_CONTROL:
+#  *
+#  * A special property that can be used to control the automatic sound
+#  * caching of sounds in the sound server. One of "permanent",
+#  * "volatile", "never". "permanent" will cause this sample to be
+#  * cached in the server permanently. This is useful for very
+#  * frequently used sound events such as those used for input
+#  * feedback. "volatile" may be used for cacheing sounds in the sound
+#  * server temporarily. They will expire after some time or on cache
+#  * pressure. Finally, "never" may be used for sounds that should never
+#  * be cached, because they are only generated very seldomly or even
+#  * only once at most (such as desktop login sounds).
+#  *
+#  * If this property is not explicitly passed to ca_context_play() it
+#  * will default to "never". If it is not explicitly passed to
+#  * ca_context_cache() it will default to "permanent".
+#  *
+#  * If the list of properties is handed on to the sound server this
+#  * property is stripped from it.
+#  */
+CA_PROP_CANBERRA_CACHE_CONTROL = "canberra.cache-control"
+ 
+# /**
+#  * CA_PROP_CANBERRA_VOLUME:
+#  *
+#  * A special property that can be used to control the volume this
+#  * sound event is played in if the backend supports it. A floating
+#  * point value for the decibel multiplier for the sound. 0 dB relates
+#  * to zero gain, and is the default volume these sounds are played in.
+#  *
+#  * If the list of properties is handed on to the sound server this
+#  * property is stripped from it.
+#  */
+CA_PROP_CANBERRA_VOLUME = "canberra.volume"
+ 
+# /**
+#  * CA_PROP_CANBERRA_XDG_THEME_NAME:
+#  *
+#  * A special property that can be used to control the XDG sound theme that
+#  * is used for this sample.
+#  *
+#  * If the list of properties is handed on to the sound server this
+#  * property is stripped from it.
+#  */
+CA_PROP_CANBERRA_XDG_THEME_NAME = "canberra.xdg-theme.name"
+ 
+# /**
+#  * CA_PROP_CANBERRA_XDG_THEME_OUTPUT_PROFILE:
+#  *
+#  * A special property that can be used to control the XDG sound theme
+#  * output profile that is used for this sample.
+#  *
+#  * If the list of properties is handed on to the sound server this
+#  * property is stripped from it.
+#  */
+CA_PROP_CANBERRA_XDG_THEME_OUTPUT_PROFILE = "canberra.xdg-theme.output-profile"
+ 
+# /**
+#  * CA_PROP_CANBERRA_ENABLE:
+#  *
+#  * A special property that can be used to control whether any sounds
+#  * are played at all. If this property is "1" or unset sounds are
+#  * played as normal. However, if it is "0" all calls to
+#  * ca_context_play() will fail with CA_ERROR_DISABLED.
+#  *
+#  * If the list of properties is handed on to the sound server this
+#  * property is stripped from it.
+#  */
+CA_PROP_CANBERRA_ENABLE = "canberra.enable"
+
+# /**
+#  * CA_PROP_CANBERRA_FORCE_CHANNEL:
+#  *
+#  * A special property that can be used to control on which channel a
+#  * sound is played. The value should be one of mono, front-left,
+#  * front-right, front-center, rear-left, rear-right, rear-center, lfe,
+#  * front-left-of-center, front-right-of-center, side-left, side-right,
+#  * top-center, top-front-left, top-front-right, top-front-center,
+#  * top-rear-left, top-rear-right, top-rear-center. This property is
+#  * only honoured by some backends, other backends may choose to ignore
+#  * it completely.
+#  *
+#  * If the list of properties is handed on to the sound server this
+#  * property is stripped from it.
+#  */
+CA_PROP_CANBERRA_FORCE_CHANNEL = "canberra.force_channel"
+
+# /**
+#  * ca_context:
+#  *
+#  * A libcanberra context object.
+#  */
+# typedef struct ca_context ca_context;
+
+ca_context = c_void_p
+
+
+# /**
+#  * ca_finish_callback_t:
+#  * @c: The libcanberra context this callback is called for
+#  * @id: The numerical id passed to the ca_context_play_full() when starting the event sound playback.
+#  * @error_code: A numerical error code describing the reason this callback is called. If CA_SUCCESS is passed in the playback of the event sound was successfully completed.
+#  * @userdata: Some arbitrary user data the caller of ca_context_play_full() passed in.
+#  *
+#  * Playback completion event callback. The context this callback is
+#  * called in is undefined, it might or might not be called from a
+#  * background thread, and from any stack frame. The code implementing
+#  * this function may not call any libcanberra API call from this
+#  * callback -- this might result in a deadlock. Instead it may only be
+#  * used to asynchronously signal some kind of notification object
+#  * (semaphore, message queue, ...).
+#  */
+# typedef void (*ca_finish_callback_t)(ca_context *c, uint32_t id, int error_code, void *userdata);
+
+CA_FINISH_TYPE = CFUNCTYPE(None, ca_context, c_uint32, c_int, c_void_p)
+
+# /**
+#  * Error codes:
+#  * @CA_SUCCESS: Success
+#  *
+#  * Error codes
+#  */
+
+CA_SUCCESS = 0
+CA_ERROR_NOTSUPPORTED = -1
+CA_ERROR_INVALID = -2
+CA_ERROR_STATE = -3
+CA_ERROR_OOM = -4
+CA_ERROR_NODRIVER = -5
+CA_ERROR_SYSTEM = -6
+CA_ERROR_CORRUPT = -7
+CA_ERROR_TOOBIG = -8
+CA_ERROR_NOTFOUND = -9
+CA_ERROR_DESTROYED = -10
+CA_ERROR_CANCELED = -11
+CA_ERROR_NOTAVAILABLE = -12
+CA_ERROR_ACCESS = -13
+CA_ERROR_IO = -14
+CA_ERROR_INTERNAL = -15
+CA_ERROR_DISABLED = -16
+CA_ERROR_FORKED = -17
+CA_ERROR_DISCONNECTED = -18
+_CA_ERROR_MAX = -19
+
+# /**
+#  * ca_proplist:
+#  *
+#  * A canberra property list object. Basically a hashtable.
+#  */
+# typedef struct ca_proplist ca_proplist;
+
+ca_proplist = c_void_p
+
+
+_libHandle = None
+
+def GetApi():
+   global _libHandle
+   if not _libHandle:
+      _libHandle = CDLL("libcanberra.so")
+   return _libHandle
+
+
+# XXX: TODO: wrap ca_proplist_*
+# int ca_proplist_create(ca_proplist **p);
+# int ca_proplist_destroy(ca_proplist *p);
+# int ca_proplist_sets(ca_proplist *p, const char *key, const char *value);
+# int ca_proplist_setf(ca_proplist *p, const char *key, const char *format, ...) __attribute__((format(printf, 3, 4)));
+# int ca_proplist_set(ca_proplist *p, const char *key, const void *data, size_t nbytes);
+
+
+class CanberraException(exceptions.Exception):
+   def __init__(self, err, *args, **kwargs):
+      self._err = err
+      super(exceptions.Exception, self).__init__(*args, **kwargs)
+
+   def get_error(self):
+      return self._err
+
+   def __str__(self):
+      return super(exceptions.Exception, self).__str__() + " (error %d)" % self._err
+   
+
+class Canberra(object):
+   def __init__(self):
+      self._handle = ca_context()
+      GetApi().ca_context_create(byref(self._handle))
+
+   def set_driver(self, driver):
+      res = GetApi().ca_context_set_driver(self._handle, driver)
+      if res != CA_SUCCESS:
+         raise CanberraException(res, "Failed to set driver")
+
+   def change_device(self, device):
+      res = GetApi().ca_context_change_device(self._handle, device)
+      if res != CA_SUCCESS:
+         raise CanberraException(res, "Failed to change device")
+   
+   def open(self):
+      res = GetApi().ca_context_open(self._handle)
+      if res != CA_SUCCESS:
+         raise CanberraException(res, "Failed to open context")
+
+   def destroy(self):
+      res = GetApi().ca_context_destroy(self._handle)
+      if res != CA_SUCCESS:
+         raise CanberraException(res, "Failed to destroy context")
+
+   def change_props(self, *args):
+      res = GetApi().ca_context_change_props(self._handle, *args)
+      if res != CA_SUCCESS:
+         raise CanberraException(res, "Failed to change props")
+
+   #XXX implement this with ca_props_* is wrapped
+   def change_props_full(self, props):
+      pass
+
+   #XXX implement this with ca_props_* is wrapped
+   def play_full(self, playId, props, cb, userData):
+      pass
+
+   #XXX implement this with ca_props_* is wrapped
+   def cache_full(self, props):
+      pass
+
+   def play(self, playId, *args):
+      res = GetApi().ca_context_play(self._handle, playId, *args)
+      if res != CA_SUCCESS:
+         raise CanberraException(res, "Failed to play!")
+
+   def cache(self, *args):
+      res = GetApi().ca_context_cache(self._handle, *args)
+      if res != CA_SUCCESS:
+         raise CanberraException(res, "Failed to cache")
+
+   def cancel(self, playId):
+      res = GetApi().ca_context_cancel(self._handle, playId)
+      if res != CA_SUCCESS:
+         raise CanberraException(res, "Failed to cancel id %d" % playId)
+
+   def playing(self, playId):
+      isPlaying = c_int()
+      res = GetApi().ca_context_playing(self._handle, playId, byref(isPlaying))
+      if res != CA_SUCCESS:
+         raise CanberraException(res, "Failed to test play status of id %d" % playId)
+      return isPlaying
+
+   def easy_play_sync(self, eventName):
+      """ play an event sound synchronously """
+      self.play(1,
+                CA_PROP_EVENT_ID, eventName,
+                None)
+      while self.playing(1):
+         time.sleep(0.01)
+
+if __name__ == "__main__":
+   import time
+   canberra = Canberra()
+   # canberra.change_props(CA_PROP_APPLICATION_NAME, "pycanberra test",
+   #                       CA_PROP_APPLICATION_ID, "org.freedesktop.pycanberra.Test",
+   #                       None)
+   canberra.easy_play_sync("system-ready")
+   # canberra.play(1,
+   #               CA_PROP_EVENT_ID, "system-ready",
+   #               None)
+   # while canberra.playing(1):
+   #    time.sleep(0.01)
+   canberra.destroy()
+
diff --git a/gnomeclocks/utils.py b/gnomeclocks/utils.py
index 0ca5247..eb6962d 100644
--- a/gnomeclocks/utils.py
+++ b/gnomeclocks/utils.py
@@ -18,8 +18,9 @@
 
 import os
 
+import pycanberra
 from xdg import BaseDirectory
-from gi.repository import Gio, Gst, Notify
+from gi.repository import Gio, Notify
 
 
 class Dirs:
@@ -62,15 +63,13 @@ class SystemSettings:
 
 class Alert:
     def __init__(self):
-        Gst.init('gst')
+        self.canberra = pycanberra.Canberra()
 
-    def do_alert(self, msg):
+    def do_alert(self, msg, eventid):
         if Notify.init("GNOME Clocks"):
             Alert = Notify.Notification.new("Clocks", msg, 'test')
             Alert.show()
-            playbin = Gst.ElementFactory.make('playbin', None)
-            playbin.set_property('uri',
-              'file:///usr/share/sounds/gnome/default/alerts/glass.ogg')
-            playbin.set_state(Gst.State.PLAYING)
         else:
             print "Error: Could not trigger Alert"
+
+        self.canberra.play(1, pycanberra.CA_PROP_EVENT_ID, eventid, None)



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]