fdf7c50dc095f3df442ea0f22e0870206aadc2e2
Stefan Schuermans initial PyGtk window

Stefan Schuermans authored 10 years ago

1) #! /usr/bin/env python
2) 
3) import os
4) from gi.repository import Gtk
Stefan Schuermans start making player work -...

Stefan Schuermans authored 10 years ago

5) import gobject
Stefan Schuermans show current playlist item...

Stefan Schuermans authored 10 years ago

6) import pango
Stefan Schuermans add menu, implement file open

Stefan Schuermans authored 10 years ago

7) import sys
Stefan Schuermans start making player work -...

Stefan Schuermans authored 10 years ago

8) import time
Stefan Schuermans initial PyGtk window

Stefan Schuermans authored 10 years ago

9) 
Stefan Schuermans reading playlist

Stefan Schuermans authored 10 years ago

10) import playlist
Stefan Schuermans show current position as h:...

Stefan Schuermans authored 10 years ago

11) import time_fmt
12) 
Stefan Schuermans initial PyGtk window

Stefan Schuermans authored 10 years ago

13) scriptdir = os.path.dirname(os.path.abspath(__file__))
14) 
15) class SyncGui:
Stefan Schuermans start making player work -...

Stefan Schuermans authored 10 years ago

16) 
Stefan Schuermans initial PyGtk window

Stefan Schuermans authored 10 years ago

17)   def __init__(self):
Stefan Schuermans start making player work -...

Stefan Schuermans authored 10 years ago

18)     """construct a SyncGui object"""
Stefan Schuermans initial PyGtk window

Stefan Schuermans authored 10 years ago

19)     self.builder = Gtk.Builder()
20)     self.builder.add_from_file(scriptdir + "/sync_gui.glade")
Stefan Schuermans add menu, implement file open

Stefan Schuermans authored 10 years ago

21)     self.widMainWindow = self.builder.get_object("MainWindow")
Stefan Schuermans start making player work -...

Stefan Schuermans authored 10 years ago

22)     self.widPlaylistView = self.builder.get_object("PlaylistView")
23)     self.widPlaylistStore = self.builder.get_object("PlaylistStore")
24)     self.widPosition = self.builder.get_object("Position")
25)     self.widPositionScale = self.builder.get_object("PositionScale")
26)     self.widPositionAt = self.builder.get_object("PositionAt")
27)     self.widPositionRemaining = self.builder.get_object("PositionRemaining")
28)     self.widBtnPause = self.builder.get_object("Pause")
29)     self.widBtnPlay = self.builder.get_object("Play")
30)     self.widStatus = self.builder.get_object("Status")
Stefan Schuermans initial PyGtk window

Stefan Schuermans authored 10 years ago

31)     handlers = {
Stefan Schuermans start making player work -...

Stefan Schuermans authored 10 years ago

32)       "onDestroy":          self.onDestroy,
Stefan Schuermans add menu, implement file open

Stefan Schuermans authored 10 years ago

33)       "onFileOpen":         self.onFileOpen,
34)       "onFileExit":         self.onFileExit,
Stefan Schuermans start making player work -...

Stefan Schuermans authored 10 years ago

35)       "onPlaylistDblClick": self.onPlaylistDblClick,
36)       "onNewPosition":      self.onNewPosition,
37)       "onPrevious":         self.onPrevious,
38)       "onStop":             self.onStop,
39)       "onPause":            self.onPause,
40)       "onPlay":             self.onPlay,
41)       "onNext":             self.onNext,
Stefan Schuermans initial PyGtk window

Stefan Schuermans authored 10 years ago

42)     }
43)     self.builder.connect_signals(handlers)
Stefan Schuermans reading playlist

Stefan Schuermans authored 10 years ago

44)     self.playlist = playlist.Playlist()
Stefan Schuermans add menu, implement file open

Stefan Schuermans authored 10 years ago

45)     if len(sys.argv) >= 2: # load initial playlist from command line
46)       self.playlist.read(sys.argv[1])
Stefan Schuermans start making player work -...

Stefan Schuermans authored 10 years ago

47)     self.playlist.update(self.widPlaylistStore)
48)     self.widStatus.push(0, "TODO...")
49)     self.stEntryIdx = -1 # no entry selected
50)     self.stName = "" # no current entry name
51)     self.stDuration = 0 # current entry has zero size
52)     self.stPosition = 0 # at begin of current entry
53)     self.stPlaying = False # not playing
54)     gobject.timeout_add(10, self.onTimer10ms)
Stefan Schuermans show current playlist item...

Stefan Schuermans authored 10 years ago

55)     self.updateEntry()
Stefan Schuermans start making player work -...

Stefan Schuermans authored 10 years ago

56)     self.updateButtonVisibility()
Stefan Schuermans show current position as h:...

Stefan Schuermans authored 10 years ago

57) 
Stefan Schuermans start making player work -...

Stefan Schuermans authored 10 years ago

58)   def showPosition(self):
59)     """update the position texts next to the position slider"""
60)     # format current time and remaining time
61)     posAt = time_fmt.sec2str(self.stPosition)
62)     posRemaining = time_fmt.sec2str(self.stDuration - self.stPosition)
63)     self.widPositionAt.set_text(posAt)
64)     self.widPositionRemaining.set_text(posRemaining)
65) 
66)   def updatePositionState(self):
67)     """update the position in the state, but not the slider"""
68)     # calculate (virtual) start time of playing
69)     # i.e. the time the playing would have had started to arrive at the
70)     # current position now if it had played continuosly
71)     self.stPlayStart = time.time() - self.stPosition
72)     # update position texts
73)     self.showPosition()
74) 
75)   def updatePosition(self):
76)     """update the position including the position slider"""
77)     # update GUI slider
78)     self.widPositionScale.set_value(self.stPosition)
79)     # update position state
80)     self.updatePositionState()
81) 
82)   def updateDuration(self):
83)     """update the duration (i.e. range for the slider) based on the current
84)        playlist entry"""
85)     # get duration of new playlist entry
86)     self.stDuration = 0
87)     if self.stEntryIdx >= 0:
88)       entry = self.playlist.entries[self.stEntryIdx]
89)       if entry["type"] == "normal":
90)         self.stDuration = entry["duration"]
91)     # set position to begin
92)     self.stPosition = 0
93)     # update value range
94)     self.widPosition.set_upper(self.stDuration)
95)     # update position of slider
96)     self.updatePosition()
97) 
Stefan Schuermans show current playlist item...

Stefan Schuermans authored 10 years ago

98)   def updateEntry(self):
99)     """update current entry of playlist and duration, position, ..."""
Stefan Schuermans remove forward and backward...

Stefan Schuermans authored 10 years ago

100)     # clear selection of playlist
101)     sel = self.widPlaylistView.get_selection()
102)     if sel:
103)       sel.unselect_all()
Stefan Schuermans show current playlist item...

Stefan Schuermans authored 10 years ago

104)     # sanity check for entry index
105)     if self.stEntryIdx < -1 or self.stEntryIdx >= len(self.playlist.entries):
106)       self.stEntryIdx = -1
Stefan Schuermans add menu, implement file open

Stefan Schuermans authored 10 years ago

107)     # get name of current entry
108)     self.stName = ""
109)     if self.stEntryIdx >= 0 and \
110)        self.playlist.entries[self.stEntryIdx]["type"] == "normal":
111)       self.stName = self.playlist.entries[self.stEntryIdx]["name"]
Stefan Schuermans show current playlist item...

Stefan Schuermans authored 10 years ago

112)     # make current entry bold, all others non-bold
113)     def update(model, path, it, user_data):
114)       (idx,) = model.get(it, 0)
115)       if idx == self.stEntryIdx:
116)         weight = pango.WEIGHT_BOLD
117)       else:
118)         weight = pango.WEIGHT_NORMAL
119)       model.set(it, 1, weight)
120)     self.widPlaylistStore.foreach(update, None)
Stefan Schuermans remove forward and backward...

Stefan Schuermans authored 10 years ago

121)     # playing and (no entry or stop entry)
122)     # -> stop playing and update button visibility
123)     if self.stPlaying and (self.stEntryIdx < 0 or \
124)        self.playlist.entries[self.stEntryIdx]["type"] == "stop"):
125)       self.stPlaying = False
126)       self.updateButtonVisibility()
Stefan Schuermans show current playlist item...

Stefan Schuermans authored 10 years ago

127)     # update duration, position, ...
128)     self.updateDuration()
129) 
Stefan Schuermans start making player work -...

Stefan Schuermans authored 10 years ago

130)   def updateButtonVisibility(self):
131)     """update the visibility of the buttons based on if playing or not"""
132)     self.widBtnPause.set_visible(self.stPlaying)
133)     self.widBtnPlay.set_visible(not self.stPlaying)
Stefan Schuermans initial PyGtk window

Stefan Schuermans authored 10 years ago

134) 
135)   def onDestroy(self, widget):
Stefan Schuermans start making player work -...

Stefan Schuermans authored 10 years ago

136)     """window will be destroyed"""
Stefan Schuermans initial PyGtk window

Stefan Schuermans authored 10 years ago

137)     Gtk.main_quit()
138) 
Stefan Schuermans add menu, implement file open

Stefan Schuermans authored 10 years ago

139)   def onFileOpen(self, widget):
140)     """File Open clicked in menu"""
141)     #print("DEBUG sync_gui File Open")
142)     # run file chooser dialog
143)     dialog = Gtk.FileChooserDialog("BlinkenArea Sync GUI - File Open..",
144)                                    self.widMainWindow,
145)                                    Gtk.FileChooserAction.OPEN,
146)                                    (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
147)                                     Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
148)     dialog.set_default_response(Gtk.ResponseType.OK)
149)     filt = Gtk.FileFilter()
150)     filt.set_name("All files")
151)     filt.add_pattern("*")
152)     dialog.add_filter(filt)
153)     response = dialog.run()
154)     if response == Gtk.ResponseType.OK:
155)       # dialog closed with OK -> load new playlist
156)       filename = dialog.get_filename()
157)       self.playlist.read(filename)
158)       self.playlist.update(self.widPlaylistStore)
159)       self.stEntryIdx = -1 # no entry selected
160)       self.stPlaying = False # not playing
161)       self.updateEntry()
162)       self.updateButtonVisibility()
163)     # cleanup
164)     dialog.destroy()
165) 
166)   def onFileExit(self, widget):
167)     """File Exit clicked in menu"""
168)     #print("DEBUG sync_gui File Exit")
169)     Gtk.main_quit()
170) 
Stefan Schuermans start making player work -...

Stefan Schuermans authored 10 years ago

171)   def onPlaylistDblClick(self, widget, row, col):
172)     """playlist entry has been double-clicked"""
173)     # get index of selected entry
174)     idx = -1
175)     sel = self.widPlaylistView.get_selection()
176)     if sel is not None:
177)       (model, it) = sel.get_selected()
178)       if it is not None:
Stefan Schuermans show current playlist item...

Stefan Schuermans authored 10 years ago

179)         (idx,) = model.get(it, 0)
Stefan Schuermans remove forward and backward...

Stefan Schuermans authored 10 years ago

180)     #print("DEBUG sync_gui playlist double-click idx=%d" % (idx))
Stefan Schuermans start making player work -...

Stefan Schuermans authored 10 years ago

181)     # update playlist entry
182)     self.stEntryIdx = idx
Stefan Schuermans remove forward and backward...

Stefan Schuermans authored 10 years ago

183)     # set position to zero if playing
184)     if self.stPlaying:
185)       self.stPosition = 0
Stefan Schuermans show current playlist item...

Stefan Schuermans authored 10 years ago

186)     # update entry
187)     self.updateEntry()
Stefan Schuermans start making player work -...

Stefan Schuermans authored 10 years ago

188) 
Stefan Schuermans show current position as h:...

Stefan Schuermans authored 10 years ago

189)   def onNewPosition(self, widget, scroll, value):
Stefan Schuermans start making player work -...

Stefan Schuermans authored 10 years ago

190)     """slider has been moved to a new position"""
Stefan Schuermans remove forward and backward...

Stefan Schuermans authored 10 years ago

191)     #print("DEBUG sync_gui new position " + str(value));
Stefan Schuermans start making player work -...

Stefan Schuermans authored 10 years ago

192)     # clamp position to valid range
193)     if value < 0:
194)       value = 0
195)     if value > self.stDuration:
196)       value = self.stDuration
197)     # update current position - and play start time if playing
198)     self.stPosition = value
199)     # update position state (do not touch the slider)
200)     self.updatePositionState()
Stefan Schuermans show current position as h:...

Stefan Schuermans authored 10 years ago

201) 
Stefan Schuermans initial PyGtk window

Stefan Schuermans authored 10 years ago

202)   def onPrevious(self, widget):
Stefan Schuermans start making player work -...

Stefan Schuermans authored 10 years ago

203)     """previous button as been pressed"""
Stefan Schuermans remove forward and backward...

Stefan Schuermans authored 10 years ago

204)     #print("DEBUG sync_gui previous")
205)     # go to begin of previous entry (with wrap around)
206)     self.stPosition = 0
207)     self.stEntryIdx = self.stEntryIdx - 1
208)     if self.stEntryIdx < 0:
209)       self.stEntryIdx = len(self.playlist.entries) - 1
210)     self.updateEntry()
Stefan Schuermans initial PyGtk window

Stefan Schuermans authored 10 years ago

211) 
212)   def onStop(self, widget):
Stefan Schuermans start making player work -...

Stefan Schuermans authored 10 years ago

213)     """stop button has been pressed"""
Stefan Schuermans remove forward and backward...

Stefan Schuermans authored 10 years ago

214)     #print("DEBUG sync_gui stop")
Stefan Schuermans start making player work -...

Stefan Schuermans authored 10 years ago

215)     self.stPlaying = False
216)     self.stPosition = 0 # stop goes back to begin
217)     self.updatePosition()
218)     self.updateButtonVisibility()
Stefan Schuermans initial PyGtk window

Stefan Schuermans authored 10 years ago

219) 
220)   def onPause(self, widget):
Stefan Schuermans start making player work -...

Stefan Schuermans authored 10 years ago

221)     """pause button has been pressed"""
Stefan Schuermans remove forward and backward...

Stefan Schuermans authored 10 years ago

222)     #print("DEBUG sync_gui pause")
Stefan Schuermans start making player work -...

Stefan Schuermans authored 10 years ago

223)     self.stPlaying = False
224)     self.updateButtonVisibility()
Stefan Schuermans initial PyGtk window

Stefan Schuermans authored 10 years ago

225) 
226)   def onPlay(self, widget):
Stefan Schuermans start making player work -...

Stefan Schuermans authored 10 years ago

227)     """play button has been pressed"""
Stefan Schuermans remove forward and backward...

Stefan Schuermans authored 10 years ago

228)     #print("DEBUG sync_gui play")
Stefan Schuermans start making player work -...

Stefan Schuermans authored 10 years ago

229)     self.stPlaying = True
230)     self.updatePosition()
231)     self.updateButtonVisibility()
Stefan Schuermans initial PyGtk window

Stefan Schuermans authored 10 years ago

232) 
233)   def onNext(self, widget):
Stefan Schuermans start making player work -...

Stefan Schuermans authored 10 years ago

234)     """next button has been pressed"""
Stefan Schuermans remove forward and backward...

Stefan Schuermans authored 10 years ago

235)     #print("DEBUG sync_gui next")
236)     # go to begin of next entry (with wrap around)
237)     self.stPosition = 0
238)     self.stEntryIdx = self.stEntryIdx + 1
239)     if self.stEntryIdx >= len(self.playlist.entries):
240)       self.stEntryIdx = 0
241)     self.updateEntry()
Stefan Schuermans start making player work -...

Stefan Schuermans authored 10 years ago

242) 
243)   def onTimer10ms(self):
244)     """timer callback, every 10ms"""
245)     # update position if playing
246)     if self.stPlaying:
247)       self.stPosition = time.time() - self.stPlayStart
Stefan Schuermans remove forward and backward...

Stefan Schuermans authored 10 years ago

248)       if self.stPosition >= self.stDuration:
249)         # end of entry reached --> go to begin of next entry (with wrap around)
250)         self.stPosition = 0
251)         self.stEntryIdx = self.stEntryIdx + 1
252)         if self.stEntryIdx >= len(self.playlist.entries):
253)           self.stEntryIdx = 0
254)         self.updateEntry()
255)       else:
256)         self.updatePosition()
Stefan Schuermans start making player work -...

Stefan Schuermans authored 10 years ago

257)     return True
258) 
259) # main application entry point
Stefan Schuermans initial PyGtk window

Stefan Schuermans authored 10 years ago

260) if __name__ == "__main__":
261)   app = SyncGui()
262)   Gtk.main()
263)