diff --git a/RaiTV/ChannelLoader.py b/RaiTV/ChannelLoader.py index b3fc24f..05978f2 100644 --- a/RaiTV/ChannelLoader.py +++ b/RaiTV/ChannelLoader.py @@ -8,10 +8,10 @@ import urllib2, re, httplib class ChannelList(): - def __init__(self): + def __init__(self, liststore): ## Inizializzo un dizionario di canali - self.channels = {} + self.channels = liststore self.UA = 'Mozilla/5.0 (X11; U; Linux i686; it; rv:1.9.0.6) Gecko/2009011912 Firefox/3.0.11' @@ -29,21 +29,45 @@ class ChannelList(): for channel, url in re.findall("<videoUnit name=\"([^\"]*)\".*>.*\\n.*<url>(\S*)</url>", xmlfile): url = re.sub(r"&", "&", url) - self.channels[channel] = url + self.channels.append( (channel,url) ) - def getChannel(self, key): + def getChannel(self, channel): """Ottiene il vero canale da cui guardare.. :)""" - if not self.channels.has_key(key): - return None + ## Scorriamo la lista per trovare il canale desiderato + # it = self.channels.get_iter_first() - host = re.search(r"^.*//([^/]*)/", self.channels[key]).group(1) - # print " => host = %s" % host - path = re.search(r"%s/(.*)$" % host, self.channels[key]).group(1) - # print " => path = %s" % path - req = urllib2.Request(self.channels[key], + + if it is None: + return None ## Qui c'è poco da fare, la lista è vuota + + ## Devo trovare l'URL associato a channel + while it is not None: + chan, url = self.channels.get(it, 0) + if chan is channel: + break + else: + ## Incremento + it = self.channels.iter_next(it) + + return self.urlToMms(url) + + + def getChannelFromPath(self, path): + """Ottiene l'URL dello streaming puntato da path + nella liststore""" + + ## Ottengo l'URL + it = self.channels.get_iter(path) + url = self.channels.get_value(it, 1) + + return self.urlToMms(url) + + def urlToMms(self, url): + """Converte un URL nello streaming MMS""" + req = urllib2.Request(url, None, {'User-Agent': self.UA}) @@ -51,6 +75,7 @@ class ChannelList(): mms = r.read() mms = re.search(r"HREF=\"(\S*)\"", mms).group(1) return mms + def getChannelList(self): return self.channels diff --git a/RaiTV/Interface.py b/RaiTV/Interface.py index c62f141..aa09db1 100644 --- a/RaiTV/Interface.py +++ b/RaiTV/Interface.py @@ -24,19 +24,19 @@ class UI(): self.win = self.builder.get_object("win") self.listacanali = self.builder.get_object("listacanali") + ## La liststore dei canali + self.liststore = self.builder.get_object("canalistore") + ## Lista dei canali (in astratto) - self.channellist = ChannelList() - + self.channellist = ChannelList(self.liststore) + ## Questo hbox è quello dove dobbiamo inserire ## la videowidget self.hbox1 = self.builder.get_object("hbox1") self.videowidget = VideoWidget() self.hbox1.pack_start(self.videowidget) - - ## La liststore dei canali - self.liststore = self.builder.get_object("canalistore") - + ## Visualizziamo il nome del canale col = gtk.TreeViewColumn("Selezione canale") cell = gtk.CellRendererText() @@ -53,6 +53,9 @@ class UI(): self.builder.get_object("pause"), self.builder.get_object("record"), \ self.builder.get_object("updatelist") + ## Colleghiamo il clic sulla lista con il playback del canale + self.listacanali.connect("row-activated", self.row_activated_callback) + ## La statusbar self.statusbar = self.builder.get_object("statusbar") self.sb_info("Applicazione inizializzata") @@ -85,18 +88,26 @@ class UI(): def updateChannels(self): """Aggiorna la lista dei canali scaricandola direttamente da quella della rai. Si rifiuta di aggiornare se la lista ottenuta è vuota""" + self.sb_info("Aggiornamento canali in corso...") self.channellist.updateChannels() self.sb_info("Canali aggiornati") if not self.channellist == {}: - for channel, url in self.channellist.getChannelList().items(): - self.liststore.append( (channel, url) ) + ## Possiamo permetterci di perdere tutti i canali, + ## perché sembra che l'operazione sia andata a buon + ## fine + self.liststore = self.channellist.getChannelList() + + def row_activated_callback(self, treeview, path, column): + ## Devo ottenere l'URL da cui prendere lo streaming + mmsurl = self.channellist.getChannelFromPath(path) + self.sb_info("Connessione a %s..." % mmsurl) + self.videowidget.load_video(mmsurl) + self.sb_info("Connessione riuscita") def start_video(self): """Avvia il video""" self.videowidget.registerXID() - self.videowidget.load_video("file:///home/leonardo/Video/The.Big.Bang.Theory.S03E02.HDTV.XviD-XII.avi") - # self.videowidget.load_video("mms://livestream.rai.it.edgestreams.net/reflector:64084?auth=daEcjcOancgdlaecAdqdccmdwbZbkb0aHd.-bk6_3l-b4-JlruuGt&aifp=V001") - # self.videowidget.load_video("mms://livestream.rai.it.edgestreams.net/reflector:64084?auth=daEcvcIa9clbgaEbjbfbFdHc_dkcCbUb7dQ-bk7abm-b4-BlvusGo&aifp=V001") + def destroy(self, w): """Chiamata per distruggere l'interfaccia""" diff --git a/RaiTV/VideoWidget.py b/RaiTV/VideoWidget.py index 2322166..1bfe557 100644 --- a/RaiTV/VideoWidget.py +++ b/RaiTV/VideoWidget.py @@ -4,7 +4,7 @@ # Implementazione del Widget per gestire il video # -import pygtk, gtk, gst +import pygtk, gtk, gst, cairo class VideoWidget(gtk.DrawingArea): @@ -25,13 +25,49 @@ class VideoWidget(gtk.DrawingArea): bus.connect("sync-message::element", self.on_sync_message) bus.connect("message", self.on_message) + ## Connetto l'expose-event + self.connect("expose-event", self.colorize) - def do_expose_event(self, event): - if self.imagesink: - self.imagesink.expose() - return False - else: - return True + self.playing = False + + + def colorize(self, widget, event): + """Quando la finestra viene creata la coloriamo di + nero. Poi sarà tutto lavoro per gstreamer""" + + ## Ci permettiamo di disegnare sopra il filmato + ## se e solo se non c'è un filmato che sta andando! :) + + if not self.playing: + cr = self.window.cairo_create() + ## Non facciamo lavoro extra e coloriamo solo ciò + ## che è stato scoperto + cr.rectangle(event.area.x, event.area.y, + event.area.width, event.area.height) + + cr.clip() + + width, height = self.window.get_size() + + cr.set_source_rgb(0,0,0) + cr.rectangle(0,0,width,height) + cr.fill() + + cr.set_source_rgb(0.5,0,0) + st = "RaiTV :)" + cr.set_font_size(height/20) + cr.select_font_face("Comic Sans MS") + xbearing , ybearing, twidth, theight, xadvance, yadvance = cr.text_extents(st) + + cr.move_to(width/2 - twidth/2, 1.6*height/3 - theight/5) + cr.show_text(st) + + cr.set_line_width(3) + cr.move_to(width/2 - twidth/2 - 5 , 1.6* height/3) + cr.rel_line_to(twidth + 10,0) + cr.stroke() + + def set_sink(self, sink): assert self.window.xid @@ -40,17 +76,20 @@ class VideoWidget(gtk.DrawingArea): def load_video(self, uri): """Start video playing with the specified URI""" + ## Stoppiamo ogni video + self.stop() self.player.set_property("uri", uri) - self.play() def pause(self): self.player.set_state(gst.STATE_PAUSED) def stop(self): + self.playing = False self.player.set_state(gst.STATE_NULL) def play(self): + self.playing = True self.player.set_state(gst.STATE_PLAYING) def on_sync_message(self, bus, message): @@ -68,27 +107,4 @@ class VideoWidget(gtk.DrawingArea): print err, debug def reset(self): - drawable = self.window - width, height = drawable.get_size() - print width, height - # Creo il graphic context, sperando che si - # aggiorni. - gc = gtk.gdk.GC(drawable, - gtk.gdk.Color(2,15,70), - gtk.gdk.Color(0,67,0) - ) - - drawable.draw_rectangle(gc, - True, - 5, - 5, - width, - height) - - ## Qua dovremmo far vedere che la finestra - ## diventa nera e invece non lo fa - self.realize() - - def registerXID(self): - self.XID = self.window.xid - + pass diff --git a/raitv.py b/raitv.py old mode 100644 new mode 100755 index 296070f..6e4cb7d --- a/raitv.py +++ b/raitv.py @@ -1,4 +1,4 @@ -# +#!/usr/bin/env python # -*- coding: utf-8 -*- # # @@ -9,7 +9,6 @@ from RaiTV import VideoWidget, Interface ui = Interface.UI() ui.show_all() -ui.start_video() gtk.main() diff --git a/ui/RaiTV.ui b/ui/RaiTV.ui index 2b3c7f5..f0481bd 100644 --- a/ui/RaiTV.ui +++ b/ui/RaiTV.ui @@ -11,6 +11,7 @@ </columns> </object> <object class="GtkWindow" id="win"> + <property name="title" translatable="yes">RaiTV prerelease</property> <child> <object class="GtkVBox" id="vbox1"> <property name="visible">True</property>