Merge lp:~laurentf/arte+7recorder/arte+7recorder into lp:arte+7recorder

Proposed by laurentf
Status: Needs review
Proposed branch: lp:~laurentf/arte+7recorder/arte+7recorder
Merge into: lp:arte+7recorder
Diff against target: 2791 lines (+1386/-1085)
6 files modified
arte7recorder/Arte7recorderWindow.ui (+945/-767)
arte7recorder/Catalog.py (+108/-79)
arte7recorder/arte7recorder.py (+79/-233)
arte7recorder/fn_download.py (+242/-0)
arte7recorder/locale_cmd.sh (+5/-0)
setup.py (+7/-6)
To merge this branch: bzr merge lp:~laurentf/arte+7recorder/arte+7recorder
Reviewer Review Type Date Requested Status
Arte +7 recorder Pending
Review via email: mp+287798@code.launchpad.net
To post a comment you must log in.
65. By laurentf

Rewritten the quality determination part in the downloading section

66. By laurentf

fixed a bug in the language selection (french=*_1, spanish=*_12, ...)

67. By laurentf

Fixed the downloading issue ; stripped the download functions from the GUI part

68. By laurentf

Included the new fn_download.py functions list into the setup script ; updated the french localization

69. By laurentf

Updated localization ; updated icon

Unmerged revisions

69. By laurentf

Updated localization ; updated icon

68. By laurentf

Included the new fn_download.py functions list into the setup script ; updated the french localization

67. By laurentf

Fixed the downloading issue ; stripped the download functions from the GUI part

66. By laurentf

fixed a bug in the language selection (french=*_1, spanish=*_12, ...)

65. By laurentf

Rewritten the quality determination part in the downloading section

64. By laurentf

Added a new window to specify the status of the videos retrieval
The Catalog object is not anymore relying on an external file to pass its knowledge to the GUI
This Catalog object is now furthermore factorized/objectified

63. By laurentf

Now parsing the whole list of shows from JSON

62. By laurentf

Added the capability to parse directly the source JSON (instead of the react output in the front page)

61. By laurentf

Fixed the crashing application due to the modified arte catalog

60. By laurentf

Adapted ARTE's switch to react.js

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'arte-icon.png'
2Binary files arte-icon.png 2014-08-30 10:22:59 +0000 and arte-icon.png 2017-03-19 14:31:17 +0000 differ
3=== modified file 'arte7recorder/Arte7recorderWindow.ui'
4--- arte7recorder/Arte7recorderWindow.ui 2015-05-12 11:58:19 +0000
5+++ arte7recorder/Arte7recorderWindow.ui 2017-03-19 14:31:17 +0000
6@@ -1,579 +1,14 @@
7-<?xml version="1.0"?>
8+<?xml version="1.0" encoding="UTF-8"?>
9+<!-- Generated with glade 3.19.0 -->
10 <interface>
11 <requires lib="gtk+" version="2.16"/>
12- <!-- interface-naming-policy project-wide -->
13- <object class="GtkListStore" id="liststore1">
14- <columns>
15- <!-- column-name Player -->
16- <column type="gchararray"/>
17- </columns>
18- <data>
19- <row>
20- <col id="0" translatable="yes">totem</col>
21- </row>
22- <row>
23- <col id="0" translatable="yes">vlc</col>
24- </row>
25- <row>
26- <col id="0" translatable="yes">mplayer</col>
27- </row>
28- </data>
29- </object>
30- <object class="GtkWindow" id="arte7recorder_window">
31- <property name="title" translatable="yes">Arte +7 Recorder</property>
32- <property name="window_position">center-always</property>
33- <property name="icon">./icon.png</property>
34- <signal name="destroy" handler="on_destroy"/>
35- <child>
36- <object class="GtkVBox" id="vbox1">
37- <property name="visible">True</property>
38- <child>
39- <object class="GtkMenuBar" id="menubar">
40- <property name="visible">True</property>
41- <child>
42- <object class="GtkMenuItem" id="fichiers">
43- <property name="visible">True</property>
44- <property name="label" translatable="yes">_Files</property>
45- <property name="use_underline">True</property>
46- <child type="submenu">
47- <object class="GtkMenu" id="menu_fichiers">
48- <property name="visible">True</property>
49- <child>
50- <object class="GtkImageMenuItem" id="actualiser">
51- <property name="label">gtk-refresh</property>
52- <property name="visible">True</property>
53- <property name="use_underline">True</property>
54- <property name="use_stock">True</property>
55- <signal name="activate" handler="on_actu"/>
56- </object>
57- </child>
58- <child>
59- <object class="GtkImageMenuItem" id="preferences">
60- <property name="label">gtk-preferences</property>
61- <property name="visible">True</property>
62- <property name="use_underline">True</property>
63- <property name="use_stock">True</property>
64- <signal name="activate" handler="preferences"/>
65- </object>
66- </child>
67- <child>
68- <object class="GtkImageMenuItem" id="quit">
69- <property name="label">gtk-quit</property>
70- <property name="visible">True</property>
71- <property name="use_underline">True</property>
72- <property name="use_stock">True</property>
73- <signal name="activate" handler="on_destroy"/>
74- </object>
75- </child>
76- </object>
77- </child>
78- </object>
79- </child>
80- <child>
81- <object class="GtkMenuItem" id="aide">
82- <property name="visible">True</property>
83- <property name="label" translatable="yes">_Help</property>
84- <property name="use_underline">True</property>
85- <child type="submenu">
86- <object class="GtkMenu" id="menu_aide">
87- <property name="visible">True</property>
88- <child>
89- <object class="GtkImageMenuItem" id="about">
90- <property name="label">gtk-about</property>
91- <property name="visible">True</property>
92- <property name="use_underline">True</property>
93- <property name="use_stock">True</property>
94- <signal name="activate" handler="about"/>
95- </object>
96- </child>
97- </object>
98- </child>
99- </object>
100- </child>
101- </object>
102- <packing>
103- <property name="expand">False</property>
104- <property name="position">1</property>
105- </packing>
106- </child>
107- <child>
108- <object class="GtkHBox" id="hbox2">
109- <property name="visible">True</property>
110- <child>
111- <object class="GtkVBox" id="vbox3">
112- <property name="visible">True</property>
113- <child>
114- <object class="GtkFrame" id="frame5">
115- <property name="height_request">300</property>
116- <property name="visible">True</property>
117- <property name="label_xalign">0</property>
118- <property name="shadow_type">none</property>
119- <child>
120- <object class="GtkAlignment" id="alignment5">
121- <property name="visible">True</property>
122- <property name="top_padding">10</property>
123- <property name="left_padding">12</property>
124- <child>
125- <object class="GtkScrolledWindow" id="scrolledwindow1">
126- <property name="visible">True</property>
127- <property name="can_focus">True</property>
128- <property name="hscrollbar_policy">never</property>
129- <property name="vscrollbar_policy">automatic</property>
130- <property name="shadow_type">etched-in</property>
131- <child>
132- <object class="GtkTreeView" id="treeview_disp">
133- <property name="visible">True</property>
134- <property name="can_focus">True</property>
135- <property name="tooltip_text" translatable="yes">Double click to show summary</property>
136- <property name="headers_clickable">False</property>
137- <property name="search_column">0</property>
138- <signal name="row_activated" handler="dl_resume"/>
139- </object>
140- </child>
141- </object>
142- </child>
143- </object>
144- </child>
145- <child type="label">
146- <object class="GtkLabel" id="label5">
147- <property name="visible">True</property>
148- <property name="label" translatable="yes">Reportage:</property>
149- <attributes>
150- <attribute name="weight" value="bold"/>
151- </attributes>
152- </object>
153- </child>
154- </object>
155- <packing>
156- <property name="padding">5</property>
157- <property name="position">0</property>
158- </packing>
159- </child>
160- <child>
161- <object class="GtkFrame" id="frame4">
162- <property name="no_show_all">True</property>
163- <property name="label_xalign">0</property>
164- <property name="shadow_type">none</property>
165- <child>
166- <object class="GtkAlignment" id="alignment4">
167- <property name="visible">True</property>
168- <property name="top_padding">10</property>
169- <property name="left_padding">12</property>
170- <child>
171- <object class="GtkVBox" id="vbox4">
172- <property name="visible">True</property>
173- <child>
174- <object class="GtkScrolledWindow" id="scrolledwindow2">
175- <property name="visible">True</property>
176- <property name="can_focus">True</property>
177- <property name="hscrollbar_policy">never</property>
178- <property name="vscrollbar_policy">automatic</property>
179- <property name="shadow_type">etched-in</property>
180- <child>
181- <object class="GtkTreeView" id="treeview_dl">
182- <property name="visible">True</property>
183- <property name="can_focus">True</property>
184- <property name="search_column">0</property>
185- <signal name="row_activated" handler="dl_resume"/>
186- </object>
187- </child>
188- </object>
189- <packing>
190- <property name="position">0</property>
191- </packing>
192- </child>
193- <child>
194- <object class="GtkVButtonBox" id="vbuttonbox1">
195- <property name="visible">True</property>
196- <child>
197- <object class="GtkButton" id="bouton_dl">
198- <property name="label" translatable="yes">Download</property>
199- <property name="visible">True</property>
200- <property name="can_focus">True</property>
201- <property name="receives_default">True</property>
202- <signal name="clicked" handler="on_telecharge"/>
203- </object>
204- <packing>
205- <property name="expand">False</property>
206- <property name="fill">False</property>
207- <property name="position">0</property>
208- </packing>
209- </child>
210- <child>
211- <object class="GtkButton" id="button3">
212- <property name="label">gtk-undo</property>
213- <property name="can_focus">True</property>
214- <property name="receives_default">True</property>
215- <property name="use_stock">True</property>
216- <signal name="clicked" handler="on_cancel"/>
217- </object>
218- <packing>
219- <property name="expand">False</property>
220- <property name="fill">False</property>
221- <property name="position">1</property>
222- </packing>
223- </child>
224- </object>
225- <packing>
226- <property name="expand">False</property>
227- <property name="fill">False</property>
228- <property name="pack_type">end</property>
229- <property name="position">1</property>
230- </packing>
231- </child>
232- </object>
233- </child>
234- </object>
235- </child>
236- <child type="label">
237- <object class="GtkLabel" id="label4">
238- <property name="visible">True</property>
239- <property name="label" translatable="yes">Programmes selected for download :</property>
240- <attributes>
241- <attribute name="weight" value="bold"/>
242- </attributes>
243- </object>
244- </child>
245- </object>
246- <packing>
247- <property name="position">1</property>
248- </packing>
249- </child>
250- </object>
251- <packing>
252- <property name="position">0</property>
253- </packing>
254- </child>
255- <child>
256- <object class="GtkVBox" id="vbox5">
257- <property name="visible">True</property>
258- <property name="homogeneous">True</property>
259- <child>
260- <object class="GtkVBox" id="vbox6">
261- <property name="visible">True</property>
262- <child>
263- <object class="GtkFixed" id="fixed2">
264- <property name="visible">True</property>
265- </object>
266- <packing>
267- <property name="fill">False</property>
268- <property name="position">0</property>
269- </packing>
270- </child>
271- <child>
272- <object class="GtkButton" id="bouton_add">
273- <property name="visible">True</property>
274- <property name="can_focus">True</property>
275- <property name="receives_default">True</property>
276- <property name="tooltip_text" translatable="yes">Add reportage</property>
277- <property name="image">image_add</property>
278- <signal name="clicked" handler="on_add_emi"/>
279- </object>
280- <packing>
281- <property name="expand">False</property>
282- <property name="fill">False</property>
283- <property name="position">1</property>
284- </packing>
285- </child>
286- <child>
287- <object class="GtkFixed" id="fixed4">
288- <property name="visible">True</property>
289- </object>
290- <packing>
291- <property name="fill">False</property>
292- <property name="position">2</property>
293- </packing>
294- </child>
295- </object>
296- <packing>
297- <property name="fill">False</property>
298- <property name="position">0</property>
299- </packing>
300- </child>
301- <child>
302- <object class="GtkVBox" id="vbox7">
303- <property name="visible">True</property>
304- <child>
305- <object class="GtkFixed" id="fixed6">
306- <property name="visible">True</property>
307- </object>
308- <packing>
309- <property name="fill">False</property>
310- <property name="position">0</property>
311- </packing>
312- </child>
313- <child>
314- <object class="GtkButton" id="bouton_del">
315- <property name="can_focus">True</property>
316- <property name="receives_default">True</property>
317- <property name="no_show_all">True</property>
318- <property name="image">image_del</property>
319- <signal name="clicked" handler="on_del_emi"/>
320- </object>
321- <packing>
322- <property name="expand">False</property>
323- <property name="fill">False</property>
324- <property name="position">1</property>
325- </packing>
326- </child>
327- <child>
328- <object class="GtkFixed" id="fixed5">
329- <property name="visible">True</property>
330- </object>
331- <packing>
332- <property name="fill">False</property>
333- <property name="position">2</property>
334- </packing>
335- </child>
336- </object>
337- <packing>
338- <property name="fill">False</property>
339- <property name="position">1</property>
340- </packing>
341- </child>
342- </object>
343- <packing>
344- <property name="expand">False</property>
345- <property name="fill">False</property>
346- <property name="position">1</property>
347- </packing>
348- </child>
349- <child>
350- <object class="GtkVBox" id="vbox2">
351- <property name="visible">True</property>
352- <child>
353- <object class="GtkFrame" id="frame1">
354- <property name="height_request">300</property>
355- <property name="visible">True</property>
356- <property name="label_xalign">0</property>
357- <property name="shadow_type">none</property>
358- <child>
359- <object class="GtkVBox" id="vbox10">
360- <property name="height_request">300</property>
361- <property name="visible">True</property>
362- <child>
363- <object class="GtkImage" id="image_emi">
364- <property name="visible">True</property>
365- <property name="yalign">1</property>
366- </object>
367- <packing>
368- <property name="expand">False</property>
369- <property name="fill">False</property>
370- <property name="position">0</property>
371- </packing>
372- </child>
373- <child>
374- <object class="GtkFrame" id="frame2">
375- <property name="visible">True</property>
376- <property name="label_xalign">0</property>
377- <property name="label_yalign">0</property>
378- <property name="shadow_type">none</property>
379- <child>
380- <object class="GtkAlignment" id="alignment1">
381- <property name="visible">True</property>
382- <property name="yalign">0</property>
383- <property name="yscale">0</property>
384- <child>
385- <object class="GtkLabel" id="label6">
386- <property name="visible">True</property>
387- <property name="xalign">0</property>
388- <property name="yalign">1</property>
389- <property name="use_markup">True</property>
390- </object>
391- </child>
392- </object>
393- </child>
394- <child type="label">
395- <object class="GtkLabel" id="label2">
396- <property name="visible">True</property>
397- <property name="yalign">0</property>
398- <property name="label" translatable="yes">Name:</property>
399- <attributes>
400- <attribute name="weight" value="bold"/>
401- </attributes>
402- </object>
403- </child>
404- </object>
405- <packing>
406- <property name="expand">False</property>
407- <property name="fill">False</property>
408- <property name="padding">2</property>
409- <property name="position">1</property>
410- </packing>
411- </child>
412- <child>
413- <object class="GtkFrame" id="frame3">
414- <property name="visible">True</property>
415- <property name="label_xalign">0</property>
416- <property name="label_yalign">0</property>
417- <property name="shadow_type">none</property>
418- <child>
419- <object class="GtkAlignment" id="alignment2">
420- <property name="visible">True</property>
421- <property name="yalign">0</property>
422- <property name="yscale">0</property>
423- <child>
424- <object class="GtkLabel" id="label7">
425- <property name="visible">True</property>
426- <property name="xalign">0</property>
427- <property name="yalign">1</property>
428- <property name="use_markup">True</property>
429- </object>
430- </child>
431- </object>
432- </child>
433- <child type="label">
434- <object class="GtkLabel" id="label3">
435- <property name="visible">True</property>
436- <property name="yalign">1</property>
437- <property name="label" translatable="yes">Date:</property>
438- <attributes>
439- <attribute name="weight" value="bold"/>
440- </attributes>
441- </object>
442- </child>
443- </object>
444- <packing>
445- <property name="expand">False</property>
446- <property name="fill">False</property>
447- <property name="padding">2</property>
448- <property name="position">2</property>
449- </packing>
450- </child>
451- <child>
452- <object class="GtkFrame" id="frame6">
453- <property name="visible">True</property>
454- <property name="label_xalign">0</property>
455- <property name="label_yalign">0</property>
456- <property name="shadow_type">none</property>
457- <child>
458- <object class="GtkAlignment" id="alignment6">
459- <property name="visible">True</property>
460- <property name="yalign">0</property>
461- <property name="yscale">0</property>
462- <child>
463- <object class="GtkLabel" id="label13">
464- <property name="visible">True</property>
465- <property name="xalign">0</property>
466- <property name="yalign">1</property>
467- <property name="use_markup">True</property>
468- </object>
469- </child>
470- </object>
471- </child>
472- <child type="label">
473- <object class="GtkLabel" id="label14">
474- <property name="visible">True</property>
475- <property name="yalign">0</property>
476- <property name="label" translatable="yes">Time:</property>
477- <attributes>
478- <attribute name="weight" value="bold"/>
479- </attributes>
480- </object>
481- </child>
482- </object>
483- <packing>
484- <property name="expand">False</property>
485- <property name="fill">False</property>
486- <property name="padding">2</property>
487- <property name="position">3</property>
488- </packing>
489- </child>
490- </object>
491- </child>
492- <child type="label_item">
493- <placeholder/>
494- </child>
495- </object>
496- <packing>
497- <property name="expand">False</property>
498- <property name="fill">False</property>
499- <property name="padding">5</property>
500- <property name="position">0</property>
501- </packing>
502- </child>
503- <child>
504- <object class="GtkFrame" id="frame8">
505- <property name="visible">True</property>
506- <property name="label_xalign">0</property>
507- <property name="shadow_type">none</property>
508- <child>
509- <object class="GtkScrolledWindow" id="scrolledwindow4">
510- <property name="visible">True</property>
511- <property name="can_focus">True</property>
512- <property name="hscrollbar_policy">never</property>
513- <property name="shadow_type">etched-in</property>
514- <child>
515- <object class="GtkTextView" id="textview2">
516- <property name="height_request">0</property>
517- <property name="visible">True</property>
518- <property name="can_focus">True</property>
519- <property name="editable">False</property>
520- <property name="wrap_mode">word</property>
521- <property name="cursor_visible">False</property>
522- <property name="buffer">textbuffer1</property>
523- </object>
524- </child>
525- </object>
526- </child>
527- <child type="label">
528- <object class="GtkLabel" id="label15">
529- <property name="visible">True</property>
530- <property name="label" translatable="yes">Summary:</property>
531- <attributes>
532- <attribute name="weight" value="bold"/>
533- </attributes>
534- </object>
535- </child>
536- </object>
537- <packing>
538- <property name="position">1</property>
539- </packing>
540- </child>
541- </object>
542- <packing>
543- <property name="position">2</property>
544- </packing>
545- </child>
546- </object>
547- <packing>
548- <property name="position">2</property>
549- </packing>
550- </child>
551- <child>
552- <object class="GtkStatusbar" id="statusbar1">
553- <property name="visible">True</property>
554- <property name="spacing">2</property>
555- <child>
556- <object class="GtkLabel" id="status">
557- <property name="visible">True</property>
558- </object>
559- <packing>
560- <property name="position">1</property>
561- </packing>
562- </child>
563- </object>
564- <packing>
565- <property name="expand">False</property>
566- <property name="pack_type">end</property>
567- <property name="position">0</property>
568- </packing>
569- </child>
570- </object>
571- </child>
572- </object>
573- <object class="GtkImage" id="image_del">
574- <property name="visible">True</property>
575- <property name="tooltip_text" translatable="yes">Remove reportage</property>
576- <property name="stock">gtk-remove</property>
577- </object>
578 <object class="GtkAboutDialog" id="arte7recorder_about">
579+ <property name="can_focus">False</property>
580 <property name="border_width">5</property>
581 <property name="resizable">False</property>
582 <property name="window_position">center-always</property>
583 <property name="icon">./icon.png</property>
584 <property name="type_hint">normal</property>
585- <property name="has_separator">False</property>
586 <property name="program_name">Arte +7 Recorder</property>
587 <property name="version">5.0</property>
588 <property name="copyright">Copyright (C) 2009 Adrien Beudin beudbeud@mail.com</property>
589@@ -864,47 +299,288 @@
590 <property name="authors">beudbeud</property>
591 <property name="logo">./icon.png</property>
592 <child internal-child="vbox">
593- <object class="GtkVBox" id="dialog-vbox1">
594+ <object class="GtkBox" id="dialog-vbox1">
595 <property name="visible">True</property>
596+ <property name="can_focus">False</property>
597 <property name="spacing">2</property>
598 <child internal-child="action_area">
599- <object class="GtkHButtonBox" id="dialog-action_area1">
600- <property name="visible">True</property>
601- <property name="layout_style">end</property>
602- </object>
603- <packing>
604- <property name="expand">False</property>
605- <property name="fill">False</property>
606- <property name="pack_type">end</property>
607- <property name="position">0</property>
608- </packing>
609- </child>
610- </object>
611- </child>
612+ <object class="GtkButtonBox" id="dialog-action_area1">
613+ <property name="visible">True</property>
614+ <property name="can_focus">False</property>
615+ <property name="layout_style">end</property>
616+ </object>
617+ <packing>
618+ <property name="expand">False</property>
619+ <property name="fill">False</property>
620+ <property name="pack_type">end</property>
621+ <property name="position">0</property>
622+ </packing>
623+ </child>
624+ </object>
625+ </child>
626+ </object>
627+ <object class="GtkMenu" id="contextMenu">
628+ <property name="visible">True</property>
629+ <property name="can_focus">False</property>
630+ <child>
631+ <object class="GtkImageMenuItem" id="menucontext_play">
632+ <property name="label">gtk-media-play</property>
633+ <property name="visible">True</property>
634+ <property name="sensitive">False</property>
635+ <property name="can_focus">False</property>
636+ <property name="use_underline">True</property>
637+ <property name="use_stock">True</property>
638+ <signal name="activate" handler="on_menucontext_play" swapped="no"/>
639+ </object>
640+ </child>
641+ <child>
642+ <object class="GtkImageMenuItem" id="menucontext_ann">
643+ <property name="label">gtk-cancel</property>
644+ <property name="visible">True</property>
645+ <property name="sensitive">False</property>
646+ <property name="can_focus">False</property>
647+ <property name="use_underline">True</property>
648+ <property name="use_stock">True</property>
649+ <signal name="activate" handler="on_menucontext_ann" swapped="no"/>
650+ </object>
651+ </child>
652+ <child>
653+ <object class="GtkImageMenuItem" id="menucontext_clean">
654+ <property name="label">gtk-clear</property>
655+ <property name="visible">True</property>
656+ <property name="sensitive">False</property>
657+ <property name="can_focus">False</property>
658+ <property name="use_underline">True</property>
659+ <property name="use_stock">True</property>
660+ <signal name="activate" handler="on_menucontext_clean" swapped="no"/>
661+ </object>
662+ </child>
663+ </object>
664+ <object class="GtkMenu" id="contextQuit">
665+ <property name="visible">True</property>
666+ <property name="can_focus">False</property>
667+ <child>
668+ <object class="GtkImageMenuItem" id="menucontext_quit">
669+ <property name="label">gtk-quit</property>
670+ <property name="visible">True</property>
671+ <property name="can_focus">False</property>
672+ <property name="right_justified">True</property>
673+ <property name="use_underline">True</property>
674+ <property name="use_stock">True</property>
675+ <property name="always_show_image">True</property>
676+ <signal name="activate" handler="on_destroy" swapped="no"/>
677+ </object>
678+ </child>
679+ </object>
680+ <object class="GtkDialog" id="error_dialog">
681+ <property name="can_focus">False</property>
682+ <property name="border_width">5</property>
683+ <property name="title" translatable="yes">Arte +7 Recorder</property>
684+ <property name="modal">True</property>
685+ <property name="window_position">center</property>
686+ <property name="icon">./icon.png</property>
687+ <property name="type_hint">normal</property>
688+ <child internal-child="vbox">
689+ <object class="GtkBox" id="dialog-vbox15">
690+ <property name="visible">True</property>
691+ <property name="can_focus">False</property>
692+ <property name="spacing">14</property>
693+ <child internal-child="action_area">
694+ <object class="GtkButtonBox" id="dialog-action_area15">
695+ <property name="visible">True</property>
696+ <property name="can_focus">False</property>
697+ <property name="layout_style">end</property>
698+ <child>
699+ <object class="GtkButton" id="zenity_error_ok_button">
700+ <property name="label">gtk-ok</property>
701+ <property name="visible">True</property>
702+ <property name="can_focus">True</property>
703+ <property name="can_default">True</property>
704+ <property name="receives_default">True</property>
705+ <property name="use_stock">True</property>
706+ </object>
707+ <packing>
708+ <property name="expand">False</property>
709+ <property name="fill">False</property>
710+ <property name="position">0</property>
711+ </packing>
712+ </child>
713+ </object>
714+ <packing>
715+ <property name="expand">False</property>
716+ <property name="fill">False</property>
717+ <property name="pack_type">end</property>
718+ <property name="position">0</property>
719+ </packing>
720+ </child>
721+ <child>
722+ <object class="GtkVBox" id="vbox11">
723+ <property name="visible">True</property>
724+ <property name="can_focus">False</property>
725+ <property name="border_width">6</property>
726+ <child>
727+ <object class="GtkHBox" id="hbox1">
728+ <property name="visible">True</property>
729+ <property name="can_focus">False</property>
730+ <property name="border_width">5</property>
731+ <property name="spacing">12</property>
732+ <child>
733+ <object class="GtkImage" id="image3">
734+ <property name="visible">True</property>
735+ <property name="can_focus">False</property>
736+ <property name="yalign">0</property>
737+ <property name="stock">gtk-dialog-error</property>
738+ <property name="icon_size">6</property>
739+ </object>
740+ <packing>
741+ <property name="expand">True</property>
742+ <property name="fill">True</property>
743+ <property name="position">0</property>
744+ </packing>
745+ </child>
746+ <child>
747+ <object class="GtkLabel" id="error_text">
748+ <property name="visible">True</property>
749+ <property name="can_focus">True</property>
750+ <property name="label" translatable="yes">There is a problem with your internet connection</property>
751+ <property name="use_markup">True</property>
752+ <property name="wrap">True</property>
753+ <property name="selectable">True</property>
754+ <property name="yalign">0</property>
755+ </object>
756+ <packing>
757+ <property name="expand">False</property>
758+ <property name="fill">False</property>
759+ <property name="position">1</property>
760+ </packing>
761+ </child>
762+ </object>
763+ <packing>
764+ <property name="expand">True</property>
765+ <property name="fill">True</property>
766+ <property name="position">0</property>
767+ </packing>
768+ </child>
769+ </object>
770+ <packing>
771+ <property name="expand">False</property>
772+ <property name="fill">True</property>
773+ <property name="position">1</property>
774+ </packing>
775+ </child>
776+ </object>
777+ </child>
778+ <action-widgets>
779+ <action-widget response="-5">zenity_error_ok_button</action-widget>
780+ </action-widgets>
781+ </object>
782+ <object class="GtkImage" id="image_add">
783+ <property name="visible">True</property>
784+ <property name="can_focus">False</property>
785+ <property name="stock">gtk-add</property>
786+ </object>
787+ <object class="GtkImage" id="image_del">
788+ <property name="visible">True</property>
789+ <property name="can_focus">False</property>
790+ <property name="tooltip_text" translatable="yes">Remove reportage</property>
791+ <property name="stock">gtk-remove</property>
792+ </object>
793+ <object class="GtkListStore" id="liststore1">
794+ <columns>
795+ <!-- column-name Player -->
796+ <column type="gchararray"/>
797+ </columns>
798+ <data>
799+ <row>
800+ <col id="0" translatable="yes">totem</col>
801+ </row>
802+ <row>
803+ <col id="0" translatable="yes">vlc</col>
804+ </row>
805+ <row>
806+ <col id="0" translatable="yes">mplayer</col>
807+ </row>
808+ </data>
809 </object>
810 <object class="GtkDialog" id="arte7recorder_pref">
811+ <property name="can_focus">False</property>
812 <property name="border_width">5</property>
813 <property name="title" translatable="yes">Arte +7 Recorder</property>
814 <property name="window_position">center</property>
815 <property name="icon">./icon.png</property>
816 <property name="type_hint">normal</property>
817- <property name="has_separator">False</property>
818 <child internal-child="vbox">
819- <object class="GtkVBox" id="dialog-vbox2">
820+ <object class="GtkBox" id="dialog-vbox2">
821 <property name="visible">True</property>
822+ <property name="can_focus">False</property>
823 <property name="spacing">2</property>
824+ <child internal-child="action_area">
825+ <object class="GtkButtonBox" id="dialog-action_area2">
826+ <property name="visible">True</property>
827+ <property name="can_focus">False</property>
828+ <property name="layout_style">end</property>
829+ <child>
830+ <object class="GtkLabel" id="label12">
831+ <property name="can_focus">False</property>
832+ <property name="label" translatable="yes">Need restart</property>
833+ </object>
834+ <packing>
835+ <property name="expand">False</property>
836+ <property name="fill">False</property>
837+ <property name="position">0</property>
838+ </packing>
839+ </child>
840+ <child>
841+ <object class="GtkButton" id="button1">
842+ <property name="label">gtk-cancel</property>
843+ <property name="visible">True</property>
844+ <property name="can_focus">True</property>
845+ <property name="receives_default">True</property>
846+ <property name="use_stock">True</property>
847+ </object>
848+ <packing>
849+ <property name="expand">False</property>
850+ <property name="fill">False</property>
851+ <property name="position">1</property>
852+ </packing>
853+ </child>
854+ <child>
855+ <object class="GtkButton" id="button2">
856+ <property name="label">gtk-ok</property>
857+ <property name="visible">True</property>
858+ <property name="can_focus">True</property>
859+ <property name="receives_default">True</property>
860+ <property name="use_stock">True</property>
861+ </object>
862+ <packing>
863+ <property name="expand">False</property>
864+ <property name="fill">False</property>
865+ <property name="position">2</property>
866+ </packing>
867+ </child>
868+ </object>
869+ <packing>
870+ <property name="expand">False</property>
871+ <property name="fill">False</property>
872+ <property name="pack_type">end</property>
873+ <property name="position">0</property>
874+ </packing>
875+ </child>
876 <child>
877 <object class="GtkVBox" id="vbox8">
878 <property name="visible">True</property>
879+ <property name="can_focus">False</property>
880 <child>
881 <object class="GtkVBox" id="vbox9">
882 <property name="visible">True</property>
883+ <property name="can_focus">False</property>
884 <child>
885 <object class="GtkLabel" id="label10">
886 <property name="visible">True</property>
887+ <property name="can_focus">False</property>
888+ <property name="label" translatable="yes">Select your video player:</property>
889 <property name="xalign">0</property>
890 <property name="yalign">1</property>
891- <property name="label" translatable="yes">Select your video player:</property>
892 </object>
893 <packing>
894 <property name="expand">False</property>
895@@ -915,6 +591,7 @@
896 <child>
897 <object class="GtkComboBox" id="combobox1">
898 <property name="visible">True</property>
899+ <property name="can_focus">False</property>
900 <property name="model">liststore1</property>
901 <property name="active">0</property>
902 <child>
903@@ -925,15 +602,18 @@
904 </child>
905 </object>
906 <packing>
907+ <property name="expand">True</property>
908+ <property name="fill">True</property>
909 <property name="position">1</property>
910 </packing>
911 </child>
912 <child>
913 <object class="GtkLabel" id="label11">
914 <property name="visible">True</property>
915- <property name="xalign">0</property>
916- <property name="yalign">0</property>
917+ <property name="can_focus">False</property>
918 <property name="label" translatable="yes">Select Directory to save reportage:</property>
919+ <property name="xalign">0</property>
920+ <property name="yalign">0</property>
921 </object>
922 <packing>
923 <property name="expand">False</property>
924@@ -944,73 +624,31 @@
925 <child>
926 <object class="GtkFileChooserButton" id="filechooserbutton1">
927 <property name="visible">True</property>
928+ <property name="can_focus">False</property>
929 <property name="action">select-folder</property>
930 <property name="focus_on_click">False</property>
931 <property name="title" translatable="yes">Select directory</property>
932 </object>
933 <packing>
934+ <property name="expand">True</property>
935+ <property name="fill">True</property>
936 <property name="position">3</property>
937 </packing>
938 </child>
939 </object>
940 <packing>
941+ <property name="expand">True</property>
942+ <property name="fill">True</property>
943 <property name="position">0</property>
944 </packing>
945 </child>
946 </object>
947 <packing>
948+ <property name="expand">False</property>
949+ <property name="fill">True</property>
950 <property name="position">1</property>
951 </packing>
952 </child>
953- <child internal-child="action_area">
954- <object class="GtkHButtonBox" id="dialog-action_area2">
955- <property name="visible">True</property>
956- <property name="layout_style">end</property>
957- <child>
958- <object class="GtkLabel" id="label12">
959- <property name="label" translatable="yes">Need restart</property>
960- </object>
961- <packing>
962- <property name="expand">False</property>
963- <property name="fill">False</property>
964- <property name="position">0</property>
965- </packing>
966- </child>
967- <child>
968- <object class="GtkButton" id="button1">
969- <property name="label">gtk-cancel</property>
970- <property name="visible">True</property>
971- <property name="can_focus">True</property>
972- <property name="receives_default">True</property>
973- <property name="use_stock">True</property>
974- </object>
975- <packing>
976- <property name="expand">False</property>
977- <property name="fill">False</property>
978- <property name="position">1</property>
979- </packing>
980- </child>
981- <child>
982- <object class="GtkButton" id="button2">
983- <property name="label">gtk-ok</property>
984- <property name="visible">True</property>
985- <property name="can_focus">True</property>
986- <property name="receives_default">True</property>
987- <property name="use_stock">True</property>
988- </object>
989- <packing>
990- <property name="expand">False</property>
991- <property name="fill">False</property>
992- <property name="position">2</property>
993- </packing>
994- </child>
995- </object>
996- <packing>
997- <property name="expand">False</property>
998- <property name="pack_type">end</property>
999- <property name="position">0</property>
1000- </packing>
1001- </child>
1002 </object>
1003 </child>
1004 <action-widgets>
1005@@ -1018,134 +656,676 @@
1006 <action-widget response="0">button2</action-widget>
1007 </action-widgets>
1008 </object>
1009- <object class="GtkDialog" id="error_dialog">
1010- <property name="border_width">5</property>
1011+ <object class="GtkWindow" id="loading_window">
1012+ <property name="can_focus">False</property>
1013+ <property name="title" translatable="yes">Loading...</property>
1014+ <property name="window_position">center-always</property>
1015+ <property name="icon">./icon.png</property>
1016+ <property name="type_hint">normal</property>
1017+ <property name="decorated">False</property>
1018+ <property name="deletable">False</property>
1019+ <child>
1020+ <object class="GtkVBox" id="loading_vbox">
1021+ <property name="visible">True</property>
1022+ <property name="can_focus">False</property>
1023+ <child>
1024+ <object class="GtkLabel" id="loading_label">
1025+ <property name="visible">True</property>
1026+ <property name="can_focus">False</property>
1027+ <property name="label" translatable="yes">Please wait while videos are loaded from Arte's website...
1028+
1029+Already fetched: xxx / yyy videos.
1030+</property>
1031+ <property name="use_markup">True</property>
1032+ <property name="wrap">True</property>
1033+ <property name="selectable">False</property>
1034+ <property name="yalign">0</property>
1035+ </object>
1036+ <packing>
1037+ <property name="expand">True</property>
1038+ <property name="fill">True</property>
1039+ <property name="padding">0</property>
1040+ <property name="position">0</property>
1041+ </packing>
1042+ </child>
1043+ <child>
1044+ <object class="GtkProgressBar" id="loading_pb">
1045+ <property name="height_request">50</property>
1046+ <property name="visible">True</property>
1047+ <property name="can_focus">False</property>
1048+ <property name="show_text">True</property>
1049+ </object>
1050+ <packing>
1051+ <property name="expand">False</property>
1052+ <property name="fill">True</property>
1053+ <property name="position">1</property>
1054+ </packing>
1055+ </child>
1056+ </object>
1057+ </child>
1058+ </object>
1059+ <object class="GtkTextBuffer" id="textbuffer1"/>
1060+ <object class="GtkWindow" id="arte7recorder_window">
1061+ <property name="can_focus">False</property>
1062 <property name="title" translatable="yes">Arte +7 Recorder</property>
1063- <property name="modal">True</property>
1064- <property name="window_position">center</property>
1065+ <property name="window_position">center-always</property>
1066 <property name="icon">./icon.png</property>
1067- <property name="type_hint">normal</property>
1068- <property name="has_separator">False</property>
1069- <child internal-child="vbox">
1070- <object class="GtkVBox" id="dialog-vbox15">
1071+ <signal name="destroy" handler="on_destroy" swapped="no"/>
1072+ <child>
1073+ <object class="GtkVBox" id="vbox1">
1074 <property name="visible">True</property>
1075- <property name="spacing">14</property>
1076- <child>
1077- <object class="GtkVBox" id="vbox11">
1078- <property name="visible">True</property>
1079- <property name="border_width">6</property>
1080- <child>
1081- <object class="GtkHBox" id="hbox1">
1082- <property name="visible">True</property>
1083- <property name="border_width">5</property>
1084- <property name="spacing">12</property>
1085- <child>
1086- <object class="GtkImage" id="image3">
1087- <property name="visible">True</property>
1088- <property name="yalign">0</property>
1089- <property name="stock">gtk-dialog-error</property>
1090- <property name="icon-size">6</property>
1091- </object>
1092- <packing>
1093- <property name="position">0</property>
1094- </packing>
1095- </child>
1096- <child>
1097- <object class="GtkLabel" id="error_text">
1098- <property name="visible">True</property>
1099- <property name="can_focus">True</property>
1100- <property name="yalign">0</property>
1101- <property name="label" translatable="yes">There is a problem with your internet connection</property>
1102- <property name="use_markup">True</property>
1103- <property name="wrap">True</property>
1104- <property name="selectable">True</property>
1105+ <property name="can_focus">False</property>
1106+ <child>
1107+ <object class="GtkStatusbar" id="statusbar1">
1108+ <property name="visible">True</property>
1109+ <property name="can_focus">False</property>
1110+ <property name="spacing">2</property>
1111+ <child>
1112+ <object class="GtkLabel" id="status">
1113+ <property name="visible">True</property>
1114+ <property name="can_focus">False</property>
1115+ </object>
1116+ <packing>
1117+ <property name="expand">False</property>
1118+ <property name="fill">True</property>
1119+ <property name="position">1</property>
1120+ </packing>
1121+ </child>
1122+ </object>
1123+ <packing>
1124+ <property name="expand">False</property>
1125+ <property name="fill">True</property>
1126+ <property name="pack_type">end</property>
1127+ <property name="position">0</property>
1128+ </packing>
1129+ </child>
1130+ <child>
1131+ <object class="GtkMenuBar" id="menubar">
1132+ <property name="visible">True</property>
1133+ <property name="can_focus">False</property>
1134+ <child>
1135+ <object class="GtkMenuItem" id="fichiers">
1136+ <property name="visible">True</property>
1137+ <property name="can_focus">False</property>
1138+ <property name="label" translatable="yes">_Files</property>
1139+ <property name="use_underline">True</property>
1140+ <child type="submenu">
1141+ <object class="GtkMenu" id="menu_fichiers">
1142+ <property name="visible">True</property>
1143+ <property name="can_focus">False</property>
1144+ <child>
1145+ <object class="GtkImageMenuItem" id="actualiser">
1146+ <property name="label">gtk-refresh</property>
1147+ <property name="visible">True</property>
1148+ <property name="can_focus">False</property>
1149+ <property name="use_underline">True</property>
1150+ <property name="use_stock">True</property>
1151+ <signal name="activate" handler="on_actu" swapped="no"/>
1152+ </object>
1153+ </child>
1154+ <child>
1155+ <object class="GtkImageMenuItem" id="preferences">
1156+ <property name="label">gtk-preferences</property>
1157+ <property name="visible">True</property>
1158+ <property name="can_focus">False</property>
1159+ <property name="use_underline">True</property>
1160+ <property name="use_stock">True</property>
1161+ <signal name="activate" handler="preferences" swapped="no"/>
1162+ </object>
1163+ </child>
1164+ <child>
1165+ <object class="GtkImageMenuItem" id="quit">
1166+ <property name="label">gtk-quit</property>
1167+ <property name="visible">True</property>
1168+ <property name="can_focus">False</property>
1169+ <property name="use_underline">True</property>
1170+ <property name="use_stock">True</property>
1171+ <signal name="activate" handler="on_destroy" swapped="no"/>
1172+ </object>
1173+ </child>
1174+ </object>
1175+ </child>
1176+ </object>
1177+ </child>
1178+ <child>
1179+ <object class="GtkMenuItem" id="aide">
1180+ <property name="visible">True</property>
1181+ <property name="can_focus">False</property>
1182+ <property name="label" translatable="yes">_Help</property>
1183+ <property name="use_underline">True</property>
1184+ <child type="submenu">
1185+ <object class="GtkMenu" id="menu_aide">
1186+ <property name="visible">True</property>
1187+ <property name="can_focus">False</property>
1188+ <child>
1189+ <object class="GtkImageMenuItem" id="about">
1190+ <property name="label">gtk-about</property>
1191+ <property name="visible">True</property>
1192+ <property name="can_focus">False</property>
1193+ <property name="use_underline">True</property>
1194+ <property name="use_stock">True</property>
1195+ <signal name="activate" handler="about" swapped="no"/>
1196+ </object>
1197+ </child>
1198+ </object>
1199+ </child>
1200+ </object>
1201+ </child>
1202+ </object>
1203+ <packing>
1204+ <property name="expand">False</property>
1205+ <property name="fill">True</property>
1206+ <property name="position">1</property>
1207+ </packing>
1208+ </child>
1209+ <child>
1210+ <object class="GtkHBox" id="hbox2">
1211+ <property name="visible">True</property>
1212+ <property name="can_focus">False</property>
1213+ <child>
1214+ <object class="GtkVBox" id="vbox3">
1215+ <property name="visible">True</property>
1216+ <property name="can_focus">False</property>
1217+ <child>
1218+ <object class="GtkFrame" id="frame5">
1219+ <property name="height_request">300</property>
1220+ <property name="visible">True</property>
1221+ <property name="can_focus">False</property>
1222+ <property name="label_xalign">0</property>
1223+ <property name="shadow_type">none</property>
1224+ <child>
1225+ <object class="GtkAlignment" id="alignment5">
1226+ <property name="visible">True</property>
1227+ <property name="can_focus">False</property>
1228+ <property name="top_padding">10</property>
1229+ <property name="left_padding">12</property>
1230+ <child>
1231+ <object class="GtkScrolledWindow" id="scrolledwindow1">
1232+ <property name="visible">True</property>
1233+ <property name="can_focus">True</property>
1234+ <property name="hscrollbar_policy">never</property>
1235+ <property name="shadow_type">etched-in</property>
1236+ <child>
1237+ <object class="GtkTreeView" id="treeview_disp">
1238+ <property name="visible">True</property>
1239+ <property name="can_focus">True</property>
1240+ <property name="tooltip_text" translatable="yes">Double click to show summary</property>
1241+ <property name="headers_clickable">False</property>
1242+ <property name="search_column">0</property>
1243+ <signal name="row-activated" handler="dl_resume" swapped="no"/>
1244+ <child internal-child="selection">
1245+ <object class="GtkTreeSelection" id="treeview-selection1"/>
1246+ </child>
1247+ </object>
1248+ </child>
1249+ </object>
1250+ </child>
1251+ </object>
1252+ </child>
1253+ <child type="label">
1254+ <object class="GtkLabel" id="label5">
1255+ <property name="visible">True</property>
1256+ <property name="can_focus">False</property>
1257+ <property name="label" translatable="yes">Reportage:</property>
1258+ <attributes>
1259+ <attribute name="weight" value="bold"/>
1260+ </attributes>
1261+ </object>
1262+ </child>
1263+ </object>
1264+ <packing>
1265+ <property name="expand">True</property>
1266+ <property name="fill">True</property>
1267+ <property name="padding">5</property>
1268+ <property name="position">0</property>
1269+ </packing>
1270+ </child>
1271+ <child>
1272+ <object class="GtkFrame" id="frame4">
1273+ <property name="can_focus">False</property>
1274+ <property name="no_show_all">True</property>
1275+ <property name="label_xalign">0</property>
1276+ <property name="shadow_type">none</property>
1277+ <child>
1278+ <object class="GtkAlignment" id="alignment4">
1279+ <property name="visible">True</property>
1280+ <property name="can_focus">False</property>
1281+ <property name="top_padding">10</property>
1282+ <property name="left_padding">12</property>
1283+ <child>
1284+ <object class="GtkVBox" id="vbox4">
1285+ <property name="visible">True</property>
1286+ <property name="can_focus">False</property>
1287+ <child>
1288+ <object class="GtkScrolledWindow" id="scrolledwindow2">
1289+ <property name="visible">True</property>
1290+ <property name="can_focus">True</property>
1291+ <property name="hscrollbar_policy">never</property>
1292+ <property name="shadow_type">etched-in</property>
1293+ <child>
1294+ <object class="GtkTreeView" id="treeview_dl">
1295+ <property name="visible">True</property>
1296+ <property name="can_focus">True</property>
1297+ <property name="search_column">0</property>
1298+ <signal name="row-activated" handler="dl_resume" swapped="no"/>
1299+ <child internal-child="selection">
1300+ <object class="GtkTreeSelection" id="treeview-selection2"/>
1301+ </child>
1302+ </object>
1303+ </child>
1304+ </object>
1305+ <packing>
1306+ <property name="expand">True</property>
1307+ <property name="fill">True</property>
1308+ <property name="position">0</property>
1309+ </packing>
1310+ </child>
1311+ <child>
1312+ <object class="GtkVButtonBox" id="vbuttonbox1">
1313+ <property name="visible">True</property>
1314+ <property name="can_focus">False</property>
1315+ <child>
1316+ <object class="GtkButton" id="bouton_dl">
1317+ <property name="label" translatable="yes">Download</property>
1318+ <property name="visible">True</property>
1319+ <property name="can_focus">True</property>
1320+ <property name="receives_default">True</property>
1321+ <signal name="clicked" handler="on_telecharge" swapped="no"/>
1322+ </object>
1323+ <packing>
1324+ <property name="expand">False</property>
1325+ <property name="fill">False</property>
1326+ <property name="position">0</property>
1327+ </packing>
1328+ </child>
1329+ <child>
1330+ <object class="GtkButton" id="button3">
1331+ <property name="label">gtk-undo</property>
1332+ <property name="can_focus">True</property>
1333+ <property name="receives_default">True</property>
1334+ <property name="use_stock">True</property>
1335+ <signal name="clicked" handler="on_cancel" swapped="no"/>
1336+ </object>
1337+ <packing>
1338+ <property name="expand">False</property>
1339+ <property name="fill">False</property>
1340+ <property name="position">1</property>
1341+ </packing>
1342+ </child>
1343+ </object>
1344+ <packing>
1345+ <property name="expand">False</property>
1346+ <property name="fill">False</property>
1347+ <property name="pack_type">end</property>
1348+ <property name="position">1</property>
1349+ </packing>
1350+ </child>
1351+ </object>
1352+ </child>
1353+ </object>
1354+ </child>
1355+ <child type="label">
1356+ <object class="GtkLabel" id="label4">
1357+ <property name="visible">True</property>
1358+ <property name="can_focus">False</property>
1359+ <property name="label" translatable="yes">Programmes selected for download :</property>
1360+ <attributes>
1361+ <attribute name="weight" value="bold"/>
1362+ </attributes>
1363+ </object>
1364+ </child>
1365+ </object>
1366+ <packing>
1367+ <property name="expand">True</property>
1368+ <property name="fill">True</property>
1369+ <property name="position">1</property>
1370+ </packing>
1371+ </child>
1372+ </object>
1373+ <packing>
1374+ <property name="expand">True</property>
1375+ <property name="fill">True</property>
1376+ <property name="position">0</property>
1377+ </packing>
1378+ </child>
1379+ <child>
1380+ <object class="GtkVBox" id="vbox5">
1381+ <property name="visible">True</property>
1382+ <property name="can_focus">False</property>
1383+ <property name="homogeneous">True</property>
1384+ <child>
1385+ <object class="GtkVBox" id="vbox6">
1386+ <property name="visible">True</property>
1387+ <property name="can_focus">False</property>
1388+ <child>
1389+ <object class="GtkFixed" id="fixed2">
1390+ <property name="visible">True</property>
1391+ <property name="can_focus">False</property>
1392+ </object>
1393+ <packing>
1394+ <property name="expand">True</property>
1395+ <property name="fill">False</property>
1396+ <property name="position">0</property>
1397+ </packing>
1398+ </child>
1399+ <child>
1400+ <object class="GtkButton" id="bouton_add">
1401+ <property name="visible">True</property>
1402+ <property name="can_focus">True</property>
1403+ <property name="receives_default">True</property>
1404+ <property name="tooltip_text" translatable="yes">Add reportage</property>
1405+ <property name="image">image_add</property>
1406+ <signal name="clicked" handler="on_add_emi" swapped="no"/>
1407+ </object>
1408+ <packing>
1409+ <property name="expand">False</property>
1410+ <property name="fill">False</property>
1411+ <property name="position">1</property>
1412+ </packing>
1413+ </child>
1414+ <child>
1415+ <object class="GtkFixed" id="fixed4">
1416+ <property name="visible">True</property>
1417+ <property name="can_focus">False</property>
1418+ </object>
1419+ <packing>
1420+ <property name="expand">True</property>
1421+ <property name="fill">False</property>
1422+ <property name="position">2</property>
1423+ </packing>
1424+ </child>
1425+ </object>
1426+ <packing>
1427+ <property name="expand">True</property>
1428+ <property name="fill">False</property>
1429+ <property name="position">0</property>
1430+ </packing>
1431+ </child>
1432+ <child>
1433+ <object class="GtkVBox" id="vbox7">
1434+ <property name="visible">True</property>
1435+ <property name="can_focus">False</property>
1436+ <child>
1437+ <object class="GtkFixed" id="fixed6">
1438+ <property name="visible">True</property>
1439+ <property name="can_focus">False</property>
1440+ </object>
1441+ <packing>
1442+ <property name="expand">True</property>
1443+ <property name="fill">False</property>
1444+ <property name="position">0</property>
1445+ </packing>
1446+ </child>
1447+ <child>
1448+ <object class="GtkButton" id="bouton_del">
1449+ <property name="can_focus">True</property>
1450+ <property name="receives_default">True</property>
1451+ <property name="no_show_all">True</property>
1452+ <property name="image">image_del</property>
1453+ <signal name="clicked" handler="on_del_emi" swapped="no"/>
1454+ </object>
1455+ <packing>
1456+ <property name="expand">False</property>
1457+ <property name="fill">False</property>
1458+ <property name="position">1</property>
1459+ </packing>
1460+ </child>
1461+ <child>
1462+ <object class="GtkFixed" id="fixed5">
1463+ <property name="visible">True</property>
1464+ <property name="can_focus">False</property>
1465+ </object>
1466+ <packing>
1467+ <property name="expand">True</property>
1468+ <property name="fill">False</property>
1469+ <property name="position">2</property>
1470+ </packing>
1471+ </child>
1472+ </object>
1473+ <packing>
1474+ <property name="expand">True</property>
1475+ <property name="fill">False</property>
1476+ <property name="position">1</property>
1477+ </packing>
1478+ </child>
1479+ </object>
1480+ <packing>
1481+ <property name="expand">False</property>
1482+ <property name="fill">False</property>
1483+ <property name="position">1</property>
1484+ </packing>
1485+ </child>
1486+ <child>
1487+ <object class="GtkVBox" id="vbox2">
1488+ <property name="visible">True</property>
1489+ <property name="can_focus">False</property>
1490+ <child>
1491+ <object class="GtkFrame" id="frame1">
1492+ <property name="height_request">300</property>
1493+ <property name="visible">True</property>
1494+ <property name="can_focus">False</property>
1495+ <property name="label_xalign">0</property>
1496+ <property name="shadow_type">none</property>
1497+ <child>
1498+ <object class="GtkVBox" id="vbox10">
1499+ <property name="height_request">300</property>
1500+ <property name="visible">True</property>
1501+ <property name="can_focus">False</property>
1502+ <child>
1503+ <object class="GtkImage" id="image_emi">
1504+ <property name="visible">True</property>
1505+ <property name="can_focus">False</property>
1506+ <property name="yalign">1</property>
1507+ </object>
1508+ <packing>
1509+ <property name="expand">False</property>
1510+ <property name="fill">False</property>
1511+ <property name="position">0</property>
1512+ </packing>
1513+ </child>
1514+ <child>
1515+ <object class="GtkFrame" id="frame2">
1516+ <property name="visible">True</property>
1517+ <property name="can_focus">False</property>
1518+ <property name="label_xalign">0</property>
1519+ <property name="label_yalign">0</property>
1520+ <property name="shadow_type">none</property>
1521+ <child>
1522+ <object class="GtkAlignment" id="alignment1">
1523+ <property name="visible">True</property>
1524+ <property name="can_focus">False</property>
1525+ <property name="yalign">0</property>
1526+ <property name="yscale">0</property>
1527+ <child>
1528+ <object class="GtkLabel" id="label6">
1529+ <property name="visible">True</property>
1530+ <property name="can_focus">False</property>
1531+ <property name="use_markup">True</property>
1532+ <property name="xalign">0</property>
1533+ <property name="yalign">1</property>
1534+ </object>
1535+ </child>
1536+ </object>
1537+ </child>
1538+ <child type="label">
1539+ <object class="GtkLabel" id="label2">
1540+ <property name="visible">True</property>
1541+ <property name="can_focus">False</property>
1542+ <property name="label" translatable="yes">Name:</property>
1543+ <property name="yalign">0</property>
1544+ <attributes>
1545+ <attribute name="weight" value="bold"/>
1546+ </attributes>
1547+ </object>
1548+ </child>
1549+ </object>
1550+ <packing>
1551+ <property name="expand">False</property>
1552+ <property name="fill">False</property>
1553+ <property name="padding">2</property>
1554+ <property name="position">1</property>
1555+ </packing>
1556+ </child>
1557+ <child>
1558+ <object class="GtkFrame" id="frame3">
1559+ <property name="visible">True</property>
1560+ <property name="can_focus">False</property>
1561+ <property name="label_xalign">0</property>
1562+ <property name="label_yalign">0</property>
1563+ <property name="shadow_type">none</property>
1564+ <child>
1565+ <object class="GtkAlignment" id="alignment2">
1566+ <property name="visible">True</property>
1567+ <property name="can_focus">False</property>
1568+ <property name="yalign">0</property>
1569+ <property name="yscale">0</property>
1570+ <child>
1571+ <object class="GtkLabel" id="label7">
1572+ <property name="visible">True</property>
1573+ <property name="can_focus">False</property>
1574+ <property name="use_markup">True</property>
1575+ <property name="xalign">0</property>
1576+ <property name="yalign">1</property>
1577+ </object>
1578+ </child>
1579+ </object>
1580+ </child>
1581+ <child type="label">
1582+ <object class="GtkLabel" id="label3">
1583+ <property name="visible">True</property>
1584+ <property name="can_focus">False</property>
1585+ <property name="label" translatable="yes">Date:</property>
1586+ <property name="yalign">1</property>
1587+ <attributes>
1588+ <attribute name="weight" value="bold"/>
1589+ </attributes>
1590+ </object>
1591+ </child>
1592+ </object>
1593+ <packing>
1594+ <property name="expand">False</property>
1595+ <property name="fill">False</property>
1596+ <property name="padding">2</property>
1597+ <property name="position">2</property>
1598+ </packing>
1599+ </child>
1600+ <child>
1601+ <object class="GtkFrame" id="frame6">
1602+ <property name="visible">True</property>
1603+ <property name="can_focus">False</property>
1604+ <property name="label_xalign">0</property>
1605+ <property name="label_yalign">0</property>
1606+ <property name="shadow_type">none</property>
1607+ <child>
1608+ <object class="GtkAlignment" id="alignment6">
1609+ <property name="visible">True</property>
1610+ <property name="can_focus">False</property>
1611+ <property name="yalign">0</property>
1612+ <property name="yscale">0</property>
1613+ <child>
1614+ <object class="GtkLabel" id="label13">
1615+ <property name="visible">True</property>
1616+ <property name="can_focus">False</property>
1617+ <property name="use_markup">True</property>
1618+ <property name="xalign">0</property>
1619+ <property name="yalign">1</property>
1620+ </object>
1621+ </child>
1622+ </object>
1623+ </child>
1624+ <child type="label">
1625+ <object class="GtkLabel" id="label14">
1626+ <property name="visible">True</property>
1627+ <property name="can_focus">False</property>
1628+ <property name="label" translatable="yes">Time:</property>
1629+ <property name="yalign">0</property>
1630+ <attributes>
1631+ <attribute name="weight" value="bold"/>
1632+ </attributes>
1633+ </object>
1634+ </child>
1635+ </object>
1636+ <packing>
1637+ <property name="expand">False</property>
1638+ <property name="fill">False</property>
1639+ <property name="padding">2</property>
1640+ <property name="position">3</property>
1641+ </packing>
1642+ </child>
1643+ </object>
1644+ </child>
1645+ <child type="label_item">
1646+ <placeholder/>
1647+ </child>
1648 </object>
1649 <packing>
1650 <property name="expand">False</property>
1651 <property name="fill">False</property>
1652+ <property name="padding">5</property>
1653+ <property name="position">0</property>
1654+ </packing>
1655+ </child>
1656+ <child>
1657+ <object class="GtkFrame" id="frame8">
1658+ <property name="visible">True</property>
1659+ <property name="can_focus">False</property>
1660+ <property name="label_xalign">0</property>
1661+ <property name="shadow_type">none</property>
1662+ <child>
1663+ <object class="GtkScrolledWindow" id="scrolledwindow4">
1664+ <property name="visible">True</property>
1665+ <property name="can_focus">True</property>
1666+ <property name="hscrollbar_policy">never</property>
1667+ <property name="shadow_type">etched-in</property>
1668+ <child>
1669+ <object class="GtkTextView" id="textview2">
1670+ <property name="height_request">0</property>
1671+ <property name="visible">True</property>
1672+ <property name="can_focus">True</property>
1673+ <property name="editable">False</property>
1674+ <property name="wrap_mode">word</property>
1675+ <property name="cursor_visible">False</property>
1676+ <property name="buffer">textbuffer1</property>
1677+ </object>
1678+ </child>
1679+ </object>
1680+ </child>
1681+ <child type="label">
1682+ <object class="GtkLabel" id="label15">
1683+ <property name="visible">True</property>
1684+ <property name="can_focus">False</property>
1685+ <property name="label" translatable="yes">Summary:</property>
1686+ <attributes>
1687+ <attribute name="weight" value="bold"/>
1688+ </attributes>
1689+ </object>
1690+ </child>
1691+ </object>
1692+ <packing>
1693+ <property name="expand">True</property>
1694+ <property name="fill">True</property>
1695 <property name="position">1</property>
1696 </packing>
1697 </child>
1698 </object>
1699 <packing>
1700- <property name="position">0</property>
1701- </packing>
1702- </child>
1703- </object>
1704- <packing>
1705- <property name="position">1</property>
1706- </packing>
1707- </child>
1708- <child internal-child="action_area">
1709- <object class="GtkHButtonBox" id="dialog-action_area15">
1710- <property name="visible">True</property>
1711- <property name="layout_style">end</property>
1712- <child>
1713- <object class="GtkButton" id="zenity_error_ok_button">
1714- <property name="label">gtk-ok</property>
1715- <property name="visible">True</property>
1716- <property name="can_focus">True</property>
1717- <property name="can_default">True</property>
1718- <property name="receives_default">True</property>
1719- <property name="use_stock">True</property>
1720- </object>
1721- <packing>
1722- <property name="expand">False</property>
1723- <property name="fill">False</property>
1724- <property name="position">0</property>
1725- </packing>
1726- </child>
1727- </object>
1728- <packing>
1729- <property name="expand">False</property>
1730- <property name="pack_type">end</property>
1731- <property name="position">0</property>
1732- </packing>
1733- </child>
1734- </object>
1735- </child>
1736- <action-widgets>
1737- <action-widget response="-5">zenity_error_ok_button</action-widget>
1738- </action-widgets>
1739- </object>
1740- <object class="GtkImage" id="image_add">
1741- <property name="visible">True</property>
1742- <property name="stock">gtk-add</property>
1743- </object>
1744- <object class="GtkMenu" id="contextMenu">
1745- <property name="visible">True</property>
1746- <child>
1747- <object class="GtkImageMenuItem" id="menucontext_play">
1748- <property name="label">gtk-media-play</property>
1749- <property name="visible">True</property>
1750- <property name="sensitive">False</property>
1751- <property name="use_underline">True</property>
1752- <property name="use_stock">True</property>
1753- <signal name="activate" handler="on_menucontext_play"/>
1754- </object>
1755- </child>
1756- <child>
1757- <object class="GtkImageMenuItem" id="menucontext_ann">
1758- <property name="label">gtk-cancel</property>
1759- <property name="visible">True</property>
1760- <property name="sensitive">False</property>
1761- <property name="use_underline">True</property>
1762- <property name="use_stock">True</property>
1763- <signal name="activate" handler="on_menucontext_ann"/>
1764- </object>
1765- </child>
1766- <child>
1767- <object class="GtkImageMenuItem" id="menucontext_clean">
1768- <property name="label">gtk-clear</property>
1769- <property name="visible">True</property>
1770- <property name="sensitive">False</property>
1771- <property name="use_underline">True</property>
1772- <property name="use_stock">True</property>
1773- <signal name="activate" handler="on_menucontext_clean"/>
1774+ <property name="expand">True</property>
1775+ <property name="fill">True</property>
1776+ <property name="position">2</property>
1777+ </packing>
1778+ </child>
1779+ </object>
1780+ <packing>
1781+ <property name="expand">True</property>
1782+ <property name="fill">True</property>
1783+ <property name="position">2</property>
1784+ </packing>
1785+ </child>
1786 </object>
1787 </child>
1788 </object>
1789 <object class="GtkWindow" id="welcom">
1790+ <property name="can_focus">False</property>
1791 <property name="border_width">5</property>
1792 <property name="title" translatable="yes">Arte +7 Recorder</property>
1793 <property name="window_position">center-always</property>
1794@@ -1155,38 +1335,49 @@
1795 <child>
1796 <object class="GtkVBox" id="vbox12">
1797 <property name="visible">True</property>
1798+ <property name="can_focus">False</property>
1799 <child>
1800 <object class="GtkHBox" id="hbox5">
1801 <property name="visible">True</property>
1802+ <property name="can_focus">False</property>
1803 <child>
1804 <object class="GtkImage" id="image1">
1805 <property name="visible">True</property>
1806+ <property name="can_focus">False</property>
1807 <property name="stock">gtk-dialog-info</property>
1808- <property name="icon-size">6</property>
1809+ <property name="icon_size">6</property>
1810 </object>
1811 <packing>
1812+ <property name="expand">True</property>
1813+ <property name="fill">True</property>
1814 <property name="position">0</property>
1815 </packing>
1816 </child>
1817 <child>
1818 <object class="GtkLabel" id="label9">
1819 <property name="visible">True</property>
1820- <property name="yalign">0.47999998927116394</property>
1821+ <property name="can_focus">False</property>
1822 <property name="label" translatable="yes">Welcome to Arte +7 recorder
1823 It's a first run please configure</property>
1824+ <property name="yalign">0.47999998927116394</property>
1825 </object>
1826 <packing>
1827+ <property name="expand">True</property>
1828+ <property name="fill">True</property>
1829 <property name="position">1</property>
1830 </packing>
1831 </child>
1832 </object>
1833 <packing>
1834+ <property name="expand">True</property>
1835+ <property name="fill">True</property>
1836 <property name="position">0</property>
1837 </packing>
1838 </child>
1839 <child>
1840 <object class="GtkHButtonBox" id="hbuttonbox1">
1841 <property name="visible">True</property>
1842+ <property name="can_focus">False</property>
1843 <property name="layout_style">end</property>
1844 <child>
1845 <object class="GtkButton" id="button4">
1846@@ -1195,8 +1386,8 @@
1847 <property name="can_focus">True</property>
1848 <property name="receives_default">True</property>
1849 <property name="use_stock">True</property>
1850- <signal name="clicked" handler="destroy_wl"/>
1851- <signal name="clicked" handler="preferences"/>
1852+ <signal name="clicked" handler="destroy_wl" swapped="no"/>
1853+ <signal name="clicked" handler="preferences" swapped="no"/>
1854 </object>
1855 <packing>
1856 <property name="expand">False</property>
1857@@ -1206,25 +1397,12 @@
1858 </child>
1859 </object>
1860 <packing>
1861+ <property name="expand">True</property>
1862+ <property name="fill">True</property>
1863 <property name="position">1</property>
1864 </packing>
1865 </child>
1866 </object>
1867 </child>
1868 </object>
1869- <object class="GtkMenu" id="contextQuit">
1870- <property name="visible">True</property>
1871- <child>
1872- <object class="GtkImageMenuItem" id="menucontext_quit">
1873- <property name="label">gtk-quit</property>
1874- <property name="visible">True</property>
1875- <property name="right_justified">True</property>
1876- <property name="use_underline">True</property>
1877- <property name="use_stock">True</property>
1878- <property name="always_show_image">True</property>
1879- <signal name="activate" handler="on_destroy"/>
1880- </object>
1881- </child>
1882- </object>
1883- <object class="GtkTextBuffer" id="textbuffer1"/>
1884 </interface>
1885
1886=== modified file 'arte7recorder/Catalog.py'
1887--- arte7recorder/Catalog.py 2015-05-12 11:58:19 +0000
1888+++ arte7recorder/Catalog.py 2017-03-19 14:31:17 +0000
1889@@ -1,86 +1,115 @@
1890 #!/usr/bin/env python
1891 # -*- coding: utf-8 -*-
1892
1893-import os, re
1894-import time
1895-import urllib2, xml.dom.minidom
1896+import urllib2
1897 import sys
1898-#import gconf
1899 import BeautifulSoup as BS
1900-import json
1901-
1902-def unescape_html(text):
1903- return BS.BeautifulStoneSoup(text, convertEntities=BS.BeautifulStoneSoup.HTML_ENTITIES).contents[0]
1904-
1905-def get_lang():
1906- lang = os.environ.get("LANG")
1907- n = lang.split('_')
1908- lang = "fr"
1909- if n[0] in ("fr","de"):
1910- lang = n[0]
1911- return lang
1912-
1913-time_re = re.compile("^\d\d[h:]\d\d$")
1914-fr_monthes = ["janvier", "fevrier", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre"]
1915-de_monthes = ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"]
1916-def parse_date( date_str ):
1917- date_array = date_str.split(",")
1918- if time_re.search( date_array[-1].strip() ) is None:
1919- return ""
1920- time_ = date_array[-1].strip()
1921- if date_array[0].strip() in ("Aujourd'hui", "Heute"):
1922- date_ = time.strftime( "%Y %m %d" )
1923- elif date_array[0].strip() in ("Hier", "Gestern"):
1924- date_ = time.strftime( "%Y %m %d", time.localtime(time.time() - (24*60*60)) )
1925- else:
1926- array = date_array[1].split()
1927- day = array[0].strip(".")
1928- month = array[1]
1929- for arr in (fr_monthes, de_monthes):
1930- if array[1] in arr:
1931- month = "%02d" % (arr.index(array[1])+1)
1932- year = array[2]
1933- date_ = "%s %s %s" % (year, month, day)
1934- return date_ + ", " + time_
1935+try:
1936+ import simplejson as json
1937+except ImportError:
1938+ import json
1939
1940 class Catalog:
1941-
1942- # Constantes
1943- ARTE_WEB_ROOT = 'http://www.arte.tv'
1944- ARTE_WEB_JSON = 'http://www.arte.tv/guide/fr/plus7.json'
1945- INDEX_TAG = 'index'
1946- TITLE_TAG = 'bigTitle'
1947- DATE_TAG = 'startDate'
1948- URL_TAG = 'targetURL'
1949- RESUME_TAG = 'resume'
1950- DURATION_TAG = 'duration'
1951- IMAGE_TAG = 'previewPictureURL'
1952-
1953- # Contenu du catalogue
1954- videos = []
1955-
1956- def __init__(self):
1957- lang = "/%s/" % get_lang()
1958- max_video_displayed = 200
1959- try:
1960- ul = urllib2.urlopen( self.ARTE_WEB_JSON )
1961- json_content = ul.read()
1962- content = json.loads( json_content )
1963- for obj in content['videos']:
1964- video = dict()
1965- video['previewPictureURL'] = obj['image_url']
1966- video['targetURL'] = obj['url']
1967- video['bigTitle'] = obj['title']
1968- video['startDate'] = obj['airdate_long']
1969- video['duration'] = int(obj['duration'])
1970- try:
1971- video['resume'] = obj['desc'].rstrip()
1972- except AttributeError:
1973- video['resume'] = ''
1974- self.videos.append(video)
1975- #if len(self.videos)>5: break
1976- print len(self.videos), "videos were found to be downloadable !"
1977- except IOError:
1978- print _("There is a problem with your internet connection")
1979- sys.exit(0)
1980-
1981+ # Constantes
1982+ ARTE_WEB_ROOT = 'http://www.arte.tv'
1983+ ARTE_WEB_JSON = 'http://www.arte.tv/guide/fr/plus7/videos?country=BE&page=PAGE_NUMBER&limit=NUM_VIDEOS&sort=newest'
1984+ ARTE_WEB_PLUS7 = 'http://www.arte.tv/guide/fr/plus7/?zone=europe-de-fr'
1985+ INDEX_TAG = 'index'
1986+ TITLE_TAG = 'bigTitle'
1987+ DATE_TAG = 'startDate'
1988+ URL_TAG = 'targetURL'
1989+ RESUME_TAG = 'resume'
1990+ DURATION_TAG = 'duration'
1991+ IMAGE_TAG = 'previewPictureURL'
1992+ MAX_VIDEOS = -1
1993+ TOTAL_VIDEOS = 0
1994+
1995+ def __init__(self):
1996+ self.num_videos = 24 # number of videos to fetch at each iteration
1997+ self.ResetCatalog()
1998+
1999+ def ResetCatalog(self):
2000+ self.page_num = 1
2001+ self.videos = []
2002+
2003+ def NumVideos(self):
2004+ return len(self.videos)
2005+
2006+ def FetchVideos(self):
2007+ try:
2008+ try:
2009+ rep = { 'PAGE_NUMBER': self.page_num, 'NUM_VIDEOS': self.num_videos }
2010+ url = self.ARTE_WEB_JSON
2011+ for k, v in rep.iteritems():
2012+ url = url.replace(k, str(v))
2013+ content = json.loads( urllib2.urlopen( url ).read() )
2014+ except urllib2.HTTPError:
2015+ print _('Failed to open the json file on %s' % url)
2016+ raise TypeError
2017+ if 'videos' in content:
2018+ for v in content['videos']:
2019+ self.ExtractVideoContent(v)
2020+ if self.MAX_VIDEOS>0 and self.NumVideos()>=self.MAX_VIDEOS:
2021+ return False
2022+ if content['total_count']!=self.TOTAL_VIDEOS:
2023+ self.TOTAL_VIDEOS = content['total_count']
2024+ print _('Parsing page %(page)d -- extracted %(num_extr)d videos / %(num_total)d' % {'page': self.page_num, 'num_extr': self.NumVideos(), 'num_total': content['total_count']})
2025+ self.page_num += 1
2026+ return content['has_more']
2027+ except TypeError:
2028+ print _('Failed to fetch the json... proceeding with parsing the home page')
2029+ self.ParseHomePage()
2030+ return True
2031+
2032+ return False
2033+
2034+ def ParseHomePage(self):
2035+ try:
2036+ ul = urllib2.urlopen( self.ARTE_WEB_PLUS7 )
2037+ soup = BS.BeautifulSoup(ul.read())
2038+ txt = u''
2039+ tags = ["categoriesVideos", "highlightedVideos", "currentLive", "dailyMostViewedVideos", "mostViewedVideos", "nextExpiringVideos", "clusters"]
2040+ for sc in soup.findAll('script', type='text/javascript'):
2041+ if 'categoriesVideos' in unicode(sc.string):
2042+ if 'React.createElement(HomePage, {' in sc.string:
2043+ txt = u'[{'+''.join(sc.string.split('createElement(HomePage, {')[1:])
2044+ else:
2045+ txt = sc.string.replace("require('js/page/home')(", '[').strip()
2046+ txt = str(txt.decode('utf-8'))
2047+ if 'ReactDOM.render' in txt:
2048+ txt = ''.join(txt.split('ReactDOM.render')[0])
2049+ break
2050+ if txt==u'': raise IOError
2051+ txt = txt.encode('utf-8')
2052+ json_content = txt.replace(');', ']')
2053+ try:
2054+ content = demjson.decode( json_content )[0]
2055+ except demjson.JSONDecodeError:
2056+ print _('Error: %s' % json_content)
2057+ exit(0)
2058+ for c in content: # loop over all collections
2059+ if type(content[c]) is dict:
2060+ if 'videos' in content[c]: self.ExtractVideoContent(content[c]['videos'])
2061+ elif type(content[c]) is list:
2062+ if len(content[c])==1:
2063+ self.ExtractVideoContent(content[c])
2064+ continue
2065+ for i in content[c]:
2066+ if 'videos' in i: self.ExtractVideoContent(i['videos'])
2067+ self.videos.sort(key=lambda x: (x['startDate']), reverse=True)
2068+ except IOError:
2069+ print _("There is a problem with your internet connection")
2070+ sys.exit(0)
2071+
2072+ def ExtractVideoContent(self, c):
2073+ video = { self.IMAGE_TAG: c['thumbnail_url'],
2074+ self.URL_TAG: c['url'],
2075+ self.TITLE_TAG: c['title'],
2076+ self.DATE_TAG: c['scheduled_on'],
2077+ self.DURATION_TAG: int(c['duration'])/60 }
2078+ try:
2079+ video[self.RESUME_TAG] = c['teaser'].rstrip()
2080+ except AttributeError:
2081+ video[self.RESUME_TAG] = ''
2082+ if video not in self.videos:
2083+ self.videos.append(video)
2084
2085=== modified file 'arte7recorder/arte7recorder.py'
2086--- arte7recorder/arte7recorder.py 2015-05-12 11:58:19 +0000
2087+++ arte7recorder/arte7recorder.py 2017-03-19 14:31:17 +0000
2088@@ -2,24 +2,28 @@
2089 # -*- coding: utf-8 -*-
2090
2091 import sys
2092-import os, subprocess, shutil, select
2093+import os, subprocess
2094 import signal
2095+
2096 import gtk
2097 import gobject
2098 import gtk.glade
2099+import pygtk
2100+pygtk.require('2.0')
2101+
2102 import re
2103-import urllib2, xml.dom.minidom
2104+import urllib2
2105 import pynotify
2106 import ConfigParser
2107-import locale
2108-import gettext
2109-import pygtk
2110-import BeautifulSoup as BS
2111+
2112 from PIL import Image
2113 import json
2114-pygtk.require('2.0')
2115-
2116-from Catalog import Catalog, unescape_html, get_lang
2117+
2118+# translation
2119+import locale, gettext, logging
2120+
2121+from Catalog import Catalog
2122+from fn_download import get_url, rtmp_download, http_download
2123
2124 APP = "messages"
2125 DIR = "locale"
2126@@ -27,195 +31,32 @@
2127
2128 gtk.glade.bindtextdomain(APP, DIR)
2129 gtk.glade.textdomain(APP)
2130-pathname = os.path.dirname(sys.argv[0])
2131-localdir = os.path.abspath(pathname) + "/locale"
2132-gettext.install("messages", localdir)
2133-
2134-def unescape_xml(text):
2135- text = text.replace( "%3A", ":").replace( "%2F", "/").replace( "%2C", ",")
2136- return BS.BeautifulStoneSoup(text, convertEntities=BS.BeautifulStoneSoup.XML_ENTITIES).contents[0]
2137-
2138-def get_url( url_page, quality ):
2139- page_soup = BS.BeautifulSoup( urllib2.urlopen(url_page).read() )
2140- vc = page_soup.find("div", {"class":"video-container"})
2141- try:
2142- vc_url = vc['arte_vp_url']
2143- except KeyError:
2144- print "FATAL ERROR: No JSON could be extracted from the web page:"
2145- print url_page
2146- sys.exit(-1)
2147- json_tree = json.load( urllib2.urlopen(vc_url) )
2148- formats = json_tree["videoJsonPlayer"]["VSR"]
2149- web_page = json_tree["videoJsonPlayer"]["VTR"]
2150- #print web_page, formats
2151- try:
2152- protoc = 'http'
2153- if 'HTTP_REACH_EQ_1' in formats.keys():
2154- obj = formats["HTTP_REACH_EQ_1"]
2155- elif 'HTTP_MP4_MQ_1' in formats.keys():
2156- obj = formats["HTTP_MP4_MQ_1"]
2157- url = obj["url"]
2158- except KeyError:
2159- protoc = 'rtmp'
2160- try:
2161- obj = formats["RTMP_SQ_1"]
2162- url = obj["streamer"]+obj["url"]
2163- except KeyError:
2164- obj = formats["RMTP_HQ"]
2165- url = obj["streamer"]+obj["url"]
2166- movie_url = {'protocol': protoc, 'url': url, 'page': web_page}
2167- #print movie_url
2168- ##FIXME!!! implement quality and language!!
2169- return movie_url
2170-
2171-def http_download( link, destination = "/dev/null", try_resume = True, resuming = False ):
2172- global subprocess_pid
2173- #print link, destination
2174- some_dl_done = False
2175- need_more_dl = True
2176-
2177- if try_resume and os.path.isfile( destination ):
2178- for percent in http_download(link, destination, False, True ):
2179- if percent != -1:
2180- some_dl_done = True
2181- need_more_dl = percent != 100.0
2182- yield percent
2183- else:
2184- break
2185-
2186- max_skip_cnt = 15
2187- cmd_dl = 'wget "%s" -O "%s"' % (link, destination)
2188- cmd_resume = 'wget -c "%s" -O "%s"' % (link, destination)
2189- SECONDS_TO_WAIT = 5
2190- #percent_re = re.compile("\((.+)%\)$")
2191- percent_re = re.compile("([0-9,]+)%")
2192-
2193- ret_code = None
2194- if some_dl_done or resuming:
2195- cmd = cmd_resume
2196- else:
2197- cmd = cmd_dl
2198- while need_more_dl:
2199- stderr_buff = ""
2200- whole_stderr_buff = ""
2201- p = subprocess.Popen( cmd, shell=True, stderr=subprocess.PIPE, close_fds=True)
2202- subprocess_pid = p.pid + 1
2203- while ret_code is None:
2204- fds_read, fds_write, fds_exception = select.select([p.stderr],[], [], SECONDS_TO_WAIT)
2205- if len(fds_read) == 1:
2206- #print p.stderr.read(100),fds_read,fds_write
2207- c = p.stderr.read(1)
2208- whole_stderr_buff += c
2209- if c in ("\n","\r"):
2210- match = percent_re.search( stderr_buff )
2211- if max_skip_cnt == 0:
2212- yield -1.0
2213- if match is not None:
2214- max_skip_cnt = 15
2215- yield float(match.group(1))
2216- else:
2217- max_skip_cnt -= 1
2218- stderr_buff = ""
2219- else:
2220- stderr_buff += c
2221- ret_code = p.poll()
2222- whole_stderr_buff += p.stderr.read()
2223- subprocess_pid = None
2224- if ret_code == 0:
2225- yield 100.0
2226- break
2227- elif ret_code == 2:
2228- cmd = cmd_resume
2229- else:
2230- print ret_code
2231- print whole_stderr_buff
2232- print
2233- yield -1.0
2234- ret_code = None
2235-
2236-
2237-def rtmp_download( link, destination = "/dev/null", try_resume = True, resuming =False, web_page=None ):
2238- global subprocess_pid
2239- some_dl_done = False
2240- need_more_dl = True
2241- if try_resume and os.path.isfile( destination ):
2242- for percent in rtmp_download(link, destination, False, True, web_page=web_page ):
2243- if percent != -1:
2244- some_dl_done = True
2245- need_more_dl = percent != 100.0
2246- yield percent
2247- else:
2248- break
2249-
2250- cmd_dl = 'flvstreamer -r "%s" -p "%s" --flv "%s" -V' % (link, web_page, destination)
2251- cmd_resume = 'flvstreamer -r "%s" --resume --flv "%s"' % (link, destination)
2252- cmd_resume_skip = 'flvstreamer -r "%s" --resume --skip 1 --flv "%s"' % (link, destination)
2253- cmd_youtube_dl = 'youtube-dl %s -f mp4 -o %s' % (web_page,'"'+destination+'"')
2254- SECONDS_TO_WAIT = 3
2255- max_skip_cnt = 10
2256- #percent_re = re.compile("\((.+)%\)$")
2257- percent_re = re.compile("([0-9,]+)%")
2258-
2259- ret_code = None
2260- #if some_dl_done or resuming:
2261- # cmd = cmd_resume
2262- #else:
2263- # cmd = cmd_dl
2264- cmd = cmd_youtube_dl
2265-
2266- print "Command invoked:\n\t%s" % cmd
2267- while need_more_dl:
2268- stderr_buff = ""
2269- whole_stderr_buff = ""
2270- p = subprocess.Popen( cmd, shell=True, stderr=subprocess.PIPE, close_fds=True)
2271- subprocess_pid = p.pid + 1
2272- while ret_code is None:
2273- fds_read, fds_write, fds_exception = select.select([p.stderr],[], [], SECONDS_TO_WAIT)
2274- if len(fds_read) == 1:
2275- c = p.stderr.read(1)
2276- whole_stderr_buff += c
2277- if c in ("\n","\r"):
2278- match = percent_re.search( stderr_buff )
2279- if match is not None:
2280- # If anyframe was retreived, then reset available skip count
2281- max_skip_cnt = 10
2282- yield float(match.group(1))
2283- stderr_buff = ""
2284- else:
2285- stderr_buff += c
2286- ret_code = p.poll()
2287- whole_stderr_buff += p.stderr.read()
2288- subprocess_pid = None
2289- if ret_code == 0:
2290- yield 100.0
2291- break
2292- elif ret_code == 2:
2293- cmd = cmd_resume
2294- else:
2295- must_resume = False
2296- for line in whole_stderr_buff.split("\n"):
2297- if line.find("Couldn't resume FLV file, try --skip 1") != -1:
2298- must_resume = True
2299- break
2300- if must_resume and max_skip_cnt >= 0:
2301- max_skip_cnt -= 1
2302- cmd = cmd_resume_skip
2303- else:
2304- print ret_code
2305- print whole_stderr_buff
2306- print
2307- yield -1.0
2308- ret_code = None
2309-
2310-
2311+
2312+def init_locale():
2313+ '''prepare l10n'''
2314+ locale.setlocale(locale.LC_ALL, '') # use user's preferred locale
2315+ # take first two characters of country code
2316+ loc = locale.getlocale()
2317+ filename = "locale/%s/messages.mo" % loc[0]
2318+ print loc, filename
2319+ try:
2320+ logging.debug( "Opening message file %s for locale %s", filename, loc[0] )
2321+ trans = gettext.GNUTranslations(open( filename, "rb" ) )
2322+ except IOError:
2323+ logging.debug( "Locale not found. Using default messages" )
2324+ trans = gettext.NullTranslations()
2325+ trans.install()
2326
2327 class GUI(object):
2328 wmvRE = re.compile('availableFormats.*=.*"(.*HQ.*wmv.*)"')
2329 mmsRE = re.compile('"(mms.*)"')
2330 resumeRE = re.compile('<p class="text">([^<]*)<')
2331 dureeRE = re.compile('[^0-9]*([0-9]+) (mn|min)')
2332+ UI_FILE = './Arte7recorderWindow.ui'
2333
2334 def __init__(self):
2335+ self.catalog = Catalog()
2336+
2337 self.staticon = gtk.StatusIcon()
2338 self.staticon.set_from_file("/usr/share/pixmaps/arte-icon.png")
2339 self.staticon.connect("activate", self.activate)
2340@@ -225,8 +66,12 @@
2341 self.first = None
2342 self.startup = True
2343 self.builder = gtk.Builder()
2344- self.builder.add_from_file("./Arte7recorderWindow.ui")
2345+ self.builder.add_from_file(self.UI_FILE)
2346 self.builder.connect_signals(self)
2347+
2348+ # first start by populating the catalog
2349+ self.update_catalog()
2350+
2351 self.window1 = self.builder.get_object("arte7recorder_window")
2352 #self.window1 = self.builder.get_object("window_newui")
2353 self.window1.maximize()
2354@@ -261,6 +106,23 @@
2355 else:
2356 self.window1.show()
2357 self.dl_resume(None, None, None)
2358+
2359+ def update_catalog(self):
2360+ #self.catalog.MAX_VIDEOS = 10 #FIXME for debugging purposes
2361+ self.loading = self.builder.get_object('loading_window')
2362+ self.loading.show()
2363+ self.loading_label = self.builder.get_object('loading_label')
2364+ self.loading_bar = self.builder.get_object('loading_pb')
2365+ txt = self.loading_label.get_text()
2366+ while self.catalog.FetchVideos(): # while there are still videos to fetch
2367+ '''Videos are fetched here'''
2368+ fraction = float(self.catalog.NumVideos())/self.catalog.TOTAL_VIDEOS
2369+ txt = txt.replace('xxx', str(self.catalog.NumVideos())).replace('yyy', str(self.catalog.TOTAL_VIDEOS))
2370+ self.loading_bar.set_fraction(fraction)
2371+ self.loading_bar.set_text('{0:0.1f}%'.format(fraction*100))
2372+ self.loading_label.set_text(txt)
2373+ print _('%d videos were found to be downloadable!' % self.catalog.NumVideos())
2374+ self.loading.destroy()
2375
2376 def destroy_wl(self, widget, data=None):
2377 self.welcom.hide()
2378@@ -279,25 +141,12 @@
2379
2380 #Bouton Refresh
2381 def on_actu(self, button):
2382- catalog
2383- datalist = open('/tmp/database', 'w')
2384- print >> datalist,'\n'.join(['%s;;%s;;%s;;%s;;%i;;%s' %
2385- (video[Catalog.TITLE_TAG],
2386- video[Catalog.DATE_TAG],
2387- video[Catalog.URL_TAG],
2388- video[Catalog.IMAGE_TAG],
2389- video[Catalog.DURATION_TAG],
2390- video[Catalog.RESUME_TAG]) for video in catalog.videos if Catalog.TITLE_TAG in video])
2391- datalist.close()
2392- self.liststore.clear()
2393- f = open ("/tmp/database", "r")
2394- for line in f:
2395- t = line.split(";;")
2396- self.liststore.append(t)
2397+ self.catalog.ResetCatalog() # resets the counter and the list of videos
2398+ self.update_catalog()
2399
2400 #Bouton About
2401 def about(self, widget):
2402- self.builder.add_from_file("./Arte7recorderWindow.ui")
2403+ self.builder.add_from_file(self.UI_FILE)
2404 self.about = self.builder.get_object("arte7recorder_about")
2405 self.result = self.about.run()
2406 self.about.destroy()
2407@@ -305,7 +154,7 @@
2408
2409 #Bouton Preference
2410 def preferences(self, widget):
2411- self.builder.add_from_file("./Arte7recorderWindow.ui")
2412+ self.builder.add_from_file(self.UI_FILE)
2413 self.pref = self.builder.get_object("arte7recorder_pref")
2414 if self.first == 'yes':
2415 self.restart = self.builder.get_object("label12")
2416@@ -408,10 +257,11 @@
2417 self.nom_fichier = self.nom_fichier.replace("/", "-")
2418 self.liststore2.set_value(self.treeiter, 3, _('Download...'))
2419 try:
2420- rtmp_url = get_url( url_page, quality = "hd" )
2421+ url = get_url( url_page, quality = "hd" )
2422 signal_fin = False
2423- if rtmp_url['protocol']=='http':
2424- for percent in http_download( rtmp_url['url'], self.directory + "/" + self.nom_fichier.replace("'", "_") ):
2425+ print _('Protocol used in download: %(protocol)s with quality: %(quality)s' % {'protocol': url['protocol'], 'quality': url['quality']})
2426+ if url['protocol']=='http':
2427+ for percent in http_download( url['url'], self.directory + "/" + self.nom_fichier.replace("'", "_") ):
2428 if percent == -1.0:
2429 raise IOError()
2430 signal_fin = percent == 100.0
2431@@ -425,8 +275,8 @@
2432 # affichage de la progression
2433 while gtk.events_pending():
2434 gtk.main_iteration()
2435- elif rtmp_url['protocol']=='rtmp':
2436- for percent in rtmp_download( rtmp_url['url'], self.directory + "/" + self.nom_fichier.replace("'", "_"), web_page=rtmp_url['page'] ):
2437+ elif url['protocol']=='rtmp':
2438+ for percent in rtmp_download( url['url'], self.directory + "/" + self.nom_fichier.replace("'", "_"), web_page=url['page'] ):
2439 if percent == -1.0:
2440 raise IOError()
2441 signal_fin = percent == 100.0
2442@@ -441,7 +291,7 @@
2443 while gtk.events_pending():
2444 gtk.main_iteration()
2445 except IOError:
2446- self.builder.add_from_file("./Arte7recorderWindow.ui")
2447+ self.builder.add_from_file(self.UI_FILE)
2448 self.erreur = self.builder.get_object("error_dialog")
2449 self.error_text = self.builder.get_object("error_text")
2450 self.error_text.set_text(_("There is a problem with your internet connection!"))
2451@@ -499,19 +349,24 @@
2452 #self.columnDate.set_sort_column_id(1)
2453 self.treeview_disp.set_search_column(0)
2454 #self.treeview_disp.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
2455- f = open ("/tmp/database", "r")
2456- for line in f:
2457- t = line.split(";;")
2458+ for video in self.catalog.videos:
2459+ if Catalog.TITLE_TAG not in video: continue
2460 try:
2461- #print t
2462- self.liststore.append(t)
2463+ self.liststore.append([
2464+ video[Catalog.TITLE_TAG],
2465+ video[Catalog.DATE_TAG],
2466+ video[Catalog.URL_TAG],
2467+ video[Catalog.IMAGE_TAG],
2468+ video[Catalog.DURATION_TAG],
2469+ video[Catalog.RESUME_TAG]
2470+ ])
2471 except ValueError:
2472- continue
2473+ continue
2474
2475 #Téléchargement de l'image
2476 def dl_resume(self, treeview_disp, path, columnNom):
2477 fetch_image = True #FIXME
2478- if self.startup == True:
2479+ if self.startup:
2480 iter = self.liststore.get_iter_first()
2481 modele = self.liststore
2482 self.startup = False
2483@@ -602,16 +457,7 @@
2484
2485
2486 if __name__ == "__main__":
2487- catalog = Catalog()
2488- datalist = open('/tmp/database', 'w')
2489- print >> datalist,'\n'.join(['%s;;%s;;%s;;%s;;%i;;%s' %
2490- (video[Catalog.TITLE_TAG],
2491- video[Catalog.DATE_TAG],
2492- video[Catalog.URL_TAG],
2493- video[Catalog.IMAGE_TAG],
2494- video[Catalog.DURATION_TAG],
2495- video[Catalog.RESUME_TAG]) for video in catalog.videos if Catalog.TITLE_TAG in video])
2496- datalist.close()
2497- app = GUI()
2498- gtk.main()
2499+ init_locale()
2500+ app = GUI()
2501+ gtk.main()
2502
2503
2504=== added file 'arte7recorder/fn_download.py'
2505--- arte7recorder/fn_download.py 1970-01-01 00:00:00 +0000
2506+++ arte7recorder/fn_download.py 2017-03-19 14:31:17 +0000
2507@@ -0,0 +1,242 @@
2508+#!/usr/bin/env python
2509+# -*- coding: utf-8 -*-
2510+
2511+import sys
2512+import os, subprocess, select
2513+import re
2514+import urllib2
2515+import BeautifulSoup as BS
2516+import json
2517+from gettext import gettext as _
2518+
2519+class InvalidPage(Exception):
2520+ pass
2521+
2522+def unquote_url( url, attr ):
2523+ if ( '%s=' % attr ) not in url:
2524+ return url
2525+ url = url.split( '%s=' % attr )[1]
2526+ if '&' in url:
2527+ url = url.split('&')[0]
2528+ return urllib2.unquote( url )
2529+
2530+def get_url( url_page, quality ):
2531+ page_soup = BS.BeautifulSoup( urllib2.urlopen(url_page).read() )
2532+ vc = page_soup.find("iframe")
2533+ if vc==None:
2534+ print 'FATAL ERROR: The video container was not found on the web page:'
2535+ print url_page
2536+ sys.exit(-1)
2537+ if vc.has_key('src'):
2538+ iframe_src = vc['src']
2539+ vc_url = urllib2.unquote( iframe_src.split('json_url=')[-1].split('&')[0] )
2540+ else:
2541+ print 'FATAL ERROR: The path to the video was not found on the web page:'
2542+ print url_page
2543+ sys.exit(-1)
2544+ json_tree = json.load( urllib2.urlopen(vc_url) )
2545+ if json_tree.has_key('videoJsonPlayer'):
2546+ formats = json_tree["videoJsonPlayer"]["VSR"]
2547+ web_page = json_tree["videoJsonPlayer"]["VTR"]
2548+ elif json_tree.has_key('html'):
2549+ ifr = BS.BeautifulSoup( json_tree['html'] ).find('iframe')
2550+ if ifr.has_key('src'):
2551+ json_url = unquote_url( ifr['src'], 'json_url' )
2552+ json_tree = json.load( urllib2.urlopen(json_url) )
2553+ formats = json_tree["videoJsonPlayer"]["VSR"]
2554+ web_page = json_tree["videoJsonPlayer"]["VTR"]
2555+ try:
2556+ protoc = 'http'
2557+ print _('Parsing JSON from %s' % web_page)
2558+ bs = BS.BeautifulSoup( urllib2.urlopen(web_page) )
2559+ ifr = bs.find('div', {'class': 'video-player', 'id': 'main-player'}).find('iframe')
2560+ if not ifr.has_key('src'):
2561+ raise InvalidPage
2562+ json_url = unquote_url( ifr['src'], 'json_url' )
2563+ json_tree = json.load( urllib2.urlopen(json_url) )
2564+ formats = json_tree['videoJsonPlayer']['VSR']
2565+ web_page = json_tree['videoJsonPlayer']['VTR']
2566+ except InvalidPage:
2567+ print _('Invalid succession of pages detected! Contact the developer!')
2568+ sys.exit(0)
2569+
2570+ try:
2571+ print _('Available formats detected in %s:' % web_page)
2572+ candidates = dict()
2573+ for k, v in formats.iteritems():
2574+ if '_1' not in k: continue # French
2575+ if '_8' in k: continue # French, subtitles
2576+ if '_2' in k: continue # German
2577+ if '_12' in k: continue # Spanish
2578+ if '_11' in k: continue # ??
2579+ if 'HTTP_' not in k and 'HTTPS_' not in k: continue
2580+ if v['bitrate']<400: continue
2581+ candidates[v['quality']] = v['url']
2582+ print _('--> [%(key)s] (quality=%(quality)s, bitrate=%(bitrate)4d) %(width)4dx%(height)4d' % {'key': k, 'quality': v['quality'], 'bitrate': v['bitrate'], 'width': v['width'], 'height': v['height']})
2583+
2584+ if 'EQ' in candidates.keys(): quality = 'EQ'
2585+ elif 'HQ' in candidates.keys(): quality = 'HQ'
2586+ elif 'SQ' in candidates.keys(): quality = 'SQ'
2587+ url = candidates[quality]
2588+ except KeyError:
2589+ protoc = 'rtmp'
2590+ print formats
2591+ try:
2592+ obj = formats["RTMP_SQ_1"]
2593+ url = obj["streamer"]+obj["url"]
2594+ quality = 'SQ'
2595+ except KeyError:
2596+ try:
2597+ obj = formats["RMTP_HQ"]
2598+ url = obj["streamer"]+obj["url"]
2599+ quality = 'HQ'
2600+ except KeyError:
2601+ raise InvalidPage
2602+ except InvalidPage:
2603+ print _('Invalid succession of pages detected! Contact the developer!')
2604+ sys_exit(0)
2605+ return dict()
2606+
2607+ movie_url = {'protocol': protoc, 'url': url, 'page': web_page, 'quality': quality}
2608+ #print movie_url
2609+ ##FIXME!!! implement quality and language!!
2610+ return movie_url
2611+
2612+def http_download( link, destination = "/dev/null", try_resume = True, resuming = False ):
2613+ global subprocess_pid
2614+ #print link, destination
2615+ some_dl_done = False
2616+ need_more_dl = True
2617+
2618+ if try_resume and os.path.isfile( destination ):
2619+ for percent in http_download(link, destination, False, True ):
2620+ if percent != -1:
2621+ some_dl_done = True
2622+ need_more_dl = percent != 100.0
2623+ yield percent
2624+ else:
2625+ break
2626+
2627+ max_skip_cnt = 15
2628+ cmd_dl = 'wget "%s" -O "%s"' % (link, destination)
2629+ cmd_resume = 'wget -c "%s" -O "%s"' % (link, destination)
2630+ SECONDS_TO_WAIT = 5
2631+ #percent_re = re.compile("\((.+)%\)$")
2632+ percent_re = re.compile("([0-9,]+)%")
2633+
2634+ ret_code = None
2635+ if some_dl_done or resuming:
2636+ cmd = cmd_resume
2637+ else:
2638+ cmd = cmd_dl
2639+ while need_more_dl:
2640+ stderr_buff = ""
2641+ whole_stderr_buff = ""
2642+ p = subprocess.Popen( cmd, shell=True, stderr=subprocess.PIPE, close_fds=True)
2643+ subprocess_pid = p.pid + 1
2644+ while ret_code is None:
2645+ fds_read, fds_write, fds_exception = select.select([p.stderr],[], [], SECONDS_TO_WAIT)
2646+ if len(fds_read) == 1:
2647+ #print p.stderr.read(100),fds_read,fds_write
2648+ c = p.stderr.read(1)
2649+ whole_stderr_buff += c
2650+ if c in ("\n","\r"):
2651+ match = percent_re.search( stderr_buff )
2652+ if max_skip_cnt == 0:
2653+ yield -1.0
2654+ if match is not None:
2655+ max_skip_cnt = 15
2656+ yield float(match.group(1))
2657+ else:
2658+ max_skip_cnt -= 1
2659+ stderr_buff = ""
2660+ else:
2661+ stderr_buff += c
2662+ ret_code = p.poll()
2663+ whole_stderr_buff += p.stderr.read()
2664+ subprocess_pid = None
2665+ if ret_code == 0:
2666+ yield 100.0
2667+ break
2668+ elif ret_code == 2:
2669+ cmd = cmd_resume
2670+ else:
2671+ print ret_code
2672+ print whole_stderr_buff
2673+ print
2674+ yield -1.0
2675+ ret_code = None
2676+
2677+
2678+def rtmp_download( link, destination = "/dev/null", try_resume = True, resuming =False, web_page=None ):
2679+ global subprocess_pid
2680+ some_dl_done = False
2681+ need_more_dl = True
2682+ if try_resume and os.path.isfile( destination ):
2683+ for percent in rtmp_download(link, destination, False, True, web_page=web_page ):
2684+ if percent != -1:
2685+ some_dl_done = True
2686+ need_more_dl = percent != 100.0
2687+ yield percent
2688+ else:
2689+ break
2690+
2691+ cmd_dl = 'flvstreamer -r "%s" -p "%s" --flv "%s" -V' % (link, web_page, destination)
2692+ cmd_resume = 'flvstreamer -r "%s" --resume --flv "%s"' % (link, destination)
2693+ cmd_resume_skip = 'flvstreamer -r "%s" --resume --skip 1 --flv "%s"' % (link, destination)
2694+ cmd_youtube_dl = 'youtube-dl %s -f mp4 -o %s' % (web_page,'"'+destination+'"')
2695+ SECONDS_TO_WAIT = 3
2696+ max_skip_cnt = 10
2697+ #percent_re = re.compile("\((.+)%\)$")
2698+ percent_re = re.compile("([0-9,]+)%")
2699+
2700+ ret_code = None
2701+ #if some_dl_done or resuming:
2702+ # cmd = cmd_resume
2703+ #else:
2704+ # cmd = cmd_dl
2705+ cmd = cmd_youtube_dl
2706+
2707+ print _("Command invoked:\n\t%s" % cmd)
2708+ while need_more_dl:
2709+ stderr_buff = ""
2710+ whole_stderr_buff = ""
2711+ p = subprocess.Popen( cmd, shell=True, stderr=subprocess.PIPE, close_fds=True)
2712+ subprocess_pid = p.pid + 1
2713+ while ret_code is None:
2714+ fds_read, fds_write, fds_exception = select.select([p.stderr],[], [], SECONDS_TO_WAIT)
2715+ if len(fds_read) == 1:
2716+ c = p.stderr.read(1)
2717+ whole_stderr_buff += c
2718+ if c in ("\n","\r"):
2719+ match = percent_re.search( stderr_buff )
2720+ if match is not None:
2721+ # If anyframe was retreived, then reset available skip count
2722+ max_skip_cnt = 10
2723+ yield float(match.group(1))
2724+ stderr_buff = ""
2725+ else:
2726+ stderr_buff += c
2727+ ret_code = p.poll()
2728+ whole_stderr_buff += p.stderr.read()
2729+ subprocess_pid = None
2730+ if ret_code == 0:
2731+ yield 100.0
2732+ break
2733+ elif ret_code == 2:
2734+ cmd = cmd_resume
2735+ else:
2736+ must_resume = False
2737+ for line in whole_stderr_buff.split("\n"):
2738+ if line.find("Couldn't resume FLV file, try --skip 1") != -1:
2739+ must_resume = True
2740+ break
2741+ if must_resume and max_skip_cnt >= 0:
2742+ max_skip_cnt -= 1
2743+ cmd = cmd_resume_skip
2744+ else:
2745+ print ret_code
2746+ print whole_stderr_buff
2747+ print
2748+ yield -1.0
2749+ ret_code = None
2750
2751=== modified file 'arte7recorder/icon.png'
2752Binary files arte7recorder/icon.png 2009-12-03 10:53:27 +0000 and arte7recorder/icon.png 2017-03-19 14:31:17 +0000 differ
2753=== renamed file 'arte7recorder/locale/de_DE/LC_MESSAGES/messages.mo' => 'arte7recorder/locale/de_DE/messages.mo'
2754=== renamed file 'arte7recorder/locale/de_DE/LC_MESSAGES/messages.po' => 'arte7recorder/locale/de_DE/messages.po'
2755=== renamed file 'arte7recorder/locale/fr_FR/LC_MESSAGES/messages.mo' => 'arte7recorder/locale/fr_FR/messages.mo'
2756Binary files arte7recorder/locale/fr_FR/LC_MESSAGES/messages.mo 2010-05-12 12:22:48 +0000 and arte7recorder/locale/fr_FR/messages.mo 2017-03-19 14:31:17 +0000 differ
2757=== renamed file 'arte7recorder/locale/fr_FR/LC_MESSAGES/messages.po' => 'arte7recorder/locale/fr_FR/messages.po'
2758=== added file 'arte7recorder/locale_cmd.sh'
2759--- arte7recorder/locale_cmd.sh 1970-01-01 00:00:00 +0000
2760+++ arte7recorder/locale_cmd.sh 2017-03-19 14:31:17 +0000
2761@@ -0,0 +1,5 @@
2762+#/bin/sh
2763+
2764+xgettext *.{py,ui}
2765+echo "Now localize the messages.po file, and run e.g."
2766+echo " msgfmt -o locale/fr_FR/messages.mo messages.po"
2767
2768=== modified file 'bin/arte7recorder' (properties changed: -x to +x)
2769=== modified file 'setup.py'
2770--- setup.py 2014-06-22 13:12:43 +0000
2771+++ setup.py 2017-03-19 14:31:17 +0000
2772@@ -39,12 +39,13 @@
2773 data_files = [('share/arte7recorder/doc',['README', 'COPYING', 'ChangeLog']),
2774 ('share/applications/',['arte+7recorder.desktop']),
2775 ('share/pyshared/arte7recorder',['arte7recorder/arte7recorder.py',
2776- 'arte7recorder/Catalog.py',
2777- 'arte7recorder/Arte7recorderWindow.ui',
2778- 'arte7recorder/__init__.py',
2779- 'arte7recorder/icon.png']),
2780- ('share/pyshared/arte7recorder/locale/fr_FR/LC_MESSAGES/',['arte7recorder/locale/fr_FR/LC_MESSAGES/messages.mo',
2781- 'arte7recorder/locale/fr_FR/LC_MESSAGES/messages.po']),
2782+ 'arte7recorder/Catalog.py',
2783+ 'arte7recorder/fn_download.py',
2784+ 'arte7recorder/Arte7recorderWindow.ui',
2785+ 'arte7recorder/__init__.py',
2786+ 'arte7recorder/icon.png']),
2787+ ('share/pyshared/arte7recorder/locale/fr_FR/',['arte7recorder/locale/fr_FR/messages.mo','arte7recorder/locale/fr_FR/messages.po']),
2788+ ('share/pyshared/arte7recorder/locale/de_DE/',['arte7recorder/locale/de_DE/messages.mo','arte7recorder/locale/de_DE/messages.po']),
2789 ('share/pixmaps/',['arte-icon.png'])],
2790 requires = ['pynotify', 'BeautifulSoup', 'gconf'],
2791 )

Subscribers

People subscribed via source and target branches