function do_insert_stream_file($mvStream, $path, $quality_msg)
{
    global $mvVideoArchivePaths;
    $dbw = wfGetDB(DB_WRITE);
    $dur = $mvStream->getDuration();
    // get file duration from nfo file :
    $dur = $mvStream->getDuration();
    if ($dur == 0) {
        $nfo_url = $path . '.nfo';
        if (url_exists($nfo_url)) {
            $nfo_txt = @file($nfo_url);
            if ($nfo_txt !== false) {
                if (isset($nfo_txt[0])) {
                    list($na, $len) = explode('n:', $nfo_txt[0]);
                    $len = trim($len);
                    // trim leading zero
                    if ($len[0] == '0') {
                        $len = substr($len, 1);
                    }
                    // trim sub frame times:
                    if (strpos($len, '.') !== false) {
                        $len = substr($len, 0, strpos($len, '.'));
                    }
                    $dur = npt2seconds($len);
                } else {
                    echo "empty nfo file: {$nfo_url} \n";
                    $dur = 0;
                }
            } else {
                echo "missing nfo file: {$nfo_url} \n";
                $dur = 0;
            }
        }
    }
    $sql = "INSERT INTO `mv_stream_files` (`stream_id`, `file_desc_msg`, `path`, `duration`)" . " VALUES ('{$mvStream->id}', '{$quality_msg}', '{$path}', {$dur} )";
    $dbw->query($sql);
}
 function get_adjust_disp($titleKey = 'new', $mvd_id = 'new')
 {
     global $mvgScriptPath;
     //
     $out = '';
     if ($mvd_id == 'new' || $mvd_id == 'seq') {
         global $mvDefaultClipLength;
         $start_time = isset($this->start_context) ? $this->start_context : seconds2npt(0);
         $end_time = isset($this->end_context) ? seconds2npt(npt2seconds($this->start_context) + $mvDefaultClipLength) : seconds2npt($mvDefaultClipLength);
     } else {
         $mvTitle = new MV_Title($titleKey);
         if (!$mvTitle->validRequestTitle()) {
             return wfMsg('mvMVDFormat');
         }
         $start_time = $mvTitle->getStartTime();
         $end_time = $mvTitle->getEndTime();
     }
     if ($start_time == "null") {
         $start_time = '0:00:00';
     }
     /*
      * @@todo move some of this to CSS
      */
     $mvd_id = htmlspecialchars($mvd_id);
     $mvgScriptPath = htmlspecialchars($mvgScriptPath);
     $out .= '<br /><div class="inOutSlider"></div><br />';
     $out .= '<span style="float:left;"><label class="mv_css_form" for="mv_start_hr_' . $mvd_id . '"><i>' . wfMsg('mv_start_desc') . ':</i></label> ' . '<input class="mv_adj_hr" size="8" maxlength="8" value="' . htmlspecialchars($start_time) . '" id="mv_start_hr_' . $mvd_id . '" name="mv_start_hr_' . $mvd_id . '">' . '</span>';
     $out .= '<span style="float:left;"><label class="mv_css_form" for="mv_end_hr_' . $mvd_id . '"><i>' . wfMsg('mv_end_desc') . ':</i></label> ' . '<input class="mv_adj_hr" size="8" maxlength="8" value="' . htmlspecialchars($end_time) . '" id="mv_end_hr_' . $mvd_id . '" name="mv_end_hr_' . $mvd_id . '">' . '</span>';
     // output page text (if not "new")
     // if($mvd_id!='new')
     //	$out.=$this->get_fd_mvd_request( $titleKey, $mvd_id);
     /*$out.='<table width="100%">'.
     		'<tr><td>'.wfMsg('mv_start_desc').'</td>'.
     		'<td><input name="mv_start_hr_'.$mvd_id.'" type="text" value=""></td>'.
     		'</tr><tr>'.
     		'<input type="text" value=""><br />
     		*/
     // clear any floats:
     $out .= '<div style="clear:both"></div>';
     // $out.='</form>';
     return $out;
 }
/**
 * enables the rewriting of links to the Stream and Sequence namespace to support inline embeding.
 * see page: sample in-wiki-embed syntax
 * @@todo should probably be integrated to respective Stream and Sequence class.
 * and maybe integrated with File / image handle
*/
function mvLinkEnd($skin, $title, $options, &$text, &$attribs, &$ret)
{
    global $mvDefaultAspectRatio, $mvDefaultVideoPlaybackRes, $mvEmbedKey;
    //only do link rewrites for $mvEmbedKey
    if (substr($title->getText(), 0, strlen($mvEmbedKey)) != $mvEmbedKey) {
        return true;
    }
    //parse text for extra parameters
    //@@todo integrate with image params / maybe file handle )
    $params = explode('|', $text);
    //setup defaults:
    $size = $mvDefaultVideoPlaybackRes;
    $start_ntp = $end_ntp = null;
    foreach ($params as $param) {
        if (substr($param, -2) == 'px') {
            //size param
            if (strpos($param, 'x') === false) {
                $k = intval(str_replace($param, 'px', ''));
                //@@todo should use the actual clips aspect ratio
                $size = intval($v) . 'x' . (int) ($mvDefaultAspectRatio * $v);
            } else {
                list($width, $height) = explode('x', str_replace('px', '', $param));
                $size = intval($width) . 'x' . intval($height);
            }
        } else {
            //only applicable to Stream:
            if ($title->getNamespace() == MV_NS_STREAM) {
                if (substr($param, 0, 6) == 'start=') {
                    $start_str = substr($param, 6);
                    $timeSec = npt2seconds($start_str);
                    if ((int) $timeSec > 0) {
                        $start_ntp = seconds2npt($timeSec);
                    }
                } elseif (substr($param, 0, 4) == 'end=') {
                    $end_str = substr($param, 6);
                    $timeSec = npt2seconds($start_str);
                    if ((int) $timeSec > 0) {
                        $end_ntp = seconds2npt($timeSec);
                    }
                } else {
                    //caption text / desc
                }
            }
        }
    }
    if (substr($title->getText(), 0, strlen($mvEmbedKey)) == $mvEmbedKey) {
        $resourceTitle = Title::newFromText(substr($title->getText(), strlen($mvEmbedKey) + 1));
        if ($resourceTitle->getNamespace() == MV_NS_STREAM) {
            $mvTitle = new MV_Title($resourceTitle);
            $ret = $mvTitle->getEmbedVideoHtml(array('size' => $size, 'showmeta' => true));
        }
        if ($resourceTitle->getNamespace() == MV_NS_SEQUENCE) {
            $seqPlayer = new MV_SequencePlayer($resourceTitle);
            $ret = $seqPlayer->getEmbedSeqHtml(array('size' => $size));
        }
        return false;
    }
    return true;
}
    function doScrapeInsert()
    {
        foreach ($this->streams as &$stream) {
            if (!isset($stream->date_start_time)) {
                $stream->date_start_time = 0;
            }
            if ($stream->date_start_time == 0) {
                print 'error stream ' . $stream->name . ' missing time info' . "\n";
                continue;
            }
            $hors = strpos($stream->name, 'house') !== false ? 'h' : 's';
            $date_req = date('Y-m-d', $stream->date_start_time);
            if (strpos($stream->name, date('m-d-y', $stream->date_start_time)) === false) {
                $dTitle = Title::newFromText('Archive:Stream_DateMissMatch');
                append_to_wiki_page($dTitle, 'DateMissMatch:[[Stream:' . $stream->stream_name . ']]:' . date('m-d-y', $stream->date_start_time) . "\n");
                // use date from stream name:
                // house_da_01-01-07_
                preg_match('/[0-9]+\\-[0-9]+\\-[0-9][0-9]/U', $stream->name, $matches);
                if (isset($matches[0])) {
                    list($month, $day, $year) = explode('-', $matches[0]);
                    $date_req = '20' . $year . '-' . $month . '-' . $day;
                } else {
                    die('could not find date in stream name');
                }
            }
            $cspan_url = $this->base_url . $this->base_query . '&date=' . $date_req . '&hors=' . $hors;
            echo $cspan_url . "\n";
            $rawpage = $this->doRequest($cspan_url);
            // get the title and href if present:
            $patern = '/overlib\\(\'(.*)\\((Length: ([^\\)]*)).*CAPTION,\'<font size=2>(.*)<((.*href="([^"]*))|.*)>/';
            preg_match_all($patern, $rawpage, $matches);
            $cspan_person_ary = array();
            // format matches:
            foreach ($matches[0] as $k => $v) {
                $href = '';
                $href_match = array();
                preg_match('/href="(.*)"/', $matches[5][$k], $href_match);
                if (count($href_match) != 0) {
                    $href = $href_match[1];
                }
                $porg = str_replace('<br />', ' ', $matches[4][$k]);
                $porg = preg_replace('/[D|R|I]+\\-\\[.*\\]/', '', $porg);
                $pparts = explode(',', $porg);
                if (isset($pparts[1]) && isset($pparts[0])) {
                    $pname = trim($pparts[1]) . '_' . trim($pparts[0]);
                    if (mv_is_valid_person($pname)) {
                        $cspan_person_ary[] = array('start_time' => strip_tags($matches[1][$k]), 'length' => $matches[3][$k], 'person_title' => str_replace('<br />', ' ', $matches[4][$k]), 'Spoken_by' => $pname, 'href' => $href);
                    }
                }
            }
            // group people in page matches
            // $g_cspan_matches=array();
            // $prev_person=null;
            // foreach($person_time_ary as $ptag){
            //	$g_cspan_matches[strtolower($ptag['Spoken_by'])][]=$ptag;
            // }
            // retrive db rows to find match:
            $dbr = wfGetDB(DB_SLAVE);
            // $mvd_res = MV_Index::getMVDInRange($stream->id, null, null, $mvd_type='ht_en',false,$smw_properties=array('Spoken_by'), '');
            /*while ($row = $dbr->fetchObject($mvd_res)) {
              $db_person_ary=$g_row_matches=array();
              //group peole in db matches:
              $cur_person = '';
              $curKey=0;
             	while ($row = $dbr->fetchObject($mvd_res)) {
             		if(!isset($row->Spoken_by))continue;
            			if($cur_person!=$row->Spoken_by){
            				$g_row_matches[]=get_object_vars($row);
            				$curKey=count($g_row_matches)-1;
            				$cur_person=$row->Spoken_by;
            			}else{
            				$g_row_matches[$curKey]['end_wiki_title']=$row->wiki_title;
            				$g_row_matches[$curKey]['end_time']+=($row->end_time-$row->start_time);
            			}
            			//print_r($g_row_matches);
            			//if($curKey>2){
            			//	die;
            			//}
             	} */
            // get people from metavid table (and conform to mvd_res)
            $sql = 'SELECT  (`people_time`.`time`-`streams`.`adj_start_time`) as `time`,
		    	   `person_lookup`.`name_clean`	 as `Spoken_by`,
				   `person_lookup`.`first` as `first`,
				   `person_lookup`.`last` as `last`
		    	   FROM  `metavid`.`people_attr_stream_time` as `people_time`
		    	   RIGHT JOIN `metavid`.`streams` as `streams` ON `streams`.`id`=`people_time`.`stream_fk`
		    	   LEFT JOIN `metavid`.`people` as `person_lookup` ON  `person_lookup`.`id` = `people_time`.`people_fk`
		    	   WHERE `streams`.`name`=\'' . $stream->name . '\'
		    	   ORDER BY `people_time`.`time` ';
            $people_res = $dbr->query($sql);
            $cur_person = '';
            $curKey = 0;
            while ($row = $dbr->fetchObject($people_res)) {
                if (!isset($row->Spoken_by)) {
                    continue;
                }
                $cur_row_person = $row->first . '_' . $row->last;
                if ($cur_person != $cur_row_person) {
                    $db_person_ary[] = get_object_vars($row);
                    $curKey = count($db_person_ary) - 1;
                    $db_person_ary[$curKey]['Spoken_by'] = $row->first . '_' . $row->last;
                    $db_person_ary[$curKey]['start_time'] = $row->time;
                    // not on screen a long time if only one hit:
                    $db_person_ary[$curKey]['end_time'] = $row->time + 10;
                    $cur_person = $cur_row_person;
                } else {
                    // update the end time:
                    $db_person_ary[$curKey]['end_time'] = $row->time;
                }
            }
            // list on screen times for everyone:
            foreach ($db_person_ary as $row) {
                print $row['Spoken_by'] . ' on screen for ' . ($row['end_time'] - $row['start_time']) . "\n";
                // $db_person_ary[]=$row;
            }
            // print_r($db_person_ary);
            // die;
            // count($cspan_person_ary)
            $cur_db_inx = 0;
            $cur_person = null;
            $fistValid = true;
            for ($i = 0; $i < count($cspan_person_ary); $i++) {
                // print "looking at: ". $cspan_person_ary[$i]['Spoken_by'] . "\n";
                print "\tCSPAN: " . $cspan_person_ary[$i]['Spoken_by'] . ' on screen for ' . $cspan_person_ary[$i]['length'] . ' or:' . npt2seconds($cspan_person_ary[$i]['length']) . "\n";
                // set up cur, the next and prev pointers:
                $cur_person = $cspan_person_ary[$i]['Spoken_by'];
                // make sure next is not the same as current:
                // note: we don't group above since the same person can give two subsequent different speeches
                $next_person = $cur_person;
                $k_person_inx = 1;
                $person_insert_set = array();
                while ($next_person == $cur_person) {
                    if (isset($cspan_person_ary[$i + $k_person_inx])) {
                        $potential_next_person = mv_is_valid_person($cspan_person_ary[$i + $k_person_inx]['Spoken_by']) ? $cspan_person_ary[$i + $k_person_inx]['Spoken_by'] : null;
                        if ($potential_next_person == null && $k_person_inx == 1) {
                            $next_person = null;
                            break;
                        } elseif ($potential_next_person != null) {
                            $next_person = $potential_next_person;
                        }
                        $k_person_inx++;
                    } else {
                        $next_person = null;
                    }
                }
                // should be no need to make sure prev is not the same as current (as we do greedy look ahead below)
                // $prev_person = $cur_person;
                // $k=1;
                // while($prev_person==$cur_person){
                if (isset($cspan_person_ary[$i - 1])) {
                    $prev_person = mv_is_valid_person($cspan_person_ary[$i - 1]['Spoken_by']) ? $cspan_person_ary[$i - 1]['Spoken_by'] : null;
                } else {
                    $prev_person = null;
                }
                // }
                if (mv_is_valid_person($cspan_person_ary[$i]['Spoken_by'])) {
                    // print "\tis valid person looking for db sync\n";
                    // print "\t prev: $prev_person cur: $cur_person next: $next_person\n";
                    if ($prev_person == null && $next_person == null) {
                        print "error both prev and next are null skiping person\n";
                        continue;
                    }
                    // check how long they where on screen (also check subquent)
                    $cspan_on_screen_time = npt2seconds($cspan_person_ary[$i]['length']);
                    // print "NOW STARTING AT: $cur_db_inx of " . count($db_person_ary) . "\n";
                    for ($j = $cur_db_inx; $j < count($db_person_ary); $j++) {
                        // print "searchig db on: " . $db_person_ary[$j]['Spoken_by'] . "!=" . $cspan_person_ary[$i]['Spoken_by'] . " \n";
                        $prevMatch = $curMatch = $nextMatch = false;
                        if ($cur_db_inx == 0 || $prev_person == null) {
                            // no need to check prev in db_inx
                            $prevMatch = true;
                            //	print "(no back check)";
                        } else {
                            if ($db_person_ary[$j - 1]['Spoken_by'] == $prev_person) {
                                //	print "found prev match: $prev_person\n;";
                                $prevMatch = true;
                            }
                        }
                        if (isset($db_person_ary[$j])) {
                            if (isset($cspan_person_ary[$i])) {
                                if ($db_person_ary[$j]['Spoken_by'] == $cspan_person_ary[$i]['Spoken_by']) {
                                    //	print "found cur match:". $cspan_person_ary[$i]['Spoken_by']."\n";
                                    $curMatch = true;
                                }
                            }
                        }
                        if ($next_person == null) {
                            // no need to check next in db_inx
                            $nextMatch = true;
                            //	print "(no next check)";
                        } else {
                            if (isset($db_person_ary[$j + 1])) {
                                if ($db_person_ary[$j + 1]['Spoken_by'] == $next_person) {
                                    // print "found next match:".$next_person."\n";
                                    $nextMatch = true;
                                }
                            }
                        }
                        // if we have a match set do insert proc:
                        if ($prevMatch && $curMatch && $nextMatch) {
                            // print "FOUND Match on $j\n";
                            // print "\t prev: $prev_person cur: $cur_person next: $next_person\n";
                            $cur_db_inx = $j;
                            // add all additional info we can from c-span:
                            // also push forward for all of current (we should always hit the first series of the same person first )
                            $k = 0;
                            // build insert set:
                            $cur_start_time = $db_person_ary[$j]['start_time'];
                            while ($cur_person == $cspan_person_ary[$i + $k]['Spoken_by']) {
                                // use the last cspan_person for start case
                                $cspan_person_ary[$i + $k]['wiki_start_time'] = $cur_start_time;
                                if (npt2seconds($cspan_person_ary[$i + $k]['length']) > $db_person_ary[$j]['end_time'] - $cur_start_time) {
                                    $cspan_person_ary[$i + $k]['wiki_end_time'] = $db_person_ary[$j]['end_time'];
                                    // already used up our db_person_ary continue:
                                    print "a cspan insert sync " . ' ' . $cspan_person_ary[$i + $k]['wiki_start_time'] . " to " . $cspan_person_ary[$i + $k]['wiki_end_time'] . " of " . $db_person_ary[$j]['end_time'] . " for: " . $cspan_person_ary[$i]['Spoken_by'] . "\n";
                                    break;
                                } else {
                                    $cspan_person_ary[$i + $k]['wiki_end_time'] = $cur_start_time + npt2seconds($cspan_person_ary[$i + $k]['length']);
                                    // print "add " . npt2seconds($cspan_person_ary[$i+$k]['length']) . "\n";
                                    $cur_start_time += npt2seconds($cspan_person_ary[$i + $k]['length']);
                                }
                                print "p cspan insert sync " . ' ' . $cspan_person_ary[$i + $k]['wiki_start_time'] . " to " . $cspan_person_ary[$i + $k]['wiki_end_time'] . " of " . $db_person_ary[$j]['end_time'] . " for: " . $cspan_person_ary[$i]['Spoken_by'] . "\n";
                                // print_r($db_person_ary[$j]);
                                // print_r($cspan_person_ary[$i+$k]);
                                $k++;
                                if (!isset($cspan_person_ary[$i + $k])) {
                                    break;
                                }
                            }
                            $k--;
                            // extend the last property if within 100 seconds
                            if (abs($cspan_person_ary[$i + $k]['wiki_end_time'] - $db_person_ary[$j]['end_time']) < 100) {
                                $cspan_person_ary[$i + $k]['wiki_end_time'] = $db_person_ary[$j]['end_time'];
                                print "updated cspan insert for: " . $cspan_person_ary[$i]['Spoken_by'] . ' ' . $cspan_person_ary[$i + $k]['wiki_start_time'] . " to " . $cspan_person_ary[$i + $k]['wiki_end_time'] . " of " . $db_person_ary[$j]['end_time'] . "\n";
                            }
                            $k++;
                            //	   						/die;
                            // move the index to the current:
                            $i = $i + $k;
                            continue;
                        }
                    }
                } else {
                    // print $cspan_person_ary[$i]['Spoken_by'] . " is not valid person\n";
                }
            }
            print "Get Additonal C-SPAN Data For \"synced\" Data:\n";
            foreach ($cspan_person_ary as $pData) {
                if (isset($pData['wiki_start_time'])) {
                    // init:
                    $bill_categories = array();
                    $annotate_body = '';
                    $body = '';
                    $bill_key = null;
                    $rawpage = $this->doRequest($this->base_url . $pData['href']);
                    // $rawpage = $this->doRequest('http://www.c-spanarchives.org/congress/?q=node/77531&id=8330447');
                    preg_match('/<\\/td><th><center>([^<]*)<\\/center><\\/th><td>/U', $rawpage, $title_matches);
                    preg_match('/<table width="400">\\n<tr><td>\\n(.*)<\\/tr><\\/td>/', $rawpage, $page_matches);
                    if (isset($title_matches[1]) && isset($page_matches[1])) {
                        $title = trim($title_matches[1]);
                        $body = $page_matches[1];
                        // print_r($page_matches);
                    } else {
                        print "error can't find title or body\n";
                        print "skip...";
                        continue;
                    }
                    // do debate tag search:
                    preg_match('/<td colspan="2">Debate:\\s*<[^>]*>([^<]*)/U', $rawpage, $debate_matches);
                    if (isset($debate_matches[1])) {
                        $bill_key = trim($debate_matches[1]);
                        print "found debate: tag " . $bill_key . "\n";
                        // build gov-track-congress-session friendly debate url:
                        if ($this->get_and_process_billid($bill_key, $stream->date_start_time) != null) {
                            $bill_categories[$bill_key] = $bill_key;
                        }
                    }
                    // title fix hack for C-span error motion to procceed
                    // @@todo add in the rest of the motions:
                    if (strpos($title, 'MOTION TO PROCEED') !== false) {
                        $title = str_replace('MOTION TO PROCEED', '', $title);
                        // $annotate_body.="[[Bill Motion:=MOTION TO PROCEED]]\n";
                    }
                    // fix title case
                    $title = ucwords(strtolower($title));
                    // don't Cap a Few of the Words: '
                    $title = str_replace(array(' And', ' Or', ' Of', ' A'), array(' and', ' or', ' of', ' a'), $title);
                    // replace '' with ``
                    $body = str_replace('\'\'', '``', $body);
                    // replace bill names with [[Catgory:: bill name #]]
                    // $bill_pattern = '/(H\.R\.\s[0-9]+)/';
                    $bill_pattern = '/';
                    $bill_pattern_ary = array();
                    $or = '';
                    foreach ($this->bill_types as $cspanT => $govtrakT) {
                        $cspanT = str_replace('RES', '[\\s]?RES', $cspanT);
                        // sometimes spaces before res in text
                        $cspanT = str_replace('CON', '[\\s]?CON', $cspanT);
                        // sometimes spaces before res in text
                        // replace . with \.[\s]?
                        $bill_pattern .= $or . '(' . str_replace('.', '\\.[\\s]?', $cspanT) . '\\s?[0-9]+)';
                        $bill_pattern_ary[] = '(' . str_replace('.', '\\.[\\s]?', $cspanT) . '\\s?[0-9]+)';
                        $or = '|';
                    }
                    $bill_pattern .= '/i';
                    // case insensative
                    // $body='bla bla H.R. 3453 test S. 3494 some more text';
                    // print "pattern:".$bill_pattern . "\n";
                    preg_match_all($bill_pattern, $body, $bill_matches);
                    // print_r($bill_matches);
                    // die;
                    if (isset($bill_matches[1])) {
                        foreach ($bill_matches as $k => $bill_type_ary) {
                            if ($k != 0) {
                                if (isset($bill_type_ary[0])) {
                                    $bill_name = $bill_type_ary[0];
                                } elseif (isset($bill_type_ary[1])) {
                                    $bill_name = $bill_type_ary[1];
                                } else {
                                    continue;
                                }
                                // if the first letter is lower case not likely a bill
                                if (trim($bill_name) == '') {
                                    continue;
                                }
                                if (islower(substr($bill_name, 0, 1))) {
                                    continue;
                                }
                                // conform white space and case:
                                $bill_name = str_replace(array('S. ', 'Con. ', 'Res. '), array('S.', 'CON.', 'RES. '), $bill_name);
                                // make sure its not a false possitave and load bill data from govTrack:
                                if ($this->get_and_process_billid($bill_name, $stream->date_start_time)) {
                                    $bill_categories[$bill_name] = $bill_name;
                                }
                            }
                        }
                    }
                    // add speech by attribute to annotation body:
                    $annotate_body .= 'Speech By: [[Speech by:=' . str_replace('_', ' ', $pData['Spoken_by']) . ']] ';
                    // add speech by attribute to body as well?
                    $body .= "\n\n" . 'Speech By: [[Speech by:=' . str_replace('_', ' ', $pData['Spoken_by']) . ']] ';
                    // add any mentions of bills with linkback to full bill title:
                    $body = preg_replace_callback($bill_pattern_ary, array('self', 'bill_pattern_cp'), $body);
                    // source the doument:
                    $body .= "\n\n" . 'Source: [[Data Source Name:=C-SPAN Congressional Chronicle]] [[Data Source URL:=' . $this->base_url . $pData['href'] . ']]';
                    $body .= "\n";
                    // add the title to the top of the page:
                    $body = "==={$title}===\n" . $body;
                    $cspan_title_str = $this->get_aligned_time_title($pData, 'Thomas_en', $stream);
                    if (!$cspan_title_str) {
                        $cspan_title_str = 'Thomas_en:' . $stream->name . '/' . seconds2npt($pData['wiki_start_time']) . '/' . seconds2npt($pData['wiki_end_time']);
                    }
                    $cspanTitle = Title::makeTitle(MV_NS_MVD, ucfirst($cspan_title_str));
                    // print "do edit ".$cspanTitle->getText()."\n";
                    do_update_wiki_page($cspanTitle, $body);
                    // protect editing of the offical record (but allow moving for sync)
                    $cspanTitle->loadRestrictions();
                    global $wgRestrictionTypes;
                    foreach ($wgRestrictionTypes as $action) {
                        // Fixme: this form currently requires individual selections,
                        // but the db allows multiples separated by commas.
                        $mRestrictions[$action] = implode('', $cspanTitle->getRestrictions($action));
                    }
                    $article = new Article($cspanTitle);
                    $mRestrictions['edit']['sysop'] = true;
                    $expiry = Block::infinity();
                    $dbw = wfGetDB(DB_MASTER);
                    $dbw->begin();
                    $ok = $article->updateRestrictions($mRestrictions, wfMsg('mv_source_material'), false, $expiry);
                    if ($ok) {
                        print "updated permisions for " . $cspanTitle->getText() . "\n";
                        $dbw->commit();
                    } else {
                        print "failed to update restrictions :(\n";
                    }
                    // process each bill to the annotation body;
                    $bcat = '';
                    $bill_lead_in = "\n\nBill ";
                    // print_r($bill_categories);
                    foreach ($bill_categories as $bill) {
                        if (trim($bill) != '') {
                            // use short title for category and long title for semantic link... (highly arbitrary)
                            $annotate_body .= $bill_lead_in . '[[Bill:=' . $this->cur_bill_short_title . ']] ';
                            $bill_lead_in = ' , ';
                            $annotate_body .= "[[Category:{$bill}]] ";
                        }
                    }
                    if (trim($title) != '') {
                        $annotate_body .= "[[Category:{$title}]]\n";
                    }
                    // see if we can align with an existing speech page:
                    $anno_title_str = $this->get_aligned_time_title($pData, 'Anno_en', $stream);
                    if (!$anno_title_str) {
                        $anno_title_str = 'Anno_en:' . $stream->name . '/' . seconds2npt($pData['wiki_start_time']) . '/' . seconds2npt($pData['wiki_end_time']);
                    }
                    $annoTitle = Title::makeTitle(MV_NS_MVD, ucfirst($anno_title_str));
                    do_update_wiki_page($annoTitle, $annotate_body);
                    // [Page: S14580] replaced with:  [[Category:BillName]]
                    // would be good to link into the official record for "pages"
                    // [[Speech by:=name]]
                    // [[category:=title]]
                    // for documentation:
                    // semantic qualities would be Aruging For:billX or Arguging Agaist billY
                    // these pages are non-editable
                    // maybe put the category info into annotations layer? (since it applies to both?)
                    // do new page mvd:or_
                }
            }
            // $inx_cspan_person_ary = array_keys($g_row_matches);
            // $inx_row_person_ary = array_keys($g_person_time_ary);
            // for($i=0;$i<5;$i++){
            // }
            // find match person1->person2
            // average switch time to get offset of stream
            // use offset to insert all $person_time_array data
        }
    }
 function procRequestTime($stream_id, $req_time)
 {
     global $mvShellOggFrameGrab, $mvImageGranularityRate;
     if (!$req_time) {
         $req_time = '0';
     }
     if (count(explode(":", $req_time)) >= 2) {
         $req_time = npt2seconds($req_time);
     } else {
         if (!is_numeric($req_time) && $req_time >= 0) {
             throw "error in req time format";
         }
     }
     // print "REQ time: $req_time\n";
     // query the image db to find the closest to req time (while still being in front)
     $dbr =& wfGetDB(DB_READ);
     // if($req_time<$mvImageGranularityRate)$req_time = $mvImageGranularityRate;
     $vars = " `id`, `time`, `time`-'{$req_time}' as distance ";
     $conds = " `stream_id`=" . mysql_real_escape_string($stream_id) . "\n\t\t\t\tAND (`time`-'{$req_time}')>=0\n\t\t\t\tAND (`time`-'{$req_time}')<= " . mysql_real_escape_string($mvImageGranularityRate);
     $opt['ORDER BY'] = ' `distance` ASC ';
     $opt['LIMIT'] = 1;
     $res = $dbr->select('mv_stream_images', $vars, $conds, __METHOD__, $opt);
     // print $dbr->lastQuery();
     // die;
     if ($dbr->numRows($res) == 0) {
         // could do a request to generate image for video here:
         if (MV_StreamImage::genLocalStreamImage($stream_id, $req_time, '320x240')) {
             // we just generated the current request time return it as valid:
             return $req_time;
         } else {
             return false;
         }
     } else {
         $img_row = $dbr->fetchObject($res);
         $req_time = $img_row->time;
     }
     // print $dbr->lastQuery();
     // print_r($img_row
     // die;
     return $req_time;
 }
function do_request()
{
    $file_req = filter_input(INPUT_GET, 'file', FILTER_SANITIZE_STRING);
    $time_req = filter_input(INPUT_GET, 't', FILTER_SANITIZE_STRING);
    //try to grab the file from /filename format
    if ($file_req == '') {
        if (isset($_SERVER['PHP_SELF'])) {
            $pathparts = explode('/', $_SERVER['PHP_SELF']);
            $file_req = strpos($pathparts[count($pathparts) - 1], '?') !== false ? substr($pathparts[count($pathparts) - 1], 0, strpos($pathparts[count($pathparts) - 1], '?')) : $pathparts[count($pathparts) - 1];
        }
    }
    //additional filtering to avoid directory traversing:
    $file_req = str_replace(array('../', './'), '', $file_req);
    if ($file_req == '') {
        die('error: missing file name');
    }
    $file_loc = BASE_LOCAL_CLIP_PATH . '/' . $file_req;
    if (!is_file($file_loc)) {
        die('error: requested file not found:' . $file_loc);
    }
    //if 't' is empty no seeking necessary:
    if ($time_req == '') {
        header('Content-type: ' . FLASH_VIDEO_CONTENT_TYPE);
        header('Content-Length: ' . filesize($file_loc));
        output_full_file($file_loc);
    } else {
        //@@todo support more time request formats
        if (strpos($time_req, '/') !== false) {
            list($start_time_ntp, $end_time_ntp) = explode('/', $time_req);
            $start_sec = npt2seconds($start_time_ntp);
            $end_sec = npt2seconds($end_time_ntp);
        } else {
            $start_sec = npt2seconds($time_req);
            $end_sec = null;
            if ($start_sec == 0) {
                output_full_file($file_loc);
            }
        }
        if ($start_sec > $end_sec) {
            die('error: requested invalid time range');
        }
        //print "DO: $start_sec $end_sec \n";
        require_once 'MvFlv.php';
        //open up the metavid Flv object:
        $flv = new MyFLV();
        try {
            $flv->open($file_loc);
        } catch (Exception $e) {
            die("<pre>The following exception was detected while trying to open a FLV file:\n" . $e->getMessage() . "</pre>");
        }
        header('Content-type: ' . FLASH_VIDEO_CONTENT_TYPE);
        $one_year = 60 * 60 * 24 * 365;
        header("Expires: " . gmdate("D, d M Y H:i:s", time() + $one_year) . " GM");
        //small meta file to parse no big deal:
        list($start_byte, $end_byte) = $flv->getKeyFrameByteTimes($start_sec, $end_sec);
        //send out content length:
        header('Content-Length: ' . ($end_byte - $start_byte));
        $flv->play($start_byte, $end_byte);
        //$end = microtime(true);
        //file_put_contents('/tmp/time.log', "<hr/>EXTRACT METADATA PROCESS TOOK " . number_format(($end-$start), 2) . " seconds<br />");
        $flv->close();
    }
}
 function parseTitle($title)
 {
     global $mvDefaultClipLength;
     // the metavid namespace:
     // stream:stream_name ||
     // mvd:type:stream_name_date/start_time/end_time
     $parts = split('/', $title);
     if (!isset($parts[1])) {
         $parts[1] = '';
     }
     // check for type:
     $sub_parts = split(':', $parts[0]);
     if (count($sub_parts) == 2) {
         if ($sub_parts[0] == '' && $sub_parts[1] == '') {
             $this->stream_name = null;
             $this->type_marker = null;
             $this->hasMVDType = false;
         } else {
             $this->stream_name = $sub_parts[1];
             $this->type_marker = $sub_parts[0];
             $this->hasMVDType = true;
         }
     } else {
         if ($parts[0] == '') {
             $this->stream_name = null;
         } else {
             // print_r($sub_parts);
             // @@todo do look up of single part request
             $this->stream_name = $sub_parts[0];
             // $this->stream_name = null;
         }
         $this->hasMVDType = false;
     }
     // check if the type isTime or "type"
     if (isset($parts[1])) {
         if (mvIsNtpTime($parts[1])) {
             $this->start_time = $parts[1];
             if (isset($parts[2])) {
                 if (mvIsNtpTime($parts[2])) {
                     $this->end_time = $parts[2];
                 }
             }
         }
     }
     // (support null endtimes)
     // if the endtime is unset set it to the default length after the start time:
     // if(!isset($end_time)){
     // $this->end_time = seconds2npt(npt2seconds($this->start_time) + $mvDefaultClipLength) ;
     // }
     // @@todo make sure start time is not negative & end time is not > duration
     // validate the start time:
     if (mvIsNtpTime($this->start_time) == false) {
         $this->start_time = null;
     }
     // validate the end time:
     if ($this->end_time != null) {
         if (mvIsNtpTime($this->end_time) == false) {
             $this->end_time = null;
         }
         // make sure the end time is > than the start time:
         if (npt2seconds($this->start_time) > npt2seconds($this->end_time)) {
             // @@TODO better error handling
             $this->start_time = null;
             $this->end_time = null;
         }
     }
 }