mirror of
https://github.com/zotanmew/nginx-rtmp-module.git
synced 2024-06-29 08:18:58 +02:00
858 lines
639 KiB
Python
858 lines
639 KiB
Python
![]() |
<!DOCTYPE html>
|
|||
|
<!-- saved from url=(0061)http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py -->
|
|||
|
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
|||
|
|
|||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
|||
|
|
|||
|
<meta name="ROBOTS" content="NOARCHIVE">
|
|||
|
|
|||
|
<link rel="icon" type="image/vnd.microsoft.icon" href="http://www.gstatic.com/codesite/ph/images/phosting.ico">
|
|||
|
|
|||
|
|
|||
|
<script src="./rtmp_files/cb=gapi.loaded0" async=""></script><script type="text/javascript" async="" src="./rtmp_files/plusone.js" gapi_processed="true"></script><script type="text/javascript">
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
var codesite_token = "vVg-YEkpsP38PydkCFlVS-ioMOA:1335711600965";
|
|||
|
|
|||
|
|
|||
|
var CS_env = {"profileUrl":["/u/102069584091941751068/"],"token":"vVg-YEkpsP38PydkCFlVS-ioMOA:1335711600965","assetHostPath":"http://www.gstatic.com/codesite/ph","domainName":null,"assetVersionPath":"http://www.gstatic.com/codesite/ph/12151595242108277468","projectHomeUrl":"/p/rtmplite","relativeBaseUrl":"","projectName":"rtmplite","loggedInUserEmail":"arutyunyan.roman@gmail.com"};
|
|||
|
var _gaq = _gaq || [];
|
|||
|
_gaq.push(
|
|||
|
['siteTracker._setAccount', 'UA-18071-1'],
|
|||
|
['siteTracker._trackPageview']);
|
|||
|
|
|||
|
|
|||
|
</script>
|
|||
|
|
|||
|
|
|||
|
<title>rtmp.py -
|
|||
|
rtmplite -
|
|||
|
|
|||
|
|
|||
|
Flash RTMP server in Python - Google Project Hosting
|
|||
|
</title>
|
|||
|
<link type="text/css" rel="stylesheet" href="./rtmp_files/core.css">
|
|||
|
|
|||
|
<link type="text/css" rel="stylesheet" href="./rtmp_files/ph_detail.css">
|
|||
|
|
|||
|
|
|||
|
<link type="text/css" rel="stylesheet" href="./rtmp_files/d_sb.css">
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<!--[if IE]>
|
|||
|
<link type="text/css" rel="stylesheet" href="http://www.gstatic.com/codesite/ph/12151595242108277468/css/d_ie.css" >
|
|||
|
<![endif]-->
|
|||
|
<style type="text/css">
|
|||
|
.menuIcon.off { background: no-repeat url(http://www.gstatic.com/codesite/ph/images/dropdown_sprite.gif) 0 -42px }
|
|||
|
.menuIcon.on { background: no-repeat url(http://www.gstatic.com/codesite/ph/images/dropdown_sprite.gif) 0 -28px }
|
|||
|
.menuIcon.down { background: no-repeat url(http://www.gstatic.com/codesite/ph/images/dropdown_sprite.gif) 0 0; }
|
|||
|
|
|||
|
|
|||
|
|
|||
|
tr.inline_comment {
|
|||
|
background: #fff;
|
|||
|
vertical-align: top;
|
|||
|
}
|
|||
|
div.draft, div.published {
|
|||
|
padding: .3em;
|
|||
|
border: 1px solid #999;
|
|||
|
margin-bottom: .1em;
|
|||
|
font-family: arial, sans-serif;
|
|||
|
max-width: 60em;
|
|||
|
}
|
|||
|
div.draft {
|
|||
|
background: #ffa;
|
|||
|
}
|
|||
|
div.published {
|
|||
|
background: #e5ecf9;
|
|||
|
}
|
|||
|
div.published .body, div.draft .body {
|
|||
|
padding: .5em .1em .1em .1em;
|
|||
|
max-width: 60em;
|
|||
|
white-space: pre-wrap;
|
|||
|
white-space: -moz-pre-wrap;
|
|||
|
white-space: -pre-wrap;
|
|||
|
white-space: -o-pre-wrap;
|
|||
|
word-wrap: break-word;
|
|||
|
font-size: 1em;
|
|||
|
}
|
|||
|
div.draft .actions {
|
|||
|
margin-left: 1em;
|
|||
|
font-size: 90%;
|
|||
|
}
|
|||
|
div.draft form {
|
|||
|
padding: .5em .5em .5em 0;
|
|||
|
}
|
|||
|
div.draft textarea, div.published textarea {
|
|||
|
width: 95%;
|
|||
|
height: 10em;
|
|||
|
font-family: arial, sans-serif;
|
|||
|
margin-bottom: .5em;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
.nocursor, .nocursor td, .cursor_hidden, .cursor_hidden td {
|
|||
|
background-color: white;
|
|||
|
height: 2px;
|
|||
|
}
|
|||
|
.cursor, .cursor td {
|
|||
|
background-color: darkblue;
|
|||
|
height: 2px;
|
|||
|
display: '';
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
.list {
|
|||
|
border: 1px solid white;
|
|||
|
border-bottom: 0;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
</style>
|
|||
|
<script type="text/javascript" async="" src="./rtmp_files/ga.js"></script></head>
|
|||
|
<body class="t4">
|
|||
|
<script type="text/javascript">
|
|||
|
(function() {
|
|||
|
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
|||
|
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
|||
|
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(ga);
|
|||
|
})();
|
|||
|
</script>
|
|||
|
<script type="text/javascript">
|
|||
|
window.___gcfg = {lang: 'en'};
|
|||
|
(function()
|
|||
|
{var po = document.createElement("script");
|
|||
|
po.type = "text/javascript"; po.async = true;po.src = "https://apis.google.com/js/plusone.js";
|
|||
|
var s = document.getElementsByTagName("script")[0];
|
|||
|
s.parentNode.insertBefore(po, s);
|
|||
|
})();
|
|||
|
</script>
|
|||
|
<div class="headbg">
|
|||
|
|
|||
|
<div id="gaia">
|
|||
|
|
|||
|
|
|||
|
<span>
|
|||
|
|
|||
|
|
|||
|
<b>arutyunyan.roman@gmail.com</b>
|
|||
|
|
|||
|
|
|||
|
| <a href="http://code.google.com/u/102069584091941751068/" id="projects-dropdown" onclick="return false;"><u>My favorites</u> <small>▼</small></a>
|
|||
|
| <a href="http://code.google.com/u/102069584091941751068/" onclick="_CS_click('/gb/ph/profile');" title="Profile, Updates, and Settings"><u>Profile</u></a>
|
|||
|
| <a href="https://www.google.com/accounts/Logout?continue=http%3A%2F%2Fcode.google.com%2Fp%2Frtmplite%2Fsource%2Fbrowse%2Ftrunk%2Frtmp.py" onclick="_CS_click('/gb/ph/signout');"><u>Sign out</u></a>
|
|||
|
|
|||
|
</span>
|
|||
|
|
|||
|
</div>
|
|||
|
|
|||
|
<div class="gbh" style="left: 0pt;"></div>
|
|||
|
<div class="gbh" style="right: 0pt;"></div>
|
|||
|
|
|||
|
|
|||
|
<div style="height: 1px"></div>
|
|||
|
<!--[if lte IE 7]>
|
|||
|
<div style="text-align:center;">
|
|||
|
Your version of Internet Explorer is not supported. Try a browser that
|
|||
|
contributes to open source, such as <a href="http://www.firefox.com">Firefox</a>,
|
|||
|
<a href="http://www.google.com/chrome">Google Chrome</a>, or
|
|||
|
<a href="http://code.google.com/chrome/chromeframe/">Google Chrome Frame</a>.
|
|||
|
</div>
|
|||
|
<![endif]-->
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<table style="padding:0px; margin: 0px 0px 10px 0px; width:100%" cellpadding="0" cellspacing="0" itemscope="" itemtype="http://schema.org/CreativeWork">
|
|||
|
<tbody><tr style="height: 58px;">
|
|||
|
|
|||
|
<td id="plogo">
|
|||
|
<link itemprop="url" href="http://code.google.com/p/rtmplite">
|
|||
|
<a href="http://code.google.com/p/rtmplite/">
|
|||
|
|
|||
|
|
|||
|
<img src="./rtmp_files/logo" alt="Logo" itemprop="image">
|
|||
|
|
|||
|
</a>
|
|||
|
</td>
|
|||
|
|
|||
|
<td style="padding-left: 0.5em">
|
|||
|
|
|||
|
<div id="pname">
|
|||
|
<a href="http://code.google.com/p/rtmplite/"><span itemprop="name">rtmplite</span></a>
|
|||
|
</div>
|
|||
|
|
|||
|
<div id="psum">
|
|||
|
<a id="project_summary_link" href="http://code.google.com/p/rtmplite/"><span itemprop="description">Flash RTMP server in Python</span></a>
|
|||
|
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
</td>
|
|||
|
<td style="white-space:nowrap;text-align:right; vertical-align:bottom;">
|
|||
|
|
|||
|
<form action="http://code.google.com/hosting/search">
|
|||
|
<input size="30" name="q" value="" type="text">
|
|||
|
|
|||
|
<input type="submit" name="projectsearch" value="Search projects">
|
|||
|
</form>
|
|||
|
|
|||
|
</td></tr>
|
|||
|
</tbody></table>
|
|||
|
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
<div id="mt" class="gtb">
|
|||
|
<a href="http://code.google.com/p/rtmplite/" class="tab ">Project Home</a>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<a href="http://code.google.com/p/rtmplite/downloads/list" class="tab ">Downloads</a>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<a href="http://code.google.com/p/rtmplite/w/list" class="tab ">Wiki</a>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<a href="http://code.google.com/p/rtmplite/issues/list" class="tab ">Issues</a>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<a href="http://code.google.com/p/rtmplite/source/checkout" class="tab active">Source</a>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<div class="gtbc"></div>
|
|||
|
</div>
|
|||
|
<table cellspacing="0" cellpadding="0" width="100%" align="center" border="0" class="st">
|
|||
|
<tbody><tr>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<td class="subt">
|
|||
|
<div class="st2">
|
|||
|
<div class="isf">
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<span class="inst1"><a href="http://code.google.com/p/rtmplite/source/checkout">Checkout</a></span>
|
|||
|
<span class="inst2"><a href="http://code.google.com/p/rtmplite/source/browse/trunk">Browse</a></span>
|
|||
|
<span class="inst3"><a href="http://code.google.com/p/rtmplite/source/list">Changes</a></span>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<form action="http://code.google.com/p/rtmplite/source/search" method="get" style="display:inline" onsubmit="document.getElementById('codesearchq').value = document.getElementById('origq').value">
|
|||
|
<input type="hidden" name="q" id="codesearchq" value="">
|
|||
|
<input type="text" maxlength="2048" size="38" id="origq" name="origq" value="" title="Google Code Search" style="font-size:92%"> <input type="submit" value="Search Trunk" name="btnG" style="font-size:92%">
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
</form>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
|
|||
|
</td>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<td align="right" valign="top" class="bevel-right"></td>
|
|||
|
</tr>
|
|||
|
</tbody></table>
|
|||
|
|
|||
|
|
|||
|
<script type="text/javascript">
|
|||
|
var cancelBubble = false;
|
|||
|
function _go(url) { document.location = url; }
|
|||
|
</script>
|
|||
|
<div id="maincol">
|
|||
|
|
|||
|
|
|||
|
<!-- IE -->
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<div class="expand">
|
|||
|
<div id="colcontrol">
|
|||
|
<style type="text/css">
|
|||
|
#file_flipper { white-space: nowrap; padding-right: 2em; }
|
|||
|
#file_flipper.hidden { display: none; }
|
|||
|
#file_flipper .pagelink { color: #0000CC; text-decoration: underline; }
|
|||
|
#file_flipper #visiblefiles { padding-left: 0.5em; padding-right: 0.5em; }
|
|||
|
</style>
|
|||
|
<table id="nav_and_rev" class="list" cellpadding="0" cellspacing="0" width="100%">
|
|||
|
<tbody><tr>
|
|||
|
|
|||
|
<td nowrap="nowrap" class="src_crumbs src_nav" width="33%">
|
|||
|
<strong class="src_nav">Source path: </strong>
|
|||
|
<span id="crumb_root">
|
|||
|
|
|||
|
<a href="http://code.google.com/p/rtmplite/source/browse/">svn</a>/ </span>
|
|||
|
<span id="crumb_links" class="ifClosed"><a href="http://code.google.com/p/rtmplite/source/browse/trunk/">trunk</a><span class="sp">/ </span>rtmp.py</span>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
</td>
|
|||
|
|
|||
|
|
|||
|
<td nowrap="nowrap" width="33%" align="center">
|
|||
|
<a href="http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py?edit=1"><img src="./rtmp_files/pencil-y14.png" class="edit_icon">Edit file</a>
|
|||
|
</td>
|
|||
|
|
|||
|
|
|||
|
<td nowrap="nowrap" width="33%" align="right">
|
|||
|
<table cellpadding="0" cellspacing="0" style="font-size: 100%"><tbody><tr>
|
|||
|
|
|||
|
|
|||
|
<td class="flipper">
|
|||
|
<ul class="leftside">
|
|||
|
|
|||
|
<li><a href="http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py?r=142" title="Previous">‹r142</a></li>
|
|||
|
|
|||
|
</ul>
|
|||
|
</td>
|
|||
|
|
|||
|
<td class="flipper"><b>r154</b></td>
|
|||
|
|
|||
|
</tr></tbody></table>
|
|||
|
</td>
|
|||
|
</tr>
|
|||
|
</tbody></table>
|
|||
|
|
|||
|
<div class="fc">
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<style type="text/css">
|
|||
|
.undermouse span {
|
|||
|
background-image: url(http://www.gstatic.com/codesite/ph/images/comments.gif); }
|
|||
|
</style>
|
|||
|
<table class="opened" id="review_comment_area"><tbody><tr>
|
|||
|
<td id="nums">
|
|||
|
<pre><table width="100%"><tbody><tr class="nocursor"><td></td></tr></tbody></table></pre>
|
|||
|
<pre><table width="100%" id="nums_table_0"><tbody><tr id="gr_svn154_1"><td id="1"><a href="http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py#1">1</a></td></tr><tr id="gr_svn154_2"><td id="2"><a href="http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py#2">2</a></td></tr><tr id="gr_svn154_3"><td id="3"><a href="http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py#3">3</a></td></tr><tr id="gr_svn154_4"><td id="4"><a href="http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py#4">4</a></td></tr><tr id="gr_svn154_5"><td id="5"><a href="http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py#5">5</a></td></tr><tr id="gr_svn154_6"><td id="6"><a href="http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py#6">6</a></td></tr><tr id="gr_svn154_7"><td id="7"><a href="http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py#7">7</a></td></tr><tr id="gr_svn154_8"><td id="8"><a href="http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py#8">8</a></td></tr><tr id="gr_svn154_9"><td id="9"><a href="http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py#9">9</a></td></tr><tr id="gr_svn154_10"><td id="10"><a href="http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py#10">10</a></td></tr><tr id="gr_svn154_11"><td id="11"><a href="http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py#11">11</a></td></tr><tr id="gr_svn154_12"><td id="12"><a href="http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py#12">12</a></td></tr><tr id="gr_svn154_13"><td id="13"><a href="http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py#13">13</a></td></tr><tr id="gr_svn154_14"><td id="14"><a href="http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py#14">14</a></td></tr><tr id="gr_svn154_15"><td id="15"><a href="http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py#15">15</a></td></tr><tr id="gr_svn154_16"><td id="16"><a href="http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py#16">16</a></td></tr><tr id="gr_svn154_17"><td id="17"><a href="http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py#17">17</a></td></tr><tr id="gr_svn154_18"><td id="18"><a href="http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py#18">18</a></td></tr><tr id="gr_svn154_19"><td id="19"><a href="http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py#19">19</a></td></tr><tr id="gr_svn154_20"><td id="20"><a href="http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py#20">20</a></td></tr><tr id="gr_svn154_21"><td id="21"><a href="http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py#21">21</a></td></tr><tr id="gr_svn154_22"><td id="22"><a href="http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py#22">22</a></td></tr><tr id="gr_svn154_23"><td id="23"><a href="http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py#23">23</a></td></tr><tr id="gr_svn154_24"><td id="24"><a href="http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py#24">24</a></td></tr><tr id="gr_svn154_25"><td id="25"><a href="http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py#25">25</a></td></tr><tr id="gr_svn154_26"><td id="26"><a href="http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py#26">26</a></td></tr><tr id="gr_svn154_27"><td id="27"><a href="http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py#27">27</a></td></tr><tr id="gr_svn154_28"><td id="28"><a href="http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py#28">28</a></td></tr><tr id="gr_svn154_29"><td id="29"><a href="http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py#29">29</a></td></tr><tr id="gr_svn154_30"><td id="30"><a href="http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py#30">30</a></td></tr><tr id="gr_svn154_31"><td id="31"><a href="http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py#31">31</a></td></tr><tr id="gr_svn154_32"><td id="32"><a href="http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py#32">32</a></td></tr><tr id="gr_svn154_33"><td id="33"><a href="http://code.google.com/p/rtmplite/sour
|
|||
|
<pre><table width="100%"><tbody><tr class="nocursor"><td></td></tr></tbody></table></pre>
|
|||
|
</td>
|
|||
|
<td id="lines">
|
|||
|
<pre><table width="100%"><tbody><tr class="cursor_stop cursor_hidden"><td></td></tr></tbody></table></pre>
|
|||
|
<pre class="prettyprint lang-py"><table id="src_table_0"><tbody><tr id="sl_svn154_1"><td class="source"><span class="com"># Copyright (c) 2007-2009, Mamta Singh. All rights reserved. see README for details.</span><span class="pln"><br></span></td></tr><tr id="sl_svn154_2"><td class="source"><span class="com"># Copyright (c) 2010-2011, Kundan Singh.</span><span class="pln"><br></span></td></tr><tr id="sl_svn154_3"><td class="source"><span class="pln"><br></span></td></tr><tr id="sl_svn154_4"><td class="source"><span class="str">'''<br></span></td></tr><tr id="sl_svn154_5"><td class="source"><span class="str">This is a simple implementation of a Flash RTMP server to accept connections and stream requests. The module is organized as follows:<br></span></td></tr><tr id="sl_svn154_6"><td class="source"><span class="str">1. The FlashServer class is the main class to provide the server abstraction. It uses the multitask module for co-operative multitasking.<br></span></td></tr><tr id="sl_svn154_7"><td class="source"><span class="str"> It also uses the App abstract class to implement the applications.<br></span></td></tr><tr id="sl_svn154_8"><td class="source"><span class="str">2. The Server class implements a simple server to receive new Client connections and inform the FlashServer application. The Client class<br></span></td></tr><tr id="sl_svn154_9"><td class="source"><span class="str"> derived from Protocol implements the RTMP client functions. The Protocol class implements the base RTMP protocol parsing. A Client contains<br></span></td></tr><tr id="sl_svn154_10"><td class="source"><span class="str"> various streams from the client, represented using the Stream class.<br></span></td></tr><tr id="sl_svn154_11"><td class="source"><span class="str">3. The Message, Header and Command represent RTMP message, header and command respectively. The FLV class implements functions to perform read<br></span></td></tr><tr id="sl_svn154_12"><td class="source"><span class="str"> and write of FLV file format.<br></span></td></tr><tr id="sl_svn154_13"><td class="source"><span class="str"><br></span></td></tr><tr id="sl_svn154_14"><td class="source"><span class="str"><br></span></td></tr><tr id="sl_svn154_15"><td class="source"><span class="str">Typically an application can launch this server as follows:<br></span></td></tr><tr id="sl_svn154_16"><td class="source"><span class="str">$ python rtmp.py<br></span></td></tr><tr id="sl_svn154_17"><td class="source"><span class="str"><br></span></td></tr><tr id="sl_svn154_18"><td class="source"><span class="str">To know the command line options use the -h option:<br></span></td></tr><tr id="sl_svn154_19"><td class="source"><span class="str">$ python rtmp.py -h<br></span></td></tr><tr id="sl_svn154_20"><td class="source"><span class="str"><br></span></td></tr><tr id="sl_svn154_21"><td class="source"><span class="str">To start the server with a different directory for recording and playing FLV files from, use the following command.<br></span></td></tr><tr id="sl_svn154_22"><td class="source"><span class="str">$ python rtmp.py -r some-other-directory/<br></span></td></tr><tr id="sl_svn154_23"><td class="source"><span class="str">Note the terminal '/' in the directory name. Without this, it is just used as a prefix in FLV file names.<br></span></td></tr><tr id="sl_svn154_24"><td class="source"><span class="str"><br></span></td></tr><tr id="sl_svn154_25"><td class="source"><span class="str">A test client is available in testClient directory, and can be compiled using Flex Builder. Alternatively, you can use the SWF file to launch<br></span></td></tr><tr id="sl_svn154_26"><td class="source"><span class="str">from testClient/bin-debug after starting the server. Once you have launched the client in the browser, you can connect to<br></span></td></tr><tr id="sl_svn154_27"><td class="source"><span class="str">local host by clicking on 'connect' button. Then click on publish button to publish a stream. Open another browser with<br></span></td></tr><tr id="sl_sv
|
|||
|
<pre><table width="100%"><tbody><tr class="cursor_stop cursor_hidden"><td></td></tr></tbody></table></pre>
|
|||
|
</td>
|
|||
|
</tr></tbody></table>
|
|||
|
|
|||
|
|
|||
|
<script type="text/javascript">
|
|||
|
var lineNumUnderMouse = -1;
|
|||
|
|
|||
|
function gutterOver(num) {
|
|||
|
gutterOut();
|
|||
|
var newTR = document.getElementById('gr_svn154_' + num);
|
|||
|
if (newTR) {
|
|||
|
newTR.className = 'undermouse';
|
|||
|
}
|
|||
|
lineNumUnderMouse = num;
|
|||
|
}
|
|||
|
function gutterOut() {
|
|||
|
if (lineNumUnderMouse != -1) {
|
|||
|
var oldTR = document.getElementById(
|
|||
|
'gr_svn154_' + lineNumUnderMouse);
|
|||
|
if (oldTR) {
|
|||
|
oldTR.className = '';
|
|||
|
}
|
|||
|
lineNumUnderMouse = -1;
|
|||
|
}
|
|||
|
}
|
|||
|
var numsGenState = {table_base_id: 'nums_table_'};
|
|||
|
var srcGenState = {table_base_id: 'src_table_'};
|
|||
|
var alignerRunning = false;
|
|||
|
var startOver = false;
|
|||
|
function setLineNumberHeights() {
|
|||
|
if (alignerRunning) {
|
|||
|
startOver = true;
|
|||
|
return;
|
|||
|
}
|
|||
|
numsGenState.chunk_id = 0;
|
|||
|
numsGenState.table = document.getElementById('nums_table_0');
|
|||
|
numsGenState.row_num = 0;
|
|||
|
if (!numsGenState.table) {
|
|||
|
return; // Silently exit if no file is present.
|
|||
|
}
|
|||
|
srcGenState.chunk_id = 0;
|
|||
|
srcGenState.table = document.getElementById('src_table_0');
|
|||
|
srcGenState.row_num = 0;
|
|||
|
alignerRunning = true;
|
|||
|
continueToSetLineNumberHeights();
|
|||
|
}
|
|||
|
function rowGenerator(genState) {
|
|||
|
if (genState.row_num < genState.table.rows.length) {
|
|||
|
var currentRow = genState.table.rows[genState.row_num];
|
|||
|
genState.row_num++;
|
|||
|
return currentRow;
|
|||
|
}
|
|||
|
var newTable = document.getElementById(
|
|||
|
genState.table_base_id + (genState.chunk_id + 1));
|
|||
|
if (newTable) {
|
|||
|
genState.chunk_id++;
|
|||
|
genState.row_num = 0;
|
|||
|
genState.table = newTable;
|
|||
|
return genState.table.rows[0];
|
|||
|
}
|
|||
|
return null;
|
|||
|
}
|
|||
|
var MAX_ROWS_PER_PASS = 1000;
|
|||
|
function continueToSetLineNumberHeights() {
|
|||
|
var rowsInThisPass = 0;
|
|||
|
var numRow = 1;
|
|||
|
var srcRow = 1;
|
|||
|
while (numRow && srcRow && rowsInThisPass < MAX_ROWS_PER_PASS) {
|
|||
|
numRow = rowGenerator(numsGenState);
|
|||
|
srcRow = rowGenerator(srcGenState);
|
|||
|
rowsInThisPass++;
|
|||
|
if (numRow && srcRow) {
|
|||
|
if (numRow.offsetHeight != srcRow.offsetHeight) {
|
|||
|
numRow.firstChild.style.height = srcRow.offsetHeight + 'px';
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
if (rowsInThisPass >= MAX_ROWS_PER_PASS) {
|
|||
|
setTimeout(continueToSetLineNumberHeights, 10);
|
|||
|
} else {
|
|||
|
alignerRunning = false;
|
|||
|
if (startOver) {
|
|||
|
startOver = false;
|
|||
|
setTimeout(setLineNumberHeights, 500);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
function initLineNumberHeights() {
|
|||
|
// Do 2 complete passes, because there can be races
|
|||
|
// between this code and prettify.
|
|||
|
startOver = true;
|
|||
|
setTimeout(setLineNumberHeights, 250);
|
|||
|
window.onresize = setLineNumberHeights;
|
|||
|
}
|
|||
|
initLineNumberHeights();
|
|||
|
</script>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<div id="log">
|
|||
|
<div style="text-align:right">
|
|||
|
<a class="ifCollapse" href="http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py#" onclick="_toggleMeta(this); return false">Show details</a>
|
|||
|
<a class="ifExpand" href="http://code.google.com/p/rtmplite/source/browse/trunk/rtmp.py#" onclick="_toggleMeta(this); return false">Hide details</a>
|
|||
|
</div>
|
|||
|
<div class="ifExpand">
|
|||
|
|
|||
|
|
|||
|
<div class="pmeta_bubble_bg" style="border:1px solid white">
|
|||
|
<div class="round4"></div>
|
|||
|
<div class="round2"></div>
|
|||
|
<div class="round1"></div>
|
|||
|
<div class="box-inner">
|
|||
|
<div id="changelog">
|
|||
|
<p>Change log</p>
|
|||
|
<div>
|
|||
|
<a href="http://code.google.com/p/rtmplite/source/detail?spec=svn154&r=145">r145</a>
|
|||
|
by kundan10
|
|||
|
on Feb 6, 2012
|
|||
|
<a href="http://code.google.com/p/rtmplite/source/diff?spec=svn154&r=145&format=side&path=/trunk/rtmp.py&old_path=/trunk/rtmp.py&old=142">Diff</a>
|
|||
|
</div>
|
|||
|
<pre>patch submitted by Teeed teeed@na1noc.pl
|
|||
|
on Jan 16 to fix the result fron onCommand</pre>
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<script type="text/javascript">
|
|||
|
var detail_url = '/p/rtmplite/source/detail?r=145&spec=svn154';
|
|||
|
var publish_url = '/p/rtmplite/source/detail?r=145&spec=svn154#publish';
|
|||
|
// describe the paths of this revision in javascript.
|
|||
|
var changed_paths = [];
|
|||
|
var changed_urls = [];
|
|||
|
|
|||
|
changed_paths.push('/trunk/rtmp.py');
|
|||
|
changed_urls.push('/p/rtmplite/source/browse/trunk/rtmp.py?r\x3d145\x26spec\x3dsvn154');
|
|||
|
|
|||
|
var selected_path = '/trunk/rtmp.py';
|
|||
|
|
|||
|
|
|||
|
changed_paths.push('/trunk/siprtmp_gevent.py');
|
|||
|
changed_urls.push('/p/rtmplite/source/browse/trunk/siprtmp_gevent.py?r\x3d145\x26spec\x3dsvn154');
|
|||
|
|
|||
|
|
|||
|
function getCurrentPageIndex() {
|
|||
|
for (var i = 0; i < changed_paths.length; i++) {
|
|||
|
if (selected_path == changed_paths[i]) {
|
|||
|
return i;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
function getNextPage() {
|
|||
|
var i = getCurrentPageIndex();
|
|||
|
if (i < changed_paths.length - 1) {
|
|||
|
return changed_urls[i + 1];
|
|||
|
}
|
|||
|
return null;
|
|||
|
}
|
|||
|
function getPreviousPage() {
|
|||
|
var i = getCurrentPageIndex();
|
|||
|
if (i > 0) {
|
|||
|
return changed_urls[i - 1];
|
|||
|
}
|
|||
|
return null;
|
|||
|
}
|
|||
|
function gotoNextPage() {
|
|||
|
var page = getNextPage();
|
|||
|
if (!page) {
|
|||
|
page = detail_url;
|
|||
|
}
|
|||
|
window.location = page;
|
|||
|
}
|
|||
|
function gotoPreviousPage() {
|
|||
|
var page = getPreviousPage();
|
|||
|
if (!page) {
|
|||
|
page = detail_url;
|
|||
|
}
|
|||
|
window.location = page;
|
|||
|
}
|
|||
|
function gotoDetailPage() {
|
|||
|
window.location = detail_url;
|
|||
|
}
|
|||
|
function gotoPublishPage() {
|
|||
|
window.location = publish_url;
|
|||
|
}
|
|||
|
</script>
|
|||
|
|
|||
|
|
|||
|
<style type="text/css">
|
|||
|
#review_nav {
|
|||
|
border-top: 3px solid white;
|
|||
|
padding-top: 6px;
|
|||
|
margin-top: 1em;
|
|||
|
}
|
|||
|
#review_nav td {
|
|||
|
vertical-align: middle;
|
|||
|
}
|
|||
|
#review_nav select {
|
|||
|
margin: .5em 0;
|
|||
|
}
|
|||
|
</style>
|
|||
|
<div id="review_nav">
|
|||
|
<table><tbody><tr><td>Go to: </td><td>
|
|||
|
<select name="files_in_rev" onchange="window.location=this.value">
|
|||
|
|
|||
|
<option value="/p/rtmplite/source/browse/trunk/rtmp.py?r=145&spec=svn154" selected="selected">/trunk/rtmp.py</option>
|
|||
|
|
|||
|
<option value="/p/rtmplite/source/browse/trunk/siprtmp_gevent.py?r=145&spec=svn154">/trunk/siprtmp_gevent.py</option>
|
|||
|
|
|||
|
</select>
|
|||
|
</td></tr></tbody></table>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
</div>
|
|||
|
<div class="round1"></div>
|
|||
|
<div class="round2"></div>
|
|||
|
<div class="round4"></div>
|
|||
|
</div>
|
|||
|
<div class="pmeta_bubble_bg" style="border:1px solid white">
|
|||
|
<div class="round4"></div>
|
|||
|
<div class="round2"></div>
|
|||
|
<div class="round1"></div>
|
|||
|
<div class="box-inner">
|
|||
|
<div id="older_bubble">
|
|||
|
<p>Older revisions</p>
|
|||
|
|
|||
|
|
|||
|
<div class="closed" style="margin-bottom:3px;">
|
|||
|
<img class="ifClosed" onclick="_toggleHidden(this)" src="./rtmp_files/plus.gif">
|
|||
|
<img class="ifOpened" onclick="_toggleHidden(this)" src="./rtmp_files/minus.gif">
|
|||
|
<a href="http://code.google.com/p/rtmplite/source/detail?spec=svn154&r=142">r142</a>
|
|||
|
by kundan10
|
|||
|
on Feb 5, 2012
|
|||
|
<a href="http://code.google.com/p/rtmplite/source/diff?spec=svn154&r=142&format=side&path=/trunk/rtmp.py&old_path=/trunk/rtmp.py&old=141">Diff</a>
|
|||
|
<br>
|
|||
|
<pre class="ifOpened">reverting <a href="http://code.google.com/p/rtmplite/source/detail?r=141">r141</a> since it causes
|
|||
|
exception in setting self.rpc because
|
|||
|
rpc exists as a function</pre>
|
|||
|
</div>
|
|||
|
|
|||
|
<div class="closed" style="margin-bottom:3px;">
|
|||
|
<img class="ifClosed" onclick="_toggleHidden(this)" src="./rtmp_files/plus.gif">
|
|||
|
<img class="ifOpened" onclick="_toggleHidden(this)" src="./rtmp_files/minus.gif">
|
|||
|
<a href="http://code.google.com/p/rtmplite/source/detail?spec=svn154&r=141">r141</a>
|
|||
|
by pratnama
|
|||
|
on Jan 28, 2012
|
|||
|
<a href="http://code.google.com/p/rtmplite/source/diff?spec=svn154&r=141&format=side&path=/trunk/rtmp.py&old_path=/trunk/rtmp.py&old=137">Diff</a>
|
|||
|
<br>
|
|||
|
<pre class="ifOpened">force self.rpc to be Message.RPC on
|
|||
|
NetConnection.connect() even in AMF3.
|
|||
|
AMF3 is fully working now</pre>
|
|||
|
</div>
|
|||
|
|
|||
|
<div class="closed" style="margin-bottom:3px;">
|
|||
|
<img class="ifClosed" onclick="_toggleHidden(this)" src="./rtmp_files/plus.gif">
|
|||
|
<img class="ifOpened" onclick="_toggleHidden(this)" src="./rtmp_files/minus.gif">
|
|||
|
<a href="http://code.google.com/p/rtmplite/source/detail?spec=svn154&r=137">r137</a>
|
|||
|
by kundan10
|
|||
|
on Jan 20, 2012
|
|||
|
<a href="http://code.google.com/p/rtmplite/source/diff?spec=svn154&r=137&format=side&path=/trunk/rtmp.py&old_path=/trunk/rtmp.py&old=121">Diff</a>
|
|||
|
<br>
|
|||
|
<pre class="ifOpened">show media flow trace only for -D.
|
|||
|
support streambegin and define FLV in
|
|||
|
gevent version. ignore stream name
|
|||
|
after ?. don't include objectEncoding
|
|||
|
in connect success if connect did not
|
|||
|
...</pre>
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
<a href="http://code.google.com/p/rtmplite/source/list?path=/trunk/rtmp.py&start=145">All revisions of this file</a>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<div class="round1"></div>
|
|||
|
<div class="round2"></div>
|
|||
|
<div class="round4"></div>
|
|||
|
</div>
|
|||
|
|
|||
|
<div class="pmeta_bubble_bg" style="border:1px solid white">
|
|||
|
<div class="round4"></div>
|
|||
|
<div class="round2"></div>
|
|||
|
<div class="round1"></div>
|
|||
|
<div class="box-inner">
|
|||
|
<div id="fileinfo_bubble">
|
|||
|
<p>File info</p>
|
|||
|
|
|||
|
<div>Size: 65812 bytes,
|
|||
|
1214 lines</div>
|
|||
|
|
|||
|
<div><a href="http://rtmplite.googlecode.com/svn/trunk/rtmp.py">View raw file</a></div>
|
|||
|
</div>
|
|||
|
|
|||
|
<div id="props">
|
|||
|
<p>File properties</p>
|
|||
|
<dl>
|
|||
|
|
|||
|
<dt>svn:executable</dt>
|
|||
|
<dd>*</dd>
|
|||
|
|
|||
|
<dt>svn:keywords</dt>
|
|||
|
<dd>Author Id Revision Date</dd>
|
|||
|
|
|||
|
</dl>
|
|||
|
</div>
|
|||
|
|
|||
|
</div>
|
|||
|
<div class="round1"></div>
|
|||
|
<div class="round2"></div>
|
|||
|
<div class="round4"></div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
</div>
|
|||
|
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
|
|||
|
<script src="./rtmp_files/prettify.js"></script>
|
|||
|
<script type="text/javascript">prettyPrint();</script>
|
|||
|
|
|||
|
|
|||
|
<script src="./rtmp_files/source_file_scripts.js"></script>
|
|||
|
|
|||
|
<script type="text/javascript" src="./rtmp_files/kibbles-1.3.3.comp.js"></script>
|
|||
|
<script type="text/javascript">
|
|||
|
var lastStop = null;
|
|||
|
var initialized = false;
|
|||
|
|
|||
|
function updateCursor(next, prev) {
|
|||
|
if (prev && prev.element) {
|
|||
|
prev.element.className = 'cursor_stop cursor_hidden';
|
|||
|
}
|
|||
|
if (next && next.element) {
|
|||
|
next.element.className = 'cursor_stop cursor';
|
|||
|
lastStop = next.index;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function pubRevealed(data) {
|
|||
|
updateCursorForCell(data.cellId, 'cursor_stop cursor_hidden');
|
|||
|
if (initialized) {
|
|||
|
reloadCursors();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function draftRevealed(data) {
|
|||
|
updateCursorForCell(data.cellId, 'cursor_stop cursor_hidden');
|
|||
|
if (initialized) {
|
|||
|
reloadCursors();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function draftDestroyed(data) {
|
|||
|
updateCursorForCell(data.cellId, 'nocursor');
|
|||
|
if (initialized) {
|
|||
|
reloadCursors();
|
|||
|
}
|
|||
|
}
|
|||
|
function reloadCursors() {
|
|||
|
kibbles.skipper.reset();
|
|||
|
loadCursors();
|
|||
|
if (lastStop != null) {
|
|||
|
kibbles.skipper.setCurrentStop(lastStop);
|
|||
|
}
|
|||
|
}
|
|||
|
// possibly the simplest way to insert any newly added comments
|
|||
|
// is to update the class of the corresponding cursor row,
|
|||
|
// then refresh the entire list of rows.
|
|||
|
function updateCursorForCell(cellId, className) {
|
|||
|
var cell = document.getElementById(cellId);
|
|||
|
// we have to go two rows back to find the cursor location
|
|||
|
var row = getPreviousElement(cell.parentNode);
|
|||
|
row.className = className;
|
|||
|
}
|
|||
|
// returns the previous element, ignores text nodes.
|
|||
|
function getPreviousElement(e) {
|
|||
|
var element = e.previousSibling;
|
|||
|
if (element.nodeType == 3) {
|
|||
|
element = element.previousSibling;
|
|||
|
}
|
|||
|
if (element && element.tagName) {
|
|||
|
return element;
|
|||
|
}
|
|||
|
}
|
|||
|
function loadCursors() {
|
|||
|
// register our elements with skipper
|
|||
|
var elements = CR_getElements('*', 'cursor_stop');
|
|||
|
var len = elements.length;
|
|||
|
for (var i = 0; i < len; i++) {
|
|||
|
var element = elements[i];
|
|||
|
element.className = 'cursor_stop cursor_hidden';
|
|||
|
kibbles.skipper.append(element);
|
|||
|
}
|
|||
|
}
|
|||
|
function toggleComments() {
|
|||
|
CR_toggleCommentDisplay();
|
|||
|
reloadCursors();
|
|||
|
}
|
|||
|
function keysOnLoadHandler() {
|
|||
|
// setup skipper
|
|||
|
kibbles.skipper.addStopListener(
|
|||
|
kibbles.skipper.LISTENER_TYPE.PRE, updateCursor);
|
|||
|
// Set the 'offset' option to return the middle of the client area
|
|||
|
// an option can be a static value, or a callback
|
|||
|
kibbles.skipper.setOption('padding_top', 50);
|
|||
|
// Set the 'offset' option to return the middle of the client area
|
|||
|
// an option can be a static value, or a callback
|
|||
|
kibbles.skipper.setOption('padding_bottom', 100);
|
|||
|
// Register our keys
|
|||
|
kibbles.skipper.addFwdKey("n");
|
|||
|
kibbles.skipper.addRevKey("p");
|
|||
|
kibbles.keys.addKeyPressListener(
|
|||
|
'u', function() { window.location = detail_url; });
|
|||
|
kibbles.keys.addKeyPressListener(
|
|||
|
'r', function() { window.location = detail_url + '#publish'; });
|
|||
|
|
|||
|
kibbles.keys.addKeyPressListener('j', gotoNextPage);
|
|||
|
kibbles.keys.addKeyPressListener('k', gotoPreviousPage);
|
|||
|
|
|||
|
|
|||
|
}
|
|||
|
</script>
|
|||
|
<script src="./rtmp_files/code_review_scripts.js"></script>
|
|||
|
<script type="text/javascript">
|
|||
|
function showPublishInstructions() {
|
|||
|
var element = document.getElementById('review_instr');
|
|||
|
if (element) {
|
|||
|
element.className = 'opened';
|
|||
|
}
|
|||
|
}
|
|||
|
var codereviews;
|
|||
|
function revsOnLoadHandler() {
|
|||
|
// register our source container with the commenting code
|
|||
|
var paths = {'svn154': '/trunk/rtmp.py'}
|
|||
|
codereviews = CR_controller.setup(
|
|||
|
{"profileUrl":["/u/102069584091941751068/"],"token":"vVg-YEkpsP38PydkCFlVS-ioMOA:1335711600965","assetHostPath":"http://www.gstatic.com/codesite/ph","domainName":null,"assetVersionPath":"http://www.gstatic.com/codesite/ph/12151595242108277468","projectHomeUrl":"/p/rtmplite","relativeBaseUrl":"","projectName":"rtmplite","loggedInUserEmail":"arutyunyan.roman@gmail.com"}, '', 'svn154', paths,
|
|||
|
CR_BrowseIntegrationFactory);
|
|||
|
|
|||
|
codereviews.registerActivityListener(CR_ActivityType.REVEAL_DRAFT_PLATE, showPublishInstructions);
|
|||
|
|
|||
|
codereviews.registerActivityListener(CR_ActivityType.REVEAL_PUB_PLATE, pubRevealed);
|
|||
|
codereviews.registerActivityListener(CR_ActivityType.REVEAL_DRAFT_PLATE, draftRevealed);
|
|||
|
codereviews.registerActivityListener(CR_ActivityType.DISCARD_DRAFT_COMMENT, draftDestroyed);
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
var initialized = true;
|
|||
|
reloadCursors();
|
|||
|
}
|
|||
|
window.onload = function() {keysOnLoadHandler(); revsOnLoadHandler();};
|
|||
|
|
|||
|
</script>
|
|||
|
<script type="text/javascript" src="./rtmp_files/dit_scripts.js"></script>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<script type="text/javascript" src="./rtmp_files/ph_core.js"></script>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<script type="text/javascript" src="./rtmp_files/codesite_product_dictionary_ph.pack.04102009.js"></script>
|
|||
|
</div>
|
|||
|
<div id="footer" dir="ltr">
|
|||
|
<div class="text">
|
|||
|
<a href="http://code.google.com/projecthosting/terms.html">Terms</a> -
|
|||
|
<a href="http://www.google.com/privacy.html">Privacy</a> -
|
|||
|
<a href="http://code.google.com/p/support/">Project Hosting Help</a>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<div class="hostedBy" style="margin-top: -20px;">
|
|||
|
<span style="vertical-align: top;">Powered by <a href="http://code.google.com/projecthosting/">Google Project Hosting</a></span>
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<div class="menuDiv instance0" id="menuDiv-projects-dropdown" style="position: absolute; display: none; top: 18px; left: 1144px; "><div class="menuCategory controls first"><hr class="menuSeparator"><a class="menuItem" style="display: block; " href="http://code.google.com/more/">Find developer products...</a><a class="menuItem" style="display: block; " href="http://code.google.com/hosting/">Find open source projects...</a></div></div></body></html>
|