]> git.sesse.net Git - vlc/blobdiff - share/http/js/functions.js
"[PATCH] http interface workaround to make the play/pause button work well" by Lauren...
[vlc] / share / http / js / functions.js
index ce4d93282921549e0f7f3a55ed15d4241910ca04..7b694db78a8fc83c5e9f33a12f6b8148fd92cf64 100644 (file)
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  *****************************************************************************/
 
-/* global variables */
+/**********************************************************************
+ * Global variables
+ *********************************************************************/
+
+var old_time = 0;
+var pl_cur_id;
+
+/**********************************************************************
+ * Slider functions
+ *********************************************************************/
+var slider_mouse_down = 0;
+var slider_dx = 0;
+
+/* findPosX() from http://www.quirksmode.rg/js/indpos.html */
+function findPosX(obj)
+{
+    var curleft = 0;
+    if (obj.offsetParent)
+    {
+        while (obj.offsetParent)
+        {
+            curleft += obj.offsetLeft
+            obj = obj.offsetParent;
+        }
+    }
+    else if (obj.x)
+        curleft += obj.x;
+    return curleft;
+}
 
-old_time = 0;
+function slider_seek( e, bar )
+{
+    seek(Math.floor(( e.clientX + document.body.scrollLeft - findPosX( bar )) / 4)+"%25");
+}
+function slider_down( e, point )
+{
+    slider_mouse_down = 1;
+    slider_dx = e.clientX - findPosX( point );
+}
+function slider_up( e, bar )
+{
+    slider_mouse_down = 0;
+    /* slider_seek( e, bar ); */
+}
+function slider_move( e, bar )
+{
+    if( slider_mouse_down == 1 )
+    {
+        var slider_position  = Math.floor( e.clientX - slider_dx + document.body.scrollLeft - findPosX( bar ));
+        document.getElementById( 'main_slider_point' ).style.left = slider_position+"px";
+        slider_seek( e, bar );
+    }
+}
 
 /**********************************************************************
  * Misc utils
@@ -56,9 +107,9 @@ function loadXMLDoc( url, callback )
 /* fomat time in second as hh:mm:ss */
 function format_time( s )
 {
-    hours = Math.floor(s/3600);
-    minutes = Math.floor((s/60)%60);
-    seconds = s%60;
+    var hours = Math.floor(s/3600);
+    var minutes = Math.floor((s/60)%60);
+    var seconds = Math.floor(s%60);
     if( hours < 10 ) hours = "0"+hours;
     if( minutes < 10 ) minutes = "0"+minutes;
     if( seconds < 10 ) seconds = "0"+seconds;
@@ -68,7 +119,7 @@ function format_time( s )
 /* delete all a tag's children and add a text child node */
 function set_text( id, val )
 {
-    elt = document.getElementById( id );
+    var elt = document.getElementById( id );
     while( elt.hasChildNodes() )
         elt.removeChild( elt.firstChild );
     elt.appendChild( document.createTextNode( val ) );
@@ -77,10 +128,10 @@ function set_text( id, val )
 /* set item's 'element' attribute to value */
 function set_css( item, element, value )
 {
-    for( j = 0; j<document.styleSheets.length; j++ )
+    for( var j = 0; j < document.styleSheets.length; j++ )
     {
         cssRules = document.styleSheets[j].cssRules;
-        for( i = 0; i<cssRules.length; i++)
+        for( var i = 0; i < cssRules.length; i++)
         {
             if( cssRules[i].selectorText == item )
             {
@@ -94,10 +145,10 @@ function set_css( item, element, value )
 /* get item's 'element' attribute */
 function get_css( item, element )
 {
-    for( j = 0; j<document.styleSheets.length; j++ )
+    for( var j = 0; j < document.styleSheets.length; j++ )
     {
         cssRules = document.styleSheets[j].cssRules;
-        for( i = 0; i<cssRules.length; i++)
+        for( var i = 0; i < cssRules.length; i++)
         {
             if( cssRules[i].selectorText == item )
             {
@@ -109,7 +160,7 @@ function get_css( item, element )
 
 function toggle_show( id )
 {
-    element = document.getElementById( id );
+    var element = document.getElementById( id );
     if( element.style.display == 'block' || element.style.display == '' )
     {
         element.style.display = 'none';
@@ -121,8 +172,8 @@ function toggle_show( id )
 }
 function toggle_show_node( id )
 {
-    element = document.getElementById( 'pl_'+id );
-    img = document.getElementById( 'pl_img_'+id );
+    var element = document.getElementById( 'pl_'+id );
+    var img = document.getElementById( 'pl_img_'+id );
     if( element.style.display == 'block' || element.style.display == '' )
     {
         element.style.display = 'none';
@@ -147,8 +198,8 @@ function value( id ){ return document.getElementById( id ).value; }
 
 function radio_value( name )
 {
-    radio = document.getElementsByName( name );
-    for( i = 0; i<radio.length; i++ )
+    var radio = document.getElementsByName( name );
+    for( var i = 0; i < radio.length; i++ )
     {
         if( radio[i].checked )
         {
@@ -168,6 +219,7 @@ function check_and_replace_int( id, val )
 }
 
 function addslashes( str ){ return str.replace(/\'/g, '\\\''); }
+function escapebackslashes( str ){ return str.replace(/\\/g, '\\\\'); }
 
 function disable( id ){ document.getElementById( id ).disabled = true; }
 
@@ -190,25 +242,32 @@ function toggle_btn_text()
     }
 }
 
+function clear_children( elt )
+{   
+    if( elt )
+        while( elt.hasChildNodes() )
+            elt.removeChild( elt.firstChild );
+}
+
 /**********************************************************************
  * Interface actions
  *********************************************************************/
 /* input actions */
 function in_play()
 {
-    input_iesuxx = value('input_mrl');
+    var input = value('input_mrl');
     if( value('sout_mrl') != '' )
-        input_iesuxx += ' '+value('sout_mrl');
-    url = 'requests/status.xml?command=in_play&input='+escape(input_iesuxx);
+        input += ' '+value('sout_mrl');
+    var url = 'requests/status.xml?command=in_play&input='+escape( input );
     loadXMLDoc( url, parse_status );
     setTimeout( 'update_playlist()', 1000 );
 }
 function in_enqueue()
 {
-    input_iesuxx = value('input_mrl');
+    var input = value('input_mrl');
     if( value('sout_mrl') != '' )
-        input_iesuxx += ' '+value('sout_mrl');
-    url = 'requests/status.xml?command=in_enqueue&input='+escape(input_iesuxx);
+        input += ' '+value('sout_mrl');
+    var url = 'requests/status.xml?command=in_enqueue&input='+escape( input );
     loadXMLDoc( url, parse_status );
     setTimeout( 'update_playlist()', 1000 );
 }
@@ -217,11 +276,12 @@ function in_enqueue()
 function pl_play( id )
 {
     loadXMLDoc( 'requests/status.xml?command=pl_play&id='+id, parse_status );
+    pl_cur_id = id;
     setTimeout( 'update_playlist()', 1000 );
 }
 function pl_pause()
 {
-    loadXMLDoc( 'requests/status.xml?command=pl_pause', parse_status );
+    loadXMLDoc( 'requests/status.xml?command=pl_pause&id='+pl_cur_id, parse_status );
 }
 function pl_stop()
 {
@@ -277,6 +337,10 @@ function volume_up()
 {
     loadXMLDoc( 'requests/status.xml?command=volume&val=%2B20', parse_status );
 }
+function seek( pos )
+{
+    loadXMLDoc( 'requests/status.xml?command=seek&val='+pos, parse_status );
+}
 function fullscreen()
 {
     loadXMLDoc( 'requests/status.xml?command=fullscreen', parse_status );
@@ -300,24 +364,104 @@ function parse_status()
     {
         if( req.status == 200 )
         {
-            status_iesuxx = req.responseXML.documentElement;
-            new_time = status_iesuxx.getElementsByTagName( 'time' )[0].firstChild.data;
+            var status = req.responseXML.documentElement;
+            var timetag = status.getElementsByTagName( 'time' );
+            if( timetag.length > 0 )
+            {
+                var new_time = timetag[0].firstChild.data;
+            }
+            else
+            {
+                new_time = old_time;
+            }
+            var lengthtag = status.getElementsByTagName( 'length' );
+            var length;
+            if( lengthtag.length > 0 )
+            {
+                length = lengthtag[0].firstChild.data;
+            }
+            else
+            {
+                length = 0;
+            }
+            var slider_position;
+            positiontag = status.getElementsByTagName( 'position' );
+            if( length < 100 && positiontag.length > 0 )
+            {
+                slider_position = ( positiontag[0].firstChild.data * 4 ) + "px";
+            }
+            else if( length > 0 )
+            {
+                /* this is more precise if length > 100 */
+                slider_position = Math.floor( ( new_time * 400 ) / length ) + "px";
+            }
+            else
+            {
+                slider_position = 0;
+            }
             if( old_time > new_time )
                 setTimeout('update_playlist()',50);
             old_time = new_time;
             set_text( 'time', format_time( new_time ) );
-            set_text( 'length', format_time( status_iesuxx.getElementsByTagName( 'length' )[0].firstChild.data ) );
-            if( status_iesuxx.getElementsByTagName( 'volume' ).length != 0 )
-            set_text( 'volume', Math.floor(status_iesuxx.getElementsByTagName( 'volume' )[0].firstChild.data/5.12)+'%' );
-            set_text( 'state', status_iesuxx.getElementsByTagName( 'state' )[0].firstChild.data );
-            if( status_iesuxx.getElementsByTagName( 'state' )[0].firstChild.data == "playing" )
+            set_text( 'length', format_time( length ) );
+            if( status.getElementsByTagName( 'volume' ).length != 0 )
+                set_text( 'volume', Math.floor(status.getElementsByTagName( 'volume' )[0].firstChild.data/5.12)+'%' );
+            var statetag = status.getElementsByTagName( 'state' );
+            if( statetag.length > 0 )
+            {
+               set_text( 'state', statetag[0].firstChild.data );
+            }
+            else
+            {
+                set_text( 'state', '(?)' );
+            }
+            if( slider_mouse_down == 0 )
+            {
+                document.getElementById( 'main_slider_point' ).style.left = slider_position;
+            }
+            var statustag = status.getElementsByTagName( 'state' );
+            if( statustag.length > 0 ? statustag[0].firstChild.data == "playing" : 0 )
             {
                 document.getElementById( 'btn_pause_img' ).setAttribute( 'src', 'images/pause.png' );
+                document.getElementById( 'btn_pause_img' ).setAttribute( 'alt', 'Pause' );
+                document.getElementById( 'btn_pause' ).setAttribute( 'title', 'Pause' );
             }
             else
             {
                 document.getElementById( 'btn_pause_img' ).setAttribute( 'src', 'images/play.png' );
+                document.getElementById( 'btn_pause_img' ).setAttribute( 'alt', 'Play' );
+                document.getElementById( 'btn_pause' ).setAttribute( 'title', 'Play' );
             }
+
+            var tree = document.createElement( "ul" );
+            var categories = status.getElementsByTagName( 'category' );
+            var i;
+            for( i = 0; i < categories.length; i++ )
+            {
+                var item = document.createElement( "li" );
+                item.appendChild( document.createTextNode( categories[i].getAttribute( 'name' ) ) );
+                var subtree = document.createElement( "dl" );
+                var infos = categories[i].getElementsByTagName( 'info' );
+                var j;
+                for( j = 0; j < infos.length; j++ )
+                {
+                    var subitem = document.createElement( "dt" );
+                    subitem.appendChild( document.createTextNode( infos[j].getAttribute( 'name' ) ) );
+                    subtree.appendChild( subitem );
+                    if( infos[j].hasChildNodes() )
+                    {
+                        var subitem = document.createElement( "dd" );
+                        subitem.appendChild( document.createTextNode( infos[j].firstChild.data ) );
+                        subtree.appendChild( subitem );
+                    }
+                }
+                item.appendChild( subtree );
+                tree.appendChild( item );
+            }
+            var infotree = document.getElementById('infotree' );
+            clear_children( infotree );
+            infotree.appendChild( tree );
+            
         }
         else
         {
@@ -333,56 +477,63 @@ function parse_playlist()
     {
         if( req.status == 200 )
         {
-            answer = req.responseXML.documentElement;
-            playtree_iesuxx = document.getElementById( 'playtree' );
-            pos = document.createElement( "div" );
-            pos_top = pos;
-            elt = answer.firstChild;
+            var answer = req.responseXML.documentElement;
+            var playtree = document.getElementById( 'playtree' );
+            var pos = document.createElement( "div" );
+            var pos_top = pos;
+            var elt = answer.firstChild;
+            
+            pl_cur_id = 0;  /* changed to the current id is there actually
+                             * is a current id */
             while( elt )
             {
                 if( elt.nodeName == "node" )
                 {
                     if( pos.hasChildNodes() )
                         pos.appendChild( document.createElement( "br" ) );
-                    nda = document.createElement( 'a' );
-                    pos.appendChild( nda );
+                    var nda = document.createElement( 'a' );
                     nda.setAttribute( 'href', 'javascript:toggle_show_node(\''+elt.getAttribute( 'id' )+'\');' );
-                    ndai = document.createElement( 'img' );
-                    nda.appendChild( ndai );
+                    var ndai = document.createElement( 'img' );
                     ndai.setAttribute( 'src', 'images/minus.png' );
                     ndai.setAttribute( 'alt', '[-]' );
                     ndai.setAttribute( 'id', 'pl_img_'+elt.getAttribute( 'id' ) );
+                    nda.appendChild( ndai );
+                    pos.appendChild( nda );
                     pos.appendChild( document.createTextNode( ' ' + elt.getAttribute( 'name' ) ) );
-                    nd = document.createElement( "div" );
-                    pos.appendChild( nd );
+                    var nd = document.createElement( "div" );
                     nd.setAttribute( 'class', 'pl_node' );
                     nd.setAttribute( 'id', 'pl_'+elt.getAttribute( 'id' ) );
+                    pos.appendChild( nd );
                 }
                 else if( elt.nodeName == "leaf" )
                 {
                     if( pos.hasChildNodes() )
                     pos.appendChild( document.createElement( "br" ) );
-                    pl = document.createElement( "a" );
-                    pos.appendChild( pl );
+                    var pl = document.createElement( "a" );
                     pl.setAttribute( 'class', 'pl_leaf' );
                     pl.setAttribute( 'href', 'javascript:pl_play('+elt.getAttribute( 'id' )+');' );
                     pl.setAttribute( 'id', 'pl_'+elt.getAttribute( 'id' ) );
                     if( elt.getAttribute( 'current' ) == 'current' )
                     {
                         pl.setAttribute( 'style', 'font-weight: bold;' );
-                        document.getElementById( 'nowplaying' ).textContent
-                            = elt.getAttribute( 'name' );
+                        var nowplaying = document.getElementById( 'nowplaying' );
+                        clear_children( nowplaying );
+                        nowplaying.appendChild( document.createTextNode( elt.getAttribute( 'name' ) ) );
+                        pl.appendChild( document.createTextNode( '* '));
+                        pl_cur_id = elt.getAttribute( 'id' );
                     }
                     pl.setAttribute( 'title', elt.getAttribute( 'uri' ));
                     pl.appendChild( document.createTextNode( elt.getAttribute( 'name' ) ) );
+                    pos.appendChild( pl );
                     pos.appendChild( document.createTextNode( ' ' ) );
-                    del = document.createElement( "a" );
-                    pos.appendChild( del );
+
+                    var del = document.createElement( "a" );
                     del.setAttribute( 'href', 'javascript:pl_delete('+elt.getAttribute( 'id' )+')' );
-                    del.appendChild( document.createElement( "img" ) );
-                    del = del.lastChild;
-                    del.setAttribute( 'src', 'images/delete_small.png' );
-                    del.setAttribute( 'alt', '(delete)' );
+                      var delimg = document.createElement( "img" );
+                      delimg.setAttribute( 'src', 'images/delete_small.png' );
+                      delimg.setAttribute( 'alt', '(delete)' );
+                    del.appendChild( delimg );
+                    pos.appendChild( del );
                 }
                 if( elt.firstChild )
                 {
@@ -396,13 +547,18 @@ function parse_playlist()
                 }
                 else
                 {
+                    while( ! elt.parentNode.nextSibling )
+                    {
+                        elt = elt.parentNode;
+                        if( ! elt.parentNode ) break;
+                    }
+                    if( ! elt.parentNode ) break;
                     elt = elt.parentNode.nextSibling;
                     pos = pos.parentNode;
                 }
             }
-            while( playtree_iesuxx.hasChildNodes() )
-                playtree_iesuxx.removeChild( playtree_iesuxx.firstChild );
-            playtree_iesuxx.appendChild( pos_top );
+            clear_children( playtree );
+            playtree.appendChild( pos_top );
         }
         else
         {
@@ -418,40 +574,42 @@ function parse_browse_dir( )
     {
         if( req.status == 200 )
         {
-            answer = req.responseXML.documentElement;
-            browser_iesuxx = document.getElementById( 'browser' );
-            pos = document.createElement( "div" );
-            elt = answer.firstChild;
+            var answer = req.responseXML.documentElement;
+            if( !answer ) return;
+            var browser = document.getElementById( 'browser' );
+            var pos = document.createElement( "div" );
+            var elt = answer.firstChild;
             while( elt )
             {
                 if( elt.nodeName == "element" )
                 {
-                    pos.appendChild( document.createElement( "a" ) );
-                    pos.lastChild.setAttribute( 'class', 'browser' );
+                    var item = document.createElement( "a" );
+                    item.setAttribute( 'class', 'browser' );
                     if( elt.getAttribute( 'type' ) == 'directory' )
                     {
-                        pos.lastChild.setAttribute( 'href', 'javascript:browse_dir(\''+addslashes(elt.getAttribute( 'path' ))+'\');');
+                        item.setAttribute( 'href', 'javascript:browse_dir(\''+escapebackslashes(addslashes(elt.getAttribute( 'path' )))+'\');');
                     }
                     else
                     {
-                        pos.lastChild.setAttribute( 'href', 'javascript:browse_path(\''+addslashes(elt.getAttribute( 'path' ))+'\');' );
+                        item.setAttribute( 'href', 'javascript:browse_path(\''+escapebackslashes(addslashes(elt.getAttribute( 'path' )))+'\');' );
                     }
-                    pos.lastChild.appendChild( document.createTextNode( elt.getAttribute( 'name' ) ) );
+                    item.appendChild( document.createTextNode( elt.getAttribute( 'name' ) ) );
+                    pos.appendChild( item );
                     if( elt.getAttribute( 'type' ) == 'directory' )
                     {
                         pos.appendChild( document.createTextNode( ' ' ) );
-                        pos.appendChild( document.createElement( "a" ) );
-                        pos.lastChild.setAttribute( 'class', 'browser' );
-                        pos.lastChild.setAttribute( 'href', 'javascript:browse_path(\''+addslashes(elt.getAttribute( 'path' ))+'\');');
-                        pos.lastChild.appendChild( document.createTextNode( '(select)' ) );
+                        var item = document.createElement( "a" );
+                        item.setAttribute( 'class', 'browser' );
+                        item.setAttribute( 'href', 'javascript:browse_path(\''+escapebackslashes(addslashes(elt.getAttribute( 'path' )))+'\');');
+                        item.appendChild( document.createTextNode( '(select)' ) );
+                        pos.appendChild( item );
                     }
                     pos.appendChild( document.createElement( "br" ) );
                 }
                 elt = elt.nextSibling;
             }
-            while( browser_iesuxx.hasChildNodes() )
-                browser_iesuxx.removeChild( browser_iesuxx.firstChild );
-            browser_iesuxx.appendChild( pos );
+            clear_children( browser );
+            browser.appendChild( pos );
         }
         else
         {
@@ -474,7 +632,7 @@ function hide_input( )
 /* FIXME ... subs support */
 function update_input_file()
 {
-    mrl = document.getElementById( 'input_mrl' );
+    var mrl = document.getElementById( 'input_mrl' );
 
     mrl.value = value( 'input_file_filename' );
 }
@@ -482,19 +640,19 @@ function update_input_file()
 /* update the input MRL using data from the input disc helper */
 function update_input_disc()
 {
-    mrl = document.getElementById( 'input_mrl' );
-    type = radio_value( "input_disc_type" );
-    device = value( "input_disc_dev" );
+    var mrl = document.getElementById( 'input_mrl' );
+    var type = radio_value( "input_disc_type" );
+    var device = value( "input_disc_dev" );
 
     check_and_replace_int( 'input_disc_title', 0 );
     check_and_replace_int( 'input_disc_chapter', 0 );
     check_and_replace_int( 'input_disc_subtrack', '' );
     check_and_replace_int( 'input_disc_audiotrack', 0 );
 
-    title = value( 'input_disc_title' );
-    chapter = value( 'input_disc_chapter' );
-    subs = value( 'input_disc_subtrack' );
-    audio = value( 'input_disc_audiotrack' );
+    var title = value( 'input_disc_title' );
+    var chapter = value( 'input_disc_chapter' );
+    var subs = value( 'input_disc_subtrack' );
+    var audio = value( 'input_disc_audiotrack' );
 
     mrl.value = "";
 
@@ -537,8 +695,8 @@ function update_input_disc()
 /* update the input MRL using data from the input network helper */
 function update_input_net()
 {
-    mrl = document.getElementById( 'input_mrl' );
-    type = radio_value( "input_net_type" );
+    var mrl = document.getElementById( 'input_mrl' );
+    var type = radio_value( "input_net_type" );
     
     check_and_replace_int( 'input_net_udp_port', 1234 );
     check_and_replace_int( 'input_net_udpmcast_port', 1234 );
@@ -561,7 +719,7 @@ function update_input_net()
     }
     else if( type == "http" )
     {
-        url = value( 'input_net_http_url' );
+        var url = value( 'input_net_http_url' );
         if( url.substring(0,7) != "http://"
             && url.substring(0,8) != "https://"
             && url.substring(0,6) != "ftp://"
@@ -572,7 +730,7 @@ function update_input_net()
     }
     else if( type == "rtsp" )
     {
-        url = value( 'input_net_rtsp_url' );
+        var url = value( 'input_net_rtsp_url' );
         if( url.substring(0,7) != "rtsp://" )
             mrl.value += "rtsp://";
         mrl.value += url;
@@ -588,8 +746,8 @@ function update_input_net()
 /* toggle show the full sout interface */
 function toggle_show_sout_helper()
 {
-    element = document.getElementById( "sout_helper" );
-        if( element.style.display == 'block' )
+    var element = document.getElementById( "sout_helper" );
+    if( element.style.display == 'block' )
     {
         element.style.display = 'none';
         document.getElementById( "sout_helper_toggle" ).value = 'Full sout interface';
@@ -604,7 +762,7 @@ function toggle_show_sout_helper()
 /* update the sout MRL using data from the sout_helper */
 function update_sout()
 {
-    mrl = document.getElementById( 'sout_mrl' );
+    var mrl = document.getElementById( 'sout_mrl' );
     mrl.value = "";
 
     check_and_replace_int( 'sout_http_port', 8080 );
@@ -624,13 +782,13 @@ function update_sout()
         enable( 'sout_sub' );
     }
 
-    transcode =  checked( 'sout_vcodec_s' ) || checked( 'sout_acodec_s' )
-                 || checked( 'sout_sub' ) || checked( 'sout_soverlay' );
+    var transcode =  checked( 'sout_vcodec_s' ) || checked( 'sout_acodec_s' )
+                  || checked( 'sout_sub' )      || checked( 'sout_soverlay' );
 
     if( transcode )
     {
         mrl.value += ":sout=#transcode{";
-        alot = false; /* alot == at least one transcode */
+        var alot = false; /* alot == at least one transcode */
         if( checked( 'sout_vcodec_s' ) )
         {
             mrl.value += "vcodec="+value( 'sout_vcodec' )+",vb="+value( 'sout_vb' )+",scale="+value( 'sout_scale' );
@@ -659,9 +817,9 @@ function update_sout()
         mrl.value += "}";
     }
 
-    output = checked( 'sout_display' ) + checked( 'sout_file' )
-             + checked( 'sout_http' ) + checked( 'sout_mmsh' )
-             + checked( 'sout_rtp' )  + checked( 'sout_udp' );
+    var output = checked( 'sout_display' ) + checked( 'sout_file' )
+               + checked( 'sout_http' )    + checked( 'sout_mmsh' )
+               + checked( 'sout_rtp' )     + checked( 'sout_udp' );
 
     if( output )
     {
@@ -669,9 +827,9 @@ function update_sout()
             mrl.value += ":";
         else
             mrl.value += ":sout=#";
-        aloo = false; /* aloo == at least one output */
-        mux = radio_value( 'sout_mux' );
-        ttl = parseInt( value( 'sout_ttl' ) );
+        var aloo = false; /* aloo == at least one output */
+        var mux = radio_value( 'sout_mux' );
+        var ttl = parseInt( value( 'sout_ttl' ) );
         if( output > 1 ) mrl.value += "duplicate{";
         if( checked( 'sout_display' ) )
         {
@@ -774,19 +932,20 @@ function save_sout()
 function browse( dest )
 {
     document.getElementById( 'browse_dest' ).value = dest;
+    document.getElementById( 'browse_lastdir' ).value;
     browse_dir( document.getElementById( 'browse_lastdir' ).value );
     show( 'browse' );
 }
 function browse_dir( dir )
 {
     document.getElementById( 'browse_lastdir' ).value = dir;
-    loadXMLDoc( 'requests/browse.xml?dir='+dir, parse_browse_dir );
+    loadXMLDoc( 'requests/browse.xml?dir='+escape(dir), parse_browse_dir );
 }
 function browse_path( p )
 {
-    document.getElementById( document.getElementById( 'browse_dest' ).value ).value = p;
+    document.getElementById( value( 'browse_dest' ) ).value = p;
     hide( 'browse' );
-    document.getElementById( document.getElementById( 'browse_dest' ).value ).focus();
+    document.getElementById( value( 'browse_dest' ) ).focus();
 }
 
 /**********************************************************************
@@ -799,12 +958,12 @@ function loop_refresh_status()
 }
 function loop_refresh_playlist()
 {
/*   setTimeout( 'loop_refresh_playlist()', 10000 ); */
   /* setTimeout( 'loop_refresh_playlist()', 10000 ); */
     update_playlist();
 }
 function loop_refresh()
 {
-    setTimeout('loop_refresh_status()',0);
-    setTimeout('loop_refresh_playlist()',0);
+    setTimeout( 'loop_refresh_status()', 1 );
+    setTimeout( 'loop_refresh_playlist()', 1 );
 }