Last active
May 12, 2021 14:10
-
-
Save jampola/ad3995e227dc46cfe069 to your computer and use it in GitHub Desktop.
Fully functioning mp3/wav/ogg playing Alarm Clock (PyGTK and Gst)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
''' | |
jamesbos [at] gmail [dot] com - originally shared at https://gist.github.com/jampola/ad3995e227dc46cfe069 | |
Fully functioning alarm clock. Very primitive I know but this shows how basic events and | |
"threading" within pygtk[1] and media playback in gst[2] works. The main reason for sharing this on gist.github.org is so | |
it is searchable via google. | |
Include a an mp3 file called "alarm.mp3" in the same directory as this file OR supply the | |
/path/to/whatever.mp3/wav/ogg that you wish to play. | |
note: For the sake of your own ability, read and really understand what everything here does. | |
[1] http://python-gtk-3-tutorial.readthedocs.org/en/latest/ | |
[2] http://blogs.gnome.org/uraeus/2011/10/04/tutorial-for-python-gstreamer-and-gtk-3/ | |
license: are you kidding? :) | |
''' | |
from gi.repository import Gtk, GObject, Pango, Gst | |
import pygst | |
from datetime import datetime | |
import os | |
Gst.init(None) | |
class MainWindow(Gtk.Window): | |
def __init__(self): | |
Gtk.Window.__init__(self, title="Alarm Clock") | |
self.alarm_state = False | |
self.table = Gtk.Table(5,4,False) | |
self.add(self.table) | |
# # GST | |
self.player = Gst.ElementFactory.make("playbin", "player") | |
self.player.set_property('uri','file://'+os.path.abspath('alarm.mp3')) | |
# # Clock label | |
self.labelClock = Gtk.Label() | |
self.labelClock.modify_font(Pango.FontDescription("sans 14")) | |
self.table.attach(self.labelClock,0, 6, 0, 1) | |
# initially set time to clock label otherwise there is a delay | |
# when displaying the clock when app is first run | |
self.labelClock.set_label(str(datetime.now())) | |
# # alarm switch | |
self.alarmSwitch = Gtk.Switch() | |
self.table.attach(self.alarmSwitch,0,6,1,2) | |
# # alarm label | |
self.labelSetAlarm = Gtk.Label("No Alarm Set") | |
self.table.attach(self.labelSetAlarm,0, 6, 2, 3) | |
# # time labels | |
self.time_hr_label = Gtk.Label("Hour") | |
self.table.attach(self.time_hr_label,0,1, 3,4) | |
self.time_min_label = Gtk.Label("Min") | |
self.table.attach(self.time_min_label,2,3, 3,4) | |
self.time_sec_label = Gtk.Label("Sec") | |
self.table.attach(self.time_sec_label,4,5, 3,4) | |
# # hours | |
self.hr_adj = Gtk.Adjustment(value = 1, lower=0, upper=23, step_incr=1) | |
self.time_hr_spinner = Gtk.SpinButton() | |
self.time_hr_spinner.set_adjustment(self.hr_adj) | |
self.table.attach(self.time_hr_spinner,0,1, 4,5) | |
# # mins | |
self.min_adj = Gtk.Adjustment(value = 1, lower=0, upper=59, step_incr=1) | |
self.time_min_spinner = Gtk.SpinButton() | |
self.time_min_spinner.set_adjustment(self.min_adj) | |
self.table.attach(self.time_min_spinner,2,3, 4,5) | |
# # seconds | |
self.sec_adj = Gtk.Adjustment(value = 1, lower=0, upper=59, step_incr=1) | |
self.time_sec_spinner = Gtk.SpinButton() | |
self.time_sec_spinner.set_adjustment(self.sec_adj) | |
self.table.attach(self.time_sec_spinner,4,5, 4,5) | |
# # alarm media file | |
self.fileEntryLabel = Gtk.Label("/path/to/file.mp3") | |
self.table.attach(self.fileEntryLabel,0,6, 5,6) | |
self.fileEntry = Gtk.Entry() | |
self.table.attach(self.fileEntry,0,6, 6,7) | |
# # connect methods | |
self.alarmSwitch.connect("notify::active", self.alarm_trigger) | |
self.alarmSwitch.set_active(False) | |
# # format time to str for comparison | |
def format_time(self,time): | |
rounded = int(round(time)) | |
if len(str(rounded)) == 1: | |
formatted = "{}{}".format("0",rounded) | |
return formatted | |
else: | |
return rounded | |
# # main alarm function | |
def set_alarm(self): | |
# get current time for compatison to alarm time | |
timenow = str(datetime.now())[11:19] | |
# get values from our time spinners | |
hour = self.time_hr_spinner.get_value() | |
minute = self.time_min_spinner.get_value() | |
seconds = self.time_sec_spinner.get_value() | |
# format our time for comparison against timenow | |
alarm_formated = "{}:{}:{}".format(self.format_time(hour),self.format_time(minute),self.format_time(seconds)) | |
# if the alarm state is true, wait for the alarm time to equal current time then trigger alarm | |
if self.alarm_state: | |
if timenow == alarm_formated: | |
# if no file is supplied to be played, play the default alarm.mp3 in CWD | |
if self.fileEntry.get_text() == "": | |
self.player.set_property('uri','file://'+os.path.abspath('alarm.mp3')) | |
print "beep beep beep" | |
# as above except file is supplied so lets play that one instead! | |
else: | |
alarmFile = 'file://'+self.fileEntry.get_text() | |
self.player.set_property('uri',alarmFile) | |
print "beep beep beep" | |
# set gst to start playing whatever file | |
self.player.set_state(Gst.State.PLAYING) | |
self.alarm_state = False | |
self.labelSetAlarm.set_label("Alarm OFF!") | |
else: | |
self.labelSetAlarm.set_label("No Alarm Set") | |
# return tree true to ensure timeout_add continues | |
return True | |
# this is called from our "alarmSwitch" button and will set our alarm state to True | |
def alarm_trigger(self,switch,gparam): | |
if self.alarmSwitch.get_active(): | |
self.alarm_state = True | |
self.labelSetAlarm.set_label("Alarm ON!") | |
else: | |
self.alarm_state = True | |
self.labelSetAlarm.set_label("Alarm OFF!") | |
self.player.set_state(Gst.State.NULL) | |
# # run clock | |
def displayclock(self,state): | |
# putting our datetime into a var and setting our label to the result. | |
# we need to return "True" to ensure the timer continues to run, otherwise it will only run once. | |
datetimenow = str(datetime.now())[11:19] | |
self.labelClock.set_label(datetimenow) | |
return state | |
# Initialize Timer | |
def startclocktimer(self): | |
# this takes 2 args: (how often to update in millisec, the method to run) | |
GObject.timeout_add(100, self.displayclock, True) | |
GObject.timeout_add(1000, self.set_alarm) | |
win = MainWindow() | |
win.connect("delete-event", Gtk.main_quit) | |
win.show_all() | |
win.startclocktimer() | |
Gtk.main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is expanded upon my original clock app (posted here: https://gist.github.com/jampola/473e963cff3d4ae96707) -- Yes, it's super primitive but it does again go over some of the semantics surrounding timeout_add and also some new toys such as GST.
If you see any ways this could be improved upon (in terms of code efficiency, not so much practicability) please leave it in the comments! :)