10 import util.misc as misc_utils
17 _moduleLogger = logging.getLogger(__name__)
20 class BasicWindow(gobject.GObject):
24 gobject.SIGNAL_RUN_LAST,
29 gobject.SIGNAL_RUN_LAST,
31 (gobject.TYPE_PYOBJECT, ),
35 def __init__(self, player, store, index):
36 gobject.GObject.__init__(self)
42 self._clipboard = gtk.clipboard_get()
43 self._windowInFullscreen = False
45 self._errorBanner = banners.StackingBanner()
47 self._layout = gtk.VBox()
48 self._layout.pack_start(self._errorBanner.toplevel, False, True)
50 self._window = gtk.Window()
51 self._window.add(self._layout)
52 self._window = hildonize.hildonize_window(self, self._window)
54 self._window.set_icon(self._store.get_pixbuf_from_store(self._store.STORE_LOOKUP["icon"]))
55 self._window.connect("key-press-event", self._on_key_press)
56 self._window.connect("window-state-event", self._on_window_state_change)
62 def save_settings(self, config, sectionName):
63 config.add_section(sectionName)
64 config.set(sectionName, "fullscreen", str(self._windowInFullscreen))
66 def load_settings(self, config, sectionName):
68 self._windowInFullscreen = config.getboolean(sectionName, "fullscreen")
69 except ConfigParser.NoSectionError, e:
71 "Settings file %s is missing section %s" % (
72 constants._user_settings_,
77 if self._windowInFullscreen:
78 self._window.fullscreen()
80 self._window.unfullscreen()
82 @misc_utils.log_exception(_moduleLogger)
83 def _on_window_state_change(self, widget, event, *args):
84 if event.new_window_state & gtk.gdk.WINDOW_STATE_FULLSCREEN:
85 self._windowInFullscreen = True
87 self._windowInFullscreen = False
88 self.emit("fullscreen", self._windowInFullscreen)
90 @misc_utils.log_exception(_moduleLogger)
91 def _on_key_press(self, widget, event, *args):
92 RETURN_TYPES = (gtk.keysyms.Return, gtk.keysyms.ISO_Enter, gtk.keysyms.KP_Enter)
93 isCtrl = bool(event.get_state() & gtk.gdk.CONTROL_MASK)
95 event.keyval == gtk.keysyms.F6 or
96 event.keyval in RETURN_TYPES and isCtrl
98 # The "Full screen" hardware key has been pressed
99 if self._windowInFullscreen:
100 self._window.unfullscreen ()
102 self._window.fullscreen ()
105 event.keyval in (gtk.keysyms.w, ) and
106 event.get_state() & gtk.gdk.CONTROL_MASK
108 self._window.destroy()
110 event.keyval in (gtk.keysyms.q, ) and
111 event.get_state() & gtk.gdk.CONTROL_MASK
114 elif event.keyval == gtk.keysyms.l and event.get_state() & gtk.gdk.CONTROL_MASK:
115 with open(constants._user_logpath_, "r") as f:
116 logLines = f.xreadlines()
117 log = "".join(logLines)
118 self._clipboard.set_text(str(log))
122 class SourceSelector(BasicWindow):
124 def __init__(self, player, store, index):
125 BasicWindow.__init__(self, player, store, index)
127 self._radioButton = self._create_button("radio", "Radio")
128 self._radioButton.connect("clicked", self._on_radio_selected)
129 self._radioWrapper = gtk.VBox()
130 self._radioWrapper.pack_start(self._radioButton, False, True)
132 self._conferenceButton = self._create_button("conferences", "Conferences")
133 #self._conferenceButton.connect("clicked", self._on_conference_selected)
134 self._conferenceWrapper = gtk.VBox()
135 self._conferenceWrapper.pack_start(self._conferenceButton, False, True)
137 self._magazineButton = self._create_button("magazines", "Magazines")
138 #self._magazineButton.connect("clicked", self._on_magazine_selected)
139 self._magazineWrapper = gtk.VBox()
140 self._magazineWrapper.pack_start(self._magazineButton, False, True)
142 self._scriptureButton = self._create_button("scriptures", "Scriptures")
143 #self._scriptureButton.connect("clicked", self._on_scripture_selected)
144 self._scriptureWrapper = gtk.VBox()
145 self._scriptureWrapper.pack_start(self._scriptureButton, False, True)
147 self._buttonLayout = gtk.VBox(True, 5)
148 self._buttonLayout.set_property("border-width", 5)
149 self._buttonLayout.pack_start(self._radioWrapper, True, True)
150 self._buttonLayout.pack_start(self._conferenceWrapper, True, True)
151 self._buttonLayout.pack_start(self._magazineWrapper, True, True)
152 self._buttonLayout.pack_start(self._scriptureWrapper, True, True)
154 self._playcontrol = playcontrol.PlayControl(player, store)
156 self._layout.pack_start(self._buttonLayout, True, True)
157 self._layout.pack_start(self._playcontrol.toplevel, False, True)
159 self._window.set_title(constants.__pretty_app_name__)
160 self._window.show_all()
161 self._errorBanner.toplevel.hide()
162 self._playcontrol.toplevel.hide()
164 def _create_button(self, icon, message):
165 image = self._store.get_image_from_store(self._store.STORE_LOOKUP[icon])
168 label.set_text(message)
170 buttonLayout = gtk.HBox(False, 5)
171 buttonLayout.pack_start(image, False, False)
172 buttonLayout.pack_start(label, False, True)
173 button = gtk.Button()
174 button.add(buttonLayout)
178 @misc_utils.log_exception(_moduleLogger)
179 def _on_radio_selected(self, *args):
180 radioView = RadioView(self._player, self._store, self._index)
181 radioView.window.set_modal(True)
182 radioView.window.set_transient_for(self._window)
183 radioView.window.set_default_size(*self._window.get_size())
186 class RadioView(BasicWindow):
188 def __init__(self, player, store, index):
189 BasicWindow.__init__(self, player, store, index)
191 self._loadingBanner = banners.GenericBanner()
193 headerPath = self._store.STORE_LOOKUP["radio_header"]
194 self._header = self._store.get_image_from_store(headerPath)
196 self._programmingModel = gtk.ListStore(
201 textrenderer = gtk.CellRendererText()
202 timeColumn = gtk.TreeViewColumn("Time")
203 timeColumn.pack_start(textrenderer, expand=True)
204 timeColumn.add_attribute(textrenderer, "text", 0)
206 textrenderer = gtk.CellRendererText()
207 titleColumn = gtk.TreeViewColumn("Program")
208 titleColumn.pack_start(textrenderer, expand=True)
209 titleColumn.add_attribute(textrenderer, "text", 1)
211 self._treeView = gtk.TreeView()
212 self._treeView.set_headers_visible(False)
213 self._treeView.set_model(self._programmingModel)
214 self._treeView.append_column(timeColumn)
215 self._treeView.append_column(titleColumn)
217 self._treeScroller = gtk.ScrolledWindow()
218 self._treeScroller.add(self._treeView)
219 self._treeScroller.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
221 self._presenter = presenter.StreamMiniPresenter(self._player, self._store)
223 self._radioLayout = gtk.VBox(False)
224 self._radioLayout.pack_start(self._header, False, False)
225 self._radioLayout.pack_start(self._treeScroller, True, True)
226 self._radioLayout.pack_start(self._presenter.toplevel, False, True)
228 self._layout.pack_start(self._loadingBanner.toplevel, False, False)
229 self._layout.pack_start(self._radioLayout, True, True)
231 self._window.set_title("Radio")
232 self._window.show_all()
233 self._errorBanner.toplevel.hide()
234 self._loadingBanner.toplevel.hide()
237 self._index.download_radio(self._on_channels, self._on_load_error)
239 def _show_loading(self):
240 animationPath = self._store.STORE_LOOKUP["loading"]
241 animation = self._store.get_pixbuf_animation_from_store(animationPath)
242 self._loadingBanner.show(animation, "Loading...")
244 def _hide_loading(self):
245 self._loadingBanner.hide()
247 @misc_utils.log_exception(_moduleLogger)
248 def _on_channels(self, channels):
249 channels = list(channels)
250 if 1 < len(channels):
251 _moduleLogger.warning("More channels now available!")
252 channel = channels[0]
253 self._index.download_radio(self._on_channel, self._on_load_error, channel["id"])
255 @misc_utils.log_exception(_moduleLogger)
256 def _on_channel(self, programs):
258 for program in programs:
259 row = program["time"], program["title"]
260 self._programmingModel.append(row)
262 path = (self._get_current_row(), )
263 self._treeView.scroll_to_cell(path)
264 self._treeView.get_selection().select_path(path)
266 def _get_current_row(self):
267 now = datetime.datetime.now()
268 nowTime = now.strftime("%H:%M:%S")
270 for i, row in enumerate(self._programmingModel):
276 @misc_utils.log_exception(_moduleLogger)
277 def _on_load_error(self, exception):
279 self._errorBanner.push_message(exception)