Code the mosaic wizard
authorAntoine Cellerier <dionoea@videolan.org>
Sat, 18 Mar 2006 17:14:19 +0000 (17:14 +0000)
committerAntoine Cellerier <dionoea@videolan.org>
Sat, 18 Mar 2006 17:14:19 +0000 (17:14 +0000)
share/http/dialogs/footer
share/http/dialogs/mosaic
share/http/dialogs/sout
share/http/js/functions.js
share/http/js/mosaic.js
share/http/mosaic.html
share/http/style.css

index 1e35d86..78613b1 100644 (file)
@@ -29,6 +29,7 @@ This dialog needs the following dialogs to be fully functional: <none>
 <div id="footer" class="dialog" >
   <a href="/">main VLC interface</a> -
   <a href="/vlm.html">VLM interface</a> -
+  <a href="/mosaic.html">Mosaic wizard</a> -
   <a href="http://www.videolan.org">VideoLAN website</a>
   <br />
   <vlc id="value" param1="copyright" />
index 9debb92..f53ea0a 100644 (file)
@@ -36,12 +36,65 @@ sout.
     </button>
   </div>
   <div class="controls">
-    <label for="mosaic_rows">Rows:</label> <input type="text" id="mosaic_rows" value="" onchange="mosaic_size_change();" />
-    <label for="mosaic_cols">Columns:</label> <input type="text" id="mosaic_cols" value="" onchange="mosaic_size_change();" />
-    <br/>
-    <label for="mosaic_input_name">Name:</label> <input type="text" id="mosaic_input_name" value="" />
-    <label for="mosaic_input">Input:</label> <input type="text" id="mosaic_input" value="" /> <input type="button" value="Add to input list" onclick="mosaic_add_input();" />
+    <b>Mosaic dimensions:</b><br/>
+    <table style="text-align: right;">
+      <tr>
+        <td>
+          <label for="bg_width">Background width*:</label> <input class="mosaic_bg" type="text" id="bg_width" value="400" size="8" onchange="mosaic_size_change();" />
+        </td>
+        <td>
+          <label for="bg_height">Background height*:</label> <input class="mosaic_bg" type="text" id="bg_height" value="300" size="8" onchange="mosaic_size_change();" />
+        </td>
+      </tr>
+      <tr>
+        <td>
+          <label for="mosaic_width">Width:</label> <input class="mosaic_tbl" type="text" id="mosaic_width" value="200" size="8" onchange="mosaic_size_change();" />
+        </td>
+        <td>
+          <label for="mosaic_height">Height:</label> <input class="mosaic_tbl" type="text" id="mosaic_height" value="200" size="8" onchange="mosaic_size_change();" />
+        </td>
+      </tr>
+      <tr>
+        <td>
+          <label for="mosaic_xoffset">X offset (left):</label> <input class="mosaic_tbl" type="text" id="mosaic_xoffset" value="10" size="8" onchange="mosaic_size_change();" />
+        </td>
+        <td>
+          <label for="mosaic_yoffset">Y offset (top):</label> <input class="mosaic_tbl" type="text" id="mosaic_yoffset" value="10" size="8" onchange="mosaic_size_change();" />
+        </td>
+      </tr>
+      <tr>
+        <td>
+          <label for="mosaic_cols">Columns:</label> <input class="mosaic_itm" type="text" id="mosaic_cols" value="2" size="8" onchange="mosaic_size_change();" />
+        </td>
+        <td>
+          <label for="mosaic_rows">Rows:</label> <input class="mosaic_itm" type="text" id="mosaic_rows" value="2" size="8" onchange="mosaic_size_change();" />
+        </td>
+      </tr>
+      <tr>
+        <td>
+          <label for="mosaic_hborder">Horizontal border:</label> <input class="mosaic_itm" type="text" id="mosaic_hborder" value="10" size="8" onchange="mosaic_size_change();" />
+        </td>
+        <td>
+          <label for="mosaic_vborder">Vertical border:</label> <input class="mosaic_itm" type="text" id="mosaic_vborder" value="5" size="8" onchange="mosaic_size_change();" />
+        </td>
+      </tr>
+      <tr>
+        <td colspan="2">
+        *: these values aren't used by the mosaic code.<br/> They're only here to adapt the preview's size.
+        </td>
+      </tr>
+    </table>
+    <b>Background:</b><br/>
+    <label for="mosaic_bg_input">Input:<label> <input type="text" id="mosaic_bg_input" class="mosaic_bg" value="" size="60" onblur="mosaic_code_update();" /> <input type="button" value="Edit" onclick="vlm_input_edit( 'mosaic_bg_input' );" /><br/>
+    <b>Item:</b><br/>
+    <label for="mosaic_input_name">Name:</label> <input type="text" id="mosaic_input_name" value="" class="mosaic_itm" />
+    <label for="mosaic_input">Input:</label> <input type="text" id="mosaic_input" value="" class="mosaic_itm" /> <input type="button" value="Edit" onclick="vlm_input_edit( 'mosaic_input' );" /> <input type="button" value="Add to input list" onclick="mosaic_add_input();" /><br/>
+    <b>Stream:</b><br/>
+    <label for="mosaic_output">Output:</label> <input type="text" id="mosaic_output" value="" size="60" onvlur="mosaic_code_update();" /> <input type="button" value="Edit" onclick="vlm_output_edit( 'mosaic_output' );" />
   </div>
-  <div  id="mosaic_list" class="popup" style="display: none">Select a stream:<br/></div>
-  <div id="mosaic_layout"></div>
+  <div  id="mosaic_list" class="popup" style="display: none; background: url('images/white.png') repeat;">[<a href="javascript:hide('mosaic_list');">hide</a>] - Select a stream:<br/><div id="mosaic_list_content"></div></div>
+  <div id="mosaic_layout" class="mosaic_bg"></div>
+  <textarea id="mosaic_code" cols="80" rows="30"></textarea>
+  <input type="button" value="Let's go!" onclick="mosaic_batch(document.getElementById('mosaic_code').value);" />
+  <input type="button" value="Stop" onclick="mosaic_stop()" />
 </div>
index 61ed37a..d5f14d1 100644 (file)
@@ -288,5 +288,6 @@ Note that the sout chain is used and sent to VLC by the input dialog
       <label for="sout_ttl">Time-To-Live (TTL)</label>
       <input type="text" id="sout_ttl" onchange="update_sout()"/>
     </div>
+    <input type="hiden" id="sout_extra" value="" />
   </div>
 </div>
index e1a0031..1eccd0e 100644 (file)
@@ -215,7 +215,8 @@ function check_and_replace_int( id, val )
     if( value( id ) != ''
         && ( !objRegExp.test( value( id ) )
              || parseInt( value( id ) ) < 1 ) )
-        document.getElementById( id ).value = val;
+        return document.getElementById( id ).value = val;
+    return document.getElementById( id ).value;
 }
 
 function addslashes( str ){ return str.replace(/\'/g, '\\\''); }
@@ -679,19 +680,14 @@ function update_input_file()
 /* update the input MRL using data from the input disc helper */
 function update_input_disc()
 {
-    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 );
+    var mrl     = document.getElementById( 'input_mrl' );
+    var type    = radio_value( "input_disc_type" );
+    var device  = value( "input_disc_dev" );
 
-    var title = value( 'input_disc_title' );
-    var chapter = value( 'input_disc_chapter' );
-    var subs = value( 'input_disc_subtrack' );
-    var audio = value( 'input_disc_audiotrack' );
+    var title   = check_and_replace_int( 'input_disc_title', 0 );
+    var chapter = check_and_replace_int( 'input_disc_chapter', 0 );
+    var subs    = check_and_replace_int( 'input_disc_subtrack', '' );
+    var audio   = check_and_replace_int( 'input_disc_audiotrack', 0 );
 
     mrl.value = "";
 
@@ -853,6 +849,8 @@ function update_sout()
             mrl.value += "scodec="+value( 'sout_scodec' );
             alot = true;
         }
+        mrl.value += value( 'sout_extra' );
+            
         mrl.value += "}";
     }
 
index c073dc9..ed135a8 100644 (file)
  * 
  *********************************************************************/
 
+var mosaic_alpha    = 255;
+var mosaic_height   = 0;
+var mosaic_width    = 0;
+var mosaic_align    = 5;
+var mosaic_xoffset  = 0;
+var mosaic_yoffset  = 0;
+var mosaic_vborder  = 0;
+var mosaic_hborder  = 0;
+var mosaic_position = 1;
+var mosaic_rows     = 0;
+var mosaic_cols     = 0;
+var mosaic_delay    = 0;
+
+var cell_width  = 0;
+var cell_height = 0;
+
+var streams = Object;
+var cells   = Object;
+
+function mosaic_init()
+{
+    document.getElementById( 'sout_extra' ).value = ",sfilter=mosaic";
+    mosaic_size_change();
+}
+
 function mosaic_size_change()
 {
-    check_and_replace_int( "mosaic_rows", "1" );
-    mr = value( "mosaic_rows" );
-    check_and_replace_int( "mosaic_cols", "1" );
-    mc = value( "mosaic_cols" );
+    var x,y;
+
+    var bg_width    = check_and_replace_int( "bg_width", "400" );
+    var bg_height   = check_and_replace_int( "bg_height", "300" );
+
+    mosaic_height   = check_and_replace_int( "mosaic_height", "100" );
+    mosaic_width    = check_and_replace_int( "mosaic_width", "100" );
+    mosaic_xoffset  = check_and_replace_int( "mosaic_xoffset", "10" );
+    mosaic_yoffset  = check_and_replace_int( "mosaic_yoffset", "10" );
+    mosaic_vborder  = check_and_replace_int( "mosaic_vborder", "5" );
+    mosaic_hborder  = check_and_replace_int( "mosaic_hborder", "10" );
+    mosaic_rows     = check_and_replace_int( "mosaic_rows", "1" );
+    mosaic_cols     = check_and_replace_int( "mosaic_cols", "1" );
     
-    mlayout = document.getElementById( "mosaic_layout" );
+    cell_width  = Math.floor((mosaic_width-(mosaic_cols-1)*mosaic_hborder)/mosaic_cols);
+    cell_height = Math.floor((mosaic_height-(mosaic_rows-1)*mosaic_vborder)/mosaic_rows);
+    
+    var mlayout = document.getElementById( "mosaic_layout" );
+
+    /* TODO: keep 'common' cells when resizing */
     while( mlayout.hasChildNodes() )
         mlayout.removeChild( mlayout.firstChild );
 
-    if( mc && mr )
+    mlayout.style.width = bg_width + "px";
+    mlayout.style.height = bg_height + "px";
+    if( mosaic_cols && mosaic_rows )
     {
-        for( y = 0; y < mr; y++ )
+        var mdt = document.createElement( 'div' );
+        mdt.setAttribute( 'id',    'mosaic_dt'  );
+        mdt.setAttribute( 'class', 'mosaic_tbl' );
+        
+        mdt.style.width  = mosaic_width   + "px";
+        mdt.style.height = mosaic_height  + "px";
+        mdt.style.top    = mosaic_yoffset + "px";
+        mdt.style.left   = mosaic_xoffset + "px";
+
+        var mtable = document.createElement( 'table' );
+        mtable.setAttribute( 'id', 'mosaic_table' );
+        mtable.style.top    = "-" + mosaic_vborder + "px";
+        mtable.style.left   = "-" + mosaic_hborder + "px";
+        mtable.style.width  = (1*mosaic_width +2*mosaic_hborder)  + "px";
+        mtable.style.height = (1*mosaic_height+2*mosaic_vborder) + "px";
+        mtable.style.borderSpacing = mosaic_hborder + "px " +
+                                     mosaic_vborder + "px";
+
+        for( y = 0; y < mosaic_rows; y++ )
         {
-            mrow = document.createElement( 'div' );
-            mrow.setAttribute( 'class', 'mosaic_row' );
-            for( x = 0; x < mc; x++ )
+            var mrow = document.createElement( 'tr' );
+            for( x = 0; x < mosaic_cols; x++ )
             {
-                melt = document.createElement( 'input' );
+                var mcell = document.createElement( 'td' );
+                mcell.setAttribute( 'class', 'mosaic_itm' );
+                mcell.style.width  = cell_width  + "px";
+                mcell.style.height = cell_height + "px";
+                
+                var melt = document.createElement( 'input' );
                 melt.setAttribute( 'type', 'button' );
-                melt.setAttribute( 'id', 'mosaic_'+x+'_'+y );
-                melt.setAttribute( 'class', 'mosaic_element' );
-                melt.setAttribute( 'onclick', 'mosaic_elt_choose(\'mosaic_'+x+'_'+y+'\');' );
-                melt.setAttribute( 'value', '(click)' );
-                mrow.appendChild( melt );
+                var id = x+'_'+y;
+                melt.setAttribute( 'id', id );
+                melt.setAttribute( 'onclick', 'mosaic_elt_choose(\''+id+'\');' );
+                if( cells[id] )
+                    melt.setAttribute( 'value', cells[id] );
+                else
+                    melt.setAttribute( 'value', '?' );
+                melt.setAttribute( 'title', 'Click to choose stream' );
+                
+                mcell.appendChild( melt );
+                mrow.appendChild( mcell );
             }
-            mlayout.appendChild( mrow );
+            mtable.appendChild( mrow );
         }
+        mdt.appendChild( mtable );
+        mlayout.appendChild( mdt );
     }
+    mosaic_code_update();
 }
 
 function mosaic_add_input()
 {
-    mlist = document.getElementById( "mosaic_list" );
-    minput = document.createElement( 'a' );
-    minput.setAttribute( 'href', 'javascript:mosaic_elt_select(\'mosaic_'+value('mosaic_input_name')+'\');');
-    minput.setAttribute( 'id', 'mosaic_'+value('mosaic_input_name') );
-    minput.setAttribute( 'value', value('mosaic_input') );
-    minput.setAttribute( 'title', value('mosaic_input') );
-    minputtxt = document.createTextNode( value('mosaic_input_name') );
-    minput.appendChild( minputtxt );
-    mlist.appendChild( minput );
-    mlist.appendChild( document.createElement( 'br' ) );
+    streams[ addunderscores( value('mosaic_input_name') ) ] =
+        value('mosaic_input');
+
+    var mlist = document.getElementById( "mosaic_list_content" );
+    while( mlist.hasChildNodes() )
+        mlist.removeChild( mlist.firstChild );
+    
+    for( var name in streams )
+    {
+        var mrl = streams[name];
+        
+        var minput = document.createElement( 'a' );
+        minput.setAttribute( 'href', 'javascript:mosaic_elt_select(\''+name+'\');');
+        minput.setAttribute( 'id', name );
+        minput.setAttribute( 'value', mrl );
+        minput.setAttribute( 'title', mrl );
+        
+        var minputtxt = document.createTextNode( name );
+
+        minput.appendChild( minputtxt );
+        mlist.appendChild( minput );
+        mlist.appendChild( document.createElement( 'br' ) );
+    }
 }
 
 function mosaic_elt_select( id )
 {
     hide( 'mosaic_list' );
-    document.getElementById( document.getElementById( 'mosaic_list' ).value ).value =
-        document.getElementById( id ).getAttribute( 'value' );
+    document.getElementById( document.getElementById( 'mosaic_list' ).value ).value = id;
+    cells[ document.getElementById( 'mosaic_list' ).value ] = id;
+    mosaic_code_update();
 }
 
 function mosaic_elt_choose( id )
@@ -83,3 +169,140 @@ function mosaic_elt_choose( id )
     document.getElementById( 'mosaic_list' ).value = id;
     show( 'mosaic_list' );
 }
+
+function mosaic_code_update()
+{
+
+    var code = document.getElementById( 'mosaic_code' );
+    code.value =
+"##################################\n"+
+"## HTTP interface mosaic wizard ##\n"+
+"##################################\n"+
+"\n"+
+"# Comment the following line if you don't want to reset you VLM configuration\n"+
+"del all\n"+
+"\n"+
+"# Background options\n"+
+"new   bg broadcast enabled\n"+
+"setup bg input     " + value( 'mosaic_bg_input' ) + "\n";
+    if( value( 'mosaic_output' ) )
+    {
+        code.value +=
+"setup bg output    " + value( 'mosaic_output' )+ "\n";
+    }
+    var o = /.*transcode.*/;
+    if(! o.test( value( 'mosaic_output' ) ) )
+    {
+        code.value +=
+"setup bg option    sub-filter=mosaic\n";
+    }
+    code.value+=
+"\n"+
+"# Mosaic options\n"+
+"setup bg option mosaic-alpha="    + mosaic_alpha    + "\n"+
+"setup bg option mosaic-height="   + mosaic_height   + "\n"+
+"setup bg option mosaic-width="    + mosaic_width    + "\n"+
+"setup bg option mosaic-align="    + mosaic_align    + "\n"+
+"setup bg option mosaic-xoffset="  + mosaic_xoffset  + "\n"+
+"setup bg option mosaic-yoffset="  + mosaic_yoffset  + "\n"+
+"setup bg option mosaic-vborder="  + mosaic_vborder  + "\n"+
+"setup bg option mosaic-hborder="  + mosaic_hborder  + "\n"+
+"setup bg option mosaic-position=" + mosaic_position + "\n"+
+"setup bg option mosaic-rows="     + mosaic_rows     + "\n"+
+"setup bg option mosaic-cols="     + mosaic_cols     + "\n"+
+"setup bg option mosaic-order=";
+    for( y = 0; y < mosaic_rows; y++ )
+    {
+        for( x = 0; x < mosaic_cols; x++ )
+        {
+            var id = x+'_'+y;
+            if( cells[id] )
+                code.value += cells[id];
+            else
+                code.value += '_';
+            if( y != mosaic_rows - 1 || x != mosaic_cols - 1 )
+                code.value += ',';
+        }
+    }
+    code.value += "\n"+
+"setup bg option mosaic-delay="    + mosaic_delay    + "\n"+
+"setup bg option mosaic-keep-picture\n"+
+"\n"+
+"# Input options\n";
+    var x, y;
+    for( y = 0; y < mosaic_rows; y++ )
+    {
+        for( x = 0; x < mosaic_cols; x++ )
+        {
+            var id = x+'_'+y;
+            if( cells[id] )
+            {
+                var s = cells[id];
+                code.value +=
+"new   " + s + " broadcast enabled\n"+
+"setup " + s + " input     " + streams[s] + "\n"+
+"setup " + s + " output #duplicate{dst=mosaic-bridge{id=" + s + ",width="+cell_width+",height="+cell_height+"},select=video,dst=bridge-out,select=audio}\n"+
+"\n";
+            }
+        }
+    }
+    code.value +=
+"# Launch everything\n"+
+"control bg play\n";
+    for( y = 0; y < mosaic_rows; y++ )
+    {
+        for( x = 0; x < mosaic_cols; x++ )
+        {
+            var id = x+'_'+y;
+            if( cells[id] )
+            {
+                var s = cells[id];
+                code.value +=
+"control " + s + " play\n";
+            }
+        }
+    }
+    code.value +=
+"\n"+
+"# end of mosaic batch\n";
+}
+
+function mosaic_batch( batch )
+{
+    var i;
+    var commands = batch.split( '\n' );
+    for( i = 0; i < commands.length; i++ )
+    {
+        mosaic_cmd( commands[i] );
+    }
+}
+
+function mosaic_cmd( cmd )
+{
+    loadXMLDoc( 'requests/vlm_cmd.xml?command='+cmd.replace(/\#/g, '%23'), parse_mosaic_cmd );
+}
+
+function parse_mosaic_cmd()
+{
+    /* TODO */
+}
+
+function mosaic_stop()
+{
+    var cmd;
+    cmd = "control bg stop\n";
+    var x,y;
+    for( y = 0; y < mosaic_rows; y++ )
+    {
+        for( x = 0; x < mosaic_cols; x++ )
+        {
+            var id = x+'_'+y;
+            if( cells[id] )
+            {
+                var s = cells[id];
+                cmd += "control " + s + " stop\n";
+            }
+        }
+    }
+    mosaic_batch( cmd );
+}   
index 1ecd809..39a8aa6 100644 (file)
   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
   <link href="style.css" rel="stylesheet" type="text/css" />
   <script type="text/javascript" src="js/functions.js"></script>
+  <script type="text/javascript" src="js/vlm.js"></script>
   <script type="text/javascript" src="js/mosaic.js"></script>
 
 </head>
 
-<body onload="mosaic_size_change();">
+<body onload="mosaic_init();">
 
-<h1>TODO : code</h1>
+<h1>Mosaic wizard</h1>
 
 <vlc id="rpn" param1="page vlm store" />
 
 <!-- do we need to browse in order to setup a mosaic ? for the background image maybe ... -->
 <vlc id="include" param1="dialogs/browse" />
 
-<!-- the actual mosaic stuff -->
-<vlc id="include" param1="dialogs/mosaic" />
 <!-- used to select background and sub streams -->
 <vlc id="include" param1="dialogs/input" />
 <!-- select final output -->
 <vlc id="include" param1="dialogs/sout" />
+<!-- the actual mosaic stuff -->
+<vlc id="include" param1="dialogs/mosaic" />
 
 <vlc id="include" param1="dialogs/footer" />
 
index 56d4a30..d585a65 100644 (file)
@@ -60,7 +60,7 @@ form {
        display: inline;
 }
 
-input {
+input, textarea {
        border: solid #000 1px;
        background-color: #fff;
 }
@@ -167,24 +167,50 @@ div#mosaic_list {
        left: 25%;
 }
 
-div#mosaic_layout {
-       border: 1px solid #000;
-       background-color: #ddf;
-       display: block;
-       margin: 1em;
-       padding: 0.3em 0.6em;
+.mosaic_bg {
+       background-color: #aaf;
+}
+.mosaic_tbl {
+       background-color: #faa;
 }
-div.mosaic_row {
-       padding: 0.6em 0em;
+.mosaic_itm {
+       background-color: #afa;
+}
+div#mosaic_layout {
+       border: 0px solid #000;
+       padding: 0px;
+       margin: 10px auto;
 }
 
-.mosaic_element {
-       display: inline;
-       border: 1px solid #000;
-       margin: 0em 0.3em;
-       padding: 0.3em 0.3em;
-       background-color: #dfd;
+div#mosaic_dt {
+       border: 0px solid #000;
+       position: relative;
+}
+table#mosaic_table {
+       border-spacing: 0px 0px;
+       position: relative;
+}
+table#mosaic_table tr {
+       padding: 0px;
+       margin: 0px;
 }
+table#mosaic_table td {
+       border: 0px solid #000;
+       text-align: center;
+       padding: 0px;
+       margin: 0px;
+}
+table#mosaic_table input {
+       border: 0px;
+       background: transparent;
+       text-align: center;
+}
+textarea#mosaic_code {
+       padding: 0px;
+       display: block;
+       margin: 10px auto;
+}
+
 div.controls button.on {
        background-color: #aaa;
 }