Version up
[raitv.user.js] / raitv.user.js
1 // ==UserScript==
2 // @name        RaiTV video
3 // @description Turn RaiTV silverlight objects into video tags
4 // @namespace   http://oblomov.myopenid.com
5 // @grant       none
6 // @include     http://rai.tv/*
7 // @include     http://rai.it/*
8 // @include     http://www.rai.tv/*
9 // @include     http://www.rai.it/*
10 // @include     http://archivioluce.com/*
11 // @include     http://www.archivioluce.com/*
12 // @author      Giuseppe "Oblomov" Bilotta
13 // @version     20131004.1734
14 // ==/UserScript==
15
16 /* Since the Chrome sandbox is _extremely_ restrictive and we can't
17  * access things such as window.videoURL from the actual document,
18  * we have to resort to script injection to be completely cross-platform.
19  */
20
21 (function() {
22
23 function addScript(source) {
24         var script = document.createElement('script');
25         script.setAttribute("type", "application/javascript");
26         script.textContent = 'window.addEventListener("load", ' + source + ', false);';
27         document.body.appendChild(script);
28 }
29
30
31 addScript(
32 function() {
33         function getURL(name) {
34                 var list = document.getElementsByName(name) ;
35                 if (list && list[0]) {
36                         return list[0].content;
37                 } else {
38                         var altname = name.toUpperCase().replace('VIDEO',
39                                 'video').replace('ANDROID', 'android');
40                         console.log(name, altname);
41                         console.log(window[name], window[altname]);
42                         return window[altname];
43                 }
44         }
45
46         var urls = {
47                 std: getURL('videourl'),
48                 mp4: getURL('videourl_mp4'),
49                 wmv: getURL('videourl_wmv'),
50                 h264: getURL('videourl_h264'),
51                 m3u8: getURL('videourl_m3u8'),
52                 m3u8_android: getURL('videourl_m3u8_android'),
53         }
54
55         function srctag(url, av, fmt) {
56                 if (!url)
57                         return '' ;
58                 var f = null;
59                 if (fmt != 'std') {
60                         f = fmt.replace('_android','');
61                 }
62                 if (f == 'h264') {
63                         f = 'mp4';
64                 }
65                 return '<source src="' + url + '" ' + (f ? 'type="' + av + '/' + f + '" ' : '') + '/>'
66         }
67
68         function H5video(fmt) {
69                 return srctag(urls[fmt], 'video', fmt);
70         }
71
72         // create a link element for one of the page-wide media streams
73         function H5a(fmt) {
74                 if (urls[fmt]) {
75                         var a = document.createElement('a');
76                         a.href = urls[fmt];
77                         a.innerHTML = fmt.toUpperCase();
78                         a.setAttribute('style', 'font-weight:bold;margin-left:1em;color:white');
79                         return a;
80                 }
81                 return null
82         }
83
84         // create a link element for a raw URL
85         function H5aRaw(name, url) {
86                 if (url) {
87                         var a = document.createElement('a');
88                         a.href = url;
89                         a.innerHTML = name.toUpperCase();
90                         a.setAttribute('style', 'font-weight:bold;margin-left:1em;color:red');
91                         return a;
92                 }
93                 return null
94         }
95
96         var streamlist = document.createElement("li");
97
98         // reset stream list: this is used in the playTg and playAudio
99         // functions to reset the stream list when changing stream,
100         function slReset() {
101                 streamlist.innerHTML = '<span>Stream/Download:</span>';
102         }
103         // and of course once at the beginning of it all 8-)
104         slReset();
105
106         var sch;
107
108         var placeStreamList = function() {
109                 // find place to append the stream list to
110                 // if possible, look for an existing ul in what is likely to be the top
111                 // otherwise, create an ul and put it either in a miniLink if available,
112                 // or the top otherwise
113                 // TODO use some smarter mechanism
114                 var pp = sch.parentNode.parentNode.previousElementSibling;
115                 var specs = pp.getElementsByTagName('ul');
116                 if (!specs || !specs[0]) {
117                         specs = document.createElement('ul');
118                         specs.className = 'Specifiche';
119                         var mid = document.getElementById('Notizie');
120                         if (mid) {
121                                 mid = mid.lastElementChild;
122                                 mid.insertBefore(specs, mid.firstElementChild);
123                         } else {
124                                 pp.appendChild(specs);
125                         }
126                 } else {
127                         specs = specs[0];
128                 }
129                 specs.appendChild(streamlist);
130                 console.log(streamlist, 'appended');
131
132         }
133
134         var ourReplayTV = function(det) {
135                 if (!sch) {
136                         sch = document.getElementById("SilverlightPlayer");
137                         sch.style.width = '100%';
138                         sch.style.height = '100%';
139                         placeStreamList();
140                 }
141                 // stop loading any current audio/video
142                 if (sch.firstChild && sch.firstChild.src) {
143                         console.log('stopping current A/V');
144                         sch.firstChild.src = '';
145                 }
146
147                 slReset();
148
149                 var srcs = "";
150                 for (var k in det) {
151                         if (k.match(/^h264/)) {
152                                 var url = det[k];
153                                 if (url && url.length > 0) {
154                                         srcs += srctag(url, 'video', 'h264');
155                                         var r = k.split('_');
156                                         if (r[1]) {
157                                                 r = r[0] + " (" + r[1] + "KB/s)";
158                                         } else {
159                                                 r = r[0];
160                                         }
161                                         streamlist.appendChild(H5aRaw(r, url));
162                                 }
163                         }
164                 }
165                 // re-create the video player
166                 sch.innerHTML = "<video width='100%' height='100%' controls autoplay>" +
167                         srcs +
168                         "<h3>Sorry, no supported video format found :-(</h3></video>";
169
170         }
171
172         if (window.replayTv) {
173                 window.replayTv.playVideo_ujs = window.replayTv.playVideo;
174                 window.replayTv.playVideo = function(det) {
175                         console.log("IN");
176                         try {
177                                 window.replayTv.playVideo_ujs.call(window.replayTv, det);
178                         } catch (e) {
179                                 console.log(e);
180                         }
181                         ourReplayTV(det);
182                         console.log("OUT");
183                 }
184                 if (window.replayTv.currVideo) {
185                         window.replayTv.playVideo(window.replayTv.vid2data[window.replayTv.currVideo]);
186                 }
187         }
188
189         sch = document.getElementById("silverlightControlHost");
190         if (sch) {
191                 // debug
192                 console.log(urls);
193
194                 placeStreamList();
195                 // if we are on a page that defines the videourl* metas, go straight to creating
196                 // the video element
197                 if (urls.std) {
198                         // prevent other JS with messing with this element further
199                         sch.id = 'html5mediaHost';
200                         sch.innerHTML = "<video style='width:100%; height:100%' controls>" +
201                                 H5video('mp4') + H5video('wmv') + H5video('h264') +
202                                 H5video('m3u8') + H5video('m3u8_android') +
203                                 H5video('std') +
204                                 "<h3>Sorry, no supported video format found :-(</h3></video>";
205                         console.log(sch, 'hacked');
206
207                         for (var fmt in urls) {
208                                 var a = H5a(fmt);
209                                 if (a)
210                                         streamlist.appendChild(a);
211                         }
212                         return; // done
213                 }
214
215                 // hack the play* JS functions
216                 if (window.playTg) {
217                         window.playTg = function (liveTg, video, h264, androidUrl) {
218                                 var dataP = new Date();
219                                 var ggP, mmP, aaaaP;
220                                 ggP = dataP.getDate() + "-";
221                                 mmP = dataP.getMonth() + 1 + "-";
222                                 aaaaP = 1900 + dataP.getYear();
223
224                                 // prevent page from refreshing, the site only checks for
225                                 // the existence of object/embed, not audio/video
226                                 window.refreshByJS = false;
227
228                                 // stop loading any current audio/video
229                                 if (sch.firstChild && sch.firstChild.src) {
230                                         console.log('stopping current A/V');
231                                         sch.firstChild.src = '';
232                                 }
233
234                                 // re-create the video player
235                                 sch.innerHTML = "<video width='258' height='195' controls autoplay>" +
236                                         srctag(h264, 'video') +
237                                         srctag(androidUrl, 'video') +
238                                         srctag(video, 'video') +
239                                         "<h3>Sorry, no supported video format found :-(</h3></video>";
240
241                                 // re-create stream list
242                                 slReset();
243                                 // oh we would like to indicate the media type somehow,
244                                 // but it seems to be somewhat random. Not even a HEAD
245                                 // on the URL works reliably all the time
246                                 var a = H5aRaw('1', h264);
247                                 if (a)
248                                         streamlist.appendChild(a);
249                                 if (androidUrl != h264) {
250                                         a = H5aRaw('2', androidUrl);
251                                         if (a)
252                                                 streamlist.appendChild(a);
253                                 }
254                                 if ((video != androidUrl) && (video != h264)) {
255                                         a = H5aRaw('3', video);
256                                         if (a)
257                                                 streamlist.appendChild(a);
258                                 }
259
260                                 setNielsen(location.href + '&video=' + liveTg + '&data=' + ggP + mmP + aaaaP + '', true);
261                                 console.log('playTg', liveTg, video, h264, androidUrl)
262                         }
263                         console.log('playTg hacked');
264                 }
265
266                 if (window.playAudio) {
267                         window.playAudio = function (grrEdizione, mediaUrl, mediatype) {
268                                 var dataP = new Date();
269                                 var ggP, mmP, aaaaP;
270                                 ggP = dataP.getDate() + "-";
271                                 mmP = dataP.getMonth() + 1 + "-";
272                                 aaaaP = 1900 + dataP.getYear();
273
274                                 // prevent page from refreshing, the site only checks for
275                                 // the existence of object/embed, not audio/video
276                                 window.refreshByJS = false;
277
278                                 // stop loading any current audio/video
279                                 if (sch.firstChild && sch.firstChild.src) {
280                                         console.log('stopping current A/V');
281                                         sch.firstChild.src = '';
282                                 }
283
284                                 // re-create the audio player
285                                 sch.innerHTML = "<audio width='258' height='35' controls autoplay>" +
286                                         srctag(mediaUrl, 'audio') +
287                                         "<h3>Sorry, no supported audio format found :-(</h3></audio>";
288
289                                 // re-create stream list
290                                 slReset();
291                                 var a = H5aRaw(mediatype ? mediatype : '(???)', mediaUrl);
292                                 if (a)
293                                         streamlist.appendChild(a);
294
295                                 setNielsen(location.href + '&audio=' + grrEdizione + '&data=' + ggP + mmP + aaaaP + '', true);
296                                 console.log('playAudio', grrEdizione, mediaUrl, mediatype);
297                         }
298                         console.log('playAudio hacked');
299                 }
300         }
301
302         // Archivio Luce
303         if (window.ply  && window.ply.configuration
304                         && window.ply.configuration.file
305                         && window.cnt) {
306                 var src = window.ply.configuration.file.replace(/^mms:\/\//,'http://');
307                 var width = window.ply.configuration.width;
308                 var height = window.ply.configuration.height;
309
310                 window.cnt.innerHTML = "<video style='width:" + width +
311                                         "px; height:" + height + "' controls autostart>" +
312                                         srctag(src, 'video', null) +
313                                         "</video>";
314                 console.log(window.cnt, 'hacked');
315                 window.cnt.appendChild(H5aRaw("WMV", src));
316         }
317 })
318
319 })();