home *** CD-ROM | disk | FTP | other *** search
/ mail.altrad.com / 2015.02.mail.altrad.com.tar / mail.altrad.com / TEST / vlc-2-0-5-win32.exe / lua / http / old / js / functions.js next >
Text File  |  2012-12-12  |  42KB  |  1,220 lines

  1. /*****************************************************************************
  2.  * functions.js: VLC media player web interface
  3.  *****************************************************************************
  4.  * Copyright (C) 2005-2006 the VideoLAN team
  5.  * $Id: functions.js 21264 2007-08-19 17:48:28Z dionoea $
  6.  *
  7.  * Authors: Antoine Cellerier <dionoea -at- videolan -dot- org>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  22.  *****************************************************************************/
  23.  
  24. /**********************************************************************
  25.  * Global variables
  26.  *********************************************************************/
  27.  
  28. var old_time = 0;
  29. var pl_cur_id;
  30. var albumart_id = -1;
  31.  
  32. /**********************************************************************
  33.  * Slider functions
  34.  *********************************************************************/
  35.  
  36. var slider_mouse_down = 0;
  37. var slider_dx = 0;
  38.  
  39. var input_options = new Array();
  40.  
  41. /* findPosX() from http://www.quirksmode.rg/js/indpos.html */
  42. function findPosX(obj)
  43. {
  44.     var curleft = 0;
  45.     if (obj.offsetParent)
  46.     {
  47.         while (obj.offsetParent)
  48.         {
  49.             curleft += obj.offsetLeft
  50.             obj = obj.offsetParent;
  51.         }
  52.     }
  53.     else if (obj.x)
  54.         curleft += obj.x;
  55.     return curleft;
  56. }
  57.  
  58. function slider_seek( e, bar )
  59. {
  60.     seek(Math.floor(( e.clientX + document.body.scrollLeft - findPosX( bar )) / 4)+"%25");
  61. }
  62. function slider_down( e, point )
  63. {
  64.     slider_mouse_down = 1;
  65.     slider_dx = e.clientX - findPosX( point );
  66. }
  67. function slider_up( e, bar )
  68. {
  69.     slider_mouse_down = 0;
  70.     /* slider_seek( e, bar ); */
  71. }
  72. function slider_move( e, bar )
  73. {
  74.     if( slider_mouse_down == 1 )
  75.     {
  76.         var slider_position  = Math.floor( e.clientX - slider_dx + document.body.scrollLeft - findPosX( bar ));
  77.         document.getElementById( 'main_slider_point' ).style.left = slider_position+"px";
  78.         slider_seek( e, bar );
  79.     }
  80. }
  81.  
  82. /**********************************************************************
  83.  * Misc utils
  84.  *********************************************************************/
  85.  
  86. /* XMLHttpRequest wrapper */
  87. function loadXMLDoc( url, callback )
  88. {
  89.   // branch for native XMLHttpRequest object
  90.   if ( window.XMLHttpRequest )
  91.   {
  92.     req = new XMLHttpRequest();
  93.     req.onreadystatechange = callback;
  94.     req.open( "GET", url, true );
  95.     req.send( null );
  96.   // branch for IE/Windows ActiveX version
  97.   }
  98.   else if ( window.ActiveXObject )
  99.   {
  100.     req = new ActiveXObject( "Microsoft.XMLHTTP" );
  101.     if ( req )
  102.     {
  103.       req.onreadystatechange = callback;
  104.       req.open( "GET", url, true );
  105.       req.send();
  106.     }
  107.   }
  108. }
  109.  
  110. /* fomat time in second as hh:mm:ss */
  111. function format_time( s )
  112. {
  113.     var hours = Math.floor(s/3600);
  114.     var minutes = Math.floor((s/60)%60);
  115.     var seconds = Math.floor(s%60);
  116.     if( hours < 10 ) hours = "0"+hours;
  117.     if( minutes < 10 ) minutes = "0"+minutes;
  118.     if( seconds < 10 ) seconds = "0"+seconds;
  119.     return hours+":"+minutes+":"+seconds;
  120. }
  121.  
  122. /* delete all a tag's children and add a text child node */
  123. function set_text( id, val )
  124. {
  125.     var elt = document.getElementById( id );
  126.     while( elt.hasChildNodes() )
  127.         elt.removeChild( elt.firstChild );
  128.     elt.appendChild( document.createTextNode( val ) );
  129. }
  130.  
  131. /* set item's 'element' attribute to value */
  132. function set_css( item, element, value )
  133. {
  134.     for( var j = 0; j < document.styleSheets.length; j++ )
  135.     {
  136.         var cssRules = document.styleSheets[j].cssRules;
  137.         if( !cssRules ) cssRules = document.styleSheets[j].rules;
  138.         for( var i = 0; i < cssRules.length; i++)
  139.         {
  140.             if( cssRules[i].selectorText == item )
  141.             {
  142.                 if( cssRules[i].style.setProperty )
  143.                     cssRules[i].style.setProperty( element, value, null );
  144.                 else
  145.                     cssRules[i].style.setAttribute( toCamelCase( element ), value );
  146.                 return;
  147.             }
  148.         }
  149.     }
  150. }
  151.  
  152. /* get item's 'element' attribute */
  153. function get_css( item, element )
  154. {
  155.     for( var j = 0; j < document.styleSheets.length; j++ )
  156.     {
  157.         var cssRules = document.styleSheets[j].cssRules;
  158.         if( !cssRules ) cssRules = document.styleSheets[j].rules;
  159.         for( var i = 0; i < cssRules.length; i++)
  160.         {
  161.             if( cssRules[i].selectorText == item )
  162.             {
  163.                 if( cssRules[i].style.getPropertyValue )
  164.                     return cssRules[i].style.getPropertyValue( element );
  165.                 else
  166.                     return cssRules[i].style.getAttribute( toCamelCase( element ) );
  167.             }
  168.         }
  169.     }
  170. }
  171.  
  172. function toggle_show( id )
  173. {
  174.     var element = document.getElementById( id );
  175.     if( element.style.display == 'block' || element.style.display == '' )
  176.     {
  177.         element.style.display = 'none';
  178.     }
  179.     else
  180.     {
  181.         element.style.display = 'block';
  182.     }
  183. }
  184. function toggle_show_node( id )
  185. {
  186.     var element = document.getElementById( 'pl_'+id );
  187.     var img = document.getElementById( 'pl_img_'+id );
  188.     if( element.style.display == 'block' || element.style.display == '' )
  189.     {
  190.         element.style.display = 'none';
  191.         img.setAttribute( 'src', '/old/images/plus.png' );
  192.         img.setAttribute( 'alt', '[+]' );
  193.     }
  194.     else
  195.     {
  196.         element.style.display = 'block';
  197.         img.setAttribute( 'src', '/old/images/minus.png' );
  198.         img.setAttribute( 'alt', '[-]' );
  199.     }
  200. }
  201.  
  202. function show( id ){ document.getElementById( id ).style.display = 'block'; }
  203. function showinline( id ){ document.getElementById( id ).style.display = 'inline'; }
  204.  
  205. function hide( id ){ document.getElementById( id ).style.display = 'none'; }
  206.  
  207. function checked( id ){ return document.getElementById( id ).checked; }
  208.  
  209. function value( id ){ return document.getElementById( id ).value; }
  210.  
  211. function setclass( obj, value )
  212. {
  213.     obj.setAttribute( 'class', value ); /* Firefox */
  214.     obj.setAttribute( 'className', value ); /* IE */
  215. }
  216.  
  217. function radio_value( name )
  218. {
  219.     var radio = document.getElementsByName( name );
  220.     for( var i = 0; i < radio.length; i++ )
  221.     {
  222.         if( radio[i].checked )
  223.         {
  224.             return radio[i].value;
  225.         }
  226.     }
  227.     return "";
  228. }
  229.  
  230. function check_and_replace_int( id, val )
  231. {
  232.     var objRegExp = /^\d+$/;
  233.     if( value( id ) != ''
  234.         && ( !objRegExp.test( value( id ) )
  235.              || parseInt( value( id ) ) < 1 ) )
  236.         return document.getElementById( id ).value = val;
  237.     return document.getElementById( id ).value;
  238. }
  239.  
  240. function addslashes( str ){ return str.replace(/\'/g, '\\\''); }
  241. function escapebackslashes( str ){ return str.replace(/\\/g, '\\\\'); }
  242.  
  243. function toCamelCase( str )
  244. {
  245.     str = str.split( '-' );
  246.     var cml = str[0];
  247.     for( var i=1; i<str.length; i++)
  248.         cml += str[i].charAt(0).toUpperCase()+str[i].substring(1);
  249.     return cml;
  250. }
  251.  
  252. function disable( id ){ document.getElementById( id ).disabled = true; }
  253.  
  254. function enable( id ){ document.getElementById( id ).disabled = false; }
  255.  
  256. function button_over( element ){ element.style.border = "1px solid #000"; }
  257.  
  258. function button_out( element ){ element.style.border = "1px solid #fff"; }
  259. function button_out_menu( element ){ element.style.border = "1px solid transparent"; }
  260.  
  261. function show_menu( id ){ document.getElementById(id).style.display = 'block'; }
  262. function hide_menu( id ){ document.getElementById(id).style.display = 'none'; }
  263.  
  264. /* toggle show help under the buttons */
  265. function toggle_btn_text()
  266. {
  267.     if( get_css( '.btn_text', 'display' ) == 'none' )
  268.     {
  269.         set_css( '.btn_text', 'display', 'block' );
  270.     }
  271.     else
  272.     {
  273.         set_css( '.btn_text', 'display', 'none' );
  274.     }
  275. }
  276.  
  277. function clear_children( elt )
  278. {   
  279.     if( elt )
  280.         while( elt.hasChildNodes() )
  281.             elt.removeChild( elt.firstChild );
  282. }
  283.  
  284. /**********************************************************************
  285.  * Interface actions
  286.  *********************************************************************/
  287. /* input actions */
  288. function in_playenqueue( cmd )
  289. {
  290.     var input = value('input_mrl');
  291.     var url = 'requests/status.xml?command=in_'+cmd+'&input='+encodeURIComponent( addslashes(escapebackslashes(input)) );
  292.     for( i in input_options )
  293.         if( input_options[i] != ':option=value' )
  294.             url += '&option='+encodeURIComponent( addslashes(escapebackslashes(input_options[i]) ));
  295.     loadXMLDoc( url, parse_status );
  296.     setTimeout( 'update_playlist()', 1000 );
  297. }
  298.  
  299. function in_play()
  300. {
  301.     in_playenqueue( 'play' );
  302. }
  303.  
  304. function in_enqueue()
  305. {
  306.     in_playenqueue( 'enqueue' );
  307. }
  308.  
  309. /* playlist actions */
  310. function pl_play( id )
  311. {
  312.     loadXMLDoc( 'requests/status.xml?command=pl_play&id='+id, parse_status );
  313.     pl_cur_id = id;
  314.     setTimeout( 'update_playlist()', 1000 );
  315. }
  316. function pl_pause()
  317. {
  318.     loadXMLDoc( 'requests/status.xml?command=pl_pause&id='+pl_cur_id, parse_status );
  319. }
  320. function pl_stop()
  321. {
  322.     loadXMLDoc( 'requests/status.xml?command=pl_stop', parse_status );
  323.     setTimeout( 'update_playlist()', 1000 );
  324. }
  325. function pl_next()
  326. {
  327.     loadXMLDoc( 'requests/status.xml?command=pl_next', parse_status );
  328.     setTimeout( 'update_playlist()', 1000 );
  329. }
  330. function pl_previous()
  331. {
  332.     loadXMLDoc( 'requests/status.xml?command=pl_previous', parse_status );
  333.     setTimeout( 'update_playlist()', 1000 );
  334. }
  335. function pl_delete( id )
  336. {
  337.     loadXMLDoc( 'requests/status.xml?command=pl_delete&id='+id, parse_status );
  338.     setTimeout( 'update_playlist()', 1000 );
  339. }
  340. function pl_empty()
  341. {
  342.     loadXMLDoc( 'requests/status.xml?command=pl_empty', parse_status );
  343.     setTimeout( 'update_playlist()', 1000 );
  344. }
  345. function pl_sort( sort, order )
  346. {
  347.     loadXMLDoc( 'requests/status.xml?command=pl_sort&id='+order+'&val='+sort, parse_status );
  348.     setTimeout( 'update_playlist()', 1000 );
  349. }
  350. function pl_shuffle()
  351. {
  352.     loadXMLDoc( 'requests/status.xml?command=pl_random', parse_status );
  353.     setTimeout( 'update_playlist()', 1000 );
  354. }
  355. function pl_loop()
  356. {
  357.     loadXMLDoc( 'requests/status.xml?command=pl_loop', parse_status );
  358. }
  359. function pl_repeat()
  360. {
  361.     loadXMLDoc( 'requests/status.xml?command=pl_repeat', parse_status );
  362. }
  363. function pl_sd( value )
  364. {
  365.     loadXMLDoc( 'requests/status.xml?command=pl_sd&val='+value, parse_status );
  366. }
  367.  
  368. /* misc actions */
  369. function volume_down()
  370. {
  371.     loadXMLDoc( 'requests/status.xml?command=volume&val=-20', parse_status );
  372. }
  373. function volume_up()
  374. {
  375.     loadXMLDoc( 'requests/status.xml?command=volume&val=%2B20', parse_status );
  376. }
  377. function volume_mute()
  378. {
  379.     loadXMLDoc( 'requests/status.xml?command=volume&val=0', parse_status );
  380. }
  381. function seek( pos )
  382. {
  383.     loadXMLDoc( 'requests/status.xml?command=seek&val='+pos, parse_status );
  384. }
  385. function fullscreen()
  386. {
  387.     loadXMLDoc( 'requests/status.xml?command=fullscreen', parse_status );
  388. }
  389. function snapshot()
  390. {
  391.     loadXMLDoc( 'requests/status.xml?command=snapshot', parse_status );
  392. }
  393. function hotkey( str )
  394. {
  395.     /* Use hotkey name (without the "key-" part) as the argument to simulate a hotkey press */
  396.     loadXMLDoc( 'requests/status.xml?command=key&val='+str, parse_status );
  397. }
  398. function update_status()
  399. {
  400.     loadXMLDoc( 'requests/status.xml', parse_status );
  401. }
  402. function update_playlist()
  403. {
  404.     loadXMLDoc( 'requests/playlist.xml', parse_playlist );
  405. }
  406. function update_playlist_search(key)
  407. {
  408.     loadXMLDoc( 'requests/playlist.xml?search='+encodeURIComponent(key), parse_playlist )
  409. }
  410. function reset_search()
  411. {
  412.     var search = document.getElementById('search')
  413.     if( search )
  414.     {
  415.         search.value = '<search>'
  416.         update_playlist_search('')
  417.     }
  418. }
  419. function audiodelay_down()
  420. {
  421.     var curdel = parseFloat(req.responseXML.documentElement.getElementsByTagName( 'audiodelay' )[0].firstChild.data);
  422.     var curdelnew = curdel - 0.05;
  423.     curdelnew=curdelnew.toFixed(2);
  424.     loadXMLDoc( 'requests/status.xml?command=audiodelay&val='+encodeURIComponent(curdelnew), parse_status );
  425. }
  426. function audiodelay_up()
  427. {
  428.     var curdel = parseFloat(req.responseXML.documentElement.getElementsByTagName( 'audiodelay' )[0].firstChild.data);
  429.     var curdelnew = curdel + 0.05;
  430.     curdelnew=curdelnew.toFixed(2);
  431.     loadXMLDoc( 'requests/status.xml?command=audiodelay&val='+encodeURIComponent(curdelnew), parse_status );
  432. }
  433. function playrate_down()
  434. {
  435.     var currate = parseFloat(req.responseXML.documentElement.getElementsByTagName( 'rate' )[0].firstChild.data);
  436.     var curratenew = currate - 0.05;
  437.     curratenew=curratenew.toFixed(2);
  438.     loadXMLDoc( 'requests/status.xml?command=rate&val='+encodeURIComponent(curratenew), parse_status );
  439. }
  440. function playrate_up()
  441. {
  442.     var currate = parseFloat(req.responseXML.documentElement.getElementsByTagName( 'rate' )[0].firstChild.data);
  443.     var curratenew = currate + 0.05;
  444.     curratenew=curratenew.toFixed(2);
  445.     loadXMLDoc( 'requests/status.xml?command=rate&val='+encodeURIComponent(curratenew), parse_status );
  446. }
  447. function subdel_down()
  448. {
  449.     var curdel = parseFloat(req.responseXML.documentElement.getElementsByTagName( 'subtitledelay' )[0].firstChild.data);
  450.     var curdelnew = curdel - 0.05;
  451.     curdelnew=curdelnew.toFixed(2);
  452.     loadXMLDoc( 'requests/status.xml?command=subdelay&val='+encodeURIComponent(curdelnew), parse_status );
  453. }
  454. function subdel_up()
  455. {
  456.     var curdel = parseFloat(req.responseXML.documentElement.getElementsByTagName( 'subtitledelay' )[0].firstChild.data);
  457.     var curdelnew = curdel + 0.05;
  458.     curdelnew=curdelnew.toFixed(2);
  459.     loadXMLDoc( 'requests/status.xml?command=subdelay&val='+encodeURIComponent(curdelnew), parse_status );
  460. }
  461.  
  462. /**********************************************************************
  463.  * Parse xml replies to XMLHttpRequests
  464.  *********************************************************************/
  465. /* parse request/status.xml */
  466. function parse_status()
  467. {
  468.     if( req.readyState == 4 )
  469.     {
  470.         if( req.status == 200 )
  471.         {
  472.             var status = req.responseXML.documentElement;
  473.             var timetag = status.getElementsByTagName( 'time' );
  474.             if( timetag.length > 0 )
  475.             {
  476.                 var new_time = timetag[0].firstChild.data;
  477.             }
  478.             else
  479.             {
  480.                 new_time = old_time;
  481.             }
  482.             var lengthtag = status.getElementsByTagName( 'length' );
  483.             var length;
  484.             if( lengthtag.length > 0 )
  485.             {
  486.                 length = lengthtag[0].firstChild.data;
  487.             }
  488.             else
  489.             {
  490.                 length = 0;
  491.             }
  492.             var slider_position;
  493.             positiontag = status.getElementsByTagName( 'position' );
  494.             if( length < 100 && positiontag.length > 0 )
  495.             {
  496.                 slider_position = ( positiontag[0].firstChild.data * 4 ) + "px";
  497.             }
  498.             else if( length > 0 )
  499.             {
  500.                 /* this is more precise if length > 100 */
  501.                 slider_position = Math.floor( ( new_time * 400 ) / length ) + "px";
  502.             }
  503.             else
  504.             {
  505.                 slider_position = 0;
  506.             }
  507.             if( old_time > new_time )
  508.                 setTimeout('update_playlist()',50);
  509.             old_time = new_time;
  510.             set_text( 'time', format_time( new_time ) );
  511.             set_text( 'length', format_time( length ) );
  512.             var audio_delay = (parseFloat(req.responseXML.documentElement.getElementsByTagName( 'audiodelay' )[0].firstChild.data).toFixed(2))*1000;
  513.             set_text( 'a_del', audio_delay ); 
  514.             var play_rate = (parseFloat(req.responseXML.documentElement.getElementsByTagName( 'rate' )[0].firstChild.data).toFixed(2));
  515.             set_text( 'p_rate', play_rate ); 
  516.             var subs_delay = (parseFloat(req.responseXML.documentElement.getElementsByTagName( 'subtitledelay' )[0].firstChild.data).toFixed(2))*1000;
  517.             set_text( 's_del', subs_delay ); 
  518.             if( status.getElementsByTagName( 'volume' ).length != 0 )
  519.                 set_text( 'volume', Math.floor(status.getElementsByTagName( 'volume' )[0].firstChild.data/5.12)+'%' );
  520.             var statetag = status.getElementsByTagName( 'state' );
  521.             if( statetag.length > 0 )
  522.             {
  523.                 set_text( 'state', statetag[0].firstChild.data );
  524.             }
  525.             else
  526.             {
  527.                 set_text( 'state', '(?)' );
  528.             }
  529.             if( slider_mouse_down == 0 )
  530.             {
  531.                 document.getElementById( 'main_slider_point' ).style.left = slider_position;
  532.             }
  533.             var statustag = status.getElementsByTagName( 'state' );
  534.             if( statustag.length > 0 ? statustag[0].firstChild.data == "playing" : 0 )
  535.             {
  536.                 document.getElementById( 'btn_pause_img' ).setAttribute( 'src', '/old/images/pause.png' );
  537.                 document.getElementById( 'btn_pause_img' ).setAttribute( 'alt', 'Pause' );
  538.                 document.getElementById( 'btn_pause' ).setAttribute( 'title', 'Pause' );
  539.             }
  540.             else
  541.             {
  542.                 document.getElementById( 'btn_pause_img' ).setAttribute( 'src', '/old/images/play.png' );
  543.                 document.getElementById( 'btn_pause_img' ).setAttribute( 'alt', 'Play' );
  544.                 document.getElementById( 'btn_pause' ).setAttribute( 'title', 'Play' );
  545.             }
  546.  
  547.             var randomtag = status.getElementsByTagName( 'random' );
  548.             if( randomtag.length > 0 ? randomtag[0].firstChild.data == "1" : 0)
  549.                 setclass( document.getElementById( 'btn_shuffle'), 'on' );
  550.             else
  551.                 setclass( document.getElementById( 'btn_shuffle'), 'off' );
  552.                
  553.             var looptag = status.getElementsByTagName( 'loop' );
  554.             if( looptag.length > 0 ? looptag[0].firstChild.data == "1" : 0)
  555.                 setclass( document.getElementById( 'btn_loop'), 'on' );
  556.             else
  557.                 setclass( document.getElementById( 'btn_loop'), 'off' );
  558.  
  559.             var repeattag = status.getElementsByTagName( 'repeat' );
  560.             if( repeattag.length > 0 ? repeattag[0].firstChild.data == "1" : 0 )
  561.                 setclass( document.getElementById( 'btn_repeat'), 'on' );
  562.             else
  563.                 setclass( document.getElementById( 'btn_repeat'), 'off' );
  564.  
  565.             var tree = document.createElement( "ul" );
  566.             var categories = status.getElementsByTagName( 'category' );
  567.             var i;
  568.             for( i = 0; i < categories.length; i++ )
  569.             {
  570.                 var item = document.createElement( "li" );
  571.                 item.appendChild( document.createTextNode( categories[i].getAttribute( 'name' ) ) );
  572.                 var subtree = document.createElement( "dl" );
  573.                 var infos = categories[i].getElementsByTagName( 'info' );
  574.                 var j;
  575.                 for( j = 0; j < infos.length; j++ )
  576.                 {
  577.                     var subitem = document.createElement( "dt" );
  578.                     subitem.appendChild( document.createTextNode( infos[j].getAttribute( 'name' ) ) );
  579.                     subtree.appendChild( subitem );
  580.                     if( infos[j].hasChildNodes() )
  581.                     {
  582.                         var subitem = document.createElement( "dd" );
  583.                         subitem.appendChild( document.createTextNode( infos[j].firstChild.data ) );
  584.                         subtree.appendChild( subitem );
  585.                     }
  586.                 }
  587.                 item.appendChild( subtree );
  588.                 tree.appendChild( item );
  589.             }
  590.             var infotree = document.getElementById('infotree' );
  591.             clear_children( infotree );
  592.             infotree.appendChild( tree );
  593.             
  594.         }
  595.         else
  596.         {
  597.             /*alert( 'Error! HTTP server replied: ' + req.status );*/
  598.         }
  599.     }
  600. }
  601.  
  602. /* parse playlist.xml */
  603. function parse_playlist()
  604. {
  605.     if( req.readyState == 4 )
  606.     {
  607.         if( req.status == 200 )
  608.         {
  609.             var answer = req.responseXML.documentElement;
  610.             var playtree = document.getElementById( 'playtree' );
  611.             var pos = document.createElement( "div" );
  612.             var pos_top = pos;
  613.             var elt = answer.firstChild;
  614.             
  615.             pl_cur_id = 0;  /* changed to the current id is there actually
  616.                              * is a current id */
  617.             while( elt )
  618.             {
  619.                 if( elt.nodeName == "node" )
  620.                 {
  621.                     if( pos.hasChildNodes() )
  622.                         pos.appendChild( document.createElement( "br" ) );
  623.                     var nda = document.createElement( 'a' );
  624.                     nda.setAttribute( 'href', 'javascript:toggle_show_node(\''+elt.getAttribute( 'id' )+'\');' );
  625.                     var ndai = document.createElement( 'img' );
  626.                     ndai.setAttribute( 'src', '/old/images/minus.png' );
  627.                     ndai.setAttribute( 'alt', '[-]' );
  628.                     ndai.setAttribute( 'id', 'pl_img_'+elt.getAttribute( 'id' ) );
  629.                     nda.appendChild( ndai );
  630.                     pos.appendChild( nda );
  631.                     pos.appendChild( document.createTextNode( ' ' + elt.getAttribute( 'name' ) ) );
  632.  
  633.                     if( elt.getAttribute( 'ro' ) == 'rw' )
  634.                     {
  635.                         pos.appendChild( document.createTextNode( ' ' ) );
  636.                         var del = document.createElement( "a" );
  637.                         del.setAttribute( 'href', 'javascript:pl_delete('+elt.getAttribute( 'id' )+')' );
  638.                             var delimg = document.createElement( "img" );
  639.                             delimg.setAttribute( 'src', '/old/images/delete_small.png' );
  640.                             delimg.setAttribute( 'alt', '(delete)' );
  641.                         del.appendChild( delimg );
  642.                         pos.appendChild( del );
  643.                     }
  644.  
  645.                     var nd = document.createElement( "div" );
  646.                     setclass( nd, 'pl_node' );
  647.                     nd.setAttribute( 'id', 'pl_'+elt.getAttribute( 'id' ) );
  648.                     pos.appendChild( nd );
  649.                 }
  650.                 else if( elt.nodeName == "leaf" )
  651.                 {
  652.                     if( pos.hasChildNodes() )
  653.                     pos.appendChild( document.createElement( "br" ) );
  654.                     var pl = document.createElement( "a" );
  655.                     setclass( pl, 'pl_leaf' );
  656.                     pl.setAttribute( 'href', 'javascript:pl_play('+elt.getAttribute( 'id' )+');' );
  657.                     pl.setAttribute( 'id', 'pl_'+elt.getAttribute( 'id' ) );
  658.                     if( elt.getAttribute( 'current' ) == 'current' )
  659.                     {
  660.                         pl.style.fontWeight = 'bold';
  661.                         var nowplaying = document.getElementById( 'nowplaying' );
  662.                         clear_children( nowplaying );
  663.                         nowplaying.appendChild( document.createTextNode( elt.getAttribute( 'name' ) ) );
  664.                         pl.appendChild( document.createTextNode( '* '));
  665.                         pl_cur_id = elt.getAttribute( 'id' );
  666.                     }
  667.                     pl.setAttribute( 'title', elt.getAttribute( 'uri' ));
  668.                     pl.appendChild( document.createTextNode( elt.getAttribute( 'name' ) ) );
  669.                     var duration = elt.getAttribute( 'duration' );
  670.                     if( duration > 0 )
  671.                         pl.appendChild( document.createTextNode( " (" + format_time( elt.getAttribute( 'duration' ) ) + ")" ) );
  672.                     pos.appendChild( pl );
  673.  
  674.                     if( elt.getAttribute( 'ro' ) == 'rw' )
  675.                     {
  676.                         pos.appendChild( document.createTextNode( ' ' ) );
  677.                         var del = document.createElement( "a" );
  678.                         del.setAttribute( 'href', 'javascript:pl_delete('+elt.getAttribute( 'id' )+')' );
  679.                             var delimg = document.createElement( "img" );
  680.                             delimg.setAttribute( 'src', '/old/images/delete_small.png' );
  681.                             delimg.setAttribute( 'alt', '(delete)' );
  682.                         del.appendChild( delimg );
  683.                         pos.appendChild( del );
  684.                     }
  685.                 }
  686.                 if( elt.firstChild )
  687.                 {
  688.                     elt = elt.firstChild;
  689.                     pos = pos.lastChild;
  690.                 }
  691.                 else if( elt.nextSibling )
  692.                 {
  693.                     elt = elt.nextSibling;
  694.                     pos = pos;
  695.                 }
  696.                 else
  697.                 {
  698.                     while( ! elt.parentNode.nextSibling )
  699.                     {
  700.                         elt = elt.parentNode;
  701.                         if( ! elt.parentNode ) break;
  702.                         pos = pos.parentNode;
  703.                     }
  704.                     if( ! elt.parentNode ) break;
  705.                     elt = elt.parentNode.nextSibling;
  706.                     pos = pos.parentNode;
  707.                 }
  708.             }
  709.             clear_children( playtree );
  710.             playtree.appendChild( pos_top );
  711.         }
  712.         else
  713.         {
  714.             /*alert( 'Error! HTTP server replied: ' + req.status );*/
  715.         }
  716.     }
  717. }
  718.  
  719. /* parse browse.xml */
  720. function parse_browse_dir( )
  721. {
  722.     if( req.readyState == 4 )
  723.     {
  724.         if( req.status == 200 )
  725.         {
  726.             var answer = req.responseXML.documentElement;
  727.             if( !answer ) return;
  728.             var browser = document.getElementById( 'browser' );
  729.             var pos = document.createElement( "div" );
  730.             var elt = answer.firstChild;
  731.             while( elt )
  732.             {
  733.                 if( elt.nodeName == "element" )
  734.                 {
  735.                     var item = document.createElement( "a" );
  736.                     setclass( item, 'browser' );
  737.                     if( elt.getAttribute( 'type' ) == 'dir' )
  738.                     {
  739.                         item.setAttribute( 'href', 'javascript:browse_dir(\''+addslashes(escapebackslashes(elt.getAttribute( 'path' )))+'\');');
  740.                     }
  741.                     else
  742.                     {
  743.                         item.setAttribute( 'href', 'javascript:browse_path(\''+addslashes(escapebackslashes(elt.getAttribute( 'path' )))+'\');' );
  744.                     }
  745.                     item.appendChild( document.createTextNode( elt.getAttribute( 'name' ) ) );
  746.                     pos.appendChild( item );
  747.                     if( elt.getAttribute( 'type' ) == 'dir' )
  748.                     {
  749.                         pos.appendChild( document.createTextNode( ' ' ) );
  750.                         var item = document.createElement( "a" );
  751.                         setclass( item, 'browser' );
  752.                         item.setAttribute( 'href', 'javascript:browse_path(\''+addslashes(escapebackslashes(elt.getAttribute( 'path' )))+'\');');
  753.                         item.appendChild( document.createTextNode( '(select)' ) );
  754.                         pos.appendChild( item );
  755.                     }
  756.                     pos.appendChild( document.createElement( "br" ) );
  757.                 }
  758.                 elt = elt.nextSibling;
  759.             }
  760.             clear_children( browser );
  761.             browser.appendChild( pos );
  762.         }
  763.         else
  764.         {
  765.             /*alert( 'Error! HTTP server replied: ' + req.status );*/
  766.         }
  767.     }
  768. }
  769.  
  770. /**********************************************************************
  771.  * Input dialog functions
  772.  *********************************************************************/
  773. function hide_input( )
  774. {
  775.     document.getElementById( 'input_file' ).style.display = 'none';
  776.     document.getElementById( 'input_disc' ).style.display = 'none';
  777.     document.getElementById( 'input_network' ).style.display = 'none';
  778.     document.getElementById( 'input_fake' ).style.display = 'none';
  779. }
  780.  
  781. /* update the input MRL using data from the input file helper */
  782. /* FIXME ... subs support */
  783. function update_input_file()
  784. {
  785.     var mrl = document.getElementById( 'input_mrl' );
  786.  
  787.     mrl.value = value( 'input_file_filename' );
  788. }
  789.  
  790. /* update the input MRL using data from the input disc helper */
  791. function update_input_disc()
  792. {
  793.     var mrl     = document.getElementById( 'input_mrl' );
  794.     var type    = radio_value( "input_disc_type" );
  795.     var device  = value( "input_disc_dev" );
  796.  
  797.     var title   = check_and_replace_int( 'input_disc_title', 0 );
  798.     var chapter = check_and_replace_int( 'input_disc_chapter', 0 );
  799.     var subs    = check_and_replace_int( 'input_disc_subtrack', '' );
  800.     var audio   = check_and_replace_int( 'input_disc_audiotrack', 0 );
  801.  
  802.     mrl.value = "";
  803.  
  804.     if( type == "dvd" )
  805.     {
  806.         mrl.value += "dvd://";
  807.     }
  808.     else if( type == "dvdsimple" )
  809.     {
  810.         mrl.value += "dvdsimple://";
  811.     }
  812.     else if( type == "vcd" )
  813.     {
  814.         mrl.value += "vcd://";
  815.     }
  816.     else if( type == "cdda" )
  817.     {
  818.         mrl.value += "cdda://";
  819.     }
  820.  
  821.     mrl.value += device;
  822.  
  823.     if( title )
  824.     {
  825.         mrl.value += "@"+title;
  826.         if( chapter && type != "cdda" )
  827.             mrl.value += ":"+chapter;
  828.     }
  829.  
  830.     remove_input_options( ':sub-track' );
  831.     remove_input_options( ':audio-track' );
  832.  
  833.     if( type != "cdda" )
  834.     {
  835.         if( subs != '' )
  836.             add_input_option( ":sub-track="+subs );
  837.         if( audio != '' )
  838.             add_input_option( ":audio-track="+audio );
  839.     }
  840.  
  841. }
  842.  
  843. /* update the input MRL using data from the input network helper */
  844. function update_input_net()
  845. {
  846.     var mrl = document.getElementById( 'input_mrl' );
  847.     var type = radio_value( "input_net_type" );
  848.     
  849.     check_and_replace_int( 'input_net_udp_port', 1234 );
  850.     check_and_replace_int( 'input_net_udpmcast_port', 1234 );
  851.  
  852.     mrl.value = "";
  853.  
  854.     if( type == "udp" )
  855.     {
  856.         mrl.value += "udp://";
  857.         if( value( 'input_net_udp_port' ) )
  858.             mrl.value += ":"+value( 'input_net_udp_port' );
  859.     }
  860.     else if( type == "udpmcast" )
  861.     {
  862.         mrl.value += "udp://@"+value( 'input_net_udpmcast_address');
  863.         if( value( 'input_net_udpmcast_port' ) )
  864.             mrl.value += ":"+value( 'input_net_udpmcast_port' );
  865.     }
  866.     else if( type == "http" )
  867.     {
  868.         var url = value( 'input_net_http_url' );
  869.         if( url.substring(0,7) != "http://"
  870.             && url.substring(0,8) != "https://"
  871.             && url.substring(0,6) != "ftp://"
  872.             && url.substring(0,6) != "mms://"
  873.             && url.substring(0,7) != "mmsh://" )
  874.             mrl.value += "http://";
  875.         mrl.value += url;
  876.     }
  877.     else if( type == "rtsp" )
  878.     {
  879.         var url = value( 'input_net_rtsp_url' );
  880.         if( url.substring(0,7) != "rtsp://" )
  881.             mrl.value += "rtsp://";
  882.         mrl.value += url;
  883.     }
  884.  
  885.     remove_input_options( ':access-filter' );
  886.     if( checked( "input_net_timeshift" ) )
  887.         add_input_option( ":access-filter=timeshift" );
  888. }
  889.  
  890. /* update the input MRL using data from the input fake helper */
  891. function update_input_fake()
  892. {
  893.     remove_input_options( ":fake" );
  894.     var mrl = document.getElementById( 'input_mrl' );
  895.  
  896.     mrl.value = "fake://";
  897.  
  898.     add_input_option( ":fake-file=" + value( "input_fake_filename" ) );
  899.  
  900.     if( value( "input_fake_width" ) )
  901.         add_input_option( ":fake-width=" + value( "input_fake_width" ) );
  902.     if( value( "input_fake_height" ) )
  903.         add_input_option( ":fake-height=" + value( "input_fake_height" ) );
  904.     if( value( "input_fake_ar" ) )
  905.         add_input_option( ":fake-ar=" + value( "input_fake_ar" ) );
  906. }
  907.  
  908. /**********************************************************************
  909.  * Sout dialog functions
  910.  *********************************************************************/
  911. /* toggle show the full sout interface */
  912. function toggle_show_sout_helper()
  913. {
  914.     var element = document.getElementById( "sout_helper" );
  915.     if( element.style.display == 'block' )
  916.     {
  917.         element.style.display = 'none';
  918.         document.getElementById( "sout_helper_toggle" ).value = 'Full sout interface';
  919.     }
  920.     else
  921.     {
  922.         element.style.display = 'block';
  923.         document.getElementById( "sout_helper_toggle" ).value = 'Hide sout interface';
  924.     }
  925. }
  926.  
  927. /* update the sout MRL using data from the sout_helper */
  928. function update_sout()
  929. {
  930.     var option = "";
  931.     /* Remove all options starting with :sout since we're going to write them
  932.      * again. */
  933.     remove_input_options( ":sout" );
  934.  
  935.     check_and_replace_int( 'sout_http_port', 8080 );
  936.     check_and_replace_int( 'sout_mmsh_port', 8080 );
  937.     check_and_replace_int( 'sout_rtp_port', 1234 );
  938.     check_and_replace_int( 'sout_udp_port', 1234 );
  939.     check_and_replace_int( 'sout_ttl', 1 );
  940.  
  941.     if( checked( 'sout_soverlay' ) )
  942.     {
  943.         disable( 'sout_scodec' );
  944.         disable( 'sout_sub' );
  945.     }
  946.     else
  947.     {
  948.         enable( 'sout_scodec' );
  949.         enable( 'sout_sub' );
  950.     }
  951.  
  952.     var transcode =  checked( 'sout_vcodec_s' ) || checked( 'sout_acodec_s' )
  953.                   || checked( 'sout_sub' )      || checked( 'sout_soverlay' );
  954.  
  955.     if( transcode )
  956.     {
  957.         option = ":sout=#transcode{";
  958.         var alot = false; /* alot == at least one transcode */
  959.         if( checked( 'sout_vcodec_s' ) )
  960.         {
  961.             option += "vcodec="+value( 'sout_vcodec' )+",vb="+value( 'sout_vb' )+",scale="+value( 'sout_scale' );
  962.             alot = true;
  963.         }
  964.         if( checked( 'sout_acodec_s' ) )
  965.         {
  966.             if( alot ) option += ",";
  967.             option += "acodec="+value( 'sout_acodec' )+",ab="+value( 'sout_ab' );
  968.             if( value( 'sout_channels' ) )
  969.                 option += ",channels="+value( 'sout_channels' );
  970.             alot = true;
  971.         }
  972.         if( checked( 'sout_soverlay' ) )
  973.         {
  974.             if( alot ) option += ",";
  975.             option += "soverlay";
  976.             alot = true;
  977.         }
  978.         else if( checked( 'sout_sub' ) )
  979.         {
  980.             if( alot ) option += ",";
  981.             option += "scodec="+value( 'sout_scodec' );
  982.             alot = true;
  983.         }
  984.         option += value( 'sout_transcode_extra' );
  985.             
  986.         option += "}";
  987.  
  988.     }
  989.  
  990.     var output = checked( 'sout_display' ) + checked( 'sout_file' )
  991.                + checked( 'sout_http' )    + checked( 'sout_mmsh' )
  992.                + checked( 'sout_rtp' )     + checked( 'sout_udp' );
  993.  
  994.     if( output )
  995.     {
  996.         if( transcode )
  997.             option += ":";
  998.         else
  999.             option += ":sout=#";
  1000.         var aloo = false; /* aloo == at least one output */
  1001.         var mux = radio_value( 'sout_mux' );
  1002.         var ttl = parseInt( value( 'sout_ttl' ) );
  1003.         if( output > 1 ) option += "duplicate{";
  1004.         if( checked( 'sout_display' ) )
  1005.         {
  1006.             if( output > 1 ) option += "dst="
  1007.             option += "display";
  1008.             aloo = true;
  1009.         }
  1010.         if( checked( 'sout_file' ) )
  1011.         {
  1012.             if( aloo ) option += ",";
  1013.             if( output > 1 ) option += "dst="
  1014.             option += "std{access=file,mux="+mux+",dst="+value( 'sout_file_filename' )+"}";
  1015.             aloo = true;
  1016.         }
  1017.         if( checked( 'sout_http' ) )
  1018.         {
  1019.             if( aloo ) option += ",";
  1020.             if( output > 1 ) option += "dst="
  1021.             option += "std{access=http,mux="+mux+",dst="+value( 'sout_http_addr' );
  1022.             if( value( 'sout_http_port' ) )
  1023.                 option += ":"+value( 'sout_http_port' );
  1024.             option += "}";
  1025.             aloo = true;
  1026.         }
  1027.         if( checked( 'sout_mmsh' ) )
  1028.         {
  1029.             if( aloo ) option += ",";
  1030.             if( output > 1 ) option += "dst="
  1031.             option += "std{access=mmsh,mux="+mux+",dst="+value( 'sout_mmsh_addr' );
  1032.             if( value( 'sout_mmsh_port' ) )
  1033.                 option += ":"+value( 'sout_mmsh_port' );
  1034.             option += "}";
  1035.             aloo = true;
  1036.         }
  1037.         if( checked( 'sout_rtp' ) )
  1038.         {
  1039.             if( aloo ) option += ",";
  1040.             if( output > 1 ) option += "dst="
  1041.             option += "std{access=rtp";
  1042.             if( ttl ) option += "{ttl="+ttl+"}";
  1043.             option += ",mux="+mux+",dst="+value( 'sout_rtp_addr' );
  1044.             if( value( 'sout_rtp_port' ) )
  1045.                 option += ":"+value( 'sout_rtp_port' );
  1046.             if( checked( 'sout_sap' ) )
  1047.             {
  1048.                 option += ",sap";
  1049.                 if( value( 'sout_sap_group' ) != '' )
  1050.                 {
  1051.                     option += ",group=\""+value( 'sout_sap_group' )+"\"";
  1052.                 }
  1053.                 option += ",name=\""+value( 'sout_sap_name' )+"\"";
  1054.             }
  1055.             option += "}";
  1056.             aloo = true;
  1057.         }
  1058.         if( checked( 'sout_udp' ) )
  1059.         {
  1060.             if( aloo ) option += ",";
  1061.             if( output > 1 ) option += "dst="
  1062.             option += "std{access=udp";
  1063.             if( ttl ) option += "{ttl="+ttl+"}";
  1064.             option += ",mux="+mux+",dst="+value( 'sout_udp_addr' );
  1065.             if( value('sout_udp_port' ) )
  1066.                 option += ":"+value( 'sout_udp_port' );
  1067.             if( checked( 'sout_sap' ) )
  1068.             {
  1069.                 option += ",sap";
  1070.                 if( value( 'sout_sap_group' ) != '' )
  1071.                 {
  1072.                     option += ",group=\""+value( 'sout_sap_group' )+"\"";
  1073.                 }
  1074.                 option += ",name=\""+value( 'sout_sap_name' )+"\"";
  1075.             }
  1076.             option += "}";
  1077.             aloo = true;
  1078.         }
  1079.         if( output > 1 ) option += "}";
  1080.     }
  1081.  
  1082.     if( option != "" )
  1083.         input_options.push( option );
  1084.  
  1085.     if( ( transcode || output ) && checked( 'sout_all' ) )
  1086.         input_options.push( ":sout-all" );
  1087.  
  1088.     var mrl = document.getElementById( 'sout_mrl' );
  1089.     mrl.value = option;
  1090.  
  1091.     refresh_input_options_list();
  1092. }
  1093.  
  1094. /* reset sout mrl value */
  1095. function reset_sout()
  1096. {
  1097.     document.getElementById('sout_mrl').value = value('sout_old_mrl');
  1098. }
  1099.  
  1100. /* save sout mrl value */
  1101. function save_sout()
  1102. {
  1103.     document.getElementById('sout_old_mrl').value = value('sout_mrl');
  1104. }
  1105.  
  1106. function refresh_input_options_list()
  1107. {
  1108.     var iol = document.getElementById( 'input_options_list' );
  1109.     clear_children( iol );
  1110.     input_options.sort();
  1111.     for( i in input_options )
  1112.     {
  1113.         var o = document.createElement( 'div' );
  1114.         var ot = document.createElement( 'input' );
  1115.         ot.setAttribute( 'type', 'text' );
  1116.         ot.setAttribute( 'size', '60' );
  1117.         ot.setAttribute( 'value', input_options[i] );
  1118.         ot.setAttribute( 'id', 'input_option_item_'+i );
  1119.         ot.setAttribute( 'onchange', 'javascript:save_input_option('+i+',this.value);' );
  1120.         ot.setAttribute( 'onfocus', 'if( this.value == ":option=value" ) this.value = ":";' );
  1121.         ot.setAttribute( 'onblur', 'if( this.value == ":" ) this.value = ":option=value";' );
  1122.         o.appendChild( ot );
  1123.         var od = document.createElement( 'a' );
  1124.         od.setAttribute( 'href', 'javascript:delete_input_option('+i+');' );
  1125.         var delimg = document.createElement( "img" );
  1126.         delimg.setAttribute( 'src', '/old/images/delete_small.png' );
  1127.         delimg.setAttribute( 'alt', '(delete)' );
  1128.         od.appendChild( delimg );
  1129.         o.appendChild( od );
  1130.         iol.appendChild( o );
  1131.     }
  1132. }
  1133.  
  1134. function delete_input_option( i )
  1135. {
  1136.     input_options.splice(i,1);
  1137.     refresh_input_options_list();
  1138. }
  1139.  
  1140. function save_input_option( i, value )
  1141. {
  1142.     input_options[i] = value;
  1143.     refresh_input_options_list();
  1144. }
  1145.  
  1146. function add_input_option( value )
  1147. {
  1148.     input_options.push( value );
  1149.     refresh_input_options_list();
  1150. }
  1151.  
  1152. function remove_input_options( prefix )
  1153. {
  1154.     for( i in input_options )
  1155.         if( input_options[i].substring( 0, prefix.length ) == prefix )
  1156.         {
  1157.             delete input_options[i];
  1158.             i--;
  1159.         }
  1160. }
  1161.  
  1162.  
  1163. /**********************************************************************
  1164.  * Browser dialog functions
  1165.  *********************************************************************/
  1166. /* only browse() should be called directly */
  1167. function browse( dest )
  1168. {
  1169.     document.getElementById( 'browse_dest' ).value = dest;
  1170.     document.getElementById( 'browse_lastdir' ).value;
  1171.     browse_dir( document.getElementById( 'browse_lastdir' ).value );
  1172.     show( 'browse' );
  1173. }
  1174. function browse_dir( dir )
  1175. {
  1176.     document.getElementById( 'browse_lastdir' ).value = dir;
  1177.     loadXMLDoc( 'requests/browse.xml?dir='+encodeURIComponent(dir), parse_browse_dir );
  1178. }
  1179. function browse_path( p )
  1180. {
  1181.     document.getElementById( value( 'browse_dest' ) ).value = p;
  1182.     hide( 'browse' );
  1183.     document.getElementById( value( 'browse_dest' ) ).focus();
  1184. }
  1185. function refresh_albumart( force )
  1186. {
  1187.     if( albumart_id != pl_cur_id || force )
  1188.     {
  1189.         var now = new Date();
  1190.         var albumart = document.getElementById( 'albumart' );
  1191.         albumart.src = '/art?timestamp=' + now.getTime();
  1192.         albumart_id = pl_cur_id;
  1193.     }
  1194. }
  1195. /**********************************************************************
  1196.  * Periodically update stuff in the interface
  1197.  *********************************************************************/
  1198. function loop_refresh_status()
  1199. {
  1200.     setTimeout( 'loop_refresh_status()', 1000 );
  1201.     update_status();
  1202. }
  1203. function loop_refresh_playlist()
  1204. {
  1205.     /* setTimeout( 'loop_refresh_playlist()', 10000 ); */
  1206.     update_playlist();
  1207. }
  1208. function loop_refresh_albumart()
  1209. {
  1210.     setTimeout( 'loop_refresh_albumart()', 1000 );
  1211.     refresh_albumart( false );
  1212. }
  1213. function loop_refresh()
  1214. {
  1215.     setTimeout( 'loop_refresh_status()', 1 );
  1216.     setTimeout( 'loop_refresh_playlist()', 1 );
  1217.     setTimeout( 'loop_refresh_albumart()', 1 );
  1218. }
  1219.  
  1220.