functions.js
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:36k
源码类别:

midi

开发平台:

Unix_Linux

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