From 2d5684a52852d46fee951c407b7d3ff10ea256ec Mon Sep 17 00:00:00 2001
From: sebastian <sebastian@cfc7b370-4200-0410-a6e3-cb6bdb053afe>
Date: Sun, 6 Mar 2005 16:57:54 +0000
Subject: [PATCH] *** empty log message ***

---
 .../htmlUI/var/SmartyExtensions.inc.php       |   1 +
 .../htmlUI/var/formmask/general.inc.php       |   7 +-
 .../modules/htmlUI/var/html/ui_browser.php    |   4 +
 .../modules/htmlUI/var/html/ui_handler.php    |  12 +-
 .../htmlUI/var/templates/library/main.tpl     |   8 +-
 .../htmlUI/var/templates/library/results.tpl  |  20 +-
 .../htmlUI/var/templates/masterpanel.tpl      |   3 +
 .../modules/htmlUI/var/templates/menu_top.tpl |   1 +
 .../var/templates/scheduler/calendar.tpl      |  31 ++
 .../htmlUI/var/templates/scheduler/day.tpl    |   0
 .../htmlUI/var/templates/scheduler/input.tpl  |  21 +
 .../htmlUI/var/templates/scheduler/main.tpl   |  14 +
 .../htmlUI/var/templates/scheduler/month.tpl  |  30 ++
 .../htmlUI/var/templates/scheduler/week.tpl   |   0
 .../htmlUI/var/templates/script/basics.js.tpl |   6 +-
 .../modules/htmlUI/var/ui_base.inc.php        |   1 +
 .../modules/htmlUI/var/ui_browse.class.php    |  56 +-
 .../modules/htmlUI/var/ui_browser_init.php    |   4 +-
 .../modules/htmlUI/var/ui_calendar.class.php  |  92 ++++
 .../modules/htmlUI/var/ui_handler_init.php    |   4 +-
 .../modules/htmlUI/var/ui_scheduler.class.php |  44 ++
 .../modules/htmlUI/var/ui_search.class.php    |  43 +-
 .../htmlUI/var/ui_xmlrpcwrapper.class.php     | 489 ++++++++++++++++++
 23 files changed, 841 insertions(+), 50 deletions(-)
 create mode 100755 livesupport/modules/htmlUI/var/templates/scheduler/calendar.tpl
 create mode 100755 livesupport/modules/htmlUI/var/templates/scheduler/day.tpl
 create mode 100755 livesupport/modules/htmlUI/var/templates/scheduler/input.tpl
 create mode 100755 livesupport/modules/htmlUI/var/templates/scheduler/main.tpl
 create mode 100755 livesupport/modules/htmlUI/var/templates/scheduler/month.tpl
 create mode 100755 livesupport/modules/htmlUI/var/templates/scheduler/week.tpl
 create mode 100755 livesupport/modules/htmlUI/var/ui_calendar.class.php
 create mode 100755 livesupport/modules/htmlUI/var/ui_scheduler.class.php
 create mode 100755 livesupport/modules/htmlUI/var/ui_xmlrpcwrapper.class.php

diff --git a/livesupport/modules/htmlUI/var/SmartyExtensions.inc.php b/livesupport/modules/htmlUI/var/SmartyExtensions.inc.php
index 336cbadb3..2a4a44c45 100644
--- a/livesupport/modules/htmlUI/var/SmartyExtensions.inc.php
+++ b/livesupport/modules/htmlUI/var/SmartyExtensions.inc.php
@@ -3,6 +3,7 @@ $Smarty->register_object('UIBROWSER', $uiBrowser);
 $Smarty->register_object('PL',        $uiBrowser->PLAYLIST);
 $Smarty->register_object('BROWSE',    $uiBrowser->BROWSE);
 $Smarty->register_object('SEARCH',    $uiBrowser->SEARCH);
+$Smarty->assign_by_ref  ('SCHEDULER', $uiBrowser->SCHEDULER);
 
 $Smarty->register_function('str_repeat', 'S_str_repeat');
 $Smarty->register_function('urlencode',  'S_urlencode');
diff --git a/livesupport/modules/htmlUI/var/formmask/general.inc.php b/livesupport/modules/htmlUI/var/formmask/general.inc.php
index 1a0151b85..63a7a1691 100755
--- a/livesupport/modules/htmlUI/var/formmask/general.inc.php
+++ b/livesupport/modules/htmlUI/var/formmask/general.inc.php
@@ -91,7 +91,8 @@ $ui_fmask = array(
             'element'   => 'stationlogo',
             'type'      => 'file',
             'label'     => 'Station Logo',
-            'requiredmsg'=> 'please select Logo file'
+            'requiredmsg'=> 'please select Logo file',
+            'attributes'=> array('multiple' => 'application/pdf')
         ),
         array(
             'element'   =>'Submit',
@@ -370,7 +371,7 @@ $ui_fmask = array(
             'type'      => 'select',
             'label'     => 'Rows per Page',
             'options'   => array(
-                                #1   => 1,
+                                2   => 2,
                                 5   => 5,
                                 10  => 10,
                                 25  => 25,
@@ -488,7 +489,7 @@ $ui_fmask = array(
             'type'      => 'select',
             'label'     => 'Rows per Page',
             'options'   => array(
-                                #1   => 1,
+                                2   => 2,
                                 5   => 5,
                                 10  => 10,
                                 25  => 25,
diff --git a/livesupport/modules/htmlUI/var/html/ui_browser.php b/livesupport/modules/htmlUI/var/html/ui_browser.php
index 8c859b294..920409b65 100644
--- a/livesupport/modules/htmlUI/var/html/ui_browser.php
+++ b/livesupport/modules/htmlUI/var/html/ui_browser.php
@@ -154,6 +154,10 @@ if ($uiBrowser->userid) {
     case "PL.simpleManagement":
         $Smarty->assign('PL_simpleManagement', TRUE);
     break;
+
+    case "SCHEDULER":
+        $Smarty->assign('showScheduler', TRUE);
+    break;
   }
 }
 
diff --git a/livesupport/modules/htmlUI/var/html/ui_handler.php b/livesupport/modules/htmlUI/var/html/ui_handler.php
index df726d1bf..ab6e03c7a 100644
--- a/livesupport/modules/htmlUI/var/html/ui_handler.php
+++ b/livesupport/modules/htmlUI/var/html/ui_handler.php
@@ -45,7 +45,7 @@ switch($_REQUEST['act']){
         if ($_REQUEST['id']) {
             $uiHandler->editWebstream($_REQUEST, $ui_fmask['webstream']);
         } else {
-            $ui_tmpid = $uiHandler->addWebstream($_REQUEST, $ui_fmask['webstream']);  
+            $ui_tmpid = $uiHandler->addWebstream($_REQUEST, $ui_fmask['webstream']);
             $uiHandler->SCRATCHPAD->addItem($ui_tmpid);
         }
     break;
@@ -217,6 +217,16 @@ switch($_REQUEST['act']){
         $uiHandler->PLAYLIST->setReload();
     break;
 
+    case "SCHEDULER.set":
+        $uiHandler->SCHEDULER->set($_REQUEST);
+        $uiHandler->SCHEDULER->setReload();
+    break;
+
+    case "SCHEDULER.uploadPL":
+        $uiHandler->SCHEDULER->uploadPL($_REQUEST['gunid']);
+        $uiHandler->SCHEDULER->setReload();
+    break;
+
     default:
         $_SESSION["alertMsg"] = tra("Unknown method: $1", $_REQUEST["act"]);
         header("Location: ".UI_BROWSER.'?popup[]=_reload_parent&popup[]=_close');
diff --git a/livesupport/modules/htmlUI/var/templates/library/main.tpl b/livesupport/modules/htmlUI/var/templates/library/main.tpl
index d4804361c..7cfddbfeb 100755
--- a/livesupport/modules/htmlUI/var/templates/library/main.tpl
+++ b/livesupport/modules/htmlUI/var/templates/library/main.tpl
@@ -3,13 +3,15 @@
 {if $searchForm}
     {assign var="_act_prefix" value="SEARCH"}
     {include file="library/searchForm.tpl"}
-    {SEARCH->getResult assign=searchResults}
+    {SEARCH->getResult assign=_results}
+    {SEARCH->getCriteria assign=_criteria}
 {/if}
 
-{if $browseForm}
+{if $browseForm}    
     {assign var="_act_prefix" value="BROWSE"}
     {include file="library/browseForm.tpl"}
-    {BROWSE->getResult assign=searchResults}
+    {BROWSE->getResult assign=_results}
+    {BROWSE->getCriteria assign=_criteria}
 {/if}
 
 {include file="library/results.tpl"}
\ No newline at end of file
diff --git a/livesupport/modules/htmlUI/var/templates/library/results.tpl b/livesupport/modules/htmlUI/var/templates/library/results.tpl
index ac84c8685..b99917af9 100755
--- a/livesupport/modules/htmlUI/var/templates/library/results.tpl
+++ b/livesupport/modules/htmlUI/var/templates/library/results.tpl
@@ -1,8 +1,6 @@
-{*Smarty template*}
-
 <div id="searchres">
 <center>
-{if $searchResults.count > 0}
+{if $_results.cnt > 0}
     <table border="0" width="50%">
         <tr style="background-color: {cycle values='#eeeeee, #dadada'}">
             <td align="center"><a href="#" onClick="hpopup('{$UI_HANDLER}?act={$_act_prefix}.reOrder&by=title', 'order');">{tra 0=Title}</a></td>
@@ -10,7 +8,7 @@
             <td align="center"><a href="#" onClick="hpopup('{$UI_HANDLER}?act={$_act_prefix}.reOrder&by=extent', 'order');">{tra 0=Duration}</a></td>
             <td align="center"><a href="#" onClick="hpopup('{$UI_HANDLER}?act={$_act_prefix}.reOrder&by=type', 'order');">{tra 0=Type}</a></td>
         </tr>
-        {foreach from=$searchResults.items item=i}
+        {foreach from=$_results.items item=i}
             <tr style="background-color: {cycle values='#eeeeee, #dadada'}" {assign var="moreContextBefore" value=", 'SP.addItem'"}{include file="sub/contextmenu.tpl"}>
                 <td align="center">
                     {if $PLAYLIST.id == $i.id}
@@ -26,17 +24,23 @@
         {/foreach}
         <tr>
             <td>
-                {if $searchResults.prev}<a href="#" onClick="hpopup('{$UI_HANDLER}?act={$_act_prefix}.setOffset&page=prev', 'pager')">back</a>{/if}
+                {if $_results.prev}<a href="#" onClick="hpopup('{$UI_HANDLER}?act={$_act_prefix}.setOffset&page=prev', 'pager')">backward</a>{/if}
+            </td>
+            <td>
+                Count:&nbsp;{$_results.cnt}
+
+                Page:&nbsp;&nbsp;{$_results.page+1}
+
+                Range:&nbsp;{$_criteria.offset+1}-{if ($_criteria.offset+$_criteria.limit)>$_results.cnt}{$_results.cnt}{else}{$_criteria.offset+$_criteria.limit}{/if}
             </td>
-            <td>count: {$searchResults.count}</td>
             <td>
                 go:
-                {foreach from=$searchResults.pages item=p key=k}
+                {foreach from=$_results.pagination item=p key=k}
                     <a href="#" onClick="hpopup('{$UI_HANDLER}?act={$_act_prefix}.setOffset&page={$k}', 'pager')">{$p}</a>
                 {/foreach}
             </td>
             <td align="right">
-                {if $searchResults.next}<a href="#" onClick="hpopup('{$UI_HANDLER}?act={$_act_prefix}.setOffset&page=next', 'pager')">forward</a>{/if}
+                {if $_results.next}<a href="#" onClick="hpopup('{$UI_HANDLER}?act={$_act_prefix}.setOffset&page=next', 'pager')">forward</a>{/if}
             </td>
         </tr>
         <tr><td colspan="4">
diff --git a/livesupport/modules/htmlUI/var/templates/masterpanel.tpl b/livesupport/modules/htmlUI/var/templates/masterpanel.tpl
index 68ce2c877..a71204f6f 100755
--- a/livesupport/modules/htmlUI/var/templates/masterpanel.tpl
+++ b/livesupport/modules/htmlUI/var/templates/masterpanel.tpl
@@ -48,6 +48,9 @@
     {include file="playlist/simpleManagement.tpl"}
 {/if}
 
+{if $showScheduler}
+    {include file="scheduler/main.tpl"}
+{/if}
 
 </div>
 
diff --git a/livesupport/modules/htmlUI/var/templates/menu_top.tpl b/livesupport/modules/htmlUI/var/templates/menu_top.tpl
index f60aa174d..43045e1db 100755
--- a/livesupport/modules/htmlUI/var/templates/menu_top.tpl
+++ b/livesupport/modules/htmlUI/var/templates/menu_top.tpl
@@ -6,6 +6,7 @@
     <a href="{$UI_BROWSER}?id={$START.fid}&act=PL.simpleManagement">[PL Editor]</a>
     <a href="{$UI_BROWSER}?id={$START.id}&act=SEARCH">[Search]</a>
     <a href="{$UI_BROWSER}?id={$START.id}&act=BROWSE">[Browse]</a>
+    <a href="{$UI_BROWSER}?act=SCHEDULER">[Scheduler]</a>
     <a href="{$UI_BROWSER}?id={$START.id}&act=subjects">{tra 0='[User/Groups]'}</a>
     <!-- <a href="{$UI_BROWSER}?act=MetaDataValues&Main=1">[Metadata]</a> -->
     <a href="{$UI_BROWSER}?act=changeStationPrefs">[StationPrefs]</a>
diff --git a/livesupport/modules/htmlUI/var/templates/scheduler/calendar.tpl b/livesupport/modules/htmlUI/var/templates/scheduler/calendar.tpl
new file mode 100755
index 000000000..b7c378809
--- /dev/null
+++ b/livesupport/modules/htmlUI/var/templates/scheduler/calendar.tpl
@@ -0,0 +1,31 @@
+{$SCHEDULER->buildMonth()}
+{$SCHEDULER->buildWeek()}
+
+<table border=1>
+<tr><th colspan="8">{$SCHEDULER->curr.year}-{$SCHEDULER->curr.month}-{$SCHEDULER->curr.day}</th></tr>
+<tr> <td></td>
+    {foreach from=$SCHEDULER->Week item="_Weekday"}
+        <td>{$_Weekday.label.short}</td>
+    {/foreach}
+</tr>
+{foreach from=$SCHEDULER->Month item="_Day"}
+    {if $_Day.isFirst}
+        <tr>
+            <th><a href="#" onClick="hpopup('{$UI_HANDLER}?act=SCHEDULER.set&week={$_Day.week}')">{$_Day.week}</a></th>
+    {/if}
+            <td>
+    {if $_Day.isEmpty}
+            &nbsp;
+    {elseif $_Day.isSelected}
+            <b>{$_Day.day}</b>
+    {else}
+            <a href="#" onClick="hpopup('{$UI_HANDLER}?act=SCHEDULER.set&day={$_Day.day}')">{$_Day.day}</a>
+    {/if}
+
+             </td>
+    {if $_Day.isLast}
+        </tr>
+    {/if}
+{/foreach}
+
+</table>
diff --git a/livesupport/modules/htmlUI/var/templates/scheduler/day.tpl b/livesupport/modules/htmlUI/var/templates/scheduler/day.tpl
new file mode 100755
index 000000000..e69de29bb
diff --git a/livesupport/modules/htmlUI/var/templates/scheduler/input.tpl b/livesupport/modules/htmlUI/var/templates/scheduler/input.tpl
new file mode 100755
index 000000000..34749d2e7
--- /dev/null
+++ b/livesupport/modules/htmlUI/var/templates/scheduler/input.tpl
@@ -0,0 +1,21 @@
+{SEARCH->getResult assign=_results}
+
+{if $_results.cnt > 0}
+    <table border="0" width="50%">
+        {foreach from=$_results.items item=i}
+            <tr style="background-color: {cycle values='#eeeeee, #dadada'}" {assign var="moreContextBefore" value=", 'SP.addItem'"}{include file="sub/contextmenu.tpl"}>
+                <td align="center">
+                    {if $PLAYLIST.id == $i.id}
+                        <b>{$i.title|truncate:30}</b>
+                    {else}
+                        {$i.title|truncate:30}
+                    {/if}
+                </td>
+                <td align="center">{$i.type}</td>
+                <td><a href="#" onClick="hpopup('{$UI_HANDLER}?act=SCHEDULER.uploadPL&gunid={$i.gunid}')">{$i.gunid}</td>
+            </tr>
+        {/foreach}
+    </table>
+{else}
+    No match found.
+{/if}
diff --git a/livesupport/modules/htmlUI/var/templates/scheduler/main.tpl b/livesupport/modules/htmlUI/var/templates/scheduler/main.tpl
new file mode 100755
index 000000000..156c78c9a
--- /dev/null
+++ b/livesupport/modules/htmlUI/var/templates/scheduler/main.tpl
@@ -0,0 +1,14 @@
+<div class="standardFrame">
+{include file="sub/x.tpl"}
+
+<input type="button" onClick="hpopup('{$UI_HANDLER}?act=SCHEDULER.set&view=day')" value="Day">
+<input type="button" onClick="hpopup('{$UI_HANDLER}?act=SCHEDULER.set&view=week')" value="Week">
+<input type="button" onClick="hpopup('{$UI_HANDLER}?act=SCHEDULER.set&view=month')" value="Month">
+<input type="button" onClick="hpopup('{$UI_HANDLER}?act=SCHEDULER.set&view=input')" value="Input">
+
+{include file="scheduler/calendar.tpl"}
+
+{assign var="view" value=$SCHEDULER->curr.view}
+{include file="scheduler/$view.tpl"}
+
+</div>
diff --git a/livesupport/modules/htmlUI/var/templates/scheduler/month.tpl b/livesupport/modules/htmlUI/var/templates/scheduler/month.tpl
new file mode 100755
index 000000000..6aea23fdd
--- /dev/null
+++ b/livesupport/modules/htmlUI/var/templates/scheduler/month.tpl
@@ -0,0 +1,30 @@
+{$SCHEDULER->buildMonth()} 
+{$SCHEDULER->buildWeek()}
+
+Month View
+
+<table border=1>
+
+<tr>
+    {foreach from=$SCHEDULER->Week item="_Weekday"}
+        <td>{$_Weekday.label.full}</td>
+    {/foreach}
+</tr>
+
+{foreach from=$SCHEDULER->Month item="_Day"}
+    {if $_Day.isFirst}
+        <tr>
+    {/if}
+
+    {if $_Day.isEmpty}
+        <td>&nbsp;</td>
+    {else}
+        <td><a href="#" onClick="hpopup('{$UI_HANDLER}?act=SCHEDULER.set&day={$_Day.day}')">{$_Day.day}</td>
+    {/if}
+
+    {if $_Day.isLast}
+        </tr>
+    {/if}
+{/foreach}
+
+</table>
diff --git a/livesupport/modules/htmlUI/var/templates/scheduler/week.tpl b/livesupport/modules/htmlUI/var/templates/scheduler/week.tpl
new file mode 100755
index 000000000..e69de29bb
diff --git a/livesupport/modules/htmlUI/var/templates/script/basics.js.tpl b/livesupport/modules/htmlUI/var/templates/script/basics.js.tpl
index 6b0322eb1..7f3f7ef00 100755
--- a/livesupport/modules/htmlUI/var/templates/script/basics.js.tpl
+++ b/livesupport/modules/htmlUI/var/templates/script/basics.js.tpl
@@ -42,10 +42,10 @@
         window.popupwin.focus();
      }
 
-     function hpopup(url, name)                 //hidden popup!
+     function hpopup(url, name)                 //hidden popup!       'width=1, height=1'
      {
-        popupwin = window.open(url, name, 'width=1, height=1');
-        window.parent.focus();
+        popupwin = window.open(url, name);
+        //window.parent.focus();
      }
      {/literal}
 
diff --git a/livesupport/modules/htmlUI/var/ui_base.inc.php b/livesupport/modules/htmlUI/var/ui_base.inc.php
index 018f377b0..74fc4523b 100644
--- a/livesupport/modules/htmlUI/var/ui_base.inc.php
+++ b/livesupport/modules/htmlUI/var/ui_base.inc.php
@@ -107,6 +107,7 @@ class uiBase
         $this->SEARCH       =& new uiSearch($this);
         $this->BROWSE       =& new uiBrowse($this);
         $this->PLAYLIST     =& new uiPlaylist($this);
+        $this->SCHEDULER    =& new uiScheduler($this);
     }
 
 
diff --git a/livesupport/modules/htmlUI/var/ui_browse.class.php b/livesupport/modules/htmlUI/var/ui_browse.class.php
index 0e15e9c94..e6997e0f3 100755
--- a/livesupport/modules/htmlUI/var/ui_browse.class.php
+++ b/livesupport/modules/htmlUI/var/ui_browse.class.php
@@ -6,6 +6,7 @@ class uiBrowse
         $this->Base       =& $uiBase;
         $this->col        =& $_SESSION[UI_BROWSE_SESSNAME]['col'];
         $this->criteria   =& $_SESSION[UI_BROWSE_SESSNAME]['criteria'];
+        $this->results    =& $_SESSION[UI_BROWSE_SESSNAME]['results'];
         $this->reloadUrl  = UI_BROWSER.'?popup[]=_reload_parent&popup[]=_close';
 
         $this->criteria['limit'] ? NULL : $this->criteria['limit'] = 5;
@@ -27,6 +28,17 @@ class uiBrowse
     }
 
 
+    function getCriteria()
+    {
+        return $this->criteria;
+    }
+
+
+    function getResult()
+    {
+        return $this->results;
+    }
+
 
     function browseForm($id, $mask2)
     {
@@ -79,11 +91,12 @@ class uiBrowse
 
     function setValue($formdata)
     {
+        $this->criteria['offset'] = 0;
         $which = $formdata['col'];
         $next  = $which + 1;
         $this->col[$which]['form_value'] =  $formdata['value'][0];
         if ($formdata['value'][0] == '%%all%%') {
-            $this->col[$next]['criteria'] = NULL;
+            $this->col[$next]['criteria'] = array('operator' => 'and');
         } else {
             $this->col[$next]['criteria'] = array(
                                             'operator' => 'and',
@@ -105,6 +118,7 @@ class uiBrowse
         #echo "\nvalues: "; print_r($this->col[$next]['values']);
 
         $this->clearHierarchy($next);
+        $this->searchDB();
         $this->Base->redirUrl = UI_BROWSER.'?act=BROWSE';
     }
 
@@ -131,9 +145,10 @@ class uiBrowse
     }
 
 
-    function getResult()
+    function searchDB()
     {
-        $this->results = NULL;
+        $this->results = array('page' => $this->criteria['offset']/$this->criteria['limit']);
+        $this->criteria['conditions'] = array();
         for($col=4; $col>=1; $col--) {
             if (is_array($this->col[$col]['criteria'])) {
                 $this->criteria = array_merge ($this->criteria, $this->col[$col]['criteria']);
@@ -141,33 +156,36 @@ class uiBrowse
             }
         }
         $results = $this->Base->gb->localSearch($this->criteria, $this->Base->sessid);
-        #$this->results['count'] = $results['cnt'];
+        $this->results['cnt'] = $results['cnt'];
         foreach ($results['results'] as $rec) {
             $this->results['items'][] = $this->Base->_getMetaInfo($this->Base->gb->_idFromGunid($rec));
         }
         $this->pagination($results);
+        #print_r($this->criteria);
         #print_r($this->results);
-        return $this->results;
+        return TRUE;
     }
 
 
     function pagination(&$results)
     {
-        if (sizeof($this->results) == 0) {
+        if (sizeof($this->results['items']) == 0) {
             return FALSE;
         }
-        $this->results['count'] = $results['cnt'];
-        $this->results['next']  = $results['cnt'] > $this->criteria['offset'] + $this->criteria['limit'] ? TRUE : FALSE;
-        $this->results['prev']  = $this->criteria['offset'] > 0 ? TRUE : FALSE;
+        $currp =  ($this->criteria['offset']/$this->criteria['limit']) + 1;   # current page
+        $maxp  =  ceil($results['cnt'] / $this->criteria['limit']);           # maximum page
 
-        $p = 1;
-        for ($n = 1; $n <= ceil($results['cnt'] / $this->criteria['limit']); $n = $n+$p) {
-            $p = bcpow(10, floor($n/10));
-            $this->results['pages'][$n-1] = $n;
+        for ($n = 1; $n <= $maxp; $n = $n+$width) {
+            $width = pow(10, floor(($n)/10));
+            $this->results['pagination'][$n] = $n;
         }
 
-        array_pop($this->results['pages']);
-        $this->results['pages'][ceil($results['cnt'] / $this->criteria['limit'])-1] = '>>';
+        #array_pop($this->results['pagination']);
+        $this->results['pagination'][1] = '|<<';
+        $this->results['pagination'][$maxp] = '>>|';
+        $this->results['next']  = $results['cnt'] > $this->criteria['offset'] + $this->criteria['limit'] ? TRUE : FALSE;
+        $this->results['prev']  = $this->criteria['offset'] > 0 ? TRUE : FALSE;
+        ksort($this->results['pagination']);
     }
 
 
@@ -182,7 +200,7 @@ class uiBrowse
 
         $this->criteria['orderby'] = $by;
         $this->setReload();
-        #$this->searchDB();
+        $this->searchDB();
     }
 
 
@@ -196,22 +214,24 @@ class uiBrowse
         } elseif ($page == 'prev') {
             $o -= $l;
         } elseif (is_numeric($page)) {
-            $o = $l * $page;
+            $o = $l * ($page-1);
         }
         $this->setReload();
-        #$this->searchDB();
+        $this->searchDB();
     }
 
     function setLimit($limit)
     {
         $this->criteria['limit'] = $limit;
         $this->setReload();
+        $this->searchDB();
     }
 
     function setFiletype($filetype)
     {
         $this->criteria['filetype'] = $filetype;
         $this->setReload();
+        $this->searchDB();
     }
 }
 ?>
diff --git a/livesupport/modules/htmlUI/var/ui_browser_init.php b/livesupport/modules/htmlUI/var/ui_browser_init.php
index 61febde86..e063c3ce0 100644
--- a/livesupport/modules/htmlUI/var/ui_browser_init.php
+++ b/livesupport/modules/htmlUI/var/ui_browser_init.php
@@ -8,9 +8,11 @@ require_once dirname(__FILE__).'/ui_browser.class.php';
 require_once dirname(__FILE__).'/ui_scratchpad.class.php';
 require_once dirname(__FILE__).'/ui_playlist.class.php'; #
 require_once dirname(__FILE__).'/ui_search.class.php';
-require_once dirname(__FILE__).'/ui_browse.class.php';  
+require_once dirname(__FILE__).'/ui_browse.class.php';
 require_once dirname(__FILE__).'/../../storageServer/var/GreenBox.php';
 require_once dirname(__FILE__).'/formmask/general.inc.php';
+require_once dirname(__FILE__).'/ui_calendar.class.php';
+require_once dirname(__FILE__).'/ui_scheduler.class.php';
 
 ## well known classes ###############################################
 require_once dirname(__FILE__).'/Smarty/libs/Smarty.class.php';
diff --git a/livesupport/modules/htmlUI/var/ui_calendar.class.php b/livesupport/modules/htmlUI/var/ui_calendar.class.php
new file mode 100755
index 000000000..f0fd260f4
--- /dev/null
+++ b/livesupport/modules/htmlUI/var/ui_calendar.class.php
@@ -0,0 +1,92 @@
+<?php
+class uiCalendar
+{
+
+    function uiCalendar()
+    {
+        $this->firstDayOfWeek = 1;
+    }
+
+
+    function buildMonth()
+    {
+        if (is_array($this->Month)) return FALSE;
+
+        require_once 'Calendar/Calendar.php';
+        require_once 'Calendar/Month/Weekdays.php';
+        require_once 'Calendar/Day.php';
+
+        $Month = new Calendar_Month_Weekdays($this->curr['year'], $this->curr['month'], $this->firstDayOfWeek);
+        # mark today #
+        $sel =   new Calendar_Day($this->curr['year'], $this->curr['month'], $this->curr['day']);
+        $selection = array($sel);
+
+        $Month->build($selection);
+        while ($Day = $Month->fetch()) {
+            $this->Month[] = array(
+                                'day'           => $this->Base->_twoDigits($Day->thisDay()),
+                                'week'          => $this->_getWeekNr($Day),
+                                'isEmpty'       => $Day->isEmpty(),
+                                'isFirst'       => $Day->isFirst(),
+                                'isLast'        => $Day->isLast(),
+                                'isSelected'    => $Day->isSelected()
+                             );
+        }
+    }
+
+
+    function buildWeek()
+    {
+        if (is_array($this->Week)) return FALSE;
+
+        require_once 'Calendar/Week.php';
+
+        $Week = new Calendar_Week ($this->curr['year'], $this->curr['month'], $this->curr['day'], $this->firstDayOfWeek);
+        $Week->build();
+        while ($Day = $Week->fetch()) {
+            $this->Week[] = array(
+                                'day'           => $this->Base->_twoDigits($Day->thisDay()),
+                                'label'         => $this->_getDayName($Day),
+                            );
+        }
+
+    }
+
+    function buildDay()
+    {
+        require_once 'Calendar/Day.php';
+
+        $Day = new Calendar_Day ($this->curr['year'], $this->curr['month'], $this->curr['day']);
+        $Day->build();
+        while ($Hour = $Day->fetch()) {
+            $this->Day[] = $Hour->thisHour();
+        }
+
+    }
+
+    function buildHour()
+    {
+        require_once 'Calendar/Hour.php';
+
+        $Hour = new Calendar_Hour ($this->curr['year'], $this->curr['month'], $this->curr['day'], $this->curr['hour']);
+        $Hour->build();
+        while ($Min = $Hour->fetch()) {
+            $this->Hour[] = $Min->thisMinute();
+        }
+    }
+
+    function _getWeekNr(&$date) {
+        $timestamp = mktime($date->thisHour(), $date->thisMinute(), $date->thisSecond(), $date->thisMonth(), $date->thisDay(), $date->thisYear());
+        #echo $date->thisHour().$date->thisMinute().$date->thisSecond().$date->thisYear().$date->thisMonth().$date->thisDay().$timestamp."<br>";
+        return date("W", $timestamp);
+    }
+
+
+    function _getDayName(&$date) {
+        $timestamp = mktime($date->thisHour(), $date->thisMinute(), $date->thisSecond(), $date->thisMonth(), $date->thisDay(), $date->thisYear());
+        #echo $date->thisHour().$date->thisMinute().$date->thisSecond().$date->thisYear().$date->thisMonth().$date->thisDay().$timestamp."<br>";
+        return array('short' => strftime("%a", $timestamp),
+                     'full'  => strftime("%A", $timestamp));
+    }
+}
+?>
diff --git a/livesupport/modules/htmlUI/var/ui_handler_init.php b/livesupport/modules/htmlUI/var/ui_handler_init.php
index 438a4d480..6ab5f71ad 100644
--- a/livesupport/modules/htmlUI/var/ui_handler_init.php
+++ b/livesupport/modules/htmlUI/var/ui_handler_init.php
@@ -9,9 +9,11 @@ require_once dirname(__FILE__).'/ui_handler.class.php';
 require_once dirname(__FILE__).'/ui_scratchpad.class.php';
 require_once dirname(__FILE__).'/ui_playlist.class.php';
 require_once dirname(__FILE__).'/ui_search.class.php';
-require_once dirname(__FILE__).'/ui_browse.class.php';  
+require_once dirname(__FILE__).'/ui_browse.class.php';
 require_once dirname(__FILE__).'/../../storageServer/var/GreenBox.php';
 require_once dirname(__FILE__).'/formmask/general.inc.php';
+require_once dirname(__FILE__).'/ui_calendar.class.php';
+require_once dirname(__FILE__).'/ui_scheduler.class.php';
 
 ## well known classes ###############################################
 require_once 'DB.php';
diff --git a/livesupport/modules/htmlUI/var/ui_scheduler.class.php b/livesupport/modules/htmlUI/var/ui_scheduler.class.php
new file mode 100755
index 000000000..bf6263731
--- /dev/null
+++ b/livesupport/modules/htmlUI/var/ui_scheduler.class.php
@@ -0,0 +1,44 @@
+<?php
+class uiScheduler extends uiCalendar
+{
+    function uiScheduler(&$uiBase)
+    {
+        $this->curr   =& $_SESSION[UI_CALENDAR_SESSNAME]['current'];
+        if (!is_array($this->curr)) {
+            $this->curr['view']     = 'month';
+            $this->curr['year']     = date("Y");
+            $this->curr['month']    = date("m");
+            $this->curr['day']      = date('d');
+        }
+
+        $this->Base =& $uiBase;
+        $this->reloadUrl = UI_BROWSER.'?popup[]=_reload_parent&popup[]=_close';
+
+        $this->uiCalendar();
+    }
+
+
+    function setReload()
+    {
+        $this->Base->redirUrl = $this->reloadUrl;
+    }
+
+    function set($arr)
+    {
+        extract($arr);
+        if ($view)  $this->curr['view'] = $view;
+        if ($day)   $this->curr['day']  = $day;
+    }
+
+
+    function uploadPL($gunid)
+    {
+        require_once dirname(__FILE__).'ui_xmlrpcwrapper.class.php';
+
+
+    }
+
+
+
+}
+?>
diff --git a/livesupport/modules/htmlUI/var/ui_search.class.php b/livesupport/modules/htmlUI/var/ui_search.class.php
index 421ed1d81..5f0f52222 100755
--- a/livesupport/modules/htmlUI/var/ui_search.class.php
+++ b/livesupport/modules/htmlUI/var/ui_search.class.php
@@ -20,6 +20,13 @@ class uiSearch
         return $this->results;
     }
 
+
+    function getCriteria()
+    {
+        return $this->criteria;
+    }
+
+
     function searchForm($id, &$mask2)
     {
         include dirname(__FILE__).'/formmask/metadata.inc.php';
@@ -91,12 +98,14 @@ class uiSearch
 
     function searchDB()
     {
-        $this->results = NULL;
+        $this->results = array('page' => $this->criteria['offset']/$this->criteria['limit']);
         $results = $this->Base->gb->localSearch($this->criteria, $this->Base->sessid);
         foreach ($results['results'] as $rec) {
             $this->results['items'][] = $this->Base->_getMetaInfo($this->Base->gb->_idFromGunid($rec));
         }
-        #print_r($this->criteria); print_r($this->results);
+        $this->results['cnt'] = $results['cnt'];
+        #print_r($this->criteria);
+        #print_r($this->results);
         $this->pagination($results);
     }
 
@@ -106,18 +115,28 @@ class uiSearch
         if (sizeof($this->results) == 0) {
             return FALSE;
         }
-        $this->results['count'] = $results['cnt'];
-        $this->results['next']  = $results['cnt'] > $this->criteria['offset'] + $this->criteria['limit'] ? TRUE : FALSE;
-        $this->results['prev']  = $this->criteria['offset'] > 0 ? TRUE : FALSE;
 
-        $p = 1;
-        for ($n = 1; $n <= ceil($results['cnt'] / $this->criteria['limit']); $n = $n+$p) {
-            $p = bcpow(10, floor($n/10));
-            $this->results['pages'][$n-1] = $n;
+        $pot = 0;             # potence
+        $lpr = 10;            # links pro range
+        $width = 1;           # width bettween pages
+        $currp = ($this->criteria['offset']/$this->criteria['limit']) +1 ; # current page
+        $maxp = ceil($results['cnt']/$this->criteria['limit']);            # maximum page
+
+        for ($n = 1; $n <= $maxp; $n = $n+$width) {
+            if ($n<$currp)
+                 $width = pow($lpr, floor(log10(abs($n-$currp))));
+            else
+                 $width = pow($lpr, floor(log10(abs($n-$currp)+1)));
+            $this->results['pagination'][$n] = $n;
+
         }
 
-        array_pop($this->results['pages']);
-        $this->results['pages'][ceil($results['cnt'] / $this->criteria['limit'])-1] = '>>';
+        #array_pop($this->results['pagination']);
+        $this->results['pagination'][$maxp] = '>>|';
+        $this->results['pagination'][1] = '|<<';
+        $this->results['next']  = $results['cnt'] > $this->criteria['offset'] + $this->criteria['limit'] ? TRUE : FALSE;
+        $this->results['prev']  = $this->criteria['offset'] > 0 ? TRUE : FALSE;
+        ksort($this->results['pagination']);
     }
 
 
@@ -154,7 +173,7 @@ class uiSearch
         } elseif ($page == 'prev') {
             $o -= $l;
         } elseif (is_numeric($page)) {
-            $o = $l * $page;
+            $o = $l * ($page-1);
         }
         $this->setReload();
         $this->searchDB();
diff --git a/livesupport/modules/htmlUI/var/ui_xmlrpcwrapper.class.php b/livesupport/modules/htmlUI/var/ui_xmlrpcwrapper.class.php
new file mode 100755
index 000000000..70de0c9b6
--- /dev/null
+++ b/livesupport/modules/htmlUI/var/ui_xmlrpcwrapper.class.php
@@ -0,0 +1,489 @@
+<?php
+/*------------------------------------------------------------------------------
+
+    Copyright (c) 2004 Media Development Loan Fund
+
+    This file is part of the LiveSupport project.
+    http://livesupport.campware.org/
+    To report bugs, send an e-mail to bugs@campware.org
+
+    LiveSupport is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    LiveSupport is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with LiveSupport; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+    Author   : $Author: sebastian $
+    Version  : $Revision: 1.1 $
+    Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/htmlUI/var/Attic/ui_xmlrpcwrapper.class.php,v $
+
+------------------------------------------------------------------------------*/
+
+/* ================================================================= includes */
+require_once dirname(__FILE__).'DB.php';
+include_once dirname(__FILE__)."../xmlrpc/XML/RPC.php";
+include_once dirname(__FILE__)."../conf.php";
+
+/* ================================================== method definition array */
+/**
+ *  Array with methods description
+ *
+ *  Each element has method name as key and contains four subfields:
+ *  <ul>
+ *   <li>m</li> full method name (include optional prefix)
+ *   <li>p</li> array of input parameter names
+ *   <li>r</li> array of result element names (not used there at present)
+ *   <li>e</li> array of error codes/messages (not used there at present)
+ *  </ul>
+ */
+$mdefs = array(
+    "AddAudioClipToPlaylistMethod" => array(
+        'm'=>'AddAudioClipToPlaylistMethod',
+        'p'=>array('sessionId'/*string*/, 'playlistId'/*string*/, 'audioClipId'/*string*/, 'relativeOffset'/*int*/),
+        'r'=>array('playlistElementId'/*string*/),
+        'e'=>array(
+            '301'=>'invalid argument format',
+            '302'=>'missing playlist ID argument',
+            '303'=>'missing audio clip ID argument',
+            '304'=>'missing relative offset argument',
+            '305'=>'playlist not found',
+            '306'=>'playlist has not been opened for editing',
+            '307'=>'audio clip does not exist',
+            '308'=>'two audio clips at the same relative offset',
+            '320'=>'missing session ID argument',
+        )
+    ),
+    "CreatePlaylistMethod" => array(
+        'm'=>'CreatePlaylistMethod',
+        'p'=>array('sessionId'/*string*/),
+        'r'=>array('playlist'/*string*/),
+        'e'=>array(
+            '201'=>'invalid argument format',
+            '202'=>'could not create playlist',
+            '220'=>'missing session ID argument',
+        )
+    ),
+    "DeletePlaylistMethod" => array(
+        'm'=>'DeletePlaylistMethod',
+        'p'=>array('sessionId'/*string*/, 'playlistId'/*string*/),
+        'r'=>array(),
+        'e'=>array(
+            '901'=>'invalid argument format',
+            '902'=>'missing playlist ID argument',
+            '903'=>'playlist not found',
+            '904'=>'playlist is locked',
+            '905'=>'playlist could not be deleted',
+            '920'=>'missing session ID argument',
+        )
+    ),
+    "DisplayAudioClipMethod" => array(
+        'm'=>'DisplayAudioClipMethod',
+        'p'=>array('sessionId'/*string*/, 'audioClipId'/*string*/),
+        'r'=>array('audioClip'/*string*/),
+        'e'=>array(
+            '601'=>'invalid argument format',
+            '602'=>'argument is not an audio clip ID',
+            '603'=>'audio clip not found',
+            '620'=>'missing session ID argument',
+        )
+    ),
+    "DisplayAudioClipsMethod" => array(
+        'm'=>'DisplayAudioClipsMethod',
+        'p'=>array('sessionId'/*string*/),
+        'r'=>array(array('audioClip'/*string*/)),
+        'e'=>array(
+            '1801'=>'invalid argument format',
+            '1802'=>'XML-RPC error',
+            '1820'=>'missing session ID argument',
+        )
+    ),
+    "DisplayPlaylistMethod" => array(
+        'm'=>'DisplayPlaylistMethod',
+        'p'=>array('sessionId'/*string*/, 'playlistId'/*string*/),
+        'r'=>array('playlist'/*string*/),
+        'e'=>array(
+            '1001'=>'invalid argument format',
+            '1002'=>'argument is not a playlist ID',
+            '1003'=>'playlist not found',
+            '1020'=>'missing session ID argument',
+        )
+    ),
+    "DisplayPlaylistsMethod" => array(
+        'm'=>'DisplayPlaylistsMethod',
+        'p'=>array('sessionId'/*string*/),
+        'r'=>array(array('playlist'/*string*/)),
+        'e'=>array(
+            '1701'=>'invalid argument format',
+            '1702'=>'XML-RPC error',
+            '1720'=>'missing session ID argument',
+        )
+    ),
+    "DisplayScheduleMethod" => array(
+        'm'=>'DisplayScheduleMethod',
+        'p'=>array('sessionId'/*string*/, 'from'/*datetime*/, 'to'/*datetime*/),
+        'r'=>array(array('id'/*int*/, 'playlistId'/*string*/, 'start'/*datetime*/, 'end'/*datetime*/)),
+        'e'=>array(
+            '1101'=>'invalid argument format',
+            '1102'=>"missing or invalid 'from' argument",
+            '1103'=>"missing or invalid 'to' argument",
+            '1120'=>'missing session ID argument',
+        )
+    ),
+    "GeneratePlayReportMethod" => array(
+        'm'=>'GeneratePlayReportMethod',
+        'p'=>array('sessionId'/*string*/, 'from'/*datetime*/, 'to'/*datetime*/),
+        'r'=>array(array('audioClipId'/*string*/, 'timestamp'/*datetime*/)),
+        'e'=>array(
+            '1501'=>'invalid argument format',
+            '1502'=>"missing or invalid 'from' argument",
+            '1503'=>"missing or invalid 'to' argument",
+            '1520'=>'missing session ID argument',
+        )
+    ),
+    "GetSchedulerTimeMethod" => array(
+        'm'=>'GetSchedulerTimeMethod',
+        'p'=>array(),
+        'r'=>array('schedulerTime'/*datetime*/),
+        'e'=>array(
+)
+    ),
+    "GetVersionMethod" => array(
+        'm'=>'GetVersionMethod',
+        'p'=>array(),
+        'r'=>array('version'/*string*/),
+        'e'=>array()
+    ),
+    "LoginMethod" => array(
+        'm'=>'LoginMethod',
+        'p'=>array('login'/*string*/, 'password'/*string*/),
+        'r'=>array('sessionId'/*string*/),
+        'e'=>array(
+            '2001'=>'invalid argument format',
+            '2002'=>'missing login argument',
+            '2003'=>'missing password argument',
+            '2004'=>'the authentication server reported an error',
+        )
+    ),
+    "LogoutMethod" => array(
+        'm'=>'LogoutMethod',
+        'p'=>array('sessionId'/*string*/),
+        'r'=>array(),
+        'e'=>array(
+            '2101'=>'invalid argument format',
+            '2120'=>'missing session ID argument',
+            '2104'=>'the authentication server reported an error',
+        )
+    ),
+    "OpenPlaylistForEditingMethod" => array(
+        'm'=>'OpenPlaylistForEditingMethod',
+        'p'=>array('sessionId'/*string*/, 'playlistId'/*string*/),
+        'r'=>array('playlist'/*string*/),
+        'e'=>array(
+            '101'=>'invalid argument format',
+            '102'=>'argument is not a playlist ID',
+            '104'=>'could not open playlist for editing',
+            '120'=>'missing session ID argument',
+        )
+    ),
+    "RemoveAudioClipFromPlaylistMethod" => array(
+        'm'=>'RemoveAudioClipFromPlaylistMethod',
+        'p'=>array('sessionId'/*string*/, 'playlistId'/*string*/, 'playlistElementId'/*string*/),
+        'r'=>array(),
+        'e'=>array(
+            '401'=>'invalid argument format',
+            '402'=>'missing playlist ID argument',
+            '403'=>'missing relative offset argument',
+            '404'=>'playlist does not exist',
+            '405'=>'playlist has not been opened for editing',
+            '406'=>'no audio clip at the specified relative offset',
+            '420'=>'missing session ID argument',
+        )
+    ),
+    "RemoveFromScheduleMethod" => array(
+        'm'=>'RemoveFromScheduleMethod',
+        'p'=>array('sessionId'/*string*/, 'scheduleEntryId'/*string*/),
+        'r'=>array(),
+        'e'=>array(
+            '1201'=>'invalid argument format',
+            '1202'=>'missing schedule entry ID argument',
+            '1203'=>'schedule entry not found',
+            '1220'=>'missing session ID argument',
+        )
+    ),
+    "RescheduleMethod" => array(
+        'm'=>'RescheduleMethod',
+        'p'=>array('sessionId'/*string*/, 'scheduleEntryId'/*string*/, 'playtime'/*datetime*/),
+        'r'=>array(),
+        'e'=>array(
+            '1301'=>'invalid argument format',
+            '1302'=>'missing schedule entry ID argument',
+            '1303'=>'missing playtime argument',
+            '1304'=>'schedule entry not found',
+            '1305'=>'could not reschedule entry',
+            '1320'=>'missing session ID argument',
+        )
+    ),
+    "ResetStorageMethod" => array(
+        'm'=>'ResetStorageMethod',
+        'p'=>array(),
+        'r'=>array(),
+        'e'=>array('3001'=>'storage client reported an error'),
+    ),
+    "RevertEditedPlaylistMethod" => array(
+        'm'=>'RevertEditedPlaylistMethod',
+        'p'=>array('sessionId'/*string*/, 'playlistId'/*string*/),
+        'r'=>array(),
+        'e'=>array(
+            '801'=>'invalid argument format',
+            '802'=>'argument is not a playlist ID',
+            '803'=>'playlist not found',
+            '804'=>'could not revert playlist',
+            '820'=>'missing session ID argument',
+        )
+    ),
+    "SavePlaylistMethod" => array(
+        'm'=>'SavePlaylistMethod',
+        'p'=>array('sessionId'/*string*/, 'playlistId'/*string*/),
+        'r'=>array(),
+        'e'=>array(
+            '701'=>'invalid argument format',
+            '702'=>'argument is not a playlist ID',
+            '703'=>'playlist not found',
+            '705'=>'could not save playlist',
+            '720'=>'missing session ID argument',
+        )
+    ),
+    "UpdateFadeInFadeOutMethod" => array(
+        'm'=>'UpdateFadeInFadeOutMethod',
+        'p'=>array('sessionId'/*string*/, 'playlistId'/*string*/, 'playlistElementId'/*string*/, 'fadeIn'/*int*/, 'fadeOut'/*int*/),
+        'r'=>array(),
+        'e'=>array(
+            '1601'=>'invalid argument format',
+            '1602'=>'missing playlist ID argument',
+            '1603'=>'missing playlist element ID argument',
+            '1604'=>'missing fade in argument',
+            '1605'=>'missing fade out argument',
+            '1606'=>'playlist does not exist',
+            '1607'=>'playlist has not been opened for editing',
+            '1608'=>'error executing setFadeInfo() method',
+            '1620'=>'missing session ID argument',
+        )
+    ),
+    "UploadPlaylistMethod" => array(
+        'm'=>'UploadPlaylistMethod',
+        'p'=>array('sessionId'/*string*/, 'playlistId'/*string*/, 'playtime'/*datetime*/),
+        'r'=>array('scheduleEntryId'/*string*/),
+        'e'=>array(
+            '1401'=>'invalid argument format',
+            '1402'=>'missing playlist ID argument',
+            '1403'=>'missing playtime argument',
+            '1404'=>'playlist not found',
+            '1405'=>'timeframe not available',
+            '1406'=>'could not schedule playlist',
+            '1420'=>'missing session ID argument',
+        )
+    ),
+    "ValidatePlaylistMethod" => array(
+        'm'=>'ValidatePlaylistMethod',
+        'p'=>array('sessionId'/*string*/, 'playlistId'/*string*/),
+        'r'=>array('valid'/*bool*/),
+        'e'=>array(
+            '501'=>'invalid argument format',
+            '502'=>'missing playlist ID argument',
+            '503'=>'playlist does not exist',
+            '504'=>'playlist has not been opened for editing',
+            '520'=>'missing session ID argument',
+        )
+    ),
+    "LoginGB" => array(
+        'm'=>'locstor.login',
+        'p'=>array('login'/*string*/, 'pass'/*string*/),
+        'r'=>array('sessid'/*string*/),
+        'e'=>array(
+            '2001'=>'invalid argument format',
+            '2002'=>'missing login argument',
+            '2003'=>'missing password argument',
+            '2004'=>'the authentication server reported an error',
+        )
+    ),
+    "LogoutGB" => array(
+        'm'=>'locstor.logout',
+        'p'=>array('sessid'/*string*/),
+        'r'=>array('status'/*boolean*/),
+        'e'=>array(
+            '2001'=>'invalid argument format',
+            '2002'=>'missing login argument',
+            '2003'=>'missing password argument',
+            '2004'=>'the authentication server reported an error',
+        )
+    ),
+);
+
+/* ======================================================== class definitions */
+
+class SchedulerPhpClient{
+    /**
+     *  Databases object reference
+     */
+    var $dbc = NULL;
+    /**
+     *  Array with methods description
+     */
+    var $mdefs = array();
+    /**
+     *  Confiduration array from ../conf.php
+     */
+    var $config = array();
+    /**
+     *  XMLRPC client object reference
+     */
+    var $client = NULL;
+    /**
+     *  Verbosity flag
+     */
+    var $verbose = FALSE;
+    /**
+     *  XMLRPC debug flag
+     */
+    var $debug = 0;
+    /**
+     *  Constructor - pelase DON'T CALL IT, use factory method instead
+     *
+     *  @param dbc object, database object reference
+     *  @param mdefs array, hash array with methods description
+     *  @param config array, hash array with configuration
+     *  @param debug int, XMLRPC debug flag
+     *  @param verbose boolean, verbosity flag
+     *  @return this
+     */
+    function SchedulerPhpClient(
+        &$dbc, $mdefs, $config, $debug=0, $verbose=FALSE)
+    {
+        $this->dbc = $dbc;
+        $this->mdefs = $mdefs;
+        $this->config = $config;
+        $this->debug = $debug;
+        $this->verbose = $verbose;
+        $confPrefix = "scheduler";
+        // $confPrefix = "storage";
+        $serverPath =
+          "http://{$config["{$confPrefix}UrlHost"]}:{$config["{$confPrefix}UrlPort"]}".
+          "{$config["{$confPrefix}UrlPath"]}/{$config["{$confPrefix}XMLRPC"]}";
+        #$serverPath = "http://localhost:80/livesupportStorageServerCVS/xmlrpc/xrLocStor.php";
+        if($this->verbose) echo "serverPath: $serverPath\n";
+        $url = parse_url($serverPath);
+        $this->client = new XML_RPC_Client($url['path'], $url['host']);
+    }
+
+    /**
+     *  Factory, create object instance
+     *
+     *  In fact it doesn't create instance of SchedulerPhpClient, but
+     *  dynamically extend this class with set of methods based on $mdefs array
+     *  (using eval function) and instantiate resulting class
+     *  SchedulerPhpClientCore instead.
+     *  Each new method in this subclass accepts parameters according to $mdefs
+     *  array, call wrapper callMethod(methodname, parameters) and return its
+     *  result.
+     *
+     *  @param dbc object, database object reference
+     *  @param mdefs array, hash array with methods description
+     *  @param config array, hash array with configuration
+     *  @param debug int, XMLRPC debug flag
+     *  @param verbose boolean, verbosity flag
+     *  @return object, created object instance
+     */
+    function &factory(&$dbc, $mdefs, $config, $debug=0, $verbose=FALSE){
+        $f = '';
+        foreach($mdefs as $fn=>$farr){
+            $f .=
+                '    function '.$fn.'(){'."\n".
+                '        $pars = func_get_args();'."\n".
+                '        $r = $this->callMethod("'.$fn.'", $pars);'."\n".
+                '        return $r;'."\n".
+                '    }'."\n";
+        }
+        $e =
+            "class SchedulerPhpClientCore extends SchedulerPhpClient{\n".
+            "$f\n".
+            "}\n";
+#        echo $e;
+        if(FALSE === eval($e)) return $dbc->raiseError("Eval failed");
+        $spc =& new SchedulerPhpClientCore(
+            $dbc, $mdefs, $config, $debug, $verbose);
+        return $spc;
+    }
+
+    /**
+     *  XMLRPC methods wrapper
+     *  Encode XMLRPC request message, send it, receive and decode response.
+     *
+     *  @param method string, method name
+     *  @param gettedPars array, returned by func_get_args() in called method
+     *  @return array, PHP hash with response
+     */
+    function callMethod($method, $gettedPars)
+    {
+        $parr = array();
+        foreach($this->mdefs[$method]['p'] as $i=>$p){
+            $parr[$p] = $gettedPars[$i];
+        }
+        $fullmethod = $this->mdefs[$method]['m'];
+        $msg = new XML_RPC_Message($fullmethod, array(XML_RPC_encode($parr)));
+        if($this->verbose){
+            echo "parr:\n";
+            var_dump($parr);
+            echo "message:\n";
+            echo $msg->serialize()."\n";
+        }
+        $this->client->setDebug($this->debug);
+        $res = $this->client->send($msg);
+        if($res->faultCode() > 0) {
+            return $this->dbc->raiseError(
+                "SchedulerPhpClient::$method:".$res->faultString()." ".
+                $res->faultCode()."\n", $res->faultCode()
+            );
+        }
+        if($verbose){
+            echo "result:\n";
+            echo $res->serialize();
+        }
+        $resp = XML_RPC_decode($res->value());
+        return $resp;
+    }
+
+}
+
+/* ======================================================== class definitions */
+
+/**
+ *  Example of use:
+ *
+ */
+
+/*
+// db object handling:
+$dbc = DB::connect($config['dsn'], TRUE);
+$dbc->setFetchMode(DB_FETCHMODE_ASSOC);
+$dbc->setErrorHandling(PEAR_ERROR_RETURN);
+
+// scheduler client instantiation:
+$spc =& SchedulerPhpClient::factory($dbc, $mdefs, $config);
+
+// call of chosen function by name according to key values in $mdefs array:
+// (for testing on storageServer XMLRPC I've changes confPrefix in
+//  SchedulerPhpClient constructor from 'scheduler' to 'storage' value)
+$r = $spc->LoginGB('root', 'q'); var_dump($r);
+#$r = $spc->LogoutGB(''); var_dump($r);
+*/
+
+?>
\ No newline at end of file