diff --git a/campcaster/src/modules/htmlUI/var/html/ui_browser.php b/campcaster/src/modules/htmlUI/var/html/ui_browser.php
index 876fe6c42..9097aeda7 100644
--- a/campcaster/src/modules/htmlUI/var/html/ui_browser.php
+++ b/campcaster/src/modules/htmlUI/var/html/ui_browser.php
@@ -410,6 +410,12 @@ if ($uiBrowser->userid) {
         case "SCHEDULER.export":
 	        $Smarty->assign('act', $action);
 	        break;
+	        
+	    case "twitter.settings":
+	        $Smarty->assign('dynform', $uiBrowser->TWITTER->getSettingsForm());
+	        $Smarty->assign('twitter', array('samplefeed' => $uiBrowser->TWITTER->getFeed()));
+	        $Smarty->assign('act', $action);
+	        break;
     }
 
     if ($action != 'SCHEDULER') {
diff --git a/campcaster/src/modules/htmlUI/var/html/ui_handler.php b/campcaster/src/modules/htmlUI/var/html/ui_handler.php
index 5c8e0af62..346509d75 100644
--- a/campcaster/src/modules/htmlUI/var/html/ui_handler.php
+++ b/campcaster/src/modules/htmlUI/var/html/ui_handler.php
@@ -436,6 +436,11 @@ switch ($_REQUEST['act']) {
 	    $_SESSION = array();
 	    die();
 	    break;
+	    
+	case 'twitter.saveSettings':
+        $uiHandler->TWITTER->saveSettings();
+        $uiHandler->redirUrl = UI_BROWSER.'?act=twitter.settings';
+	    break;
 
     case NULL:
 	    if ($uiHandler->userid) {
diff --git a/campcaster/src/modules/htmlUI/var/html/ui_twitter-cron.php b/campcaster/src/modules/htmlUI/var/html/ui_twitter-cron.php
new file mode 100644
index 000000000..48bc67cc6
--- /dev/null
+++ b/campcaster/src/modules/htmlUI/var/html/ui_twitter-cron.php
@@ -0,0 +1,22 @@
+<?php
+require_once(dirname(__FILE__).'/../ui_handler_init.php');
+require_once("../Input.php");
+
+if (get_magic_quotes_gpc()) {
+    $_REQUEST = Input::CleanMagicQuotes($_REQUEST);
+}
+
+if ($feed = $uiHandler->TWITTER->getFeed()) {
+    if ($uiHandler->TWITTER->needsUpdate()) {
+        print "Prepare for update...\n";
+        if ($res = $uiHandler->TWITTER->sendFeed($feed)) {
+            print "Feed id {$res->id}\n $feed";   
+        } else {
+            print "Update failed, check auth data.";   
+        }
+    } else {
+        print "Update interval not reached.";   
+    }
+} else {
+    print "No playlist found.";   
+}
\ No newline at end of file
diff --git a/campcaster/src/modules/htmlUI/var/lib/twitter.class.php b/campcaster/src/modules/htmlUI/var/lib/twitter.class.php
new file mode 100644
index 000000000..0098bfba5
--- /dev/null
+++ b/campcaster/src/modules/htmlUI/var/lib/twitter.class.php
@@ -0,0 +1,287 @@
+<?php
+///////////////////////////////////////////
+//
+// twitterPHP
+// version 0.1
+// By David Billingham
+// david [at] slawcup [dot] com
+// http://twitter.slawcup.com/twitter.class.phps
+//
+//
+// Example 1:
+//
+// $t= new twitter();
+// $res = $t->publicTimeline();
+// if($res===false){
+//   echo "ERROR<hr/>";
+//     echo "<pre>";
+//   print_r($t->responseInfo);
+//     echo "</pre>";
+// }else{
+//   echo "SUCCESS<hr/>";
+//     echo "<pre>";
+//   print_r($res);
+//     echo "</pre>";
+// }
+//
+//
+// Example 2:
+//
+// $t= new twitter();
+// $t->username='username';
+// $t->password='password';
+// $res = $t->update('i am testing twitter.class.php');
+// if($res===false){
+//   echo "ERROR<hr/>";
+//     echo "<pre>";
+//   print_r($t->responseInfo);
+//     echo "</pre>";
+// }else{
+//   echo "SUCCESS<hr/>Status Posted";
+// }
+//
+//
+//////////////////////////////////////////
+
+class twitter{
+    var $username='';
+    var $password='';
+    var $user_agent='';
+    
+    ///////////////
+    //
+    // I don't know if these headers have become standards yet
+    // but I would suggest using them.
+    // more discussion here.
+    // http://tinyurl.com/3xtx66
+    //
+    ///////////////
+    var $headers=array('X-Twitter-Client: ',
+                                            'X-Twitter-Client-Version: ',
+                                            'X-Twitter-Client-URL: ');
+    
+    var $responseInfo=array();
+                                            
+    
+    function twitter(){}
+    
+    
+    
+    
+    
+    /////////////////////////////////////////
+    //
+    // Twitter API calls
+    //
+    // $this->update($status)
+    // $this->publicTimeline($sinceid=false)
+    // $this->friendsTimeline($id=false,$since=false)
+    // $this->userTimeline($id=false,$count=20,$since=false)
+    // $this->showStatus($id)
+    // $this->friends($id=false)
+    // $this->followers()
+    // $this->featured()
+    // $this->showUser($id)
+    // $this->directMessages($since=false)
+    // $this->sendDirectMessage($user,$text)
+    //
+    // If SimpleXMLElement exists the results will be returned as a SimpleXMLElement
+    // otherwise the raw XML will be returned for a successful request.  If the request
+    // fails a FALSE will be returned.
+    //
+    //
+    /////////////////////////////////////////
+    
+    
+    // Updates the authenticating user's status.  
+    // Requires the status parameter specified below.
+    //
+    // status. (string) Required.  The text of your status update.  Must not be
+    //                             more than 160 characters and should not be
+    //                             more than 140 characters to ensure optimal display.
+    //
+    function update($status){
+        $request = 'http://twitter.com/statuses/update.xml';
+        $postargs = 'status='.urlencode($status);
+        return $this->process($request,$postargs);
+    }
+    
+    // Returns the 20 most recent statuses from non-protected users who have
+    // set a custom user icon.  Does not require authentication.
+    //
+    // sinceid. (int) Optional.  Returns only public statuses with an ID greater
+    //                           than (that is, more recent than) the specified ID.
+    //
+    function publicTimeline($sinceid=false){
+        $qs='';
+        if($sinceid!==false)
+            $qs='?since_id='.intval($sinceid);
+        $request = 'http://twitter.com/statuses/public_timeline.xml'.$qs;
+        return $this->process($request);
+    }
+    
+    // Returns the 20 most recent statuses posted in the last 24 hours from the
+    // authenticating user and that user's friends.  It's also possible to request
+    // another user's friends_timeline via the id parameter below.
+    //
+    // id. (string OR int) Optional.  Specifies the ID or screen name of the user for whom
+    //                                to return the friends_timeline. (set to false if you
+    //                                want to use authenticated user).
+    // since. (HTTP-formatted date) Optional.  Narrows the returned results to just those
+    //                                         statuses created after the specified date.  
+    //
+    function friendsTimeline($id=false,$since=false){
+        $qs='';
+        if($since!==false)
+            $qs='?since='.urlencode($since);
+            
+        if($id===false)
+            $request = 'http://twitter.com/statuses/friends_timeline.xml'.$qs;
+        else
+            $request = 'http://twitter.com/statuses/friends_timeline/'.urlencode($id).'.xml'.$qs;
+        
+        return $this->process($request);
+    }
+    
+    // Returns the 20 most recent statuses posted in the last 24 hours from the
+    // authenticating user.  It's also possible to request another user's timeline
+    // via the id parameter below.
+    //
+    // id. (string OR int) Optional.  Specifies the ID or screen name of the user for whom
+    //                                to return the user_timeline.
+    // count. (int) Optional.  Specifies the number of statuses to retrieve.  May not be
+    //                         greater than 20 for performance purposes.
+    // since. (HTTP-formatted date) Optional.  Narrows the returned results to just those
+    //                                         statuses created after the specified date.
+    //
+    function userTimeline($id=false,$count=20,$since=false){
+        $qs='?count='.intval($count);
+        if($since!==false)
+            $qs .= '&since='.urlencode($since);
+            
+        if($id===false)
+            $request = 'http://twitter.com/statuses/user_timeline.xml'.$qs;
+        else
+            $request = 'http://twitter.com/statuses/user_timeline/'.urlencode($id).'.xml'.$qs;
+        
+        return $this->process($request);
+    }
+    
+    // Returns a single status, specified by the id parameter below.  The status's author
+    // will be returned inline.
+    //
+    // id. (int) Required.  Returns status of the specified ID.
+    //
+    function showStatus($id){
+        $request = 'http://twitter.com/statuses/show/'.intval($id).'.xml';
+        return $this->process($request);
+    }
+    // Returns the authenticating user's friends, each with current status inline.  It's
+    // also possible to request another user's friends list via the id parameter below.
+    //
+    // id. (string OR int) Optional.  The ID or screen name of the user for whom to request
+    //                                a list of friends.
+    //
+    function friends($id=false){
+        if($id===false)
+            $request = 'http://twitter.com/statuses/friends.xml';
+        else
+            $request = 'http://twitter.com/statuses/friends/'.urlencode($id).'.xml';
+        return $this->process($request);
+    }
+    
+    // Returns the authenticating user's followers, each with current status inline.
+    //
+    function followers(){
+        $request = 'http://twitter.com/statuses/followers.xml';
+        return $this->process($request);
+    }
+    
+    // Returns a list of the users currently featured on the site with their current statuses inline.
+    function featured(){
+        $request = 'http://twitter.com/statuses/featured.xml';
+        return $this->process($request);
+    }
+    
+    // Returns extended information of a given user, specified by ID or screen name as per the required
+    // id parameter below.  This information includes design settings, so third party developers can theme
+    // their widgets according to a given user's preferences.
+    //
+    // id. (string OR int) Required.  The ID or screen name of a user.
+    //
+    function showUser($id){
+        $request = 'http://twitter.com/users/show/'.urlencode($id).'.xml';
+        return $this->process($request);
+    }
+    
+    // Returns a list of the direct messages sent to the authenticating user.
+    //
+    // since. (HTTP-formatted date) Optional.  Narrows the resulting list of direct messages to just those
+    //                                         sent after the specified date.  
+    //
+    function directMessages($since=false){
+        $qs='';
+        if($since!==false)
+            $qs='?since='.urlencode($since);
+        $request = 'http://twitter.com/direct_messages.xml'.$qs;
+        return $this->process($request);
+    }
+    
+    // Sends a new direct message to the specified user from the authenticating user.  Requires both the user
+    // and text parameters below.
+    //
+    // user. (string OR int) Required.  The ID or screen name of the recipient user.
+    // text. (string) Required.  The text of your direct message.  Be sure to URL encode as necessary, and keep
+    //                           it under 140 characters.  
+    //
+    function sendDirectMessage($user,$text){
+        $request = 'http://twitter.com/direct_messages/new.xml';
+        $postargs = 'user='.urlencode($user).'&text='.urlencode($text);
+        return $this->process($request,$postargs);
+    }
+    
+    
+    
+    
+    
+    // internal function where all the juicy curl fun takes place
+    // this should not be called by anything external unless you are
+    // doing something else completely then knock youself out.
+    function process($url,$postargs=false){
+        
+        $ch = curl_init($url);
+
+        if($postargs !== false){
+            curl_setopt ($ch, CURLOPT_POST, true);
+            curl_setopt ($ch, CURLOPT_POSTFIELDS, $postargs);
+        }
+        
+        if($this->username !== false && $this->password !== false)
+            curl_setopt($ch, CURLOPT_USERPWD, $this->username.':'.$this->password);
+        
+        curl_setopt($ch, CURLOPT_VERBOSE, 1);
+        curl_setopt($ch, CURLOPT_NOBODY, 0);
+        curl_setopt($ch, CURLOPT_HEADER, 0);
+        curl_setopt($ch, CURLOPT_USERAGENT, $this->user_agent);
+        curl_setopt($ch, CURLOPT_FOLLOWLOCATION,1);
+        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+        curl_setopt($ch, CURLOPT_HTTPHEADER, $this->headers);
+
+        $response = curl_exec($ch);
+        
+        $this->responseInfo=curl_getinfo($ch);
+        curl_close($ch);
+        
+        
+        if(intval($this->responseInfo['http_code'])==200){
+            if(class_exists('SimpleXMLElement')){
+                $xml = new SimpleXMLElement($response);
+                return $xml;
+            }else{
+                return $response;    
+            }
+        }else{
+            return false;
+        }
+    }
+}
diff --git a/campcaster/src/modules/htmlUI/var/templates/masterpanel.tpl b/campcaster/src/modules/htmlUI/var/templates/masterpanel.tpl
index 44a29a4ef..47d7f8fa0 100644
--- a/campcaster/src/modules/htmlUI/var/templates/masterpanel.tpl
+++ b/campcaster/src/modules/htmlUI/var/templates/masterpanel.tpl
@@ -73,6 +73,10 @@
             {include file="scheduler/import.tpl"}
         {/if}
         
+        {if $act === 'twitter.settings'}
+            {include file="twitter/settings.tpl"}
+        {/if}
+        
         <div class="content">
             {if $simpleSearchForm}
                 {include file="library/simpleSearchForm.tpl"}
diff --git a/campcaster/src/modules/htmlUI/var/templates/menu.tpl b/campcaster/src/modules/htmlUI/var/templates/menu.tpl
index 493da973e..49dfabc1d 100644
--- a/campcaster/src/modules/htmlUI/var/templates/menu.tpl
+++ b/campcaster/src/modules/htmlUI/var/templates/menu.tpl
@@ -70,6 +70,7 @@ if (window.attachEvent) window.attachEvent("onload", sfHover);
             <ul>
             {* if $SUBJECTS->isMemberOf('StationPrefs') *}
                 <li><a href="{$UI_BROWSER}?act=changeStationPrefs">##Station Settings##</a></li>
+                <li><a href="{$UI_BROWSER}?act=twitter.settings">##Twitter Settings##</a></li>
             {* /if *}
             {*if $SUBJECTS->isMemberOf('Subjects')*}
                 <li><a href="{$UI_BROWSER}?act=SUBJECTS">##User/Groups##</a></li>
diff --git a/campcaster/src/modules/htmlUI/var/templates/statusbar.tpl b/campcaster/src/modules/htmlUI/var/templates/statusbar.tpl
index 09e879d3c..8f5ab0958 100644
--- a/campcaster/src/modules/htmlUI/var/templates/statusbar.tpl
+++ b/campcaster/src/modules/htmlUI/var/templates/statusbar.tpl
@@ -1,5 +1,5 @@
 {assign var='_nowplaying'  value=$SCHEDULER->getNowNextClip()}
-{assign var='_nextplaying' value=$SCHEDULER->getNowNextClip(1)}
+{assign var='_nextplaying' value=$SCHEDULER->getNowNextClip()}
 
 <div id="masterpalette"> 
 <table border="0" class="masterpalette">
@@ -26,15 +26,31 @@
                     <div class="scala">
                         <div class="scala_in" id="now_scala" style="width: {$_nowplaying.percentage}%;">&nbsp;</div>
                     </div>
+                    
                     <div class="time">
-                        <div class="left">Elapsed:    <strong id="now_elapsed"></strong></div>
-                        <div class="right">Remaining: <strong id="now_remaining"></strong></div>
+                        <span class="left">
+                          <span class="left_title">##Elapsed:##</span>
+                          <strong id="now_elapsed"></strong>
+                        </span>
+                        
+                        <span class="right">
+                          ##Remaining:##
+                          <strong id="now_remaining"></strong>
+                        </span>
+                    </div>
+                    
+                    <div class="playlist">
+                        <span class="left">
+                          <span class="left_title">##Playlist:##</span>
+                        <span>
+
+                        <strong class="playlist_title" id="now_pl_title"></strong> 
                     </div>
                 {/if}
-                <div  style="height:5px"> </div>
+                <div  style="height:3px"> </div>
                 <div id="next_clip">
                 {if $_nextplaying}
-                    <p class="next">##Playing Next##: <span id="next_title"></span>&nbsp; <span id="next_duration"></span></p>
+                    <span class="next">##Next Clip##:</span> <strong id="next_title"></strong>&nbsp; <strong id="next_duration"></strong></div>
                 {/if}
                 </div>
             </div>  
diff --git a/campcaster/src/modules/htmlUI/var/templates/twitter/settings.tpl b/campcaster/src/modules/htmlUI/var/templates/twitter/settings.tpl
new file mode 100644
index 000000000..e318b79a1
--- /dev/null
+++ b/campcaster/src/modules/htmlUI/var/templates/twitter/settings.tpl
@@ -0,0 +1,10 @@
+<div class="content">
+<div class="container_elements" style="width: 607px;">
+<h1>##Twitter settings##</h1>
+
+Current tweet layout (sample length: {$twitter.samplefeed|strlen}): <br>
+<div style='border: 1px solid #aaa; padding: 5px 20px; background: #f6f9ff; font-size: 1.5em; margin: 20px 0px;'>{$twitter.samplefeed}</div>
+
+{include file="sub/dynForm_plain.tpl"}
+</div>
+</div>
\ No newline at end of file
diff --git a/campcaster/src/modules/htmlUI/var/ui_base.inc.php b/campcaster/src/modules/htmlUI/var/ui_base.inc.php
index 5e917e211..b39e382c6 100644
--- a/campcaster/src/modules/htmlUI/var/ui_base.inc.php
+++ b/campcaster/src/modules/htmlUI/var/ui_base.inc.php
@@ -238,7 +238,9 @@ class uiBase
         'EXCHANGE'     => array('class' => 'uiexchange', 'file' => 'ui_exchange.class.php'),
         'TRANSFERS'    => array('class' => 'uitransfers', 'file' => 'ui_transfers.class.php'),
         'CALENDAR'     => array('class' => 'uicalendar', 'file' => 'ui_calendar.class.php'),
-        'JSCOM'        => array('class' => 'jscom', 'file' => 'ui_jscom.php')   
+        array('class' => 'jscom', 'file' => 'ui_jscom.php'),
+        'TWITTER'      => array('class' => 'uitwitter', 'file' => 'ui_twitter.class.php'),
+        array('class' => 'twitter', 'file' => 'lib/twitter.class.php') 
     );
 
 
diff --git a/campcaster/src/modules/htmlUI/var/ui_scheduler.class.php b/campcaster/src/modules/htmlUI/var/ui_scheduler.class.php
index 908ce688e..63096e471 100644
--- a/campcaster/src/modules/htmlUI/var/ui_scheduler.class.php
+++ b/campcaster/src/modules/htmlUI/var/ui_scheduler.class.php
@@ -668,7 +668,7 @@ class uiScheduler extends uiCalendar {
      * @param string $i
      * @return int
      */
-    private static function datetimeToTimestamp($i)
+    public static function datetimeToTimestamp($i)
     {
         $i = str_replace('T', ' ', $i);
         $formatted = $i[0].$i[1].$i[2].$i[3].'-'.$i[4].$i[5].'-'.$i[6].$i[7].strrchr($i, ' ');
diff --git a/campcaster/src/modules/htmlUI/var/ui_twitter.class.php b/campcaster/src/modules/htmlUI/var/ui_twitter.class.php
new file mode 100644
index 000000000..1c9b03b35
--- /dev/null
+++ b/campcaster/src/modules/htmlUI/var/ui_twitter.class.php
@@ -0,0 +1,302 @@
+<?php
+class uiTwitter {
+    private $Base;
+
+    public function __construct(&$uiBase)
+    {
+        $this->Base =& $uiBase;
+    }
+    
+    private static function getSettingFormMask()
+    {
+        $formmask = array(
+            array(
+                'element'   => 'act',
+                'type'      => 'hidden',
+                'constant'  => 'twitter.saveSettings'
+            ),
+            array(
+                'element'   => 'twitter-is_active',
+                'type'      => 'checkbox',
+                'label'     => 'Activate posts',
+                'isPref'    => true
+            ),
+            array(
+                'element'   => 'twitter-login',
+                'type'      => 'text',
+                'label'     => 'Login / user'
+                ,
+                'isPref'    => true
+            ),
+            array(
+                'element'   => 'twitter-password',
+                'type'      => 'text',
+                'label'     => 'Login / password'
+                ,
+                'isPref'    => true
+            ),
+            array(
+                'element'   => 'twitter-prefix',
+                'type'      => 'text',
+                'label'     => 'Prefix',
+                'isPref'    => true
+            ),
+            array(
+                'element'   => 'twitter-has_tracktitle',
+                'type'      => 'checkbox',
+                'label'     => 'Track title',
+                'isPref'    => true
+            ),
+            array(
+                'element'   => 'twitter-has_trackartist',
+                'type'      => 'checkbox',
+                'label'     => 'Track artist',
+                'isPref'    => true
+            ),
+            array(
+                'element'   => 'twitter-has_playlisttitle',
+                'type'      => 'checkbox',
+                'label'     => 'Playlist title',
+                'isPref'    => true
+            ),
+            array(
+                'element'   => 'twitter-has_stationname',
+                'type'      => 'checkbox',
+                'label'     => 'Station name',
+                'isPref'    => true
+            ),
+            array(
+                'element'   => 'twitter-suffix',
+                'type'      => 'text',
+                'label'     => 'Suffix',
+                'isPref'    => true
+            ),
+            array(
+                'element'   => 'twitter-url',
+                'type'      => 'text',
+                'label'     => 'URL (optional)',
+                'isPref'    => true
+            ),
+            array(
+                'element'   => 'twitter-offset',
+                'type'      => 'select',
+                'label'     => 'Tweet what\'s...',
+                'options'   => array(
+                    "0"  => "playing now",
+                    "3000"  => "in five minutes",
+                    "6000" => "in ten minutes",
+                    "9000" => "in 15 minutes",
+                    "1800" => "in 30 minutes",
+                    "3600" => "in one hour",
+                ),
+                'isPref'    => true
+            ),
+            array(
+                'element'   => 'twitter-interval',
+                'type'      => 'select',
+                'label'     => 'Tweet every...',
+                'options'   => array(
+                    "60"    => "minute",
+                    "180"    => "three minutes",
+                    "300"    => "five minutes",
+                    "600"   => "ten minutes",
+                    "900"   => "15 minutes",
+                    "1800"   => "30 minutes",
+                    "3600"   => "hour",
+                    "21600"  => "6 hours",
+                    "43200" => "24 hours",
+                ),
+                'isPref'    => true
+            ),
+            array(
+                'element'   => 'Submit',
+                'type'      => 'submit',
+                'label'     => 'Submit',
+            )
+        );
+        return $formmask; 
+    }
+    
+    private function getSettings()
+    {
+        static $settings;
+        
+        if (is_array($settings)) {
+            return $settings;   
+        }
+        
+        $settings = array();
+        $mask = uiTwitter::getSettingFormMask();
+        
+        foreach($mask as $key => $val) {
+            if (isset($val['isPref']) && $val['isPref']) {
+                $element = isset($val['element']) ? $val['element'] : null;
+                $p = $this->Base->gb->loadGroupPref($this->Base->sessid, 'StationPrefs', $element);
+                if (is_string($p)) {
+                    $settings[$element] = $p;
+                }
+            }
+        }
+          
+        return $settings;
+    }
+    
+    public function getSettingsForm()
+    {
+        $mask = uiTwitter::getSettingFormMask();
+        $form = new HTML_QuickForm('twitter', UI_STANDARD_FORM_METHOD, UI_HANDLER);#
+        $settings = $this->getSettings();
+        
+        foreach($mask as $key => $val) {
+            if (isset($val['isPref']) && $val['isPref']) {
+                $element = isset($val['element']) ? $val['element'] : null;
+                $p = $settings[$element];
+                if (is_string($p)) {
+                    $mask[$key]['default'] = $p;
+                }
+            }
+        }
+        uiBase::parseArrayToForm($form, $mask);
+        $renderer = new HTML_QuickForm_Renderer_Array(true, true);
+        $form->accept($renderer);
+        return $renderer->toArray();
+    }
+    
+    public function saveSettings()
+    {
+        if ($this->Base->_validateForm($_REQUEST, uiTwitter::getSettingFormMask()) !== TRUE) {
+            $this->Base->_retMsg('An error has occured on validating the form.');
+            return FALSE;
+        }
+        
+        $mask = uiTwitter::getSettingFormMask();
+        $form = new HTML_QuickForm('twitter', UI_STANDARD_FORM_METHOD, UI_HANDLER);
+        uiBase::parseArrayToForm($form, $mask);
+        $formdata = $form->exportValues();
+        
+        foreach ($mask as $key => $val) {
+            if (isset($val['isPref']) && $val['isPref']) {
+                if (!empty($formdata[$val['element']])) {
+                	$result = $this->Base->gb->saveGroupPref($this->Base->sessid, 'StationPrefs', $val['element'], $formdata[$val['element']]);
+                    if (PEAR::isError($result))
+                        $this->_retMsg('Error while saving twitter settings.');
+                } else {
+                    $this->Base->gb->delGroupPref($this->Base->sessid,  'StationPrefs', $val['element']);
+                }
+            }
+        }
+        
+        $this->Base->_retMsg('Twitter settings saved.');
+    }
+    
+    public function getFeed($p_withSample = false)
+    {
+        $settings = $this->getSettings();
+        $whatsplaying = $this->getWhatsplaying($settings['twitter-offset']);
+        
+        if (!$p_withSample && !$whatsplaying) {
+            return;   
+        }
+        
+        $whatsplaying = @array_merge(
+            array(
+                "tracktitle"     => "Gimme Shelter",
+                "trackartist"    => "The Rolling Stones",
+                "playlisttitle"  => "The Blues Hour"
+            ),
+            $whatsplaying
+        );
+
+        ////////////////////////////////////////////////////////////////////////
+        // create twitter tweet sample
+        // TWEET PREFIX
+        if (!empty($settings['twitter-prefix'])) {
+            $tweetprefix = $settings['twitter-prefix'] . " ";
+        } else {
+            $tweetprefix = "";
+        }
+        // TWEET SUFFIX
+        if (!empty($settings['twitter-suffix'])) {
+            $tweetsuffix = " " . $settings['twitter-suffix'];
+        } else {
+            $tweetsuffix = "";
+        }
+        if (!empty($settings['twitter-url'])) {
+            $tweetsuffix = $tweetsuffix . " " . self::GetTinyUrl($settings['twitter-url']);
+        }
+        // TWEET BODY
+        $tweetbody = array();
+        if ($settings['twitter-has_tracktitle']) { $tweetbody[] = $whatsplaying['tracktitle']; }
+        if ($settings['twitter-has_trackartist']) { $tweetbody[] = $whatsplaying['trackartist']; }
+        if ($settings['twitter-has_playlisttitle']) { $tweetbody[] = $whatsplaying['playlisttitle']; }
+        if ($settings['twitter-has_stationname']) { $tweetbody[] = $this->Base->STATIONPREFS['stationName']; }
+        
+        $tweetbody = implode (". ",$tweetbody);
+        
+        // chop body to fit if necessary
+        if ((strlen($tweetprefix) + strlen($tweetbody) + strlen($tweetsuffix)) > 140) {
+            $tweetbody = substr($tweetbody, 0, (140 - (strlen($tweetprefix) + strlen($tweetsuffix) + 3))) . "...";
+        }
+        
+        $tweet = $tweetprefix . $tweetbody . $tweetsuffix;
+                
+        return $tweet;
+
+    }
+    
+    public function getTinyUrl($p_url)
+    {
+        $tiny = file_get_contents('http://tinyurl.com/api-create.php?url='.$p_url);
+        return $tiny;
+    }
+    
+    public function getWhatsplaying($p_offset)
+    {
+        $timestamp = time() + $p_offset;
+        $xmldatetime = strftime('%Y%m%dT%H:%M:%S', $timestamp);
+
+        $pl = $this->Base->SCHEDULER->displayScheduleMethod($xmldatetime, $xmldatetime);
+
+        if (!is_array($pl) || !count($pl)) {
+            return FALSE;
+        }
+
+        $pl = current($pl);
+        //  subtract difference to UTC
+        $offset = strftime('%H:%M:%S', $timestamp - uiScheduler::datetimeToTimestamp($pl['start']) - 3600 * strftime('%H', 0));
+
+        $clip = $this->Base->gb->displayPlaylistClipAtOffset($this->Base->sessid, $pl['playlistId'], $offset, $distance, $_SESSION['langid'], UI_DEFAULT_LANGID);
+
+        if (!$clip['gunid']) {
+            return FALSE;
+        }
+        
+        return array(
+            'tracktitle' => $this->Base->gb->getMetadataValue(BasicStor::IdFromGunid($clip['gunid']), UI_MDATA_KEY_TITLE, $this->Base->sessid),
+            'trackartist' => $this->Base->gb->getMetadataValue(BasicStor::IdFromGunid($clip['gunid']), UI_MDATA_KEY_CREATOR, $this->Base->sessid),
+            'playlisttitle' => $this->Base->gb->getMetadataValue(BasicStor::IdFromGunid($pl['playlistId']), UI_MDATA_KEY_TITLE, $this->Base->sessid),
+        );
+    }
+    
+    public function sendFeed($p_feed)
+    {
+        $settings = $this->getSettings();
+        
+        $twitter = new twitter();
+        $twitter->username = $settings['twitter-login'];
+        $twitter->password = $settings['twitter-password'];
+        
+        $this->Base->gb->saveGroupPref($this->Base->sessid, 'StationPrefs', 'twitter-lastupdate', time());
+        
+        return $twitter->update($p_feed);
+    }
+    
+    public function needsUpdate()
+    {
+        $settings = $this->getSettings();
+        if (time() -  $this->Base->gb->loadGroupPref($this->Base->sessid, 'StationPrefs', 'twitter-lastupdate') > $settings['twitter-interval']) {
+            return true;
+        }
+        return false;
+    }
+}
\ No newline at end of file