Merge lp:~joni-noplu/moovida/moovida-dvb into lp:moovida

Proposed by Jonathan Rauprich
Status: Needs review
Proposed branch: lp:~joni-noplu/moovida/moovida-dvb
Merge into: lp:moovida
Diff against target: 872 lines (+713/-30)
14 files modified
elisa-plugins/elisa/plugins/amp/protocol.py (+1/-1)
elisa-plugins/elisa/plugins/gdvbd/controller.py (+257/-0)
elisa-plugins/elisa/plugins/gdvbd/models.py (+85/-0)
elisa-plugins/elisa/plugins/gdvbd/resource_provider.py (+264/-0)
elisa-plugins/elisa/plugins/lirc/lirc_input.py (+1/-1)
elisa-plugins/elisa/plugins/pigment/widgets/panel.py (+36/-26)
elisa-plugins/elisa/plugins/poblesec/player_video.py (+45/-2)
elisa-plugins/elisa_plugin_gdvbd.egg-info/PKG-INFO (+10/-0)
elisa-plugins/elisa_plugin_gdvbd.egg-info/controller_mappings.txt (+4/-0)
elisa-plugins/elisa_plugin_gdvbd.egg-info/decorator_mappings.txt (+3/-0)
elisa-plugins/elisa_plugin_gdvbd.egg-info/dependency_links.txt (+1/-0)
elisa-plugins/elisa_plugin_gdvbd.egg-info/entry_points.txt (+3/-0)
elisa-plugins/elisa_plugin_gdvbd.egg-info/namespace_packages.txt (+2/-0)
elisa-plugins/elisa_plugin_gdvbd.egg-info/top_level.txt (+1/-0)
To merge this branch: bzr merge lp:~joni-noplu/moovida/moovida-dvb
Reviewer Review Type Date Requested Status
Moovida Developers Pending
Review via email: mp+26379@code.launchpad.net

Description of the change

Added plugin for gnome-dvb-daemon
Added support for deinterlacing of dvb streams and recordings
Filtered message about missing teletext decoder
Converted some exceptions into warnings

To post a comment you must log in.
Revision history for this message
Olivier Tilloy (osomon) wrote :

Hi Jonathan,
Support for DVB looks like an amazing feature (I recall it being discussed extensively but resources were never allocated for implementation).
I haven't tested your code, but I have a bunch of important remarks:

1) In case you didn't know, Moovida 1.x is not supported any longer by Fluendo Embedded (see http://www.moovida.com/blog/2010/03/26/moovida-update/ and an interesting thread on the developers' mailing list: http://lists.moovida.com/pipermail/developers-list/2010-March/001804.html). Basically that means that your best bet to get your work reviewed is to count on the community. However a large part of said community is now focused on the fork (temporarily named Elisa until a better name is agreed upon: https://launchpad.net/elisa), and the ongoing efforts are focused on:
  a) Fixing the outstanding issues in the 1.0 branch to keep it usable (no new features)
  b) Brainstorming and designing for the next version

2) Your patch mixes new features (the new gdvbd plugin) and unrelated fixes, I'd advise to submit each as separate merge requests, it will ease the life of potential reviewers.

3) For the reasons detailed in 1, you probably want to submit bug fixes against lp:elisa, you'll stand a better chance to have them reviewed and merged.

4) The fix for the amp plugin is already merged in lp:elisa, see http://bazaar.launchpad.net/~elisa-developers/elisa/1.0/revision/1616

5) A fix for bug #379409 (CSS values with no units) is already pending a review, see https://code.launchpad.net/~osomon/elisa/css_property_no_unit/+merge/26369

6) There is a bug report for the issue with teletext (bug #415031). It is in general a good practice to link to existing bug reports in the merge request. Again, this will make the life of the reviewer(s) much easier.

7) Your branch is missing the setup.py script for the new gdvbd plugin. If you haven't done so yet, I encourage you to go through the good practices detailed in the developers' guide at http://www.moovida.com/documentation/developers_guide/developers_guide.html

8) The plugin shouldn't be merged in elisa/moovida's tree: it is preferable to create a standalone project in Launchpad to host its code, track its issues separately and release it in an independent manner. This project should be declared as part of the Moovida Universe meta-project (https://launchpad.net/moovida-universe).

9) The change to the LIRC plugin seems unrelated, and in any case should be carefully explained, because it touches a sensitive piece of code.

Thanks for reading patiently my remarks! Some of them might sound picky, but please know that your effort is valued, as a former core developer on the project it is very rewarding to see such cool contributions coming in. If you're interested in the fork, drop by on irc://freenode.net/#elisa, there's always someone hanging around there.

Revision history for this message
Jonathan Rauprich (joni-noplu) wrote :
Download full text (4.4 KiB)

Hi Oliver,

thanks for the reply.

1) I read that Fluendo switch to Banshee for Moovida 2.0, and searched
for a fork but didn't found it. Maybe you could announce it anywhere?

2) The fixes are unrelated agreed, but i couldn't write the plugin on
Ubuntu 10.04 with tons of exceptions in the output. Since i didn't know
u already have a fork with some bugs fixed i thought it could help.

3) true

4/5) true too, thanks for fixing it, your code for the css problem
running well here, should i make a comment about that in your merge
proposal?

6) see 8

7) I added a setup.py script, thanks for the hint.

8) Ok about that, i did only the plugin as a separate project
https://launchpad.net/elisa-gdvbd
The Problem is that using the plugin without the changes i made on the
video_player.py (teletext issue and deinterlacing support) isn't funny
(at least here in Germany where we have DVB streams interlaced and with
teletext). For the teletext issue i can publish a patch and relate it to
the bug, and for deinterlacing support i write a new bug report, is that
the correct solution?

9) Strange none else got issues with the lirc plugin (at least i found
no bug report). On my machine its not working without that change, maybe
its because i am using inputlirc
( http://www.realh.co.uk/dvbhowto/ar01s08.html ) instead of lirc, I'll
try to track the problem and write a bug report.

I'm pretty new to launchpad and bzr and i din't fully understand the way
development is working there, so thanks again for the help.

greets

joni

On Sun, 2010-05-30 at 17:13 +0000, Olivier Tilloy wrote:
> Hi Jonathan,
> Support for DVB looks like an amazing feature (I recall it being discussed extensively but resources were never allocated for implementation).
> I haven't tested your code, but I have a bunch of important remarks:
>
> 1) In case you didn't know, Moovida 1.x is not supported any longer by Fluendo Embedded (see http://www.moovida.com/blog/2010/03/26/moovida-update/ and an interesting thread on the developers' mailing list: http://lists.moovida.com/pipermail/developers-list/2010-March/001804.html). Basically that means that your best bet to get your work reviewed is to count on the community. However a large part of said community is now focused on the fork (temporarily named Elisa until a better name is agreed upon: https://launchpad.net/elisa), and the ongoing efforts are focused on:
> a) Fixing the outstanding issues in the 1.0 branch to keep it usable (no new features)
> b) Brainstorming and designing for the next version
>
> 2) Your patch mixes new features (the new gdvbd plugin) and unrelated fixes, I'd advise to submit each as separate merge requests, it will ease the life of potential reviewers.
>
> 3) For the reasons detailed in 1, you probably want to submit bug fixes against lp:elisa, you'll stand a better chance to have them reviewed and merged.
>
> 4) The fix for the amp plugin is already merged in lp:elisa, see http://bazaar.launchpad.net/~elisa-developers/elisa/1.0/revision/1616
>
> 5) A fix for bug #379409 (CSS values with no units) is already pending a review, see https://code.launchpad.net/~osomon/elisa/css_property_no_unit/+merge/26369
>
> 6)...

Read more...

Revision history for this message
Jonathan Rauprich (joni-noplu) wrote :

Another short question: Should i delete this proposal?

On Sun, 2010-05-30 at 17:13 +0000, Olivier Tilloy wrote:
> Hi Jonathan,
> Support for DVB looks like an amazing feature (I recall it being discussed extensively but resources were never allocated for implementation).
> I haven't tested your code, but I have a bunch of important remarks:
>
> 1) In case you didn't know, Moovida 1.x is not supported any longer by Fluendo Embedded (see http://www.moovida.com/blog/2010/03/26/moovida-update/ and an interesting thread on the developers' mailing list: http://lists.moovida.com/pipermail/developers-list/2010-March/001804.html). Basically that means that your best bet to get your work reviewed is to count on the community. However a large part of said community is now focused on the fork (temporarily named Elisa until a better name is agreed upon: https://launchpad.net/elisa), and the ongoing efforts are focused on:
> a) Fixing the outstanding issues in the 1.0 branch to keep it usable (no new features)
> b) Brainstorming and designing for the next version
>
> 2) Your patch mixes new features (the new gdvbd plugin) and unrelated fixes, I'd advise to submit each as separate merge requests, it will ease the life of potential reviewers.
>
> 3) For the reasons detailed in 1, you probably want to submit bug fixes against lp:elisa, you'll stand a better chance to have them reviewed and merged.
>
> 4) The fix for the amp plugin is already merged in lp:elisa, see http://bazaar.launchpad.net/~elisa-developers/elisa/1.0/revision/1616
>
> 5) A fix for bug #379409 (CSS values with no units) is already pending a review, see https://code.launchpad.net/~osomon/elisa/css_property_no_unit/+merge/26369
>
> 6) There is a bug report for the issue with teletext (bug #415031). It is in general a good practice to link to existing bug reports in the merge request. Again, this will make the life of the reviewer(s) much easier.
>
> 7) Your branch is missing the setup.py script for the new gdvbd plugin. If you haven't done so yet, I encourage you to go through the good practices detailed in the developers' guide at http://www.moovida.com/documentation/developers_guide/developers_guide.html
>
> 8) The plugin shouldn't be merged in elisa/moovida's tree: it is preferable to create a standalone project in Launchpad to host its code, track its issues separately and release it in an independent manner. This project should be declared as part of the Moovida Universe meta-project (https://launchpad.net/moovida-universe).
>
> 9) The change to the LIRC plugin seems unrelated, and in any case should be carefully explained, because it touches a sensitive piece of code.
>
> Thanks for reading patiently my remarks! Some of them might sound picky, but please know that your effort is valued, as a former core developer on the project it is very rewarding to see such cool contributions coming in. If you're interested in the fork, drop by on irc://freenode.net/#elisa, there's always someone hanging around there.

Revision history for this message
Olivier Tilloy (osomon) wrote :

> 1) I read that Fluendo switch to Banshee for Moovida 2.0, and searched
> for a fork but didn't found it. Maybe you could announce it anywhere?

The reason it hasn't been announced very visibly is that we don't have anything to show off yet, merely a forked branch with a couple of patches in it.

> 4/5) true too, thanks for fixing it, your code for the css problem
> running well here, should i make a comment about that in your merge
> proposal?

Please do!

> 8) Ok about that, i did only the plugin as a separate project
> https://launchpad.net/elisa-gdvbd
> The Problem is that using the plugin without the changes i made on the
> video_player.py (teletext issue and deinterlacing support) isn't funny
> (at least here in Germany where we have DVB streams interlaced and with
> teletext). For the teletext issue i can publish a patch and relate it to
> the bug, and for deinterlacing support i write a new bug report, is that
> the correct solution?

Yes, definitely the way to go about those issues.

> 9) Strange none else got issues with the lirc plugin (at least i found
> no bug report). On my machine its not working without that change, maybe
> its because i am using inputlirc
> ( http://www.realh.co.uk/dvbhowto/ar01s08.html ) instead of lirc, I'll
> try to track the problem and write a bug report.

Cool. The LIRC plugin is a delicate beast, usually a fix for a set of configurations is likely to break for another set of configurations, which is why a change needs a solid justification, so your investigation will be welcome.

> I'm pretty new to launchpad and bzr and i din't fully understand the way
> development is working there, so thanks again for the help.

No problem! Thanks for your contributions.

> Another short question: Should i delete this proposal?

No need to do this, it can remain here for reference.

Unmerged revisions

1619. By Jonathan Rauprich

DVB plugin done now.
Support for basic deinterlacing of TV stuff in play_video.py
Doesn't show message about not finding a teletext decoder.

1618. By Jonathan Rauprich

Support for EPG program guide and recordings. Code needs to be cleaned
up, documentated, and made nicer, but features working so far.

1617. By Jonathan Rauprich <joni@bb>

Fixed bug in lirc module.
Added initial dvb support.
Added initial recording support.

1616. By Jonathan Rauprich <joni@bb>

Convertet some exceptions to warnings, since they dosn't seem to make things bad

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'elisa-plugins/elisa/plugins/amp/protocol.py'
2--- elisa-plugins/elisa/plugins/amp/protocol.py 2009-11-09 15:44:51 +0000
3+++ elisa-plugins/elisa/plugins/amp/protocol.py 2010-05-30 10:34:24 +0000
4@@ -106,7 +106,7 @@
5 if diff < self.ping_period:
6 return
7
8- dfr = self.callRemote(Ping, cookie=self._cookie)
9+ dfr = self.callRemote(Ping)
10 self._startTimeout()
11 dfr.addCallback(self._pingCb)
12 dfr.addErrback(self._pingEb)
13
14=== added directory 'elisa-plugins/elisa/plugins/gdvbd'
15=== added file 'elisa-plugins/elisa/plugins/gdvbd/__init__.py'
16=== added file 'elisa-plugins/elisa/plugins/gdvbd/controller.py'
17--- elisa-plugins/elisa/plugins/gdvbd/controller.py 1970-01-01 00:00:00 +0000
18+++ elisa-plugins/elisa/plugins/gdvbd/controller.py 2010-05-30 10:34:24 +0000
19@@ -0,0 +1,257 @@
20+from elisa.core.utils import defer
21+from elisa.core.utils.i18n import install_translation
22+
23+from elisa.core.media_uri import MediaUri
24+from elisa.core.common import application
25+
26+from elisa.plugins.poblesec.base.preview_list import \
27+ DoubleLineMenuItemPreviewListController, SimpleListController
28+from elisa.plugins.poblesec.base.list import GenericListViewMode
29+from elisa.plugins.poblesec.actions import OpenControllerActionWithItem, \
30+ ContextualAction
31+from elisa.plugins.database.actions import PlayVideoAction
32+
33+from elisa.plugins.poblesec.link import Link
34+
35+from datetime import datetime
36+
37+_ = install_translation('gdvbd')
38+_p = install_translation('poblesec')
39+
40+def timestamp_to_day_time(timestamp):
41+ d = datetime.fromtimestamp(timestamp)
42+ return d.strftime('%a %H:%M')
43+
44+def channels_decorator(controller):
45+ link = Link()
46+ link.controller_path = '/gdvbd/devicegroups'
47+ link.label = _('TV Stations')
48+ controller.model.append(link)
49+ return defer.succeed(None)
50+
51+def recordings_decorator(controller):
52+ link = Link()
53+ link.controller_path = '/gdvbd/recordings'
54+ link.label = _('Recordings')
55+ controller.model.append(link)
56+ return defer.succeed(None)
57+
58+class OpenControllerActionWithItemAndName(OpenControllerActionWithItem):
59+ def __init__(self, controller, path):
60+ return super(OpenControllerActionWithItemAndName, self).__init__(\
61+ controller, path)
62+
63+ def execute(self, item):
64+ self._kwargs['item'] = item
65+ return self.open_controller(self.path, item.name, **self._kwargs)
66+
67+class DeviceGroupViewMode(GenericListViewMode):
68+ """
69+ Implementation of the common view modes API.
70+ """
71+ def get_label(self, item):
72+ return defer.succeed(item.name)
73+
74+ def get_sublabel(self, item):
75+ return defer.succeed("")
76+
77+ def get_default_image(self, item):
78+ return 'elisa.plugins.poblesec.glyphs.small.video'
79+
80+ def get_image(self, item, theme):
81+ return None
82+
83+ def get_preview_image(self, item, theme):
84+ return None
85+
86+class ScheduleViewMode(GenericListViewMode):
87+ """
88+ Implementation of the common view modes API.
89+ """
90+ def get_label(self, item):
91+ return defer.succeed("%s: %s" % (timestamp_to_day_time(\
92+ item.start_timestamp), item.name))
93+
94+ def get_sublabel(self, item):
95+ return defer.succeed(item.short_description)
96+
97+ def get_default_image(self, item):
98+ return 'elisa.plugins.poblesec.glyphs.small.video'
99+
100+ def get_image(self, item, theme):
101+ return None
102+
103+ def get_preview_image(self, item, theme):
104+ return None
105+
106+class ChannelViewMode(GenericListViewMode):
107+ """
108+ Implementation of the common view modes API.
109+ """
110+ def get_label(self, item):
111+ if len(item.network) > 0:
112+ return defer.succeed("%s (%s)" % (item.name, item.network))
113+ else:
114+ return defer.succeed("%s" % item.name)
115+
116+ def get_sublabel(self, item):
117+ if len(item.now_playing_name) > 0:
118+ return defer.succeed("%s %s" % (timestamp_to_day_time(
119+ item.now_playing_start_timestamp), item.now_playing_name))
120+ else:
121+ return defer.succeed("")
122+
123+
124+ def get_default_image(self, item):
125+ if item.is_radio_channel:
126+ return 'elisa.plugins.poblesec.glyphs.small.music'
127+ return 'elisa.plugins.poblesec.glyphs.small.video'
128+
129+ def get_image(self, item, theme):
130+ return None
131+
132+ def get_preview_image(self, item, theme):
133+ return None
134+
135+class RecordingViewMode(GenericListViewMode):
136+ """
137+ Implementation of the common view modes API.
138+ """
139+ def get_label(self, item):
140+ return defer.succeed(item.name)
141+
142+ def get_sublabel(self, item):
143+ return defer.succeed("%s %s %d min" % (item.channel_name, \
144+ timestamp_to_day_time(item.start_timestamp), item.length/60))
145+
146+ def get_default_image(self, item):
147+ return 'elisa.plugins.poblesec.glyphs.small.video'
148+
149+ def get_image(self, item, theme):
150+ return None
151+
152+ def get_preview_image(self, item, theme):
153+ return None
154+
155+class RecordScheduleAction(ContextualAction):
156+ name = "more"
157+
158+ def execute(self, item):
159+ def _close():
160+ main_controller.hide_popup()
161+
162+ def _record():
163+ muri = MediaUri("gdvbd://device-group/%d/channel/%d/schedule/%d" % \
164+ (self.controller.dg_id, self.controller.ch_id, item.id))
165+ application.resource_manager.post(muri)
166+ main_controller.hide_popup()
167+
168+ frontend = self.controller.frontend
169+ main_controller = frontend.controller
170+ caption = _('Record %s' % item.name )
171+ title = caption
172+
173+ text = _('%s Duration: %d min.' % (item.extended_description, \
174+ item.duration/60))
175+ buttons = [
176+ (_('Record this'), _record),
177+ (_('Close'), _close)
178+ ]
179+ return defer.succeed(main_controller.enqueue_popup(caption, \
180+ title, text, buttons))
181+
182+class DeleteRecordingAction(ContextualAction):
183+ name = "remove"
184+
185+ def execute(self, item):
186+ def _close():
187+ main_controller.hide_popup()
188+
189+ def _delete():
190+ muri = MediaUri("gdvbd://recording/%d" % item.id)
191+ application.resource_manager.delete(muri)
192+ self.controller.model.remove(item)
193+ main_controller.hide_popup()
194+
195+ frontend = self.controller.frontend
196+ main_controller = frontend.controller
197+ caption = _('%s' % item.name )
198+ title = caption
199+
200+ text = _('You sure u want to delete this recording?')
201+ buttons = [
202+ (_('Delete it'), _delete),
203+ (_('Close'), _close)
204+ ]
205+ return defer.succeed(main_controller.enqueue_popup(caption, \
206+ title, text, buttons))
207+
208+class DeviceGroupController(DoubleLineMenuItemPreviewListController):
209+ view_mode = DeviceGroupViewMode
210+ empty_label = _('No registered device groups found.')
211+ item_widget_kwargs = {'with_artwork_box': False}
212+
213+ def populate_model(self):
214+ muri = MediaUri("gdvbd://device-group/list")
215+ model, dfr = application.resource_manager.get(muri)
216+ return dfr
217+
218+ def create_actions(self):
219+ to_channels = OpenControllerActionWithItemAndName(self, \
220+ '/gdvbd/channels')
221+ return (to_channels, [])
222+
223+class ChannelsController(DoubleLineMenuItemPreviewListController):
224+ view_mode = ChannelViewMode
225+ empty_label = _('No Stations found.')
226+
227+ def initialize(self, item):
228+ self.dg_id = item.id
229+ return super(ChannelsController, self).initialize()
230+
231+ def populate_model(self):
232+ muri = MediaUri("gdvbd://device-group/%d/channel/list" % self.dg_id)
233+ model, dfr = application.resource_manager.get(muri)
234+ return dfr
235+
236+ def create_actions(self):
237+ play_tv = PlayVideoAction(self)
238+ show_epg = OpenControllerActionWithItemAndName(self, '/gdvbd/schedule')
239+ show_epg.name = "list"
240+ return (play_tv, [show_epg])
241+
242+class ScheduleController(DoubleLineMenuItemPreviewListController):
243+ view_mode = ScheduleViewMode
244+ empty_label = _("There is currently no schedule available for this channel")
245+
246+ def initialize(self, item):
247+ self.ch_id = item.id
248+ self.dg_id = item.device_group.id
249+ return super(ScheduleController, self).initialize()
250+
251+ def populate_model(self):
252+ muri = MediaUri("gdvbd://device-group/%d/channel/%d/schedule/list" % \
253+ (self.dg_id, self.ch_id))
254+ model, dfr = application.resource_manager.get(muri)
255+ return dfr
256+
257+ def create_actions(self):
258+ record_item = RecordScheduleAction(self)
259+ return (record_item, [])
260+
261+class RecordingController(DoubleLineMenuItemPreviewListController):
262+ view_mode = RecordingViewMode
263+ item_widget_kwargs = {'with_artwork_box': False}
264+
265+ empty_label = _("There is currently no recording available")
266+
267+ def populate_model(self):
268+ muri = MediaUri("gdvbd://recording/list")
269+ model, dfr = application.resource_manager.get(muri)
270+ return dfr
271+
272+ def create_actions(self):
273+ play_recording = PlayVideoAction(self)
274+ delete_recording = DeleteRecordingAction(self)
275+ return (play_recording, [delete_recording])
276+
277
278=== added directory 'elisa-plugins/elisa/plugins/gdvbd/i18n'
279=== added file 'elisa-plugins/elisa/plugins/gdvbd/i18n/__init__.py'
280=== added directory 'elisa-plugins/elisa/plugins/gdvbd/icons'
281=== added file 'elisa-plugins/elisa/plugins/gdvbd/icons/icon1.png'
282Binary files elisa-plugins/elisa/plugins/gdvbd/icons/icon1.png 1970-01-01 00:00:00 +0000 and elisa-plugins/elisa/plugins/gdvbd/icons/icon1.png 2010-05-30 10:34:24 +0000 differ
283=== added file 'elisa-plugins/elisa/plugins/gdvbd/icons/icon2.png'
284Binary files elisa-plugins/elisa/plugins/gdvbd/icons/icon2.png 1970-01-01 00:00:00 +0000 and elisa-plugins/elisa/plugins/gdvbd/icons/icon2.png 2010-05-30 10:34:24 +0000 differ
285=== added file 'elisa-plugins/elisa/plugins/gdvbd/models.py'
286--- elisa-plugins/elisa/plugins/gdvbd/models.py 1970-01-01 00:00:00 +0000
287+++ elisa-plugins/elisa/plugins/gdvbd/models.py 2010-05-30 10:34:24 +0000
288@@ -0,0 +1,85 @@
289+# -*- coding: utf-8 -*-
290+#
291+# This file is licensed under the GPL version 3.
292+# See "LICENSE.GPL" in the root of this distribution including a special
293+# exception to use Moovida with Fluendo's plugins.
294+#
295+# Author: Jonathan Rauprich <joni@noplu.de>
296+
297+from elisa.core.utils import defer
298+from elisa.core.components.model import Model
299+from elisa.plugins.base.models.media import PlayableModel
300+from elisa.core.media_uri import MediaUri
301+
302+class DeviceGroupModel(Model):
303+ def __init__(self):
304+ """
305+ Constructor. Initialize all the fields.
306+ """
307+ super(DeviceGroupModel, self).__init__()
308+ self.id = None
309+ self.name = None
310+ self.client = None
311+ self.recorder = None
312+ self.channel_list = None
313+
314+class ChannelModel(Model):
315+ def __init__(self):
316+ """
317+ Constructor. Initialize all the fields.
318+ """
319+ super(ChannelModel, self).__init__()
320+ self.id = None
321+ self.name = None
322+ self.network = None
323+ self.is_radio_channel = None
324+ self.url = None
325+ self.device_group = None
326+ self.now_playing_name = None
327+ self.now_playing_start_timestamp = None
328+
329+ def get_playable_model(self):
330+ playable_model = PlayableModel()
331+ playable_model.title = self.name
332+ playable_model.uri = MediaUri(self.url)
333+ playable_model.do_deinterlace = True
334+ return defer.succeed(playable_model)
335+
336+
337+class ScheduleModel(Model):
338+ def __init__(self):
339+ """
340+ Constructor. Initialize all the fields.
341+ """
342+ super(ScheduleModel, self).__init__()
343+ self.id = None
344+ self.name = None
345+ self.short_description = None
346+ self.extended_description = None
347+ self.duration = None
348+ self.start_time = None
349+ self.start_timestamp = None
350+ self.is_running = None
351+ self.is_scrambled = None
352+
353+class RecordingModel(Model):
354+ def __init__(self):
355+ """
356+ Constructor. Initialize all the fields.
357+ """
358+ super(RecordingModel, self).__init__()
359+ self.id = None
360+ self.name = None
361+ self.location = None
362+ self.description = None
363+ self.length = None
364+ self.start_time = None
365+ self.start_timestamp = None
366+ self.channel_name = None
367+
368+ def get_playable_model(self):
369+ playable_model = PlayableModel()
370+ playable_model.title = self.name
371+ playable_model.uri = MediaUri("file://%s" % self.location)
372+ playable_model.do_deinterlace = True
373+ return defer.succeed(playable_model)
374
375=== added file 'elisa-plugins/elisa/plugins/gdvbd/resource_provider.py'
376--- elisa-plugins/elisa/plugins/gdvbd/resource_provider.py 1970-01-01 00:00:00 +0000
377+++ elisa-plugins/elisa/plugins/gdvbd/resource_provider.py 2010-05-30 10:34:24 +0000
378@@ -0,0 +1,264 @@
379+# -*- coding: utf-8 -*-
380+#
381+# This file is licensed under the GPL version 3.
382+# See "LICENSE.GPL" in the root of this distribution including a special
383+# exception to use Moovida with Fluendo's plugins.
384+#
385+# Author: Jonathan Rauprich <joni@noplu.de>
386+
387+"""
388+Provide access to resources served by gnome-dvb-daemon over DBUS.
389+"""
390+
391+from elisa.core.components.resource_provider import ResourceProvider, \
392+ ResourceNotFound
393+from elisa.plugins.gdvbd.models import DeviceGroupModel, ChannelModel, \
394+ ScheduleModel, RecordingModel
395+from elisa.core.utils import defer
396+
397+from gnomedvb import DVBManagerClient, DVBRecordingsStoreClient
398+import re
399+
400+
401+
402+class GdvbdResourceProvider(ResourceProvider):
403+ """
404+ Implements REST access to gnome-dvb-daemon, with simple urls.
405+
406+ The interresting part of the gnome-dvb-daemon is like the following:
407+
408+ gdvbd
409+ |-> Device Groups
410+ | |-> Device Group 1
411+ | | |-> Channel List
412+ | | | |-> Channel 1
413+ | | | | |-> schedule
414+ | | | |-> Channel 2
415+ | | | | |-> ...
416+ | |-> Device Group 2
417+ | | |-> ....
418+ |-> Recordings
419+ | |-> Recording 1
420+ | |-> Recording 2
421+ | |-> ....
422+
423+ This REST implementation allows u the following actions
424+
425+ GET gdvbd://device-group/list
426+ Return list of device groups
427+ GET gdvbd://device-group/<GROUP_ID>/channel/list
428+ Return list of channels for device group
429+ GET gdvbd://device-group/<GROUP_ID>/channel/<CHANNEL_ID>/schedule/list
430+ Return list of schedules for channel
431+ GET gdvbd://recording/list
432+ Returns a list of recordings
433+
434+ POST gdvbd://device-group/<GROUP_ID>/channel/<CHANNEL_ID>/schedule/<schedule_ID>
435+ Recording the schedule on the channel
436+
437+ DELETE gdvbd://recording/<RECORDING_ID>
438+ Delete the recording
439+ """
440+
441+ base_uri = "gdvbd://"
442+ dev_groups = "%sdevice-group/list" % base_uri
443+ dev_groups_re = re.compile(dev_groups)
444+ channel_list = "%sdevice-group/(\d*)/channel/list" % base_uri
445+ channel_list_re = re.compile(channel_list)
446+ schedule_list = "%sdevice-group/(\d*)/channel/(\d*)/schedule/list" % base_uri
447+ schedule_list_re = re.compile(schedule_list)
448+ recording_list = "%srecording/list" % base_uri
449+ recording_list_re = re.compile(recording_list)
450+ create_recording = "%sdevice-group/(\d*)/channel/(\d*)/schedule/(\d*)" \
451+ % base_uri
452+ create_recording_re = re.compile(create_recording)
453+ delete_recording = "%srecording/(\d*)" % base_uri
454+ delete_recording_re = re.compile(delete_recording)
455+
456+ supported_uri = dev_groups + "|" + channel_list + "|" + schedule_list + "|" \
457+ + recording_list + "|" + create_recording + "|" + delete_recording
458+
459+ RELOAD_TIME = 300.0
460+
461+ def initialize(self):
462+ """
463+ Init the data stucture and register callbacks, but since this is
464+ taking a time, do it threaded.
465+ """
466+ dfr = super(GdvbdResourceProvider, self).initialize()
467+ # get a manager
468+ self.manager = DVBManagerClient()
469+ self.recorder = DVBRecordingsStoreClient()
470+ # load device groups, also do that if they change
471+ self._init_dgs()
472+ self.manager.connect("group-added", self._init_dgs)
473+ self.manager.connect("group-removed", self._init_dgs)
474+ self._init_recordings()
475+ self.recorder.connect("changed", self._init_recordings)
476+ return dfr
477+
478+ def _init_dgs(self, *args):
479+ self.device_groups = []
480+ for device_group in self.manager.get_registered_device_groups():
481+ dgmodel = self._create_dg_model(device_group)
482+ self.device_groups.append(dgmodel)
483+
484+ def _init_recordings(self, *args):
485+ self.recordings = []
486+ for rid in self.recorder.get_recordings():
487+ #informations -> 0 -> rid # 1 -> title # 2 -> description
488+ # 3 -> length # 4 -> start_timestamp # 5 -> channel_name
489+ # 6 -> location
490+ (informations, success) = self.recorder.get_all_informations(rid)
491+ if success:
492+ rmodel = RecordingModel()
493+ rmodel.id = rid
494+ rmodel.name = informations[1]
495+ rmodel.description = informations[2]
496+ rmodel.length = informations[3]
497+ rmodel.start_timestamp = informations[4]
498+ rmodel.channel_name = informations[5]
499+ rmodel.location = informations[6]
500+ (start_time, success) = self.recorder.get_start_time(rid)
501+ if success:
502+ rmodel.start_time = start_time
503+ self.recordings.append(rmodel)
504+
505+
506+ def _create_dg_model(self, device_group):
507+ dgmodel = DeviceGroupModel()
508+ dgmodel.id = device_group.get_id()
509+ dgmodel.name = device_group.get_name()
510+ dgmodel.client = device_group
511+ dgmodel.recorder = device_group.get_recorder()
512+ dgmodel.channels = []
513+ dgmodel.channel_list = device_group.get_channel_list()
514+ return dgmodel
515+
516+ def _create_chan_model(self, cid, cl):
517+ cm = ChannelModel()
518+ cm.id = cid
519+ (name, success) = cl.get_channel_name(cid)
520+ if success:
521+ cm.name = name
522+ (network, success) = cl.get_channel_network(cid)
523+ if success:
524+ cm.network = network
525+ (is_radio_channel, success) = cl.is_radio_channel(cid)
526+ if success:
527+ cm.is_radio_channel = is_radio_channel
528+ (url, success) = cl.get_channel_url(cid)
529+ if success:
530+ cm.url = url
531+ return cm
532+
533+ def _create_schedule(self, dg, cid):
534+ shed = dg.client.get_schedule(cid)
535+ schedule = []
536+ for eid in shed.get_all_events():
537+ smodel = ScheduleModel()
538+ smodel.id = eid
539+ (name, success) = shed.get_name(eid)
540+ if success:
541+ smodel.name = name
542+ (short_description, success) = shed.get_short_description(eid)
543+ if success:
544+ smodel.short_description = short_description
545+ (extended_description, success) = shed.get_extended_description(eid)
546+ if success:
547+ smodel.extended_description = extended_description
548+ (duration, success) = shed.get_duration(eid)
549+ if success:
550+ smodel.duration = duration
551+ (start_time, success) = shed.get_local_start_time(eid)
552+ if success:
553+ smodel.start_time = start_time
554+ (start_timestamp, success) = shed.get_local_start_timestamp(eid)
555+ if success:
556+ smodel.start_timestamp = start_timestamp
557+ (is_running, success) = shed.is_running(eid)
558+ if success:
559+ smodel.is_running = is_running
560+ (is_scrambled, success) = shed.is_scrambled(eid)
561+ if success:
562+ smodel.is_scrambled = is_scrambled
563+ schedule.append(smodel)
564+ return schedule
565+
566+ def _get_dg_for_dgid(self, dgid):
567+ for dg in self.device_groups:
568+ if dg.id == dgid:
569+ return dg
570+ return None
571+
572+
573+ def get(self, uri, context_model=None):
574+ url = str(uri)
575+
576+ m = self.dev_groups_re.match(url)
577+ if m:
578+ self._init_dgs()
579+ return (self.device_groups, defer.succeed(self.device_groups))
580+
581+ m = self.channel_list_re.match(url)
582+ if m:
583+ dg = self._get_dg_for_dgid(int(m.group(1)))
584+ if dg:
585+ channels = []
586+ for cid in dg.client.get_channel_list().get_channels():
587+ chmodel = self._create_chan_model(cid, dg.channel_list)
588+ chmodel.device_group = dg
589+ # Look whats on now
590+ shed = dg.client.get_schedule(chmodel.id)
591+ now = shed.now_playing()
592+ (chmodel.now_playing_name, success) = shed.get_name(now)
593+ (chmodel.now_playing_start_timestamp, success) = shed.\
594+ get_local_start_timestamp(now)
595+ channels.append(chmodel)
596+ return (channels, defer.succeed(channels))
597+ return (None, defer.fail(ResourceNotFound()))
598+
599+ m = self.schedule_list_re.match(url)
600+ if m:
601+
602+ dg = self._get_dg_for_dgid(int(m.group(1)))
603+ if dg:
604+ schedule = self._create_schedule(dg, int(m.group(2)))
605+ return (schedule, defer.succeed(schedule))
606+ return (None, defer.fail(ResourceNotFound()))
607+
608+ m = self.recording_list_re.match(url)
609+ if m:
610+ return (self.recordings, defer.succeed(self.recordings))
611+
612+ return (None, defer.fail(ResourceNotFound()))
613+
614+ def delete(self, uri):
615+ url = str(uri)
616+ m = self.delete_recording_re.match(url)
617+ if m:
618+ if self.recorder.delete(int(m.group(1))) == 1:
619+ return defer.succeed(None)
620+ return defer.fail(ResourceNotFound())
621+
622+ def post(self, uri, **parameters):
623+ url = str(uri)
624+ m = self.create_recording_re.match(url)
625+ if m:
626+ dg = self._get_dg_for_dgid(int(m.group(1)))
627+ (rec_id, success) = dg.recorder.add_timer_for_epg_event(
628+ int(m.group(3)), int(m.group(2)))
629+ if success:
630+ return defer.succeed(None)
631+ return defer.fail(ResourceNotFound())
632+
633+
634+
635+
636+
637+
638+
639+
640+
641+
642+
643
644=== modified file 'elisa-plugins/elisa/plugins/lirc/lirc_input.py'
645--- elisa-plugins/elisa/plugins/lirc/lirc_input.py 2009-11-09 15:44:51 +0000
646+++ elisa-plugins/elisa/plugins/lirc/lirc_input.py 2010-05-30 10:34:24 +0000
647@@ -141,7 +141,7 @@
648
649 def _got_event(self, hex_key, repeat, key_value, remote):
650 now = time.time()
651- if repeat != '00':
652+ if repeat != '0':
653 # If the remote sends a repeat signal, ie. repeat different from 00
654 elapsed_since_first_event = now - self._first_event_time
655 elapsed_since_last_repeat = now - self._last_repeat_time
656
657=== modified file 'elisa-plugins/elisa/plugins/pigment/widgets/panel.py'
658--- elisa-plugins/elisa/plugins/pigment/widgets/panel.py 2009-11-17 22:55:46 +0000
659+++ elisa-plugins/elisa/plugins/pigment/widgets/panel.py 2010-05-30 10:34:24 +0000
660@@ -14,6 +14,8 @@
661 # See "LICENSE.Moovida" in the root directory of this distribution package
662 # for details on that license.
663
664+from elisa.core import log
665+
666 from elisa.plugins.pigment.graph.node import Node
667 from elisa.plugins.pigment.graph.image import Image
668 from elisa.plugins.pigment.graph import keysyms
669@@ -210,37 +212,45 @@
670 self.bottom_right.set_position(x, y, az)
671
672 def _compute_border_sizes(self):
673- fx, fy = self.get_factors_absolute(self.left_width.unit)
674- self._left_width = fx*self.left_width.value
675-
676- fx, fy = self.get_factors_absolute(self.right_width.unit)
677- self._right_width = fx*self.right_width.value
678-
679- fx, fy = self.get_factors_absolute(self.top_height.unit)
680- self._top_height = fy*self.top_height.value
681-
682- fx, fy = self.get_factors_absolute(self.bottom_height.unit)
683- self._bottom_height = fy*self.bottom_height.value
684- self._sizes_computed = True
685+ try:
686+ fx, fy = self.get_factors_absolute(self.left_width.unit)
687+ self._left_width = fx*self.left_width.value
688+
689+ fx, fy = self.get_factors_absolute(self.right_width.unit)
690+ self._right_width = fx*self.right_width.value
691+
692+ fx, fy = self.get_factors_absolute(self.top_height.unit)
693+ self._top_height = fy*self.top_height.value
694+
695+ fx, fy = self.get_factors_absolute(self.bottom_height.unit)
696+ self._bottom_height = fy*self.bottom_height.value
697+
698+ self._sizes_computed = True
699+
700+ except AttributeError as e:
701+ log.warning('panel', e.message)
702
703 def _update_size(self):
704 if not self.is_mapped:
705 return
706 self._compute_border_sizes()
707- self.top_left.set_size(self._left_width, self._top_height)
708- self.top_right.set_size(self._right_width, self._top_height)
709- self.bottom_left.set_size(self._left_width, self._bottom_height)
710- self.bottom_right.set_size(self._right_width, self._bottom_height)
711-
712- self._middle_width = self.absolute_width - self._left_width - self._right_width
713- self._middle_height = self.absolute_height - self._top_height - self._bottom_height
714-
715- self.top_middle.set_size(self._middle_width, self._top_height)
716- self.middle_left.set_size(self._left_width, self._middle_height)
717- self.middle_middle.set_size(self._middle_width, self._middle_height)
718- self.middle_right.set_size(self._right_width, self._middle_height)
719- self.bottom_middle.set_size(self._middle_width, self._bottom_height)
720-
721+
722+ try:
723+ self.top_left.set_size(self._left_width, self._top_height)
724+ self.top_right.set_size(self._right_width, self._top_height)
725+ self.bottom_left.set_size(self._left_width, self._bottom_height)
726+ self.bottom_right.set_size(self._right_width, self._bottom_height)
727+
728+ self._middle_width = self.absolute_width - self._left_width - self._right_width
729+ self._middle_height = self.absolute_height - self._top_height - self._bottom_height
730+
731+ self.top_middle.set_size(self._middle_width, self._top_height)
732+ self.middle_left.set_size(self._left_width, self._middle_height)
733+ self.middle_middle.set_size(self._middle_width, self._middle_height)
734+ self.middle_right.set_size(self._right_width, self._middle_height)
735+ self.bottom_middle.set_size(self._middle_width, self._bottom_height)
736+ except AttributeError as e:
737+ log.warning('panel', e.message)
738
739
740 @classmethod
741
742=== modified file 'elisa-plugins/elisa/plugins/poblesec/player_video.py'
743--- elisa-plugins/elisa/plugins/poblesec/player_video.py 2010-01-28 17:18:54 +0000
744+++ elisa-plugins/elisa/plugins/poblesec/player_video.py 2010-05-30 10:34:24 +0000
745@@ -489,7 +489,33 @@
746
747 self.pgm_sink = gst.element_factory_make('pgmimagesink')
748 self.pipeline = gst.element_factory_make('playbin')
749- self.pipeline.set_property('video-sink', self.pgm_sink)
750+ # Here we go now and add deinteralcing support for the pipeline
751+ # This is done, by adding the following pipeline as video-sink
752+ #
753+ # -> ffmpegcolorspace -> deinterlace -> ffmpegcolorspace -> pgmimagesink
754+ # csc1 deinterlacde csc2 pgm_sink
755+ #
756+ # ffdeinterlace could do this without colorspaceconversion, but it can't
757+ # be disabled that simple and has no further options
758+ bin = gst.Bin("deinterlacebin")
759+ csc = gst.element_factory_make("ffmpegcolorspace")
760+ csc2 = gst.element_factory_make("ffmpegcolorspace")
761+
762+ self.deinterlace = gst.element_factory_make("deinterlace")
763+ # Disable deinterlacing by default
764+ self.deinterlace.set_property("mode", 2)
765+
766+ bin.add(csc)
767+ bin.add(self.deinterlace)
768+ bin.add(self.pgm_sink)
769+ bin.add(csc2)
770+
771+ pad = csc.get_pad("sink")
772+ ghostpad = gst.GhostPad("sink", pad)
773+ bin.add_pad(ghostpad)
774+
775+ gst.element_link_many(csc, self.deinterlace, csc2, self.pgm_sink)
776+ self.pipeline.set_property("video-sink", bin)
777
778 self.status = self.STOPPED
779 self.target_status = self.STOPPED
780@@ -654,7 +680,12 @@
781 details = caps.to_string().split(', ')
782 mimetype = details[0]
783 decoder = pbutils.get_decoder_description(mimetype)
784- self.emit('player-missing-decoder', mimetype, decoder)
785+ # Gestreamer complains that teletext decoder is missing, but there
786+ # is no teletext decoder and ints not realy a problem as long as u
787+ # don't care for teletext. So this is to prevent the warning message
788+ # poping up everytime a videostream with teletext is played.
789+ if mimetype != "private/teletext":
790+ self.emit('player-missing-decoder', mimetype, decoder)
791 elif message.structure.get_name() == 'redirect':
792 new_location = message.structure['new-location']
793 if '://' not in new_location:
794@@ -821,6 +852,18 @@
795 self.filename = model.title or model.uri.filename
796 self.stop()
797 uri = unicode(model.uri).encode(locale_helper.gst_file_encoding())
798+
799+ # Here we enable deinterlacing if the model got a attribute
800+ # do deinterlace set to True
801+ try:
802+ if model.do_deinterlace:
803+ self.deinterlace.set_property("mode", 1)
804+ self.debug("Enabling deinterlacing for this video")
805+ else:
806+ self.deinterlace.set_property("mode", 2)
807+ except AttributeError:
808+ self.deinterlace.set_property("mode", 2)
809+
810 if uri.startswith('file://'):
811 # Hack to workaround the messy handling of file paths using MediaUri
812 # objects. In various places in the code, file paths are not
813
814=== added directory 'elisa-plugins/elisa_plugin_gdvbd.egg-info'
815=== added file 'elisa-plugins/elisa_plugin_gdvbd.egg-info/PKG-INFO'
816--- elisa-plugins/elisa_plugin_gdvbd.egg-info/PKG-INFO 1970-01-01 00:00:00 +0000
817+++ elisa-plugins/elisa_plugin_gdvbd.egg-info/PKG-INFO 2010-05-30 10:34:24 +0000
818@@ -0,0 +1,10 @@
819+Metadata-Version: 1.0
820+Name: elisa-plugin-gdvbd
821+Version: 0.1
822+Summary: Gnome DVB Daemon Plugin
823+Home-page: https://code.launchpad.net/~joni-noplu/moovida/moovida-dvb
824+Author: Jonathan Rauprich
825+Author-email: joni@noplu.de
826+License: GPL3
827+Description: Watch TV, Record Shows, View ur Recordings via gnome-dvb-daemon, now availible in moovida.
828+Platform: UNKNOWN
829
830=== added file 'elisa-plugins/elisa_plugin_gdvbd.egg-info/controller_mappings.txt'
831--- elisa-plugins/elisa_plugin_gdvbd.egg-info/controller_mappings.txt 1970-01-01 00:00:00 +0000
832+++ elisa-plugins/elisa_plugin_gdvbd.egg-info/controller_mappings.txt 2010-05-30 10:34:24 +0000
833@@ -0,0 +1,4 @@
834+/gdvbd/channels = elisa.plugins.gdvbd.controller:ChannelsController
835+/gdvbd/devicegroups = elisa.plugins.gdvbd.controller:DeviceGroupController
836+/gdvbd/schedule = elisa.plugins.gdvbd.controller:ScheduleController
837+/gdvbd/recordings = elisa.plugins.gdvbd.controller:RecordingController
838
839=== added file 'elisa-plugins/elisa_plugin_gdvbd.egg-info/decorator_mappings.txt'
840--- elisa-plugins/elisa_plugin_gdvbd.egg-info/decorator_mappings.txt 1970-01-01 00:00:00 +0000
841+++ elisa-plugins/elisa_plugin_gdvbd.egg-info/decorator_mappings.txt 2010-05-30 10:34:24 +0000
842@@ -0,0 +1,3 @@
843+/poblesec/tv_menu = elisa.plugins.gdvbd.controller:recordings_decorator
844+/poblesec/tv_menu = elisa.plugins.gdvbd.controller:channels_decorator
845+
846
847=== added file 'elisa-plugins/elisa_plugin_gdvbd.egg-info/dependency_links.txt'
848--- elisa-plugins/elisa_plugin_gdvbd.egg-info/dependency_links.txt 1970-01-01 00:00:00 +0000
849+++ elisa-plugins/elisa_plugin_gdvbd.egg-info/dependency_links.txt 2010-05-30 10:34:24 +0000
850@@ -0,0 +1,1 @@
851+
852
853=== added file 'elisa-plugins/elisa_plugin_gdvbd.egg-info/entry_points.txt'
854--- elisa-plugins/elisa_plugin_gdvbd.egg-info/entry_points.txt 1970-01-01 00:00:00 +0000
855+++ elisa-plugins/elisa_plugin_gdvbd.egg-info/entry_points.txt 2010-05-30 10:34:24 +0000
856@@ -0,0 +1,3 @@
857+ [elisa.core.components.resource_provider]
858+ YoutubeResourceProvider = elisa.plugins.gdvbd.resource_provider:GdvbdResourceProvider
859+
860
861=== added file 'elisa-plugins/elisa_plugin_gdvbd.egg-info/namespace_packages.txt'
862--- elisa-plugins/elisa_plugin_gdvbd.egg-info/namespace_packages.txt 1970-01-01 00:00:00 +0000
863+++ elisa-plugins/elisa_plugin_gdvbd.egg-info/namespace_packages.txt 2010-05-30 10:34:24 +0000
864@@ -0,0 +1,2 @@
865+elisa
866+elisa.plugins
867
868=== added file 'elisa-plugins/elisa_plugin_gdvbd.egg-info/top_level.txt'
869--- elisa-plugins/elisa_plugin_gdvbd.egg-info/top_level.txt 1970-01-01 00:00:00 +0000
870+++ elisa-plugins/elisa_plugin_gdvbd.egg-info/top_level.txt 2010-05-30 10:34:24 +0000
871@@ -0,0 +1,1 @@
872+elisa

Subscribers

People subscribed via source and target branches