[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] /srv/bzr/gnash/trunk r11741: Regenertated preformatted do
From: |
Rob Savoye |
Subject: |
[Gnash-commit] /srv/bzr/gnash/trunk r11741: Regenertated preformatted documentation after updating the copyright. |
Date: |
Fri, 01 Jan 2010 13:41:28 -0700 |
User-agent: |
Bazaar (2.0.2) |
------------------------------------------------------------
revno: 11741 [merge]
committer: Rob Savoye <address@hidden>
branch nick: trunk
timestamp: Fri 2010-01-01 13:41:28 -0700
message:
Regenertated preformatted documentation after updating the copyright.
Fix xml syntax bug in gnashrc.xml from new entry.
Big merge from experimental cygnal branch.
modified:
cygnal/cgi-bin/oflaDemo/oflaDemo.cpp
cygnal/cygnal.cpp
cygnal/handler.cpp
cygnal/handler.h
cygnal/http_server.cpp
cygnal/http_server.h
cygnal/rtmp_server.cpp
cygnal/rtmp_server.h
doc/C/preformatted/cygnal.1.in
doc/C/preformatted/dumpshm.1.in
doc/C/preformatted/flvdumper.1.in
doc/C/preformatted/gnash.1.in
doc/C/preformatted/gnash_user.info.in
doc/C/preformatted/gnashref.html.in
doc/C/preformatted/gnashuser.html.in
doc/C/preformatted/gprocessor.1.in
doc/C/preformatted/rtmpget.1.in
doc/C/preformatted/soldumper.1.in
doc/C/usermanual/gnashrc.xml
libamf/amf.cpp
libamf/amf.h
libamf/buffer.cpp
libamf/flv.cpp
libamf/flv.h
libbase/sharedlib.cpp
libnet/cache.cpp
libnet/cache.h
libnet/diskstream.cpp
libnet/diskstream.h
libnet/http.cpp
libnet/http.h
libnet/network.cpp
libnet/network.h
libnet/rtmp.cpp
libnet/rtmp.h
libnet/rtmp_msg.cpp
libnet/rtmp_msg.h
testsuite/libamf.all/test_amf.cpp
testsuite/libamf.all/test_buffer.cpp
testsuite/libnet.all/test_diskstream.cpp
testsuite/libnet.all/test_http.cpp
testsuite/libnet.all/test_rtmp.cpp
testsuite/network.all/Makefile.am
testsuite/network.all/test_ssl.cpp
utilities/flvdumper.cpp
=== modified file 'cygnal/cgi-bin/oflaDemo/oflaDemo.cpp'
--- a/cygnal/cgi-bin/oflaDemo/oflaDemo.cpp 2010-01-01 17:48:26 +0000
+++ b/cygnal/cgi-bin/oflaDemo/oflaDemo.cpp 2010-01-01 20:41:28 +0000
@@ -525,7 +525,7 @@
#endif
}
} else {
- log_error("Unknown oflaDemp method \"%s\" to INVOKE!", el1->getName());
+ log_error("Unknown oflaDemo method \"%s\" to INVOKE!", el1->getName());
}
return headers;
=== modified file 'cygnal/cygnal.cpp'
--- a/cygnal/cygnal.cpp 2010-01-01 17:48:26 +0000
+++ b/cygnal/cygnal.cpp 2010-01-01 20:41:28 +0000
@@ -110,13 +110,8 @@
void connection_handler(Network::thread_params_t *args);
void event_handler(Network::thread_params_t *args);
-void dispatch_handler(Network::thread_params_t *args);
void admin_handler(Network::thread_params_t *args);
-// This is the global object for Cygnl
-// The debug log used by all the gnash libraries.
-static Cygnal& cyg = Cygnal::getDefaultInstance();
-
// Toggles very verbose debugging info from the network Network class
static bool netdebug = false;
@@ -153,7 +148,9 @@
map<int, Network *> networks;
-// end of globals
+// This is the global object for Cygnl
+// The debug log used by all the gnash libraries.
+static Cygnal& cyg = Cygnal::getDefaultInstance();
// The debug log used by all the gnash libraries.
static LogFile& dbglogfile = LogFile::getDefaultInstance();
@@ -164,8 +161,8 @@
// Cache support for responses and files.
static Cache& cache = Cache::getDefaultInstance();
-// The list of active cgis beiung executed.
-static std::map<std::string, Proc> procs; // = proc::getDefaultInstance();
+// The list of active cgis being executed.
+//static std::map<std::string, Proc> procs; // = proc::getDefaultInstance();
// This mutex is used to signify when all the threads are done.
static boost::condition alldone;
@@ -223,7 +220,7 @@
bool
Cygnal::loadPeersFile()
{
- GNASH_REPORT_FUNCTION;
+ // GNASH_REPORT_FUNCTION;
loadPeersFile("./peers.conf");
@@ -339,7 +336,7 @@
// tmp += (*it);
// log_network("Constructed: %s/%s", uri.str(), *it);
- URL url(uri.str());
+ gnash::URL url(uri.str());
if (!(peer.fd = net.connectToServer(uri.str()))) {
log_network("Couldn't connect to %s", uri.str());
peer.connected = false;
@@ -450,6 +447,7 @@
docroot = crcfile.getDocumentRoot();
} else {
docroot = "/var/www/html/software/tests/";
+ crcfile.setDocumentRoot(docroot);
}
if (crcfile.getPortOffset()) {
port_offset = crcfile.getPortOffset();
@@ -748,7 +746,12 @@
// All threads should exit now.
alldone.notify_all();
}
-
+
+// A connection handler is started for each port the server needs to
+// wait on for incoming connections. When it gets an incoming
+// connection, it reads the first packet to get the resource name, and
+// then starts the event handler thread if it's a newly requested
+// resource, otherwise it loads a copy of the cached resource.
void
connection_handler(Network::thread_params_t *args)
{
@@ -807,8 +810,7 @@
// Rotate in a range of 0 to the limit.
tid = (tid + 1) % (spawn_limit + 1);
- log_network("%s handler: thread ID #%d, fd #%d",
proto_str[args->protocol], tid,
- fd);
+ // log_network("%s handler: thread ID #%d, fd #%d",
proto_str[args->protocol], tid, fd);
// Wait for a connection to this tcp/ip from a client. If set
// to true, this will block until a request comes in. If set
@@ -821,61 +823,73 @@
continue;
} else {
log_network("*** New %s network connection for thread ID #%d, fd
#%d ***",
- proto_str[args->protocol], tid, fd);
+ proto_str[args->protocol], tid, args->netfd);
}
-
- // struct pollfd fds;
- // fds.fd = args->netfd;
- // fds.events = POLLIN | POLLRDHUP;
-
- // Each dispatch thread gets it's own argument data and
- // network connection data.
//
// Setup HTTP handler
//
if (args->protocol == Network::HTTP) {
- boost::shared_ptr<Handler> hand(new Handler);
Network::thread_params_t *hargs = new Network::thread_params_t;
+ // std::copy(args, args+sizeof(Network::thread_params_t), &hargs);
+ hargs->protocol = args->protocol;
+ hargs->netfd = args->netfd;
+#if 0
+ boost::shared_ptr<Handler> hand = cyg.findHandler(path);
HTTPServer *http = new HTTPServer;
-#if 0
- http->recvMsg(args->netfd);
+ hargs.entry = http;
+ http->setDocRoot(crcfile.getDocumentRoot());
boost::shared_ptr<amf::Buffer> buf(http->peekChunk());
http->processHeaderFields(*buf);
- string hostname;
+ string hostname, path;
string::size_type pos = http->getField("host").find(":", 0);
if (pos != string::npos) {
hostname += http->getField("host").substr(0, pos);
} else {
hostname += "localhost";
}
- hargs->filespec = hostname + http->getFilespec();
-#else
- hargs->filespec = docroot;
+ path = http->getFilespec();
+ string key = hostname + path;
#endif
- hargs->netfd = args->netfd;
- hargs->protocol = args->protocol;
- hargs->entry = http;
- hargs->tid = tid;
- log_network("Starting new event handler thread for fd #%d, tid #%d",
- args->netfd, tid);
- tids.increment();
- hand->addClient(hargs->netfd, Network::HTTP);
- hargs->handler = reinterpret_cast<void *>(hand.get());
- boost::bind(http_handler, hargs);
-
- // If in multi-threaded mode (the default), start a thread
- // with a connection_handler for each port we're interested
- // in. Each port of course has a different protocol.
-#if 0
- if (crcfile.getThreadingFlag() == true) {
- boost::thread event_thread(boost::bind(&event_handler, hargs));
+ string key;
+ Handler *hand = 0;
+ if (!hand) {
+ hand = new Handler;
+ hand->addClient(args->netfd, Network::HTTP);
+ int retries = 3;
+ amf::Buffer *buf = 0;
+ do {
+ buf = hand->parseFirstRequest(args->netfd, Network::HTTP);
+ if (!buf) {
+ retries--;
+ continue;
+ } else {
+ break;
+ }
+ } while (retries);
+ string &key = hand->getKey(args->netfd);
+ log_network("Creating new %s Handler for %s using fd #%d",
+ proto_str[hargs->protocol], key, hargs->netfd);
+ hargs->handler = hand;
+ hargs->buffer = buf;
+ hargs->filespec = key;
+ // cyg.addHandler(key, hand);
+
+ // If in multi-threaded mode (the default), start a thread
+ // with a connection_handler for each port we're interested
+ // in. Each port of could have a different protocol.
+ boost::bind(event_handler, hargs);
+ if (crcfile.getThreadingFlag() == true) {
+ boost::thread event_thread(boost::bind(&event_handler,
hargs));
+ } else {
+ event_handler(hargs);
+ // We're done, close this network connection
+ }
} else {
-#endif
- event_handler(hargs);
- // We're done, close this network connection
- net.closeNet(args->netfd);
- // }
+ log_network("Resuing %s Handler for %s using fd #%d",
+ proto_str[hargs->protocol], key, hargs->netfd);
+ hand->addClient(args->netfd, Network::HTTP);
+ }
// delete http;
} // end of if HTTP
@@ -892,14 +906,14 @@
return;
}
URL url(tcurl->to_string());
- std::string key = url.hostname() + url.path();
+ string key = url.hostname() + url.path();
boost::shared_ptr<Handler> hand = cyg.findHandler(url.path());
if (!hand) {
log_network("Creating new %s Handler for: %s for fd %#d",
proto_str[args->protocol], key, args->netfd);
hand.reset(new Handler);
cyg.addHandler(key, hand);
- args->entry = rtmp;
+ // args->entry = rtmp;
hand->setNetConnection(rtmp->getNetConnection());
std::vector<boost::shared_ptr<Cygnal::peer_t> >::iterator it;
std::vector<boost::shared_ptr<Cygnal::peer_t> > active =
cyg.getActive();
@@ -945,7 +959,7 @@
} else {
log_error("Couldn't load plugin for %s", key);
}
-
+
// // We're done, close this network connection
// if (crcfile.getThreadingFlag() == true) {
// net.closeNet(args->netfd);
@@ -965,138 +979,77 @@
} // end of connection_handler
-#if 0
-void
-dispatch_handler(Network::thread_params_t *args)
-{
- GNASH_REPORT_FUNCTION;
-
-// Handler *hand = reinterpret_cast<Handler *>(args->handler);
- Network *net = reinterpret_cast<Network *>(args->handler);
-// Network net;
- int timeout = 30;
- bool done = false;
-
- do {
- int limit = net->getPollFDSize();
- net->setTimeout(timeout);
- cerr << "LIMIT is: " << limit << endl;
- if (limit > 0) {
- struct pollfd *fds = net->getPollFDPtr();
- boost::shared_ptr< vector<struct pollfd> > hits;
- try {
-// boost::shared_ptr< vector< int > >
hits(net.waitForNetData(limit, fds));
- hits = net->waitForNetData(limit, fds);
- vector<struct pollfd>::iterator it;
- cerr << "Hits: " << hits->size() << endl;
- cerr << "Pollfds: " << net->getPollFDSize() << endl;
- for (it = hits->begin(); it != hits->end(); it++) {
- // We got an error, which isn't always a crises, as some
are normal
- // if the client disconnects while we're talking to it.
- if ((it->revents & POLLRDHUP) || (it->revents & POLLNVAL))
{
- log_network("Revents has a POLLRDHUP or POLLNVAL set to
%d for fd #%d",
- it->revents, it->fd);
- if (it->fd > 0) {
- net->erasePollFD(it->fd);
- net->closeNet(it->fd);
- }
-// continue;
- break;
- } else {
- // We got some data, so process it
- log_network("Got something on fd #%d, 0x%x", it->fd,
it->revents);
- if (it->fd > 0) {
- // Call the protocol handler for this network
connection
- /* bool ret = */ net->getEntry(it->fd)(args);
- // Call the protocol handler for this network connection
-// bool ret = net->getEntry(it->fd)(args);
-
-// log_network("Handler returned %s", (ret) ? "true" :
"false");
- // FIXME: we currently force a 'close connection'
at the end
- // of sending a file, since apache does too. This
pretty much
- // blows persistance,
-// if (ret) {
- networks[args->tid] = 0;
- net->closeNet(it->fd);
- net->erasePollFD(it->fd);
-// }
- }
- }
- }
- } catch (std::exception& e) {
- log_error("Network connection was dropped: %s", e.what());
- vector<struct pollfd>::const_iterator it;
- if (hits) {
- for (it = hits->begin(); it != hits->end(); it++) {
- log_network("Need to disconnect fd #%d, it got an
error.", (*it).fd);
- }
- }
- }
- } else {
- log_network("nothing to wait for...");
- if (crcfile.getThreadingFlag()) {
- done = true;
- }
- }
- } while (!done);
- tids.decrement();
-
-} // end of dispatch_handler
-#endif
-
void
event_handler(Network::thread_params_t *args)
{
GNASH_REPORT_FUNCTION;
- Network net;
- int timeout = 30;
- bool done = false;
-
+ Network::thread_params_t largs;
+ // std::copy(args, args+sizeof(Network::thread_params_t), &largs);
Handler *hand = reinterpret_cast<Handler *>(args->handler);
-
- // Extract the hostname and path to the cgi-bin sandbox.
- string host;
- string path;
- string::size_type pos = args->filespec.find("/", 0);
- if (pos != string::npos) {
- host = args->filespec.substr(0, pos);
- path = args->filespec.substr(pos+1, args->filespec.size());
- }
-
- if (args->protocol != Network::HTTP) {
- if (host.empty()) {
- log_error("No hostname supplied for handler!");
- return;
- }
- if (path.empty()) {
- log_error("No pathname supplied for handler!");
- return;
- }
- }
-
- hand->setName(path);
+
+ largs.protocol = args->protocol;
+ largs.netfd = args->netfd;
+ largs.port = args->port;
+ largs.buffer = args->buffer;
+ largs.entry = args->entry;
+ largs.filespec = args->filespec;
+
+ Network net;
+ int timeout = 30;
+ int retries = 0;
+ bool done = false;
+
+ fd_set hits;
+ FD_ZERO(&hits);
+ FD_SET(args->netfd, &hits);
+
+ tids.increment();
+
+ // We need to calculate the highest numbered file descriptor
+ // for select. We may want to do this elsewhere, as it could
+ // be a performance hit as the number of file descriptors gets
+ // larger.
+ log_debug("Handler has %d clients attached, %d threads",
+ hand->getClients().size(), tids.num_of_tids());
+
+ int max = 0;
+ for (size_t i = 0; i<hand->getClients().size(); i++) {
+ log_debug("Handler client[%d] is: %d", i, hand->getClient(i));
+ if (hand->getClient(i) >= max) {
+ max = hand->getClient(i);
+ // hand->dump();
+ }
+ }
+
+ do {
+
+ // If we have active disk streams, send those packets first.
+ // 0 is a reserved stream, so we start with 1, as the reserved
+ // stream isn't one we care about here.
+ if (hand->getActiveDiskStreams()) {
+ log_network("%d active disk streams",
+ hand->getActiveDiskStreams());
+ // hand->dump();
+ }
#if 0
- if (!hand->initialized()) {
- log_network("Starting Handler for %s", path);
- }
+ boost::shared_ptr<DiskStream>
filestream(cache.findFile(args->filespec));
+ if (filestream) {
+ filestream->dump();
+ }
+// #else
+// cache.dump();
#endif
- do {
- net.setTimeout(timeout);
- fd_set hits;
- // Wait for something from one of the file descriptors
- hits = net.waitForNetData(hand->getClients());
- int max = 0;
- // We need to calculate the highest numbered file descriptor
- // for select. We may want to do this elsewhere, as it could
- // be a performance hit as the number of file descriptors gets
- // larger.
- for (size_t i = 0; i<hand->getClients().size(); i++) {
- if (hand->getClients()[i] > max) {
- max = hand->getClients()[i];
+ hand->dump();
+ for (int i=1; i <= hand->getActiveDiskStreams(); i++) {
+ boost::shared_ptr<DiskStream> ds = hand->getDiskStream(i);
+ if (ds) {
+// ds->dump();
+ // Only play the next chunk of the file.
+ ds->play(i, true);
}
}
-
+
// See if we have any data waiting behind any of the file
// descriptors.
for (int i=0; i <= max + 1; i++) {
@@ -1109,28 +1062,53 @@
log_error("No protocol specified!");
break;
case Network::HTTP:
- args->netfd = i;
- args->filespec = path;
- if (!http_handler(args)) {
- log_network("Done with HTTP connection for fd #%d,
CGI %s", i, path);
- return;
- }
- break;
+ {
+ net.setTimeout(30);
+ largs.netfd = i;
+ // largs.filespec = fullpath;
+ boost::shared_ptr<HTTPServer> &http =
hand->getHTTPHandler(i);
+ if (!http->http_handler(hand, args->netfd, args->buffer))
{
+ log_network("Done with HTTP connection for fd #%d,
CGI %s", i, args->filespec);
+ net.closeNet(args->netfd);
+ hand->removeClient(args->netfd);
+ done = true;
+ } else {
+ log_network("Not Done with HTTP connection for fd
#%d, it's a persistant connection.", i);
+
+ }
+ continue;
+ }
case Network::RTMP:
args->netfd = i;
- args->filespec = path;
+ // args->filespec = path;
if (!rtmp_handler(args)) {
- log_network("Done with RTMP connection for fd #%d,
CGI %s", i, path);
- return;
+ log_network("Done with RTMP connection for fd #%d,
CGI ", i, args->filespec);
+ done = true;
}
break;
case Network::RTMPT:
+ {
+ net.setTimeout(timeout);
args->netfd = i;
- args->filespec = path;
- http_handler(args);
- break;
+ boost::shared_ptr<HTTPServer> &http =
hand->getHTTPHandler(i);
+ // args->filespec = path;
+ if (!http->http_handler(hand, args->netfd, args->buffer))
{
+ log_network("Done with HTTP connection for fd #%d,
CGI %s", i, largs.filespec);
+ return;
+ }
+ break;
+ }
case Network::RTMPTS:
+ {
+ args->netfd = i;
+ // args->filespec = path;
+ boost::shared_ptr<HTTPServer> &http =
hand->getHTTPHandler(i);
+ if (!http->http_handler(hand, args->netfd, args->buffer))
{
+ log_network("Done with HTTP connection for fd #%d,
CGI %s", i, args->filespec);
+ return;
+ }
break;
+ }
case Network::RTMPE:
break;
case Network::RTMPS:
@@ -1139,13 +1117,37 @@
break;
default:
log_error("Unsupported network protocol for fd #%d, %d",
- args->netfd, hand->getProtocol(i));
+ largs.netfd, hand->getProtocol(i));
done = true;
break;
}
+ delete args->buffer;
}
}
+
+ // // Clear the current message so next time we read new data
+ // args->buffer->clear();
+ // largs.buffer->clear();
+
+ // Wait for something from one of the file descriptors
+ net.setTimeout(30);
+ hits = net.waitForNetData(hand->getClients());
+ if (FD_ISSET(0, &hits)) {
+ FD_CLR(0, &hits);
+ log_network("Got no hits, %d retries", retries);
+ // net.closeNet(args->netfd);
+ // hand->removeClient(args->netfd);
+ // done = true;
+ }
+ retries++;
+ if (retries >= 10) {
+ net.closeNet(args->netfd);
+ hand->removeClient(args->netfd);
+ done = true;
+ }
} while (!done);
+
+ tids.decrement();
} // end of event_handler
=== modified file 'cygnal/handler.cpp'
--- a/cygnal/handler.cpp 2010-01-01 17:48:26 +0000
+++ b/cygnal/handler.cpp 2010-01-01 20:41:28 +0000
@@ -23,6 +23,8 @@
#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/shared_ptr.hpp>
+#include <boost/shared_array.hpp>
+#include <boost/scoped_ptr.hpp>
#include <boost/bind.hpp>
#include <algorithm>
#include <string>
@@ -46,10 +48,16 @@
#include "buffer.h"
#include "utility.h"
#include "dsodefs.h" //For DSOEXPORT.
+#include "URL.h"
#include "handler.h"
-
+#include "diskstream.h"
#include "rtmp.h"
#include "http.h"
+#include "crc.h"
+#include "flv.h"
+
+#include "rtmp_server.h"
+#include "http_server.h"
using namespace gnash;
using namespace std;
@@ -60,12 +68,17 @@
map<int, Handler *> DSOEXPORT handlers;
+// The user config for Cygnal is loaded and parsed here:
+static CRcInitFile& crcfile = CRcInitFile::getDefaultInstance();
+
Handler::Handler()
- : _streams(2), // streams 0 and 1 appear to be
- // reserved by the system.
- _in_fd(0)
+ :_streams(1), // note that stream 0 is reserved by the system.
+ // _diskstreams(new gnash::DiskStream[STREAMS_BLOCK]),
+ _in_fd(0)
{
// GNASH_REPORT_FUNCTION;
+ // reserve memory for the vector as it makes vector operations
+ // must faster.
}
Handler::~Handler()
@@ -82,22 +95,171 @@
}
size_t
-Handler::addClient(int x, Network::protocols_supported_e proto)
+Handler::addClient(int fd, Network::protocols_supported_e proto)
{
-// GNASH_REPORT_FUNCTION;
+ // GNASH_REPORT_FUNCTION;
+
boost::mutex::scoped_lock lock(_mutex);
- _clients.push_back(x);
- _protocol[x] = proto;
+
+ log_debug("Adding %d to the client array.", fd);
+ switch (proto) {
+ case Network::NONE:
+ break;
+ case Network::HTTP:
+ {
+ boost::shared_ptr<HTTPServer> http(new HTTPServer);
+ _http[fd] = http;
+ break;
+ }
+ case Network::HTTPS:
+ break;
+ case Network::RTMP:
+ {
+ boost::shared_ptr<RTMPServer> rtmp(new RTMPServer);
+ _rtmp[fd] = rtmp;
+ break;
+ }
+ case Network::RTMPT:
+ case Network::RTMPTS:
+ case Network::RTMPE:
+ case Network::RTMPS:
+ case Network::DTN:
+ default:
+ log_unimpl("Protocol %d for Handler::AddClient()", proto);
+ break;
+ }
+
+ _clients.push_back(fd);
+ _protocol[fd] = proto;
return _clients.size();
+}
+
+// Parse the first nessages when starting a new message handler,
+// which is used to determine the name of the resource to
+// initialize, or load from the cache.
+amf::Buffer *
+Handler::parseFirstRequest(int fd, gnash::Network::protocols_supported_e proto)
+{
+ GNASH_REPORT_FUNCTION;
+ string key;
+ Network net;
+ amf::Buffer *buf = 0;
+ boost::mutex::scoped_lock lock(_mutex);
+
+ switch (proto) {
+ case Network::NONE:
+ break;
+ case Network::HTTP:
+ {
+#if 0
+ int ret = _http[fd]->readNet(fd, buf);
+ if (ret) {
+ _http[fd]->processHeaderFields(buf);
+ string hostname, path;
+ string::size_type pos = _http[fd]->getField("host").find(":", 0);
+ if (pos != string::npos) {
+ hostname += _http[fd]->getField("host").substr(0, pos);
+ } else {
+ hostname += "localhost";
+ }
+ path = _http[fd]->getFilespec();
+ key = hostname + path;
+ log_debug("HTTP key is: %s", key);
+ _keys[fd] = key;
+ } else {
+ log_error("HTTP key couldn't be read!");
+ }
+#else
+ HTTPServer http;
+ size_t bytes = http.sniffBytesReady(fd);
+ if (bytes) {
+ buf = new amf::Buffer(bytes);
+ } else {
+ return 0;
+ }
+ int ret = http.readNet(fd, buf);
+ if (ret) {
+ http.processHeaderFields(buf);
+ string hostname, path;
+ string::size_type pos = http.getField("host").find(":", 0);
+ if (pos != string::npos) {
+ hostname += http.getField("host").substr(0, pos);
+ } else {
+ hostname += "localhost";
+ }
+ path = http.getFilespec();
+ key = hostname + path;
+ log_debug("HTTP key is: %s", key);
+ _keys[fd] = key;
+ } else {
+ log_error("HTTP key couldn't be read!");
+ }
+#endif
+ break;
+ }
+ case Network::HTTPS:
+ break;
+ case Network::RTMP:
+ {
+ // _rtmp[fd]->recvMsg(fd);
+ break;
+ }
+ case Network::RTMPT:
+ case Network::RTMPTS:
+ case Network::RTMPE:
+ case Network::RTMPS:
+ case Network::DTN:
+ default:
+ log_error("FD #%d has no protocol handler registered", fd);
+ break;
+ };
+
+ return buf;
+}
+
+int
+Handler::recvMsg(int fd)
+{
+ // GNASH_REPORT_FUNCTION;
+ boost::mutex::scoped_lock lock(_mutex);
+
+ switch (_protocol[fd]) {
+ case Network::NONE:
+ break;
+ case Network::HTTP:
+ {
+ return _http[fd]->recvMsg(fd);
+ break;
+ }
+ case Network::HTTPS:
+ break;
+ case Network::RTMP:
+ case Network::RTMPT:
+ case Network::RTMPTS:
+ case Network::RTMPE:
+ case Network::RTMPS:
+ case Network::DTN:
+ default:
+ log_error("FD #%d has no protocol handler registered", fd);
+ break;
+ }
};
void
Handler::removeClient(int x)
{
-// GNASH_REPORT_FUNCTION;
+ // GNASH_REPORT_FUNCTION;
+
boost::mutex::scoped_lock lock(_mutex);
- _clients.erase(_clients.begin()+x);
+
+ vector<int>::iterator it;
+ for (it = _clients.begin(); it < _clients.end(); ++it) {
+ if (*it == x) {
+ log_debug("Removing %d from the client array.", *it);
+ _clients.erase(it);
+ }
+ }
}
void
@@ -108,7 +270,7 @@
}
void
-Handler::setPlugin(Handler::cygnal_io_t /* read_ptr */, Handler::cygnal_io_t
/* write_ptr */)
+Handler::setPlugin(Handler::cygnal_io_read_t /* read_ptr */,
Handler::cygnal_io_write_t /* write_ptr */)
{
// GNASH_REPORT_FUNCTION;
@@ -118,7 +280,7 @@
boost::shared_ptr<Handler::cygnal_init_t>
Handler::initModule(const std::string& module)
{
- GNASH_REPORT_FUNCTION;
+ // GNASH_REPORT_FUNCTION;
SharedLib *sl;
std::string symbol(module);
@@ -170,7 +332,7 @@
// to the cgi-bin as a dynamically loadable plugin.
symbol = module;
symbol.append("_write_func");
- Handler::cygnal_io_t write_symptr = reinterpret_cast<Handler::cygnal_io_t>
+ Handler::cygnal_io_write_t write_symptr =
reinterpret_cast<Handler::cygnal_io_write_t>
(sl->getInitEntry(symbol));
if (!write_symptr) {
@@ -187,8 +349,7 @@
size_t
Handler::writeToPlugin(boost::uint8_t *data, size_t size)
{
- GNASH_REPORT_FUNCTION;
-
+ // GNASH_REPORT_FUNCTION;
size_t ret = 0;
if (_plugin) {
ret = _plugin->write_func(data, size);
@@ -200,7 +361,8 @@
boost::shared_ptr<amf::Buffer>
Handler::readFromPlugin()
{
- GNASH_REPORT_FUNCTION;
+ // GNASH_REPORT_FUNCTION;
+
boost::shared_ptr<amf::Buffer> buf;
if (_plugin) {
buf = _plugin->read_func();
@@ -212,7 +374,7 @@
bool
Handler::initialized()
{
-// GNASH_REPORT_FUNCTION;
+ // GNASH_REPORT_FUNCTION;
if (_files.empty()
&& (_clients.size() == 1)
&& !_local
@@ -224,48 +386,88 @@
return true;
}
-int
-Handler::createStream()
-{
- // GNASH_REPORT_FUNCTION;
-
- return createStream("");
-}
-
-int
-Handler::createStream(const std::string &filespec)
-{
- // GNASH_REPORT_FUNCTION;
-
- int streamid = _streams;
+// Find a stream in the vector or Disk Streams
+boost::shared_ptr<gnash::DiskStream>
+Handler::findStream(const std::string &filespec)
+{
+// GNASH_REPORT_FUNCTION;
+
+ for (int i; i < _streams; i++) {
+ if (_diskstreams[i]->getFilespec() == filespec) {
+ return _diskstreams[i];
+ }
+ }
+
+ return _diskstreams[0];
+}
+
+// Create a new DiskStream
+double
+Handler::createStream(double /* transid */)
+{
+ GNASH_REPORT_FUNCTION;
+
+ _diskstreams[_streams]->setState(DiskStream::CREATED);
+
+ return _streams;
+}
+
+// Create a new DiskStream
+double
+Handler::createStream(double /* transid */, const std::string &filespec)
+{
+ GNASH_REPORT_FUNCTION;
if (filespec.empty()) {
return -1;
}
- _streams++;
- return streamid;
+
+ _diskstreams[_streams]->setState(DiskStream::CREATED);
+ _diskstreams[_streams]->setFilespec(filespec);
+
+ return _streams;
}
-int
+bool
Handler::playStream()
{
GNASH_REPORT_FUNCTION;
- return -1;
+ // _diskstreams[int(streamid)]->setState(DiskStream::PLAY);
+
+ return false;
}
-int
-Handler::playStream(const std::string &/* filespec */)
+bool
+Handler::playStream(const std::string &filespec)
{
GNASH_REPORT_FUNCTION;
- return -1;
+
+ boost::shared_ptr<gnash::DiskStream> ds = _diskstreams[_streams];
+
+ string fullpath = crcfile.getDocumentRoot();
+ fullpath += "/";
+ fullpath += filespec;
+ log_debug("FILENAME: %s", fullpath);
+
+ // gnash::DiskStream &ds = findStream(filespec);
+ if (ds->getState() == DiskStream::CREATED) {
+ if (ds->open(fullpath)) {
+ ds->loadToMem(0); // FIXME: load only part of the whole file for now
+ ds->setState(DiskStream::PLAY);
+ return true;
+ }
+ }
+
+ return false;
}
-// Publish a live RTMP stream
+// Publish a live stream
int
Handler::publishStream()
{
GNASH_REPORT_FUNCTION;
+
return publishStream("", Handler::LIVE);
}
@@ -274,6 +476,9 @@
*/)
{
GNASH_REPORT_FUNCTION;
+
+ // _diskstreams[int(streamid)]->setState(DiskStream::PUBLISH);
+
return -1;
}
@@ -282,6 +487,8 @@
Handler::seekStream()
{
GNASH_REPORT_FUNCTION;
+ // _diskstreams[int(streamid)]->setState(DiskStream::SEEK);
+
return -1;
}
@@ -289,41 +496,72 @@
Handler::seekStream(int /* offset */)
{
GNASH_REPORT_FUNCTION;
- return -1;
-}
-
-// Pause the RTMP stream
-int
-Handler::pauseStream()
-{
- GNASH_REPORT_FUNCTION;
- return -1;
-}
-
-// Pause the RTMP stream
-int
-Handler::togglePause()
-{
- GNASH_REPORT_FUNCTION;
+ // _diskstreams[int(streamid)]->setState(DiskStream::SEEK);
+
+ return -1;
+}
+
+// Pause the RTMP stream
+int
+Handler::pauseStream(double streamid)
+{
+ GNASH_REPORT_FUNCTION;
+
+ _diskstreams[int(streamid)]->setState(DiskStream::PAUSE);
+
+ return -1;
+}
+
+// Pause the RTMP stream
+int
+Handler::togglePause(double streamid)
+{
+ GNASH_REPORT_FUNCTION;
+
+ if (_diskstreams[int(streamid)]->getState() == DiskStream::PAUSE) {
+ _diskstreams[int(streamid)]->setState(DiskStream::PLAY);
+ } if (_diskstreams[int(streamid)]->getState() == DiskStream::PLAY) {
+ _diskstreams[int(streamid)]->setState(DiskStream::PAUSE);
+ }
+
return -1;
}
// Resume the paused RTMP stream
-int
-Handler::resumeStream()
+double
+Handler::resumeStream(double streamid)
{
GNASH_REPORT_FUNCTION;
+
+ togglePause(streamid);
+
return -1;
}
// Close the RTMP stream
-int
-Handler::closeStream()
+double
+Handler::closeStream(double streamid)
{
GNASH_REPORT_FUNCTION;
+
+ _diskstreams[int(streamid)]->setState(DiskStream::CLOSED);
+
return -1;
}
+// Delete the RTMP stream
+double
+Handler::deleteStream(double streamid)
+{
+ GNASH_REPORT_FUNCTION;
+
+ _diskstreams[int(streamid)]->setState(DiskStream::NO_STATE);
+
+ _streams++;
+
+ return _streams;
+}
+
// Dump internal data.
void
Handler::dump()
@@ -341,10 +579,23 @@
};
// GNASH_REPORT_FUNCTION;
+ cerr << "Currently there are " <<_clients.size() << " clients connected."
+ << endl;
for (size_t i = 0; i < _clients.size(); i++) {
cerr << "Client on fd #" << _clients[i] << " is using "
<< proto_str[_protocol[i]] << endl;
}
+
+ cerr << "Currently there are " << dec <<_diskstreams.size() << "
DiskStreams."
+ << endl;
+ map<int, boost::shared_ptr<DiskStream> >::iterator it;
+ for (it = _diskstreams.begin(); it != _diskstreams.end(); ++it) {
+ if (it->second) {
+ cerr << "DiskStream for fd #" << dec << it->first << endl;
+ it->second->dump();
+ }
+ }
+
}
} // end of gnash namespace
=== modified file 'cygnal/handler.h'
--- a/cygnal/handler.h 2010-01-01 17:48:26 +0000
+++ b/cygnal/handler.h 2010-01-01 20:41:28 +0000
@@ -26,6 +26,8 @@
#include <boost/cstdint.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/shared_ptr.hpp>
+#include <boost/shared_array.hpp>
+#include <boost/scoped_ptr.hpp>
//#include <boost/thread/condition.hpp>
#include <vector>
@@ -52,19 +54,25 @@
#include "diskstream.h"
#include "sharedlib.h"
#include "extension.h"
+#include "diskstream.h"
#include "rtmp.h"
#include "rtmp_msg.h"
-#include "rtmp_server.h"
+#include "http.h"
#include "network.h"
// _definst_ is the default instance name
namespace cygnal
{
+// The number of disk streams in the array.
+const size_t STREAMS_BLOCK = 1000;
+
class Cygnal;
+class HTTPServer;
+class RTMPServer;
-class Handler : public gnash::Extension
+class Handler : public gnash::Extension, gnash::Network
{
public:
/// \enum admin_cmd_e
@@ -86,15 +94,18 @@
} pub_stream_e;
/// This typedef is only used for the io function that must be
/// supported by the plugin.
- typedef size_t (*cygnal_io_t)(boost::uint8_t *data, size_t size);
+ typedef size_t (*cygnal_io_write_t)(boost::uint8_t *data, size_t size);
typedef boost::shared_ptr<amf::Buffer> (*cygnal_io_read_t)();
typedef struct {
- const char *version;
- const char *description;
+ std::string version;
+ std::string description;
+ std::string hostname;
+ std::string path;
cygnal_io_read_t read_func;
- cygnal_io_t write_func;
+ cygnal_io_write_t write_func;
gnash::Network::protocols_supported_e protocol;
} cygnal_init_t;
+
/// This typedef is only used for the init function optionally
/// supported by the plugin.
typedef
boost::shared_ptr<cygnal_init_t>(*cygnal_io_init_t)(boost::shared_ptr<gnash::RTMPMsg>
&msg);
@@ -111,28 +122,52 @@
void setName(const std::string &x) { _name = x; };
std::string &getName() { return _name; }
+ // Check the status of active disk streams, which is one less than
+ // default as the Streams IDs start at 1.
+ int getActiveDiskStreams() { return _diskstreams.size(); }
+ // int removeDiskStream(boost::shared_ptr<DiskStream> x);
+
+ // Operate on a disk streaming inprogress
+ boost::shared_ptr<gnash::DiskStream> getDiskStream(int x) { return
_diskstreams[x]; }
+ void setDiskStream(int x, boost::shared_ptr<gnash::DiskStream> y) {
_diskstreams[x] = y; }
+
+ /// Add a SharedObject
void addSOL(boost::shared_ptr<amf::Element> x) {
_sol.push_back(x);
};
/// \method addClient
- /// Add a client to the list for output messages.
- size_t addClient(int x, gnash::Network::protocols_supported_e proto);
+ /// Add a client to the list for output messages for a
+ /// resource. This also specifies the protocol handler
+ /// required for data on this file descriptor.
+ size_t addClient(int fd, gnash::Network::protocols_supported_e proto);
/// \method removeClient
/// Remove a client from the list for messages.
- void removeClient(int x);
+ void removeClient(int fd);
/// \var getClients
/// Get the vector of file descriptors for this handler.
std::vector<int> &getClients() { return _clients; };
+ /// \var getClient
+ /// Get a client from the list of clients, we have too many
+ /// arrays so using an operator isn't useful.
+ int getClient(int x) { return _clients[x]; };
+
+ /// \brief Receive a message from the other end of the network connection.
+ ///
+ /// @param fd The file descriptor to read from
+ ///
+ /// @return The number of bytes sent
+ int recvMsg(int fd);
+
gnash::Network::protocols_supported_e getProtocol(int x) { return
_protocol[x]; };
void setProtocol(int fd, gnash::Network::protocols_supported_e x) {
_protocol[fd] = x; };
-
+
/// \method addRemote
/// Add a remote machine to the list for input messages.
size_t addRemote(int x) { _remote.push_back(x); return _remote.size(); };
void setPlugin(boost::shared_ptr<Handler::cygnal_init_t> &init);
- void setPlugin(Handler::cygnal_io_t read_ptr, Handler::cygnal_io_t
write_ptr );
+ void setPlugin(Handler::cygnal_io_read_t read_ptr,
Handler::cygnal_io_write_t write_ptr );
/// Initialize the named module within Cygnal
//
@@ -142,25 +177,28 @@
/// See if any of the cgi-bins has been loaded.
bool initialized();
+ /// This method reads raw data from a plugin.
boost::shared_ptr<amf::Buffer> readFromPlugin();
+ /// This method writes raw data to a plugin.
size_t writeToPlugin(amf::Buffer &buf) {
return writeToPlugin(buf.begin(), buf.allocated()); };
size_t writeToPlugin(boost::uint8_t *data, size_t size);
- // These methods handle control of the file streaming
+ // These methods handle control of the file streaming, and are
+ // used by both HTTP and RTMP*
/// \fn int createStream()
- int createStream();
+ double createStream(double transid);
/// \overload int createStream(const std::string &filespec)
/// @param filespec The spec of the file to stream
- int createStream(const std::string &filespec);
+ double createStream(double transid, const std::string &filespec);
/// \fn playStream
/// Play the specified file as a stream
- int playStream();
+ bool playStream();
/// \overload int playStream(const std::string &filespec)
- int playStream(const std::string &filespec);
+ bool playStream(const std::string &filespec);
// Publish a live RTMP stream
int publishStream();
@@ -171,49 +209,83 @@
int seekStream(int offset);
// Pause the RTMP stream
- int pauseStream();
+ int pauseStream(double transid);
+
+ // Find a stream in the vector or Disk Streams
+ boost::shared_ptr<gnash::DiskStream> findStream(const std::string
&filespec);
+
// Pause the RTMP stream
- int togglePause();
+ int togglePause(double);
// Resume the paused RTMP stream
- int resumeStream();
+ double resumeStream(double transid);
// Close the RTMP stream
- int closeStream();
-
+ double closeStream(double transid);
+
+ // Delete the RTMP stream
+ double deleteStream(double transid);
+
+ // This is a site specific identifier of some kind.
void setFCSubscribe(const std::string &x) { _fcsubscribe = x; };
std::string &getFCSubscribe() { return _fcsubscribe; }
+#if 1
+ // FIXME: This holds the data from the first NetConnection packet,
+ // and shouldn't really be done here, but we're trying not to
+ // break things while refactoring.
void setNetConnection(gnash::RTMPMsg *msg) { _netconnect.reset(msg); };
void setNetConnection(boost::shared_ptr<gnash::RTMPMsg> msg) { _netconnect
= msg; };
boost::shared_ptr<gnash::RTMPMsg> getNetConnection() { return
_netconnect;};
+#endif
+
+#if 1
+ boost::shared_ptr<HTTPServer> &getHTTPHandler(int fd) { return _http[fd];
};
+ boost::shared_ptr<RTMPServer> getRTMPHandler(int fd) { return _rtmp[fd];
};
+#endif
+
+ // Parse the first nessages when starting a new message handler,
+ // which is used to determine the name of the resource to
+ // initialize, or load from the cache.
+ amf::Buffer *parseFirstRequest(int fd,
gnash::Network::protocols_supported_e proto);
+
+ std::string &getKey(int x) { return _keys[x]; };
+ void setKey(int fd, std::string x) { _keys[fd] = x; };
// Dump internal data.
void dump();
protected:
- /// \var _streams
- /// This is a counter of how many streams have been allocated
- /// by the server.
- int _streams;
/// \var _name
/// The name of the path this handler is supporting.
- std::string _name;
+ std::string _name;
/// Each incoming request has one of 4 states the server has
/// to handle to send a response.
-
+ /// \var _streams
+ /// This is a counter of how many streams have been allocated
+ /// by the server.
+ int _streams;
+ /// \var _diskstreams
+ /// This is all the opened disk based files that are currently
+ /// being streamed by the server.
+ // boost::shared_array<gnash::DiskStream> _diskstreams;
+ std::map<int, boost::shared_ptr<gnash::DiskStream> > _diskstreams;
/// \var _protocol
/// this is the map of which protocol is being used by which
/// file descriptor.
std::map<int, gnash::Network::protocols_supported_e> _protocol;
+#if 1
+ std::map<int, boost::shared_ptr<HTTPServer> > _http;
+ std::map<int, boost::shared_ptr<RTMPServer> > _rtmp;
+#endif
/// \var _clients
/// is the array of all clients connected to this server for
/// this application. This is where all the output goes.
- std::vector<int> _clients;
+ std::vector<int> _clients;
/// \var _remote
/// This is network connections to other processes,
/// on other computers.
- std::vector<int> _remote;
+ std::vector<int> _remote;
/// \var _local
/// These are local process we're responsible for
@@ -243,12 +315,16 @@
/// appears to be a unique ID number.
std::string _fcsubscribe;
+#if 1
/// \var _netconnect
/// This store the data from the NetConnection ActionScript
/// object we get as the final part of the handshake process
/// that is used to set up the connection. This has all the
/// file paths and other information needed by the server.
boost::shared_ptr<gnash::RTMPMsg> _netconnect;
+#endif
+
+ std::map<int, std::string> _keys;
private:
boost::mutex _mutex;
=== modified file 'cygnal/http_server.cpp'
--- a/cygnal/http_server.cpp 2010-01-01 17:48:26 +0000
+++ b/cygnal/http_server.cpp 2010-01-01 20:41:28 +0000
@@ -49,6 +49,7 @@
//#include "handler.h"
#include "utility.h"
#include "buffer.h"
+#include "http.h"
#include "diskstream.h"
// Cygnal specific headers
@@ -84,91 +85,73 @@
// GNASH_REPORT_FUNCTION;
}
-boost::shared_ptr<amf::Buffer>
+HTTP::http_method_e
HTTPServer::processClientRequest(int fd)
{
-// GNASH_REPORT_FUNCTION;
- boost::shared_ptr<amf::Buffer> buf(_que.peek());
- boost::shared_ptr<amf::Buffer> result;
-
+ GNASH_REPORT_FUNCTION;
+
+ amf::Buffer *buf = new amf::Buffer;
+
+ // return processClientRequest(fd, buf);
+ return HTTP::HTTP_NONE;
+}
+
+HTTP::http_method_e
+HTTPServer::processClientRequest(Handler *hand, int fd, amf::Buffer *buf)
+{
+ GNASH_REPORT_FUNCTION;
+
+ amf::Buffer result;
+
if (buf) {
_cmd = extractCommand(buf->reference());
switch (_cmd) {
case HTTP::HTTP_GET:
- result = processGetRequest(fd);
+ result = processGetRequest(hand, fd, buf);
break;
case HTTP::HTTP_POST:
- result = processPostRequest(fd);
+ result = processPostRequest(fd, buf);
break;
case HTTP::HTTP_HEAD:
- result = processHeadRequest(fd);
+ result = processHeadRequest(fd, buf);
break;
case HTTP::HTTP_CONNECT:
- result = processConnectRequest(fd);
+ result = processConnectRequest(fd, buf);
break;
case HTTP::HTTP_TRACE:
- result = processTraceRequest(fd);
+ result = processTraceRequest(fd, buf);
break;
case HTTP::HTTP_OPTIONS:
- result = processOptionsRequest(fd);
+ result = processOptionsRequest(fd, buf);
break;
case HTTP::HTTP_PUT:
- result = processPutRequest(fd);
+ result = processPutRequest(fd, buf);
break;
case HTTP::HTTP_DELETE:
- result = processDeleteRequest(fd);
+ result = processDeleteRequest(fd, buf);
break;
default:
break;
}
}
- return result;
-}
-
-// A GET request asks the server to send a file to the client
-boost::shared_ptr<amf::Buffer>
-HTTPServer::processGetRequest(int fd)
-{
- GNASH_REPORT_FUNCTION;
-
-// boost::uint8_t buffer[readsize+1];
-// const char *ptr = reinterpret_cast<const char *>(buffer);
-// memset(buffer, 0, readsize+1);
-
-// _handler->wait();
-// _handler->dump();
-
- cerr << "QUE = " << _que.size() << endl;
- boost::shared_ptr<amf::Buffer> buf;
-
- if (_que.size() == 0) {
- return buf;
- }
-
- buf = _que.pop();
-// cerr << "YYYYYYY: " << (char *)buf->reference() << endl;
-// cerr << hexify(buf->reference(), buf->allocated(), false) << endl;
-
- if (buf == 0) {
- // log_debug("Que empty, net connection dropped for fd #%d",
getFileFd());
- log_debug("Que empty, net connection dropped for fd #%d", fd);
- return buf;
- }
-
- clearHeader();
- processHeaderFields(*buf);
-
+#if 0
+
+ writeNet(fd, result);
+
+ _docroot = crcfile.getDocumentRoot();
+
string url = _docroot + _filespec;
+
// See if the file is in the cache and already opened.
- boost::shared_ptr<DiskStream> filestream(cache.findFile(url));
+ boost::shared_ptr<DiskStream> filestream(cache.findFile(_filespec));
if (filestream) {
- cerr << "FIXME: found file in cache!" << endl;
+ log_debug("FIXME: found filestream %s in cache!", _filespec);
+ filestream->dump();
} else {
filestream.reset(new DiskStream);
-// cerr << "New Filestream at 0x" << hex << filestream.get() << endl;
-
-// cache.addFile(url, filestream); FIXME: always reload from disk
for now.
+ log_network("New filestream %s", _filespec);
+ // cache.addFile(url, filestream); FIXME: always reload from disk
for now.
// Oopen the file and read the first chunk into memory
if (filestream->open(url)) {
@@ -178,47 +161,97 @@
if (filestream->getFileType() == DiskStream::FILETYPE_NONE) {
formatErrorResponse(HTTPServer::NOT_FOUND);
} else {
- cache.addPath(_filespec, filestream->getFilespec());
+ // cache.addPath(_filespec, filestream->getFilespec());
+ // cache.addFile(_filespec, filestream);
}
}
- }
-
- // Send the reply
- amf::Buffer &reply = formatHeader(filestream->getFileType(),
- filestream->getFileSize(),
- HTTPServer::OK);
+ // Close the file but leave resident for now.
+ if (filestream->fullyPopulated()) {
+ filestream->close();
+ }
+// cache.addFile(_filespec, filestream);
+ }
+#endif
+
+ return _cmd;
+}
+
+// A GET request asks the server to send a file to the client
+amf::Buffer &
+HTTPServer::processGetRequest(Handler *hand, int fd, amf::Buffer *buf)
+{
+ GNASH_REPORT_FUNCTION;
+
+ // cerr << "QUE = " << _que.size() << endl;
+
+// cerr << "YYYYYYY: " << (char *)buf->reference() << endl;
+// cerr << hexify(buf->reference(), buf->allocated(), false) << endl;
+
+ if (buf == 0) {
+ // log_debug("Que empty, net connection dropped for fd #%d",
getFileFd());
+ log_debug("Que empty, net connection dropped for fd #%d", fd);
+ amf::Buffer buf;
+ return buf;
+ }
+
+ clearHeader();
+ processHeaderFields(buf);
+
+ _docroot = crcfile.getDocumentRoot();
+
+ string url = _docroot + _filespec;
+
+ boost::shared_ptr<DiskStream> ds = hand->getDiskStream(fd);
+ if (ds) {
+ _diskstream = ds;
+ }
+ if (!_diskstream) {
+ _diskstream.reset(new DiskStream);
+ log_network("New filestream %s", _filespec);
+ } else {
+ log_network("Reusing filestream %s", _filespec);
+ }
+
+ // Oopen the file and read the first chunk into memory
+ if (_diskstream->open(url)) {
+ formatErrorResponse(HTTPServer::NOT_FOUND);
+ } else {
+ // Get the file size for the HTTPServer header
+ if (_diskstream->getFileType() == DiskStream::FILETYPE_NONE) {
+ formatErrorResponse(HTTPServer::NOT_FOUND);
+ } else {
+ // cache.addPath(_filespec, filestream->getFilespec());
+ // cache.addFile(_filespec, filestream);
+ }
+ }
+ // Closing the file closes the disk file, but leaves data resident
+ // in memory for future access to this file. If we've been opened,
+ // the next operation is to start writing the file next time
+ // ::play() is called.
+ if (_diskstream->fullyPopulated()) {
+ _diskstream->close();
+ }
+ _diskstream->setState(DiskStream::PLAY);
+// cache.addFile(_filespec, _diskstream);
+
+ // Create the reply message
+// _close = true; Force sending the close connection in the header
+ amf::Buffer &reply = formatHeader(_diskstream->getFileType(),
+ _diskstream->getFileSize(),
+ HTTPServer::OK);
+
writeNet(fd, reply);
- size_t filesize = filestream->getFileSize();
- size_t bytes_read = 0;
- int ret;
- size_t page = 0;
+ size_t filesize = _diskstream->getFileSize();
+ // size_t bytes_read = 0;
+ // int ret;
+ // size_t page = 0;
if (filesize) {
#ifdef USE_STATS_CACHE
struct timespec start;
clock_gettime (CLOCK_REALTIME, &start);
-#endif
- size_t getbytes = 0;
- if (filesize <= filestream->getPagesize()) {
- getbytes = filesize;
- } else {
- getbytes = filestream->getPagesize();
- }
- if (filesize >= CACHE_LIMIT) {
- do {
- filestream->loadToMem(page);
- ret = writeNet(fd, filestream->get(), getbytes);
- if (ret <= 0) {
- break;
- }
- bytes_read += ret;
- page += filestream->getPagesize();
- } while (bytes_read <= filesize);
- } else {
- filestream->loadToMem(filesize, 0);
- ret = writeNet(fd, filestream->get(), filesize);
- }
- filestream->close();
+#endif
+
#ifdef USE_STATS_CACHE
struct timespec end;
clock_gettime (CLOCK_REALTIME, &end);
@@ -228,17 +261,15 @@
<< time << " seconds for net fd #" << fd << endl;
#endif
}
-
- log_debug("http_handler all done transferring requested file \"%s\".",
_filespec);
- return buf;
+ return reply;
}
// A POST request asks sends a data from the client to the server. After
processing
// the header like we normally do, we then read the amount of bytes specified
by
// the "content-length" field, and then write that data to disk, or decode the
amf.
boost::shared_ptr<amf::Buffer>
-HTTPServer::processPostRequest(int fd)
+HTTPServer::processPostRequest(int fd, amf::Buffer *bufFIXME)
{
GNASH_REPORT_FUNCTION;
@@ -258,7 +289,7 @@
// cerr << __FUNCTION__ << buf->allocated() << " : " <<
hexify(buf->reference(), buf->allocated(), true) << endl;
clearHeader();
- boost::uint8_t *data = processHeaderFields(*buf);
+ boost::uint8_t *data = processHeaderFields(buf.get());
size_t length = strtol(getField("content-length").c_str(), NULL, 0);
boost::shared_ptr<amf::Buffer> content(new amf::Buffer(length));
int ret = 0;
@@ -330,7 +361,7 @@
}
boost::shared_ptr<amf::Buffer>
-HTTPServer::processPutRequest(int /* fd */)
+HTTPServer::processPutRequest(int /* fd */, amf::Buffer */* buf */)
{
boost::shared_ptr<amf::Buffer> buf;
// GNASH_REPORT_FUNCTION;
@@ -340,7 +371,7 @@
}
boost::shared_ptr<amf::Buffer>
-HTTPServer::processDeleteRequest(int /* fd */)
+HTTPServer::processDeleteRequest(int /* fd */, amf::Buffer */* buf */)
{
// GNASH_REPORT_FUNCTION;
boost::shared_ptr<amf::Buffer> buf;
@@ -350,7 +381,7 @@
}
boost::shared_ptr<amf::Buffer>
-HTTPServer::processConnectRequest(int /* fd */)
+HTTPServer::processConnectRequest(int /* fd */, amf::Buffer */* buf */)
{
// GNASH_REPORT_FUNCTION;
boost::shared_ptr<amf::Buffer> buf;
@@ -360,7 +391,7 @@
}
boost::shared_ptr<amf::Buffer>
-HTTPServer::processOptionsRequest(int /* fd */)
+HTTPServer::processOptionsRequest(int /* fd */, amf::Buffer */* buf */)
{
// GNASH_REPORT_FUNCTION;
boost::shared_ptr<amf::Buffer> buf;
@@ -370,7 +401,7 @@
}
boost::shared_ptr<amf::Buffer>
-HTTPServer::processHeadRequest(int /* fd */)
+HTTPServer::processHeadRequest(int /* fd */, amf::Buffer */* buf */)
{
// GNASH_REPORT_FUNCTION;
boost::shared_ptr<amf::Buffer> buf;
@@ -380,7 +411,7 @@
}
boost::shared_ptr<amf::Buffer>
-HTTPServer::processTraceRequest(int /* fd */)
+HTTPServer::processTraceRequest(int /* fd */, amf::Buffer */* buf */)
{
// GNASH_REPORT_FUNCTION;
boost::shared_ptr<amf::Buffer> buf;
@@ -840,7 +871,7 @@
// This is fine as long as end is within the buffer.
_filespec = std::string(start, end);
}
- log_debug("Requesting file: \"%s\"", _filespec);
+ // log_debug("Requesting file: \"%s\"", _filespec);
// The third field is always the HTTP version
// The version is the last field and is the protocol name
@@ -849,7 +880,7 @@
// in it. It's actually two separate integers.
_version.major = *(end+6) - '0';
_version.minor = *(end+8) - '0';
- log_debug (_("Version: %d.%d"), _version.major, _version.minor);
+ // log_debug (_("Version: %d.%d"), _version.major, _version.minor);
}
return cmd;
@@ -923,7 +954,7 @@
// in it. It's actually two separate integers.
_version.major = i->at(pos+5) - '0';
_version.minor = i->at(pos+7) - '0';
- log_debug (_("Version: %d.%d"), _version.major,
_version.minor);
+ // log_debug (_("Version: %d.%d"), _version.major,
_version.minor);
// the filespec in the request is the middle field,
deliminated
// by a space on each end.
if (params != string::npos) {
@@ -933,7 +964,7 @@
} else {
_filespec = i->substr(start+1, pos-start-2);
}
- log_debug("Requesting file: \"%s\"", _filespec);
+ // log_debug("Requesting file: \"%s\"", _filespec);
// HTTP 1.1 enables persistant network connections
// by default.
@@ -955,100 +986,96 @@
HTTPServer::dump()
{
// GNASH_REPORT_FUNCTION;
+ if (_diskstream) {
+ _diskstream->dump();
+ }
}
-
-extern "C" {
-
+
bool
-http_handler(Network::thread_params_t *args)
+HTTPServer::http_handler(Handler *hand, int netfd, amf::Buffer *buf)
{
GNASH_REPORT_FUNCTION;
- string url, filespec, parameters;
- HTTPServer *www = new HTTPServer;
- bool result = false;
-
-// Network *net = reinterpret_cast<Network *>(args->handler);
- bool done = false;
-// www.setHandler(net);
-
- log_network(_("Starting HTTP Handler for fd #%d, tid %d"),
- args->netfd, args->tid);
-
- www->setDocRoot(crcfile.getDocumentRoot());
-
- log_network("Docroot for HTTP files is %s", crcfile.getDocumentRoot());
-
- log_network("Starting to wait for data in net for fd #%d", args->netfd);
-
+ // Handler *hand = reinterpret_cast<Handler *>(args->handler);
+ // amf::Buffer *buf = args->buffer;
+ // boost::shared_ptr<HTTPServer> www(new HTTPServer); // =
hand->getHTTPHandler (args->netfd);
+
+ string url, parameters;
+ // by default, only look once unless changed later
+ // www->setDocRoot(crcfile.getDocumentRoot());
+ // log_network("Docroot for HTTP files is %s", crcfile.getDocumentRoot());
+ log_network("Processing HTTP data for fd #%d", netfd);
+
// Wait for data, and when we get it, process it.
- do {
-
#ifdef USE_STATISTICS
- struct timespec start;
- clock_gettime (CLOCK_REALTIME, &start);
+ struct timespec start;
+ clock_gettime (CLOCK_REALTIME, &start);
#endif
+ if (buf) {
+ log_network("FIXME: Existing data in packet!");
+ } else {
+ log_network("FIXME: No existing data in packet!");
// See if we have any messages waiting
- if (www->recvMsg(args->netfd) == 0) {
- done = true;
- }
-
- // Process incoming messages
- if (!www->processClientRequest(args->netfd)) {
-// hand->die(); // tell all the threads for this connection to
die
-// hand->notifyin();
- log_debug("Net HTTP server done for fd #%d...", args->netfd);
-// done = true;
- }
+ if (recvMsg(netfd) == 0) {
+ log_debug("Net HTTP server failed to read from fd #%d...", netfd);
+ return false;
+ }
+ }
+
+ // Process incoming messages
+ HTTP::http_method_e cmd = processClientRequest(hand, netfd, buf);
+ if (cmd != HTTP::HTTP_GET) {
+ log_debug("No active DiskStreams for fd #%d: %s...", netfd, _filespec);
+ } else {
+ if (_diskstream) {
+ log_debug("Found active DiskStream! for fd #%d: %s", netfd,
_filespec);
+ hand->setDiskStream(netfd, _diskstream);
+ cache.addFile(_filespec, _diskstream);
+// Send the first chunk of the file to the client.
+ _diskstream->play(netfd, false);
+ }
+ }
+
// www->dump();
- if ((www->getField("content-type") == "application/x-amf")
- && (www->getField("content-type") == "application/x-amf")
- && (www->getFilespec() == "/echo/gateway")) {
- cerr << "GOT A GATEWAY REQUEST" << endl;
- }
-
+ if ((getField("content-type") == "application/x-amf")
+ && (getField("content-type") == "application/x-amf")
+ && (getFilespec() == "/echo/gateway")) {
+ cerr << "GOT A GATEWAY REQUEST" << endl;
+ }
+
#if 0
- string response = cache.findResponse(filestream->getFilespec());
- if (response.empty()) {
- cerr << "FIXME no cache hit for: " << www.getFilespec() << endl;
+ string response = cache.findResponse(filestream->getFilespec());
+ if (response.empty()) {
+ cerr << "FIXME no cache hit for: " << www.getFilespec() << endl;
// www.clearHeader();
// amf::Buffer &ss = www.formatHeader(filestream->getFileSize(),
HTTP::LIFE_IS_GOOD);
// www.writeNet(args->netfd, (boost::uint8_t
*)www.getHeader().c_str(), www.getHeader().size());
// cache.addResponse(www.getFilespec(), www.getHeader());
- } else {
- cerr << "FIXME cache hit on: " << www.getFilespec() << endl;
- www.writeNet(args->netfd, (boost::uint8_t *)response.c_str(),
response.size());
- }
+ } else {
+ cerr << "FIXME cache hit on: " << www.getFilespec() << endl;
+ www.writeNet(args->netfd, (boost::uint8_t *)response.c_str(),
response.size());
+ }
#endif
-
- // Unless the Keep-Alive flag is set, this isn't a persisant network
- // connection.
- if (!www->keepAlive()) {
- log_debug("Keep-Alive is off", www->keepAlive());
- result = false;
- done = true;
- } else {
- log_debug("Keep-Alive is on", www->keepAlive());
- result = true;
-// done = true;
- }
+
+ // Unless the Keep-Alive flag is set, this isn't a persisant network
+ // connection.
+ if (!keepAlive()) {
+ log_debug("Keep-Alive is off", keepAlive());
+ } else {
+ log_debug("Keep-Alive is on", keepAlive());
+ }
#ifdef USE_STATISTICS
- struct timespec end;
- clock_gettime (CLOCK_REALTIME, &end);
- log_debug("Processing time for GET request was %f seconds",
- static_cast<float>(((end.tv_sec - start.tv_sec) +
- ((end.tv_nsec - start.tv_nsec)/1e9))));
+ struct timespec end;
+ clock_gettime (CLOCK_REALTIME, &end);
+ log_debug("Processing time for GET request was %f seconds",
+ static_cast<float>(((end.tv_sec - start.tv_sec) +
+ ((end.tv_nsec - start.tv_nsec)/1e9))));
#endif
- } while(done != true);
-
-// hand->notify();
-
- log_debug("http_handler all done now finally...");
-
- return result;
-} // end of httphandler
-} // end of extern C
+
+ return keepAlive();
+
+} // end of http_handler
} // end of gnash namespace
=== modified file 'cygnal/http_server.h'
--- a/cygnal/http_server.h 2010-01-01 17:48:26 +0000
+++ b/cygnal/http_server.h 2010-01-01 20:41:28 +0000
@@ -46,15 +46,16 @@
~HTTPServer();
// These are for the protocol itself
- boost::shared_ptr<amf::Buffer> processClientRequest(int fd);
- boost::shared_ptr<amf::Buffer> processGetRequest(int fd);
- boost::shared_ptr<amf::Buffer> processPostRequest(int fd);
- boost::shared_ptr<amf::Buffer> processPutRequest(int fd);
- boost::shared_ptr<amf::Buffer> processDeleteRequest(int fd);
- boost::shared_ptr<amf::Buffer> processConnectRequest(int fd);
- boost::shared_ptr<amf::Buffer> processOptionsRequest(int fd);
- boost::shared_ptr<amf::Buffer> processHeadRequest(int fd);
- boost::shared_ptr<amf::Buffer> processTraceRequest(int fd);
+ http_method_e processClientRequest(int fd);
+ http_method_e processClientRequest(Handler *hand, int fd, amf::Buffer
*buf);
+ amf::Buffer &processGetRequest(Handler *hand, int fd, amf::Buffer *buf);
+ boost::shared_ptr<amf::Buffer> processPostRequest(int fd, amf::Buffer
*buf);
+ boost::shared_ptr<amf::Buffer> processPutRequest(int fd, amf::Buffer *buf);
+ boost::shared_ptr<amf::Buffer> processDeleteRequest(int fd, amf::Buffer
*buf);
+ boost::shared_ptr<amf::Buffer> processConnectRequest(int fd, amf::Buffer
*buf);
+ boost::shared_ptr<amf::Buffer> processOptionsRequest(int fd, amf::Buffer
*buf);
+ boost::shared_ptr<amf::Buffer> processHeadRequest(int fd, amf::Buffer
*buf);
+ boost::shared_ptr<amf::Buffer> processTraceRequest(int fd, amf::Buffer
*buf);
// Handle the response for the request.
boost::shared_ptr<amf::Buffer> formatServerReply(http_status_e code);
@@ -95,17 +96,14 @@
gnash::amf::Buffer &formatEchoResponse(const std::string &num, uint8_t
*data, size_t size);
#endif
- void dump();
-
+ bool http_handler(Handler *hand, int netfd, amf::Buffer *buf);
+ boost::shared_ptr<gnash::DiskStream> getDiskStream() { return _diskstream;
};
+
+ void dump();
private:
-
+ boost::shared_ptr<gnash::DiskStream> _diskstream;
};
-// This is the thread for all incoming HTTP connections
-extern "C" {
- DSOEXPORT bool http_handler(gnash::Network::thread_params_t *args);
-}
-
} // end of gnash namespace
// end of _HTTP_SERVER_H_
=== modified file 'cygnal/rtmp_server.cpp'
--- a/cygnal/rtmp_server.cpp 2010-01-01 17:48:26 +0000
+++ b/cygnal/rtmp_server.cpp 2010-01-01 20:41:28 +0000
@@ -24,10 +24,14 @@
#include <iostream>
#include <string>
#include <map>
+#include <cstdlib>
+#include <cstdio>
+
#include <boost/cstdint.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/detail/endian.hpp>
#include <boost/random/uniform_real.hpp>
+#include <boost/random/uniform_int.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/lexical_cast.hpp>
@@ -36,6 +40,7 @@
#endif
#include "log.h"
+#include "URL.h"
#include "amf.h"
#include "rtmp.h"
#include "rtmp_server.h"
@@ -48,7 +53,9 @@
#include "crc.h"
#include "cache.h"
#include "diskstream.h"
-
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
using namespace gnash;
using namespace std;
using namespace amf;
@@ -220,7 +227,7 @@
if (!encoding) {
// Send a onBWDone to the client to start the new NetConnection,
boost::shared_ptr<amf::Buffer> bwdone = encodeBWDone(2.0);
- if (RTMP::sendMsg(fd, qhead->channel, RTMP::HEADER_12,
+ if (RTMP::sendMsg(fd, qhead->channel, RTMP::HEADER_8,
bwdone->size(), RTMP::INVOKE, RTMPMsg::FROM_SERVER,
*bwdone)) {
log_network("Sent onBWDone to client");
} else {
@@ -618,15 +625,15 @@
}
boost::shared_ptr<amf::Buffer>
-RTMPServer::encodeResult(gnash::RTMPMsg::rtmp_status_e status, double
&streamid)
+RTMPServer::encodeResult(gnash::RTMPMsg::rtmp_status_e status, double &transid)
{
// GNASH_REPORT_FUNCTION;
double clientid = 0.0;
- return encodeResult(status, "", streamid, clientid);
+ return encodeResult(status, "", transid, clientid);
}
boost::shared_ptr<amf::Buffer>
-RTMPServer::encodeResult(gnash::RTMPMsg::rtmp_status_e status, const
std::string &filename, double &streamid, double &clientid)
+RTMPServer::encodeResult(gnash::RTMPMsg::rtmp_status_e status, const
std::string &filename, double &transid, double &clientid)
{
// GNASH_REPORT_FUNCTION;
// Buffer *buf = new Buffer;
@@ -643,8 +650,8 @@
str->makeString("_result");
Element *number = new Element;
- // add The server ID
- number->makeNumber(streamid);
+ // add the transaction ID
+ number->makeNumber(transid);
Element top;
// top.makeObject("application");
@@ -718,7 +725,38 @@
case RTMPMsg::NS_DATA_START:
case RTMPMsg::NS_FAILED:
case RTMPMsg::NS_INVALID_ARGUMENT:
+ // The response to a successful pauseStream command is this
+ // message.
case RTMPMsg::NS_PAUSE_NOTIFY:
+ {
+ str->makeString("onStatus");
+
+ boost::shared_ptr<amf::Element> level(new Element);
+ level->makeString("level", "status");
+ top.addProperty(level);
+
+ boost::shared_ptr<amf::Element> code(new Element);
+ code->makeString("code", "NetStream.Pause.Notify");
+ top.addProperty(code);
+
+ boost::shared_ptr<amf::Element> description(new Element);
+ string field = "Pausing ";
+ if (!filename.empty()) {
+ field += filename;
+ }
+ description->makeString("description", field);
+ top.addProperty(description);
+
+ boost::shared_ptr<amf::Element> details(new Element);
+ details->makeString("details", filename);
+ top.addProperty(details);
+
+ boost::shared_ptr<amf::Element> cid(new Element);
+ cid->makeNumber("clientid", clientid);
+ top.addProperty(cid);
+
+ break;
+ }
case RTMPMsg::NS_PLAY_COMPLETE:
case RTMPMsg::NS_PLAY_FAILED:
case RTMPMsg::NS_PLAY_FILE_STRUCTURE_INVALID:
@@ -753,7 +791,19 @@
top.addProperty(details);
boost::shared_ptr<amf::Element> cid(new Element);
+#ifdef CLIENT_ID_NUMERIC
+ double clientid = createClientID();
cid->makeNumber("clientid", clientid);
+#else
+ string clientid;
+ if (!_clientids[transid].empty()) {
+ clientid =_clientids[transid].c_str();
+ } else {
+ clientid = createClientID();
+ _clientids[transid] = clientid;
+ }
+ cid->makeString("clientid", _clientids[transid]);
+#endif
top.addProperty(cid);
break;
@@ -783,13 +833,39 @@
top.addProperty(details);
boost::shared_ptr<amf::Element> cid(new Element);
+#ifdef CLIENT_ID_NUMERIC
+ double clientid = createClientID();
cid->makeNumber("clientid", clientid);
+#else
+ string clientid;
+ if (!_clientids[transid].empty()) {
+ clientid =_clientids[transid].c_str();
+ } else {
+ clientid = createClientID();
+ _clientids[transid] = clientid;
+ }
+ cid->makeString("clientid", _clientids[transid]);
+#endif
top.addProperty(cid);
break;
}
case RTMPMsg::NS_PLAY_STOP:
case RTMPMsg::NS_PLAY_STREAMNOTFOUND:
+ {
+ boost::shared_ptr<amf::Element> level(new Element);
+ level->makeString("level", "error");
+ top.addProperty(level);
+
+ boost::shared_ptr<amf::Element> description(new Element);
+ description->makeString("description",
"NetStream.Play.StreamNotFound.");
+ top.addProperty(description);
+
+ boost::shared_ptr<amf::Element> code(new Element);
+ code->makeString("code", "NetStream.Play.StreamNotFound");
+ top.addProperty(code);
+ break;
+ }
case RTMPMsg::NS_PLAY_SWITCH:
case RTMPMsg::NS_PLAY_UNPUBLISHNOTIFY:
case RTMPMsg::NS_PUBLISH_BADNAME:
@@ -798,8 +874,13 @@
case RTMPMsg::NS_RECORD_NOACCESS:
case RTMPMsg::NS_RECORD_START:
case RTMPMsg::NS_RECORD_STOP:
+ // The reponse to a failed seekStream is this message.
case RTMPMsg::NS_SEEK_FAILED:
+ // The reponse to a successful seekStream is this message.
case RTMPMsg::NS_SEEK_NOTIFY:
+ break;
+ // The response to a successful pauseStream command is this
+ // message when the stream is started again.
case RTMPMsg::NS_UNPAUSE_NOTIFY:
case RTMPMsg::NS_UNPUBLISHED_SUCCESS:
case RTMPMsg::SO_CREATION_FAILED:
@@ -807,19 +888,24 @@
case RTMPMsg::SO_NO_WRITE_ACCESS:
case RTMPMsg::SO_PERSISTENCE_MISMATCH:
break;
- // Anything below here is specific to Gnash's implementation
+ // The response for a createStream message is the
+ // transaction ID, followed by the command object (usually a
+ // NULL object), and the Stream ID. The Stream ID is just a
+ // simple incrementing counter of streams.
case RTMPMsg::NS_CREATE_STREAM:
{
// Don't encode as an object, just the properties
notobject = true;
boost::shared_ptr<amf::Element> id2(new Element);
+
double sid = createStreamID();
id2->makeNumber(sid);
top.addProperty(id2);
break;
}
+ // There is no response to a deleteStream request.
case RTMPMsg::NS_DELETE_STREAM:
default:
break;
@@ -960,6 +1046,30 @@
return buf;
}
+boost::shared_ptr<amf::Buffer>
+RTMPServer::encodeAudio(boost::uint8_t *data, size_t size)
+{
+ GNASH_REPORT_FUNCTION;
+
+ boost::shared_ptr<amf::Buffer> buf;
+
+ if (size) {
+ if (data) {
+ buf.reset(new amf::Buffer(size));
+ buf->copy(data, size);
+ }
+ }
+
+ return buf;
+}
+
+boost::shared_ptr<amf::Buffer>
+RTMPServer::encodeVideo(boost::uint8_t *data, size_t size)
+{
+ GNASH_REPORT_FUNCTION;
+}
+
+#if 0
// Parse an Echo Request message coming from the Red5 echo_test. This
// method should only be used for testing purposes.
vector<boost::shared_ptr<amf::Element > >
@@ -1044,12 +1154,17 @@
return buf;
}
+#endif
-// Create a new client ID, which appears to be a random double.
+// Create a new client ID, which appears to be a random double,
+// although I also see a temporary 8 character string used often as
+// well.
+#ifdef CLIENT_ID_NUMERIC
double
RTMPServer::createClientID()
{
// GNASH_REPORT_FUNCTION;
+
boost::mt19937 seed;
// Pick the number of errors to create based on the Buffer's data size
boost::uniform_real<> numbers(1, 65535);
@@ -1059,6 +1174,54 @@
return id;
}
+#else
+std::string
+RTMPServer::createClientID()
+{
+// GNASH_REPORT_FUNCTION;
+ string id;
+
+// FIXME: This turns out to be a crappy random number generator,
+ // and should be replaced with something less repititous.
+#if 0
+ boost::mt19937 seed;
+ for (size_t i=0; i < 8; i++) {
+ boost::uniform_int<> numbers(0x30, 0x7a);
+ id += numbers(seed);
+ }
+#else
+ char letters[] =
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+ boost::uint64_t random_time_bits = 0;
+ boost::uint64_t value = 0;
+# ifdef HAVE_GETTIMEOFDAY
+ timeval tv;
+ gettimeofday(&tv, NULL);
+ random_time_bits = ((uint64_t)tv.tv_usec << 16) ^ tv.tv_sec;
+# else
+ random_time_bits = time(NULL);
+# endif
+ value += random_time_bits ^ getpid();
+ boost::uint64_t v = value;
+ id = letters[v % 62];
+ v /= 62;
+ id += letters[v % 62];
+ v /= 62;
+ id += letters[v % 62];
+ v /= 62;
+ id += letters[v % 62];
+ v /= 62;
+ id += letters[v % 62];
+ v /= 62;
+ id += letters[v % 62];
+ v /= 62;
+ id += letters[v % 62];
+ v /= 62;
+#endif
+
+ return id;
+}
+#endif
// Get the next streamID
double
@@ -1082,7 +1245,7 @@
// cache.addFile(url, filestream); FIXME: always reload from disk
for now.
- // Oopen the file and read the first chunk into memory
+ // Open the file and read the first chunk into memory
if (!filestream->open(filespec)) {
return false;
} else {
@@ -1191,7 +1354,7 @@
static bool initialize = true;
// bool sendfile = false;
log_network(_("Starting RTMP Handler for fd #%d, cgi-bin is \"%s\""),
- args->netfd, args->filespec);
+ args->netfd, args->filespec);
#ifdef USE_STATISTICS
struct timespec start;
@@ -1206,10 +1369,6 @@
boost::shared_ptr<amf::Element> swfurl;
boost::shared_ptr<amf::Buffer> response;
- string basepath = docroot;
-
-// RTMP::rtmp_headersize_e response_head_size = RTMP::HEADER_12;
-
// Keep track of the network statistics
// See if we have any messages waiting. After the initial connect, this is
// the main loop for processing messages.
@@ -1217,9 +1376,29 @@
// Adjust the timeout
rtmp->setTimeout(30);
// boost::shared_ptr<amf::Buffer> buf;
-
- // This is the main message processing loop for rtmp. All message
- // received require a response.
+
+ // If we have active disk streams, send those packets first.
+ // 0 is a reserved stream, so we start with 1, as the reserved
+ // stream isn't one we care about here.
+ log_network("%d active disk streams", hand->getActiveDiskStreams());
+ for (int i=1; i <= hand->getActiveDiskStreams(); i++) {
+ hand->getDiskStream(i)->dump();
+ if (hand->getDiskStream(i)->getState() == DiskStream::PLAY) {
+ boost::uint8_t *ptr = hand->getDiskStream(i)->get();
+ if (ptr) {
+ if (rtmp->sendMsg(hand->getClient(i), 8,
+ RTMP::HEADER_8, 4096,
+ RTMP::NOTIFY, RTMPMsg::FROM_SERVER,
+ ptr, 4096)) {
+ }
+ } else {
+ log_network("ERROR: No stream for client %d", i);
+ }
+ }
+ }
+
+ // This is the main message processing loop for rtmp. Most
+ // messages received require a response.
do {
// If there is no data left from the previous chunk, process
// that before reading more data.
@@ -1252,7 +1431,7 @@
if (qhead->channel == RTMP_SYSTEM_CHANNEL) {
if (qhead->type == RTMP::USER) {
boost::shared_ptr<RTMP::user_event_t> user
- = rtmp->decodeUser(tmpptr);
+ = rtmp->decodeUserControl(tmpptr);
switch (user->type) {
case RTMP::STREAM_START:
log_unimpl("Stream Start");
@@ -1295,119 +1474,13 @@
}
}
}
-// boost::shared_ptr<amf::Buffer> bufptr = que->at(i)->pop();
-// // que->at(i)->dump();
-// if (bufptr) {
-// bufptr->dump();
-// qhead = rtmp->decodeHeader(bufptr->reference());
-// log_network("Message for channel #%d", qhead->channel);
-// // tmpptr = bufptr->reference();
-// tmpptr = bufptr->reference() + qhead->head_size;
-// if (qhead->channel == RTMP_SYSTEM_CHANNEL) {
-// boost::shared_ptr<RTMP::rtmp_ping_t> ping =
rtmp->decodePing(tmpptr);
-// log_network("Processed Ping message from client,
type %d", ping->type);
-// } else {
-// if (echo) {
-// log_network("Got an echo request");
-// // process the echo test request
-// vector<boost::shared_ptr<amf::Element> >
request = rtmp->parseEchoRequest(
-//
bufptr->reference() + qhead->head_size, bufptr->allocated() - qhead->head_size);
-// if (request[3]) {
-// boost::shared_ptr<amf::Buffer> result =
rtmp->formatEchoResponse(request[1]->to_number(), *request[3]);
-// if (rtmp->sendMsg(args->netfd,
qhead->channel, RTMP::HEADER_8, result->allocated(),
-// RTMP::INVOKE,
RTMPMsg::FROM_SERVER, *result)) {
-// // If we're in single threaded mode, we
Just want to stay in
-// // this thread for now and do
everything all at once. Otherwise
-// // we're done, so we return to the
dispatch handler waiting for
-// // the next packet. Single threaded
mode is primarily used by
-// // developers for debugging protocols.
-// log_network("Sent echo test response
response to client.");
-// }
-// } else {
-// log_error("Couldn't send echo test response
to client!");
-// done = true;
-// }
-// } else {
-// body = rtmp->decodeMsgBody(tmpptr,
qhead->bodysize);
-// if (body) {
-// body->setChannel(qhead->channel);
-// // Invoke the NetConnection::connect()
method
-// if (body->getMethodName() == "connect") {
-// response_head_size = RTMP::HEADER_12;
-// tcurl = body->findProperty("tcUrl");
-// if (tcurl) {
-// log_network("Client request for
remote file is: %s", tcurl->to_string());
-// string path = tcurl->to_string();
-// string::size_type start =
path.find("://", 0) + 4;
-// if (start != string::npos) {
-// string::size_type end =
path.find("/", start);
-// if (end != string::npos) {
-// basepath +=
path.substr(end, path.size());
-// }
-// }
-// log_network("Base path to files
from connect is: %s", basepath);
-
-// }
-
-// }
-// // Invoke the NetStream::createStream()
method
-// if (body->getMethodName() ==
"createStream") {
-// double streamid = body->getStreamID();
-// log_network("The streamID from
NetStream::createStream() is: %d", streamid);
-// response_head_size = RTMP::HEADER_8;
-// response =
rtmp->encodeResult(RTMPMsg::NS_CREATE_STREAM, streamid);
-// // body->dump();
-// }
-// if (body->getMethodName() ==
"deleteStream") {
-// double streamid = body->getStreamID();
-// log_network("The streamID from
NetStream::deleyeStream() is: %d", streamid);
-// response_head_size = RTMP::HEADER_8;
-// response =
rtmp->encodeResult(RTMPMsg::NS_DELETE_STREAM, streamid);
-// body->dump();
-// }
-// // Invoke the NetStream::play() method
-// if (body->getMethodName() == "play") {
-// double streamid = body->getStreamID();
-// log_network("The streamID from
NetStream::plays: %d", streamid);
-// filespec = body->at(1)->to_string();
-// response_head_size = RTMP::HEADER_8;
-// double clientid =
rtmp->createClientID();
-// // response =
rtmp->encodeResult(RTMPMsg::NS_PLAY_RESET, filespec);
-// body->setChannel(4);
-// // rtmp->sendMsg(args->netfd,
body->getChannel(), response_head_size, response->allocated(),
-// // RTMP::INVOKE,
RTMPMsg::FROM_SERVER, *response);
-// // response.reset();
-// // rtmp->setChannel(4);
-// // rtmp->sendMsg(args->netfd,
body->getChannel(), response_head_size, response->allocated(),
-// response =
rtmp->encodeResult(RTMPMsg::NS_PLAY_START, filespec, clientid);
-// // body->dump();
-// sendfile = true;
-// }
-// if (body->getMethodName() == "recData") {
-// }
-// if (body->getMethodName() ==
"onEchoonServ") {
-// }
-// if (rtmp->sendMsg(args->netfd,
body->getChannel(), response_head_size, response->allocated(),
-// RTMP::INVOKE,
RTMPMsg::FROM_SERVER, *response)) {
-// log_error("Sent response to client.");
-// } else {
-// log_error("Couldn't send response to
client!");
-// }
-// if (sendfile) {
-// string fullspec = basepath;
-// fullspec += filespec;
-// rtmp->sendFile(args->netfd, fullspec);
-// sendfile = false;
-// }
-// }
-// }
-// }
-// } else {
-// log_error("Message contains no data!");
-// }
switch (qhead->type) {
case RTMP::CHUNK_SIZE:
+ log_unimpl("Set Chunk Size");
+ break;
case RTMP::BYTES_READ:
+ log_unimpl("Bytes Read");
+ break;
case RTMP::ABORT:
case RTMP::USER:
// already handled as this is a system channel message
@@ -1439,6 +1512,7 @@
log_unimpl("RTMP type %d", qhead->type);
break;
case RTMP::INVOKE:
+ {
body = rtmp->decodeMsgBody(tmpptr, qhead->bodysize);
if (!body) {
log_error("Error INVOKING method \"%s\"!",
body->getMethodName());
@@ -1451,30 +1525,114 @@
// NetStream class, which like NetConnection,
// is a speacial one handled directly by the
// server instead of any cgi-bin plugins.
+ double transid = body->getTransactionID();
+ log_network("The Transaction ID from the client is:
%g", transid);
if (body->getMethodName() == "createStream") {
- /* int streamid = */ hand->createStream();
- double streamid = body->getStreamID();
- log_network("StreamID is: %g", streamid);
- response =
rtmp->encodeResult(RTMPMsg::NS_CREATE_STREAM, streamid);
+ hand->createStream(transid);
+ response =
rtmp->encodeResult(RTMPMsg::NS_CREATE_STREAM, transid);
if (rtmp->sendMsg(args->netfd, qhead->channel,
- RTMP::HEADER_8,
response->allocated(),
- RTMP::INVOKE,
RTMPMsg::FROM_SERVER,
- *response)) {
- }
+ RTMP::HEADER_8, response->allocated(),
+ RTMP::INVOKE, RTMPMsg::FROM_SERVER,
+ *response)) {
+ }
} else if (body->getMethodName() == "play") {
- hand->playStream();
+ string filespec;
+ boost::shared_ptr<gnash::RTMPMsg> nc =
rtmp->getNetConnection();
+ boost::shared_ptr<amf::Element> tcurl =
nc->findProperty("tcUrl");
+ URL url(tcurl->to_string());
+ filespec += url.hostname() + url.path();
+ filespec += '/';
+ filespec += body->at(1)->to_string();
+
+ if (hand->playStream(filespec)) {
+ // Send the Set Chunk Size response
+#if 1
+ response = rtmp->encodeChunkSize(4096);
+ if (rtmp->sendMsg(args->netfd,
RTMP_SYSTEM_CHANNEL,
+ RTMP::HEADER_12, response->allocated(),
+ RTMP::CHUNK_SIZE, RTMPMsg::FROM_SERVER,
+ *response)) {
+ }
+#endif
+ // Send the Play.Resetting response
+ response =
rtmp->encodeResult(RTMPMsg::NS_PLAY_RESET, body->at(1)->to_string(), transid);
+ if (rtmp->sendMsg(args->netfd, qhead->channel,
+ RTMP::HEADER_8, response->allocated(),
+ RTMP::INVOKE, RTMPMsg::FROM_SERVER,
+ *response)) {
+ }
+ // Send the Play.Start response
+ response =
rtmp->encodeResult(RTMPMsg::NS_PLAY_START, body->at(1)->to_string(), transid);
+ if (rtmp->sendMsg(args->netfd, qhead->channel,
+ RTMP::HEADER_8, response->allocated(),
+ RTMP::INVOKE, RTMPMsg::FROM_SERVER,
+ *response)) {
+ }
+ } else {
+ response =
rtmp->encodeResult(RTMPMsg::NS_PLAY_STREAMNOTFOUND, body->at(1)->to_string(),
transid);
+ if (rtmp->sendMsg(args->netfd, qhead->channel,
+ RTMP::HEADER_8, response->allocated(),
+ RTMP::INVOKE, RTMPMsg::FROM_SERVER,
+ *response)) {
+ }
+ }
+ sleep(1); // FIXME: debugging crap
+ // Send the User Control - Stream Live
+ response =
rtmp->encodeUserControl(RTMP::STREAM_LIVE, 1);
+ if (rtmp->sendMsg(args->netfd,
RTMP_SYSTEM_CHANNEL,
+ RTMP::HEADER_12, response->allocated(),
+ RTMP::USER, RTMPMsg::FROM_SERVER,
+ *response)) {
+ }
+ sleep(1); // FIXME: debugging crap
+ // Send an empty Audio packet to get
+ // things started.
+ if (rtmp->sendMsg(args->netfd, 6,
+ RTMP::HEADER_12, 0,
+ RTMP::AUDIO_DATA, RTMPMsg::FROM_SERVER,
+ 0, 0)) {
+ }
+ // Send an empty Video packet to get
+ // things started.
+ if (rtmp->sendMsg(args->netfd, 5,
+ RTMP::HEADER_12, 0,
+ RTMP::VIDEO_DATA, RTMPMsg::FROM_SERVER,
+ 0, 0)) {
+ }
+ sleep(1); // FIXME: debugging crap
+ // Send the User Control - Stream Start
+ response =
rtmp->encodeUserControl(RTMP::STREAM_START, 1);
+ if (rtmp->sendMsg(args->netfd,
RTMP_SYSTEM_CHANNEL,
+ RTMP::HEADER_12, response->allocated(),
+ RTMP::USER, RTMPMsg::FROM_SERVER,
+ *response)) {
+ }
+ int active_stream = hand->getActiveDiskStreams();
+ boost::uint8_t *ptr =
hand->getDiskStream(active_stream)->get();
+ if (ptr) {
+ log_network("Sending %s to client",
+
hand->getDiskStream(active_stream)->getFilespec());
+ if (rtmp->sendMsg(args->netfd, 5,
+ RTMP::HEADER_12, 400,
+ RTMP::NOTIFY, RTMPMsg::FROM_SERVER,
+ ptr, 400)) {
+ log_network("Sent first page to client");
+ }
+ }
} else if (body->getMethodName() == "seek") {
hand->seekStream();
} else if (body->getMethodName() == "pause") {
- hand->pauseStream();
+ hand->pauseStream(transid);
} else if (body->getMethodName() == "close") {
- hand->closeStream();
+ hand->closeStream(transid);
} else if (body->getMethodName() == "resume") {
- hand->resumeStream();
+ hand->resumeStream(transid);
+ } else if (body->getMethodName() == "delete") {
+ hand->deleteStream(transid);
} else if (body->getMethodName() == "publish") {
hand->publishStream();
} else if (body->getMethodName() == "togglePause") {
- hand->togglePause();
+ hand->togglePause(transid);
// This is a server installation specific method.
} else if (body->getMethodName() == "FCSubscribe") {
hand->setFCSubscribe(body->at(0)->to_string());
@@ -1494,6 +1652,7 @@
done = true;
}
break;
+ }
case RTMP::FLV_DATA:
log_unimpl("RTMP type %d", qhead->type);
break;
@@ -1539,7 +1698,7 @@
return true;
}
} else {
- log_error("Communication error with client using fd #%d",
args->netfd);
+ // log_error("Communication error with client using fd #%d",
args->netfd);
rtmp->closeNet(args->netfd);
initialize = true;
return false;
=== modified file 'cygnal/rtmp_server.h'
--- a/cygnal/rtmp_server.h 2010-01-01 17:48:26 +0000
+++ b/cygnal/rtmp_server.h 2010-01-01 20:41:28 +0000
@@ -20,6 +20,7 @@
#include <boost/cstdint.hpp>
#include <boost/shared_ptr.hpp>
+#include <boost/array.hpp>
#include <string>
#include <map>
@@ -35,6 +36,10 @@
namespace cygnal
{
+// Define this if you want to use numeric client ID. Undefining this
+// create ASCII based client IDs instead.
+// #define CLIENT_ID_NUMERIC 1
+
class RTMPServer : public gnash::RTMP
{
public:
@@ -57,13 +62,16 @@
// These are handlers for the various types
boost::shared_ptr<amf::Buffer> encodeResult(gnash::RTMPMsg::rtmp_status_e
status);
boost::shared_ptr<amf::Buffer> encodeResult(gnash::RTMPMsg::rtmp_status_e
status, const std::string &filename);
- boost::shared_ptr<amf::Buffer> encodeResult(gnash::RTMPMsg::rtmp_status_e
status, const std::string &filename, double &streamid);
- boost::shared_ptr<amf::Buffer> encodeResult(gnash::RTMPMsg::rtmp_status_e
status, double &streamid);
- boost::shared_ptr<amf::Buffer> encodeResult(gnash::RTMPMsg::rtmp_status_e
status, const std::string &filename, double &streamid, double &clientid);
+ boost::shared_ptr<amf::Buffer> encodeResult(gnash::RTMPMsg::rtmp_status_e
status, const std::string &filename, double &transid);
+ boost::shared_ptr<amf::Buffer> encodeResult(gnash::RTMPMsg::rtmp_status_e
status, double &transid);
+ boost::shared_ptr<amf::Buffer> encodeResult(gnash::RTMPMsg::rtmp_status_e
status, const std::string &filename, double &transid, double &clientid);
// Encode a Ping for the client
boost::shared_ptr<amf::Buffer> encodePing(rtmp_ping_e type,
boost::uint32_t milliseconds);
boost::shared_ptr<amf::Buffer> encodePing(rtmp_ping_e type);
+ // boost::shared_ptr<amf::Buffer> encodeUser(user_control_e type,
boost::uint32_t milliseconds);
+ boost::shared_ptr<amf::Buffer> encodeAudio(boost::uint8_t *data, size_t
size);
+ boost::shared_ptr<amf::Buffer> encodeVideo(boost::uint8_t *data, size_t
size);
// Encode a onBWDone message for the client
boost::shared_ptr<amf::Buffer> encodeBWDone(double id);
@@ -80,7 +88,14 @@
bool sendFile(int fd, const std::string &filespec);
+ // Create a new client ID
+#ifdef CLIENT_ID_NUMERIC
double createClientID();
+#else
+ std::string createClientID();
+#endif
+
+ // Create a new stream ID, which is simply an incrementing counter.
double createStreamID();
void setStreamID(double id) { _streamid = id; };
@@ -118,7 +133,11 @@
std::string _filespec;
boost::uint32_t _filesize;
std::map<boost::uint16_t, amf::Element> _references;
- std::vector<double> _clientids;
+#ifdef CLIENT_ID_NUMERIC
+ std::array<double> _clientids;
+#else
+ boost::array<std::string, 1000> _clientids;
+#endif
double _streamid;
/// \var _netconnect
/// This store the data from the NetConnection ActionScript
=== modified file 'doc/C/preformatted/cygnal.1.in'
--- a/doc/C/preformatted/cygnal.1.in 2008-06-23 04:34:05 +0000
+++ b/doc/C/preformatted/cygnal.1.in 2010-01-01 20:41:28 +0000
@@ -1,11 +1,11 @@
-'\" -*- coding: us-ascii -*-
+.\" -*- coding: us-ascii -*-
.if \n(.g .ds T< \\FC
.if \n(.g .ds T> \\F[\n[.fam]]
.de URL
\\$2 \(la\\$1\(ra\\$3
..
.if \n(.g .mso www.tmac
-.TH cygnal 1 "20 June 2008" "" ""
+.TH cygnal 1 "20 December 2009" "" ""
.SH NAME
cygnal \- Cygnal
.SH Synopsis
=== modified file 'doc/C/preformatted/dumpshm.1.in'
--- a/doc/C/preformatted/dumpshm.1.in 2009-11-16 12:57:54 +0000
+++ b/doc/C/preformatted/dumpshm.1.in 2010-01-01 20:41:28 +0000
@@ -5,7 +5,7 @@
\\$2 \(la\\$1\(ra\\$3
..
.if \n(.g .mso www.tmac
-.TH dumpshm 1 "16 November 2009" "" ""
+.TH dumpshm 1 "20 December 2009" "" ""
.SH NAME
dumpshm \- Gnash LocalConnection Memory Dumper
.SH Synopsis
=== modified file 'doc/C/preformatted/flvdumper.1.in'
--- a/doc/C/preformatted/flvdumper.1.in 2009-07-07 11:38:41 +0000
+++ b/doc/C/preformatted/flvdumper.1.in 2010-01-01 20:41:28 +0000
@@ -1,43 +1,34 @@
-.\" Title: flvdumper
-.\" Author:
-.\" Generator: DocBook XSL Stylesheets v1.73.2 <http://docbook.sf.net/>
-.\" Date: 07/07/2009
-.\" Manual:
-.\" Source:
-.\"
-.TH "FLVDUMPER" "1" "07/07/2009" "" ""
-.\" disable hyphenation
-.nh
-.\" disable justification (adjust text to left margin only)
-.ad l
-.SH "NAME"
-flvdumper - Gnash FLash Video File Dumper
-.SH "SYNOPSIS"
-.sp
-.RS 4
+.\" -*- coding: us-ascii -*-
+.if \n(.g .ds T< \\FC
+.if \n(.g .ds T> \\F[\n[.fam]]
+.de URL
+\\$2 \(la\\$1\(ra\\$3
+..
+.if \n(.g .mso www.tmac
+.TH flvdumper 1 "20 December 2009" "" ""
+.SH NAME
+flvdumper \- Gnash FLash Video File Dumper
+.SH Synopsis
.nf
-flvdumper (options)\.\.\. (file)\.\.\.
+
+flvdumper (options)... (file)...
.fi
-.RE
-.SH "DESCRIPTION"
-.PP
-Dump information about \.flv files\.
-.PP
-When a SWF player, including Gnash, plays a SWF "movie", the movie can contain
video files\. Flvdumper prints these files, which are comprised of an H\.263
variant or H\.254 video bit stream\.
-.PP
-More information about Flash Video is available at the Wikipedia Flash Video
article: http://en\.wikipedia\.org/wiki/Flash_Video
-.PP
-\-h
-.RS 4
-Print usage info\.
-.RE
-.PP
-\-m
-.RS 4
-Print only meta tags (default)\.
-.RE
-.PP
-\-a
-.RS 4
-Print all the tags\.
-.RE
+.SH DESCRIPTION
+Dump information about .flv files.
+.PP
+When a SWF player, including Gnash, plays a SWF "movie",
+the movie can contain video files.
+Flvdumper prints these files,
+which are comprised of an H.263 variant or H.254 video bit stream.
+.PP
+More information about Flash Video is available at the Wikipedia Flash
+Video article: http://en.wikipedia.org/wiki/Flash_Video
+.TP
+-h
+Print usage info.
+.TP
+-m
+Print only meta tags (default).
+.TP
+-a
+Print all the tags.
=== modified file 'doc/C/preformatted/gnash.1.in'
--- a/doc/C/preformatted/gnash.1.in 2009-03-19 09:13:48 +0000
+++ b/doc/C/preformatted/gnash.1.in 2010-01-01 20:41:28 +0000
@@ -1,11 +1,11 @@
-'\" -*- coding: us-ascii -*-
+.\" -*- coding: us-ascii -*-
.if \n(.g .ds T< \\FC
.if \n(.g .ds T> \\F[\n[.fam]]
.de URL
\\$2 \(la\\$1\(ra\\$3
..
.if \n(.g .mso www.tmac
-.TH gnash 1 "19 March 2009" "" ""
+.TH gnash 1 "20 December 2009" "" ""
.SH NAME
gnash \- GNU Flash (SWF) Player
.SH Synopsis
=== modified file 'doc/C/preformatted/gnash_user.info.in'
--- a/doc/C/preformatted/gnash_user.info.in 2009-03-19 09:13:48 +0000
+++ b/doc/C/preformatted/gnash_user.info.in 2010-01-01 20:41:28 +0000
@@ -1,4 +1,4 @@
-This is gnash_user.info, produced by makeinfo version 4.11 from stdin.
+This is gnash_user.info, produced by makeinfo version 4.13 from stdin.
START-INFO-DIR-ENTRY
* Gnash User Manual: (gnash_user). [MISSING TEXT]
@@ -137,10 +137,10 @@
http://www.gnashdev.org/dev_snapshots
(http://www.gnashdev.org/dev_snapshots/).
- Gnash uses ffmpeg for codecs, so any file supported by Mplayer
+ Gnash uses FFmpeg for codecs, so any file supported by Mplayer
should work with Gnash. Gnash supports the loading of patent free
codecs like Ogg Vorbis or Theora from disk based files, while work is
-being done to support these codecs when embedded in a SWF file. Ffmpeg
+being done to support these codecs when embedded in a SWF file. FFmpeg
contains the codecs used by the current SWF defintion, FLV, VP6 (ON2),
H.263, H.264, and MP3.
@@ -526,6 +526,25 @@
movie on a webpage.
This option is _off_ by
default.
+webcamDevice integer The integer value
+ (index into vector of
+ video devices) that
+ represents the default
+ webcam. To easily get
+ this entry run
+ utilities/findwebcams
+ (only works with
+ Gstreamer right now)
+microphoneDevice integer The integer value
+ (index into vector of
+ microphone devices)
+ that represents the
+ default microphone. To
+ easily get this entry
+ run
+ utilities/findmicrophones
+ (only works with
+ Gstreamer right now)
flashVersionString string Set the string returned
by $version and
System.capabilities.version.
@@ -579,6 +598,10 @@
Object files ("flash
cookies") if they are
enabled.
+solLocalDomain on/off If set to _on_, allow
+ the loading of Shared
+ Objects only on the
+ localhost.
SOLreadonly on/off If set to _on_, Gnash
will not write Shared
Object files.
@@ -766,7 +789,7 @@
3.1.2 Software Requirements
---------------------------
-The 0.8.5 release of Gnash has been designed to run on UNIX/Linux
+The 0.8.6 release of Gnash has been designed to run on UNIX/Linux
variants, and has been run on most of the free ones. However, Gnash
has successfully run on Windows, Darwin (Mac OS X), Irix, Solaris,
BeOs, OS/2, and Haiku. Gnash has also run on the following 64-bit
@@ -1055,8 +1078,8 @@
F
=
-ffmpeg
- ffmpeg is an audio and video decoding library which can be used by
+FFmpeg
+ FFmpeg is an audio and video decoding library which can be used by
Gnash to decode mp3, FLV and other media types.
Flash
@@ -1222,7 +1245,7 @@
independent of each other: you can use it for a task and not for
the other if you wish. This version of Gnash does not implement
menus in the SDL GUI; the SDL sound handler is the most feature
- rich, supporting video through ffmpeg.
+ rich, supporting video through FFmpeg.
sound handler
The _sound handler_ is the part of Gnash which handles both event
@@ -1230,7 +1253,7 @@
through the sound handler when SDL is used. The sound handler
must be selected during configuration of Gnash when compiling.
- There are currently two sound handlers available in Gnash: ffmpeg
+ There are currently two sound handlers available in Gnash: FFmpeg
and Gstreamer. The ffmpeg sound handler uses SDL for mixing. The
Gstreamer-sound handler uses the available plugins to decode the
audio, so it might not work if some important plugins are missing.
@@ -1752,60 +1775,60 @@
Ref: Gnash Interactive Control Keys <1>13301
Node: User Configuration File14050
Ref: User Configuration Variables14835
-Node: Installing and Configuring Gnash35967
-Node: Requirements36328
-Node: Hardware Requirements36649
-Ref: Build Matrix37426
-Node: Software Requirements38656
-Node: Downloading Gnash39489
-Node: Getting the Source40124
-Node: Releases40484
-Node: Snapshot41042
-Node: Repository41513
-Node: Getting Codec Support42334
-Node: Reporting Bugs43051
-Node: Get a Fresh Binary Package44041
-Node: Determine if the bug was previously reported44828
-Node: Review the bug writing guidelines45647
-Node: Filing a bug report46699
-Node: Glossary46983
-Ref: A47097
-Ref: C47917
-Ref: D48203
-Ref: E48615
-Ref: F48857
-Ref: G49742
-Ref: K50727
-Ref: M51087
-Ref: N51438
-Ref: O51595
-Ref: P52210
-Ref: Q52497
-Ref: R52681
-Ref: S53922
-Ref: T55409
-Ref: X56117
-Node: Authors56210
-Node: GNU Free Documentation License56920
-Node: 0_ PREAMBLE57684
-Node: 1_ APPLICABILITY AND DEFINITIONS58991
-Ref: fdl-document59217
-Ref: fdl-modified59508
-Ref: fdl-secondary59695
-Ref: fdl-invariant60340
-Ref: fdl-cover-texts60589
-Ref: fdl-transparent60802
-Ref: fdl-title-page62092
-Node: 2_ VERBATIM COPYING62481
-Node: 3_ COPYING IN QUANTITY63462
-Node: 4_ MODIFICATIONS65820
-Node: 5_ COMBINING DOCUMENTS71881
-Node: 6_ COLLECTIONS OF DOCUMENTS73379
-Node: 7_ AGGREGATION WITH INDEPENDENT WORKS74271
-Node: 8_ TRANSLATION75500
-Node: 9_ TERMINATION76404
-Node: 10_ FUTURE REVISIONS OF THIS LICENSE77060
-Node: Addendum78201
+Node: Installing and Configuring Gnash37567
+Node: Requirements37928
+Node: Hardware Requirements38249
+Ref: Build Matrix39026
+Node: Software Requirements40256
+Node: Downloading Gnash41089
+Node: Getting the Source41724
+Node: Releases42084
+Node: Snapshot42642
+Node: Repository43113
+Node: Getting Codec Support43934
+Node: Reporting Bugs44651
+Node: Get a Fresh Binary Package45641
+Node: Determine if the bug was previously reported46428
+Node: Review the bug writing guidelines47247
+Node: Filing a bug report48299
+Node: Glossary48583
+Ref: A48697
+Ref: C49517
+Ref: D49803
+Ref: E50215
+Ref: F50457
+Ref: G51342
+Ref: K52327
+Ref: M52687
+Ref: N53038
+Ref: O53195
+Ref: P53810
+Ref: Q54097
+Ref: R54281
+Ref: S55522
+Ref: T57009
+Ref: X57717
+Node: Authors57810
+Node: GNU Free Documentation License58520
+Node: 0_ PREAMBLE59284
+Node: 1_ APPLICABILITY AND DEFINITIONS60591
+Ref: fdl-document60817
+Ref: fdl-modified61108
+Ref: fdl-secondary61295
+Ref: fdl-invariant61940
+Ref: fdl-cover-texts62189
+Ref: fdl-transparent62402
+Ref: fdl-title-page63692
+Node: 2_ VERBATIM COPYING64081
+Node: 3_ COPYING IN QUANTITY65062
+Node: 4_ MODIFICATIONS67420
+Node: 5_ COMBINING DOCUMENTS73481
+Node: 6_ COLLECTIONS OF DOCUMENTS74979
+Node: 7_ AGGREGATION WITH INDEPENDENT WORKS75871
+Node: 8_ TRANSLATION77100
+Node: 9_ TERMINATION78004
+Node: 10_ FUTURE REVISIONS OF THIS LICENSE78660
+Node: Addendum79801
End Tag Table
=== modified file 'doc/C/preformatted/gnashref.html.in'
--- a/doc/C/preformatted/gnashref.html.in 2009-09-24 16:32:22 +0000
+++ b/doc/C/preformatted/gnashref.html.in 2010-01-01 20:41:28 +0000
@@ -1,6 +1,6 @@
-<html><head><meta http-equiv="Content-Type" content="text/html;
charset=ISO-8859-1"><title>Gnash Reference Manual</title><meta name="generator"
content="DocBook XSL Stylesheets V1.74.3"></head><body bgcolor="white"
text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="book"
lang="en"><div class="titlepage"><div><div><h1 class="title"><a
name="index"></a>Gnash Reference Manual</h1></div><div><p class="releaseinfo">
- This manual describes version 0.8.5 of Gnash.
- </p></div><div><p class="copyright">Copyright ? 2005, 2006, 2007, 2008
Free Software Foundation</p></div><div><div class="legalnotice"><a
name="legalnotice"></a><p>
+<html><head><meta http-equiv="Content-Type" content="text/html;
charset=ISO-8859-1"><title>Gnash Reference Manual</title><meta name="generator"
content="DocBook XSL Stylesheets V1.75.2"></head><body bgcolor="white"
text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div lang="en"
class="book" title="Gnash Reference Manual"><div
class="titlepage"><div><div><h1 class="title"><a name="index"></a>Gnash
Reference Manual</h1></div><div><p class="releaseinfo">
+ This manual describes version 0.8.6 of Gnash.
+ </p></div><div><p class="copyright">Copyright ? 2005, 2006, 2007, 2008,
2009, 2010 Free Software Foundation</p></div><div><div class="legalnotice"
title="Legal Notice"><a name="legalnotice"></a><p>
Permission is granted to copy, distribute and/or modify this document
under the terms of the <a class="link" href="#fdl" title="Appendix?A.?GNU
Free Documentation License"><em class="citetitle">GNU
Free Documentation License</em></a>, Version 1.1 or any later
@@ -18,7 +18,7 @@
</p>
<p class="publisher">Open Media Now! Foundation</p>
- </td></tr></table></div></div></div><hr></div><div class="toc"><p><b>Table
of Contents</b></p><dl><dt><span class="chapter"><a href="#intro">1.
Introduction</a></span></dt><dd><dl><dt><span class="sect1"><a
href="#audience">Audience</a></span></dt><dt><span class="sect1"><a
href="#runs-on">What Is Supported?</a></span></dt></dl></dd><dt><span
class="chapter"><a href="#build">2. Building from
Source</a></span></dt><dd><dl><dt><span class="sect1"><a
href="#building_overview">Overview</a></span></dt><dt><span class="sect1"><a
href="#gettingsource">Getting The Source</a></span></dt><dd><dl><dt><span
class="sect2"><a href="#sourcereleases">Releases</a></span></dt><dt><span
class="sect2"><a href="#sourcecvs">Bzr
Access</a></span></dt></dl></dd><dt><span class="sect1"><a
href="#dependencies">Code Dependencies</a></span></dt><dt><span
class="sect1"><a href="#testdep">Testing Dependencies</a></span></dt><dt><span
class="sect1"><a href="#docdepend">Documentation
Dependencies</a></span></dt><dt><span class="sect1"><a
href="#configure">Configuring Gnash</a></span></dt><dt><span class="sect1"><a
href="#compile">Compiling the Code</a></span></dt><dt><span class="sect1"><a
href="#processdoc">Creating the Documentation</a></span></dt><dt><span
class="sect1"><a href="#runtests">Running the
Tests</a></span></dt><dd><dl><dt><span class="sect2"><a href="#dejagnu">Using
DejaGnu</a></span></dt><dt><span class="sect2"><a href="#manually">Running The
Tests Manually</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a
href="#internals">3. Software Internals</a></span></dt><dd><dl><dt><span
class="sect1"><a href="#tour">A Tour of Gnash</a></span></dt><dd><dl><dt><span
class="sect2"><a href="#The%20Libraries">The Libraries</a></span></dt><dt><span
class="sect2"><a href="#apps">The Applications</a></span></dt><dt><span
class="sect2"><a href="#plugin">The Plugin</a></span></dt><dt><span
class="sect2"><a href="#logging">The Message Logging
System</a></span></dt></dl></dd><dt><span class="sect1"><a
href="#soundhandlers">Sound handling in Gnash</a></span></dt><dd><dl><dt><span
class="sect2"><a href="#soundtypes">Sound types</a></span></dt><dt><span
class="sect2"><a href="#soundparsing">Sound parsing</a></span></dt><dt><span
class="sect2"><a href="#soundplayback">Sound playback</a></span></dt><dt><span
class="sect2"><a href="#sdlsound">The SDL sound
backend</a></span></dt><dt><span class="sect2"><a href="#gstreamer">The
Gstreamer backend</a></span></dt><dt><span class="sect2"><a
href="#audio-future">Future audio backends</a></span></dt><dt><span
class="sect2"><a href="#gstreamer-details">Detailed description of the
Gstreamer backend</a></span></dt></dl></dd><dt><span class="sect1"><a
href="#testing">Testing </a></span></dt><dd><dl><dt><span class="sect2"><a
href="#testtools">Testing Tools</a></span></dt><dt><span class="sect2"><a
href="#testcases">Test Cases</a></span></dt><dt><span class="sect2"><a
href="#writeastests">Writing ActionScript Tests</a></span></dt><dt><span
class="sect2"><a href="#writemingtests">Writing Ming-based self-contained SWF
tests</a></span></dt><dt><span class="sect2"><a
href="#writing_dejagnu_so_tests">Writing self-contained SWF tests with other
compilers</a></span></dt><dt><span class="sect2"><a
href="#writing_test_runners">Writing Test
Runners</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a
href="#bugreport">5. Reporting Bugs</a></span></dt><dd><dl><dt><span
class="sect1"><a href="#bugstep_package">Get a Fresh Binary
Package</a></span></dt><dt><span class="sect1"><a
href="#bugstep_search">Determine if the bug was previously
reported</a></span></dt><dt><span class="sect1"><a
href="#bugstep_guidelines">Review the bug writing
guidelines</a></span></dt><dt><span class="sect1"><a
href="#bugstep_file">Filing a bug report</a></span></dt></dl></dd><dt><span
class="chapter"><a href="#extensions">6. Gnash
Extensions</a></span></dt><dd><dl><dt><span class="sect1"><a
href="#newext">Creating A New Extension</a></span></dt><dd><dl><dt><span
class="sect2"><a href="#craftext">Crafting an
Extension</a></span></dt></dl></dd><dt><span class="sect1"><a
href="#debuext">Debugging An Extension</a></span></dt><dt><span
class="sect1"><a href="#inclext">Included
Extensions</a></span></dt></dl></dd><dt><span class="chapter"><a
href="#rtmp">7. RTMP Protocol</a></span></dt><dd><dl><dt><span class="sect1"><a
href="#amf">AMF Format</a></span></dt></dl></dd><dt><span class="chapter"><a
href="#nsapi">8. Mozilla/Firefox NPAPI Plugin</a></span></dt><dd><dl><dt><span
class="sect1"><a href="#plugincapi">Plugin C API</a></span></dt><dt><span
class="sect1"><a href="#plugincppapi">Plugin C++ API</a></span></dt><dt><span
class="sect1"><a href="#glthread">OpenGL and Threads</a></span></dt><dt><span
class="sect1"><a href="#eventhandle">Plugin Event
Handling</a></span></dt></dl></dd><dt><span class="chapter"><a
href="#authors">9. Authors</a></span></dt><dt><span class="appendix"><a
href="#fdl">A. GNU Free Documentation License</a></span></dt><dd><dl><dt><span
class="sect1"><a href="#fdl-preamble">0. PREAMBLE</a></span></dt><dt><span
class="sect1"><a href="#fdl-section1">1. APPLICABILITY AND
DEFINITIONS</a></span></dt><dt><span class="sect1"><a href="#fdl-section2">2.
VERBATIM COPYING</a></span></dt><dt><span class="sect1"><a
href="#fdl-section3">3. COPYING IN QUANTITY</a></span></dt><dt><span
class="sect1"><a href="#fdl-section4">4. MODIFICATIONS</a></span></dt><dt><span
class="sect1"><a href="#fdl-section5">5. COMBINING
DOCUMENTS</a></span></dt><dt><span class="sect1"><a href="#fdl-section6">6.
COLLECTIONS OF DOCUMENTS</a></span></dt><dt><span class="sect1"><a
href="#fdl-section7">7. AGGREGATION WITH INDEPENDENT
WORKS</a></span></dt><dt><span class="sect1"><a href="#fdl-section8">8.
TRANSLATION</a></span></dt><dt><span class="sect1"><a href="#fdl-section9">9.
TERMINATION</a></span></dt><dt><span class="sect1"><a href="#fdl-section10">10.
FUTURE REVISIONS OF THIS LICENSE</a></span></dt><dt><span class="sect1"><a
href="#fdl-using">Addendum</a></span></dt></dl></dd></dl></div><div
class="list-of-tables"><p><b>List of Tables</b></p><dl><dt>2.1. <a
href="#codedeps">Code Dependency Table</a></dt><dt>2.2. <a
href="#testdeps">Testing Dependency Table</a></dt><dt>2.3. <a
href="#docdeps">Documentation Dependency Table</a></dt><dt>2.4. <a
href="#tb-config-features">Configuration Options - Features</a></dt><dt>2.5. <a
href="#tb-configure-paths">Custom Path Options</a></dt></dl></div><div
class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a
name="intro"></a>Chapter?1.?Introduction</h2></div></div></div><div
class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a
href="#audience">Audience</a></span></dt><dt><span class="sect1"><a
href="#runs-on">What Is Supported?</a></span></dt></dl></div><p>
+ </td></tr></table></div></div></div><hr></div><div class="toc"><p><b>Table
of Contents</b></p><dl><dt><span class="chapter"><a href="#intro">1.
Introduction</a></span></dt><dd><dl><dt><span class="sect1"><a
href="#audience">Audience</a></span></dt><dt><span class="sect1"><a
href="#runs-on">What Is Supported?</a></span></dt></dl></dd><dt><span
class="chapter"><a href="#build">2. Building from
Source</a></span></dt><dd><dl><dt><span class="sect1"><a
href="#building_overview">Overview</a></span></dt><dt><span class="sect1"><a
href="#gettingsource">Getting The Source</a></span></dt><dd><dl><dt><span
class="sect2"><a href="#sourcereleases">Releases</a></span></dt><dt><span
class="sect2"><a href="#sourcecvs">Bzr
Access</a></span></dt></dl></dd><dt><span class="sect1"><a
href="#dependencies">Code Dependencies</a></span></dt><dt><span
class="sect1"><a href="#testdep">Testing Dependencies</a></span></dt><dt><span
class="sect1"><a href="#docdepend">Documentation
Dependencies</a></span></dt><dt><span class="sect1"><a
href="#configure">Configuring Gnash</a></span></dt><dt><span class="sect1"><a
href="#compile">Compiling the Code</a></span></dt><dt><span class="sect1"><a
href="#processdoc">Creating the Documentation</a></span></dt><dt><span
class="sect1"><a href="#runtests">Running the
Tests</a></span></dt><dd><dl><dt><span class="sect2"><a href="#dejagnu">Using
DejaGnu</a></span></dt><dt><span class="sect2"><a href="#manually">Running The
Tests Manually</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a
href="#internals">3. Software Internals</a></span></dt><dd><dl><dt><span
class="sect1"><a href="#tour">A Tour of Gnash</a></span></dt><dd><dl><dt><span
class="sect2"><a href="#The%20Libraries">The Libraries</a></span></dt><dt><span
class="sect2"><a href="#apps">The Applications</a></span></dt><dt><span
class="sect2"><a href="#plugin">The Plugin</a></span></dt><dt><span
class="sect2"><a href="#logging">The Message Logging
System</a></span></dt></dl></dd><dt><span class="sect1"><a
href="#soundhandlers">Sound handling in Gnash</a></span></dt><dd><dl><dt><span
class="sect2"><a href="#soundtypes">Sound types</a></span></dt><dt><span
class="sect2"><a href="#soundparsing">Sound parsing</a></span></dt><dt><span
class="sect2"><a href="#soundplayback">Sound playback</a></span></dt><dt><span
class="sect2"><a href="#sdlsound">The SDL sound
backend</a></span></dt><dt><span class="sect2"><a href="#gstreamer">The
Gstreamer backend</a></span></dt><dt><span class="sect2"><a
href="#audio-future">Future audio backends</a></span></dt><dt><span
class="sect2"><a href="#gstreamer-details">Detailed description of the
Gstreamer backend</a></span></dt></dl></dd><dt><span class="sect1"><a
href="#testing">Testing </a></span></dt><dd><dl><dt><span class="sect2"><a
href="#testtools">Testing Tools</a></span></dt><dt><span class="sect2"><a
href="#testcases">Test Cases</a></span></dt><dt><span class="sect2"><a
href="#writeastests">Writing ActionScript Tests</a></span></dt><dt><span
class="sect2"><a href="#writemingtests">Writing Ming-based self-contained SWF
tests</a></span></dt><dt><span class="sect2"><a
href="#writing_dejagnu_so_tests">Writing self-contained SWF tests with other
compilers</a></span></dt><dt><span class="sect2"><a
href="#writing_test_runners">Writing Test
Runners</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a
href="#bugreport">5. Reporting Bugs</a></span></dt><dd><dl><dt><span
class="sect1"><a href="#bugstep_package">Get a Fresh Binary
Package</a></span></dt><dt><span class="sect1"><a
href="#bugstep_search">Determine if the bug was previously
reported</a></span></dt><dt><span class="sect1"><a
href="#bugstep_guidelines">Review the bug writing
guidelines</a></span></dt><dt><span class="sect1"><a
href="#bugstep_file">Filing a bug report</a></span></dt></dl></dd><dt><span
class="chapter"><a href="#extensions">6. Gnash
Extensions</a></span></dt><dd><dl><dt><span class="sect1"><a
href="#newext">Creating A New Extension</a></span></dt><dd><dl><dt><span
class="sect2"><a href="#craftext">Crafting an
Extension</a></span></dt></dl></dd><dt><span class="sect1"><a
href="#debuext">Debugging An Extension</a></span></dt><dt><span
class="sect1"><a href="#inclext">Included
Extensions</a></span></dt></dl></dd><dt><span class="chapter"><a
href="#rtmp">7. RTMP Protocol</a></span></dt><dd><dl><dt><span class="sect1"><a
href="#amf">AMF Format</a></span></dt></dl></dd><dt><span class="chapter"><a
href="#nsapi">8. Mozilla/Firefox NPAPI Plugin</a></span></dt><dd><dl><dt><span
class="sect1"><a href="#plugincapi">Plugin C API</a></span></dt><dt><span
class="sect1"><a href="#plugincppapi">Plugin C++ API</a></span></dt><dt><span
class="sect1"><a href="#glthread">OpenGL and Threads</a></span></dt><dt><span
class="sect1"><a href="#eventhandle">Plugin Event
Handling</a></span></dt></dl></dd><dt><span class="chapter"><a
href="#authors">9. Authors</a></span></dt><dt><span class="appendix"><a
href="#fdl">A. GNU Free Documentation License</a></span></dt><dd><dl><dt><span
class="sect1"><a href="#fdl-preamble">0. PREAMBLE</a></span></dt><dt><span
class="sect1"><a href="#fdl-section1">1. APPLICABILITY AND
DEFINITIONS</a></span></dt><dt><span class="sect1"><a href="#fdl-section2">2.
VERBATIM COPYING</a></span></dt><dt><span class="sect1"><a
href="#fdl-section3">3. COPYING IN QUANTITY</a></span></dt><dt><span
class="sect1"><a href="#fdl-section4">4. MODIFICATIONS</a></span></dt><dt><span
class="sect1"><a href="#fdl-section5">5. COMBINING
DOCUMENTS</a></span></dt><dt><span class="sect1"><a href="#fdl-section6">6.
COLLECTIONS OF DOCUMENTS</a></span></dt><dt><span class="sect1"><a
href="#fdl-section7">7. AGGREGATION WITH INDEPENDENT
WORKS</a></span></dt><dt><span class="sect1"><a href="#fdl-section8">8.
TRANSLATION</a></span></dt><dt><span class="sect1"><a href="#fdl-section9">9.
TERMINATION</a></span></dt><dt><span class="sect1"><a href="#fdl-section10">10.
FUTURE REVISIONS OF THIS LICENSE</a></span></dt><dt><span class="sect1"><a
href="#fdl-using">Addendum</a></span></dt></dl></dd></dl></div><div
class="list-of-tables"><p><b>List of Tables</b></p><dl><dt>2.1. <a
href="#codedeps">Code Dependency Table</a></dt><dt>2.2. <a
href="#testdeps">Testing Dependency Table</a></dt><dt>2.3. <a
href="#docdeps">Documentation Dependency Table</a></dt><dt>2.4. <a
href="#tb-config-features">Configuration Options - Features</a></dt><dt>2.5. <a
href="#tb-configure-paths">Custom Path Options</a></dt></dl></div><div
class="chapter" title="Chapter?1.?Introduction"><div
class="titlepage"><div><div><h2 class="title"><a
name="intro"></a>Chapter?1.?Introduction</h2></div></div></div><div
class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a
href="#audience">Audience</a></span></dt><dt><span class="sect1"><a
href="#runs-on">What Is Supported?</a></span></dt></dl></div><p>
<span class="application">Gnash</span> is a free SWF movie player. It is
available as a
stand-alone application or as a plugin for several popular
web browsers. It supports playing media from a disk or streaming
@@ -31,12 +31,12 @@
extending ActionScript by creating your own classes. You can write
wrappers for any development library, and import them into the
player much like Perl or Python does.
- </p><div class="sect1" lang="en"><div class="titlepage"><div><div><h2
class="title" style="clear: both"><a
name="audience"></a>Audience</h2></div></div></div><p>
+ </p><div class="sect1" title="Audience"><div class="titlepage"><div><div><h2
class="title" style="clear: both"><a
name="audience"></a>Audience</h2></div></div></div><p>
This manual is primarily focused on users interested in how to
get Gnash installed from a package, and basic usage as a web
browser plugin. For more technical details, please refer to the
Gnash Reference manual.
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="runs-on"></a>What Is Supported?</h2></div></div></div><p>
+ </p></div><div class="sect1" title="What Is Supported?"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="runs-on"></a>What Is Supported?</h2></div></div></div><p>
Gnash is known to compile for most any POSIX and ANSI C++
conforming system if you have all the dependent libraries
installed. Systems we test on, and which Gnash is known to
@@ -84,7 +84,7 @@
while work is being done to support these codecs when embedded
in a SWF file. FFmpeg contains the codecs used by the current
SWF defintion, FLV, VP6 (ON2), H.263, H.264, and MP3.
- </p></div></div><div class="chapter" lang="en"><div
class="titlepage"><div><div><h2 class="title"><a
name="build"></a>Chapter?2.?Building from Source</h2></div></div></div><div
class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a
href="#building_overview">Overview</a></span></dt><dt><span class="sect1"><a
href="#gettingsource">Getting The Source</a></span></dt><dd><dl><dt><span
class="sect2"><a href="#sourcereleases">Releases</a></span></dt><dt><span
class="sect2"><a href="#sourcecvs">Bzr
Access</a></span></dt></dl></dd><dt><span class="sect1"><a
href="#dependencies">Code Dependencies</a></span></dt><dt><span
class="sect1"><a href="#testdep">Testing Dependencies</a></span></dt><dt><span
class="sect1"><a href="#docdepend">Documentation
Dependencies</a></span></dt><dt><span class="sect1"><a
href="#configure">Configuring Gnash</a></span></dt><dt><span class="sect1"><a
href="#compile">Compiling the Code</a></span></dt><dt><span class="sect1"><a
href="#processdoc">Creating the Documentation</a></span></dt><dt><span
class="sect1"><a href="#runtests">Running the
Tests</a></span></dt><dd><dl><dt><span class="sect2"><a href="#dejagnu">Using
DejaGnu</a></span></dt><dt><span class="sect2"><a href="#manually">Running The
Tests Manually</a></span></dt></dl></dd></dl></div><div class="sect1"
lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear:
both"><a name="building_overview"></a>Overview</h2></div></div></div><p>
+ </p></div></div><div class="chapter" title="Chapter?2.?Building from
Source"><div class="titlepage"><div><div><h2 class="title"><a
name="build"></a>Chapter?2.?Building from Source</h2></div></div></div><div
class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a
href="#building_overview">Overview</a></span></dt><dt><span class="sect1"><a
href="#gettingsource">Getting The Source</a></span></dt><dd><dl><dt><span
class="sect2"><a href="#sourcereleases">Releases</a></span></dt><dt><span
class="sect2"><a href="#sourcecvs">Bzr
Access</a></span></dt></dl></dd><dt><span class="sect1"><a
href="#dependencies">Code Dependencies</a></span></dt><dt><span
class="sect1"><a href="#testdep">Testing Dependencies</a></span></dt><dt><span
class="sect1"><a href="#docdepend">Documentation
Dependencies</a></span></dt><dt><span class="sect1"><a
href="#configure">Configuring Gnash</a></span></dt><dt><span class="sect1"><a
href="#compile">Compiling the Code</a></span></dt><dt><span class="sect1"><a
href="#processdoc">Creating the Documentation</a></span></dt><dt><span
class="sect1"><a href="#runtests">Running the
Tests</a></span></dt><dd><dl><dt><span class="sect2"><a href="#dejagnu">Using
DejaGnu</a></span></dt><dt><span class="sect2"><a href="#manually">Running The
Tests Manually</a></span></dt></dl></dd></dl></div><div class="sect1"
title="Overview"><div class="titlepage"><div><div><h2 class="title"
style="clear: both"><a
name="building_overview"></a>Overview</h2></div></div></div><p>
The typical process of building from source will involve
<a class="link" href="#gettingsource" title="Getting The Source">getting
the source</a>,
<a class="link" href="#dependencies" title="Code Dependencies">build
dependencies</a>,
@@ -112,7 +112,7 @@
</p><p>
Continue reading for detailed step-by-step instructions
of the entire procedure.
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="gettingsource"></a>Getting The Source</h2></div></div></div><div
class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a
name="sourcereleases"></a>Releases</h3></div></div></div><p>
+ </p></div><div class="sect1" title="Getting The Source"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="gettingsource"></a>Getting The Source</h2></div></div></div><div
class="sect2" title="Releases"><div class="titlepage"><div><div><h3
class="title"><a name="sourcereleases"></a>Releases</h3></div></div></div><p>
Tarballs of official releases can be found in the download area
of the project's GNU Savannah page at
<a class="ulink" href="http://savannah.gnu.org/projects/gnash"
target="_top">
@@ -122,7 +122,7 @@
<a class="ulink" href="http://ftp.gnu.org/gnu/gnash" target="_top">
http://ftp.gnu.org/gnu/gnash
</a>
- </p></div><div class="sect2" lang="en"><div
class="titlepage"><div><div><h3 class="title"><a name="sourcecvs"></a>Bzr
Access</h3></div></div></div><p>
+ </p></div><div class="sect2" title="Bzr Access"><div
class="titlepage"><div><div><h3 class="title"><a name="sourcecvs"></a>Bzr
Access</h3></div></div></div><p>
The latest <span class="application">Gnash</span> development sources
are available via bzr.
Use the following commands to check them out:
</p><pre class="programlisting">
@@ -145,7 +145,7 @@
<a class="ulink" href="http://www.gnashdev.org/dev_snapshots/"
target="_top">
http://www.gnashdev.org/dev_snapshots
</a>
- </p></div></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="dependencies"></a>Code Dependencies</h2></div></div></div><p>
+ </p></div></div><div class="sect1" title="Code Dependencies"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="dependencies"></a>Code Dependencies</h2></div></div></div><p>
<span class="application">Gnash</span> has a number of dependencies on
other packages.
If you install the dependencies using a package
manager, be certain to install the development versions
@@ -332,7 +332,7 @@
This package is required to run
<span class="emphasis"><em>autogen.sh</em></span>, which is a
requirement
if you are using the development source from CVS.
- </td><td align="left"><code
class="filename">libltdl3-dev</code></td><td align="left"><code
class="filename">libtool</code></td><td align="left"><code
class="filename">libtool</code></td></tr></tbody></table></div></div><br
class="table-break"></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="testdep"></a>Testing Dependencies</h2></div></div></div><p>
+ </td><td align="left"><code
class="filename">libltdl3-dev</code></td><td align="left"><code
class="filename">libtool</code></td><td align="left"><code
class="filename">libtool</code></td></tr></tbody></table></div></div><br
class="table-break"></div><div class="sect1" title="Testing Dependencies"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="testdep"></a>Testing Dependencies</h2></div></div></div><p>
<span class="application">Gnash</span> tries to run as many tests as
possible, but will
silentl skip tests if the tools to run them are unavailable.
</p><div class="table"><a name="testdeps"></a><p
class="title"><b>Table?2.2.?Testing Dependency Table</b></p><div
class="table-contents"><table summary="Testing Dependency Table"
border="1"><colgroup><col><col><col><col><col><col><col></colgroup><thead><tr><th
align="left">Name</th><th align="left">Level</th><th
align="left">Version</th><th align="left">Description</th><th
align="left">Explanation</th><th align="left">apt-get package</th><th
align="left">RPM/Yum package</th><th align="left">BSD
package</th></tr></thead><tbody><tr><td align="left">Ming</td><td
align="left">Optional</td><td align="left">0.4.0_beta4 or higher</td><td
align="left">
@@ -360,7 +360,7 @@
</td><td align="left">
DejaGnu is used to run multiple tests in an
automated fashion.
- </td><td align="left"><code class="filename">dejagnu</code></td><td
align="left"><code class="filename">dejagnu</code></td><td align="left"><code
class="filename">dejagnu</code></td></tr></tbody></table></div></div><br
class="table-break"></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="docdepend"></a>Documentation Dependencies</h2></div></div></div><p>
+ </td><td align="left"><code class="filename">dejagnu</code></td><td
align="left"><code class="filename">dejagnu</code></td><td align="left"><code
class="filename">dejagnu</code></td></tr></tbody></table></div></div><br
class="table-break"></div><div class="sect1" title="Documentation
Dependencies"><div class="titlepage"><div><div><h2 class="title" style="clear:
both"><a name="docdepend"></a>Documentation
Dependencies</h2></div></div></div><p>
The following packages are used to build <span
class="application">Gnash</span>'s documentation.
</p><div class="table"><a name="docdeps"></a><p
class="title"><b>Table?2.3.?Documentation Dependency Table</b></p><div
class="table-contents"><table summary="Documentation Dependency Table"
border="1"><colgroup><col><col><col><col><col><col><col></colgroup><thead><tr><th
align="left">Name</th><th align="left">Level</th><th
align="left">Version</th><th align="left">Description</th><th
align="left">Explanation</th><th align="left">apt-get package</th><th
align="left">RPM/Yum package</th><th align="left">BSD
package</th></tr></thead><tbody><tr><td align="left">Docbook</td><td
align="left">Required</td><td align="left">?</td><td align="left">
<a class="ulink" href="http://http://docbook.sourceforge.net/"
target="_top">Docbook</a> is
@@ -430,7 +430,7 @@
installation. If you encounter problems with the Java
installation, you may also need to add this path to the
<span class="emphasis"><em>CLASSPATH</em></span> environment variable.
- </p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2
class="title" style="clear: both"><a name="configure"></a>Configuring
Gnash</h2></div></div></div><p>
+ </p></div><div class="sect1" title="Configuring Gnash"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="configure"></a>Configuring Gnash</h2></div></div></div><p>
<span class="application">Gnash</span>, like most GNU projects, allows a
user to select various
options before compiling its source code. These options include
selecting from the available features, specifying custom paths for
@@ -486,17 +486,17 @@
available, and not all are supposed to work together. A common
mistake when configuring <span class="application">Gnash</span> is to
supply too many options,
overdriving <span class="application">Gnash</span>'s ability to do the
right thing.
- </p><div class="sect1" lang="en"><div class="titlepage"><div><div><h2
class="title" style="clear: both"><a
name="configfeatures"></a>Features</h2></div></div></div><p>
+ </p><div class="sect1" title="Features"><div class="titlepage"><div><div><h2
class="title" style="clear: both"><a
name="configfeatures"></a>Features</h2></div></div></div><p>
Some switches can be used during configuration to enable or disable
features of <span class="application">Gnash</span>. Some of the most
important configuration options
are:
- </p><div class="itemizedlist"><ul type="opencircle"><li
style="list-style-type: circle"><p>
+ </p><div class="itemizedlist"><ul class="itemizedlist" type="opencircle"><li
class="listitem" style="list-style-type: circle"><p>
<code class="option">--enable-gui</code> lets you specify your GUI of
choice.
The default option is GTK.
- </p></li><li style="list-style-type: circle"><p>
+ </p></li><li class="listitem" style="list-style-type: circle"><p>
<code class="option">--enable-renderer</code> allows a renderer to be
chosen. The default renderer is AGG.
- </p></li><li style="list-style-type: circle"><p>
+ </p></li><li class="listitem" style="list-style-type: circle"><p>
<code class="option">--enable-media</code> permits a media handler to be
selected. The default is Gstreamer.
</p></li></ul></div><p>
@@ -599,7 +599,7 @@
Currently support is only available using GTK gui and AGG renderer.
Keeping it enabled is not a problem as it will not be used if not
available in the current X session.
- </td></tr></tbody></table></div></div><br
class="table-break"></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="custompath"></a>Specifying Custom Paths</h2></div></div></div><p>
+ </td></tr></tbody></table></div></div><br
class="table-break"></div><div class="sect1" title="Specifying Custom
Paths"><div class="titlepage"><div><div><h2 class="title" style="clear:
both"><a name="custompath"></a>Specifying Custom Paths</h2></div></div></div><p>
By default, none of these options should be required
unless you want <span class="application">Gnash</span> to use a specific
version of a
development package, or if the configure test fails to
@@ -851,7 +851,7 @@
</td></tr></tbody></table></div></div><br
class="table-break"></div></div><p>
Once you have <span class="application">Gnash</span> configured, you are
ready to build the code. <span class="application">Gnash</span> is built using
<span class="emphasis"><em>GNU make</em></span>.
- </p><div class="sect1" lang="en"><div class="titlepage"><div><div><h2
class="title" style="clear: both"><a name="compile"></a>Compiling the
Code</h2></div></div></div><p>
+ </p><div class="sect1" title="Compiling the Code"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="compile"></a>Compiling the Code</h2></div></div></div><p>
The most basic way to compile code is simply:
</p><pre class="programlisting">
make
@@ -870,7 +870,7 @@
</p><pre class="programlisting">./configure --help</pre><p>
In the following example, debugging is enabled and optimization is
disabled:
- </p><pre class="programlisting">make CFLAGS=-g CXXFLAGS=-g</pre></div><div
class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title"
style="clear: both"><a name="processdoc"></a>Creating the
Documentation</h2></div></div></div><p>
+ </p><pre class="programlisting">make CFLAGS=-g CXXFLAGS=-g</pre></div><div
class="sect1" title="Creating the Documentation"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="processdoc"></a>Creating the Documentation</h2></div></div></div><p>
By default, documentation is not built when you
<a class="link" href="#install" title="Installation">install</a> <span
class="application">Gnash</span>. This is because
there are a number of <a class="link" href="#docdepend"
title="Documentation Dependencies">dependencies
@@ -902,12 +902,12 @@
</p><pre class="programlisting">
make apidoc
</pre><p>
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="runtests"></a>Running the Tests</h2></div></div></div><p>
+ </p></div><div class="sect1" title="Running the Tests"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="runtests"></a>Running the Tests</h2></div></div></div><p>
Before beginning the potentially lengthy install, it is wise to
test the installation. If a test fails, please report it by
following the <a class="link" href="#bugreport"
title="Chapter?5.?Reporting Bugs">instructions for
reporting a bug</a>.
- </p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3
class="title"><a name="dejagnu"></a>Using DejaGnu</h3></div></div></div><p>
+ </p><div class="sect2" title="Using DejaGnu"><div
class="titlepage"><div><div><h3 class="title"><a name="dejagnu"></a>Using
DejaGnu</h3></div></div></div><p>
The easiest way to run <span class="application">Gnash</span>'s test
suite is to install
<span class="emphasis"><em><a class="ulink"
href="http://www.gnu.org/software/dejagnu"
target="_top">DejaGnu</a></em></span>.
@@ -915,7 +915,7 @@
</p><pre class="programlisting">
make check
</pre><p>
- </p><div class="sect4" lang="en"><div class="titlepage"><div><div><h5
class="title"><a name="testing_verbosity"></a>Increasing
Verbosity</h5></div></div></div><p>
+ </p><div class="sect4" title="Increasing Verbosity"><div
class="titlepage"><div><div><h5 class="title"><a
name="testing_verbosity"></a>Increasing Verbosity</h5></div></div></div><p>
If you encounter a problem with a test, increasing the
verbosity may make the issue easier to spot.
Additional details are visible when
@@ -926,7 +926,7 @@
</p><pre class="programlisting">
make check RUNTESTFLAGS="-v -a"
</pre><p>
- </p></div><div class="sect4" lang="en"><div
class="titlepage"><div><div><h5 class="title"><a
name="running_some_tests"></a>Running Some Tests</h5></div></div></div><p>
+ </p></div><div class="sect4" title="Running Some Tests"><div
class="titlepage"><div><div><h5 class="title"><a
name="running_some_tests"></a>Running Some Tests</h5></div></div></div><p>
It is possible to run just a single test, or
a subdirectory of tests, by specifying the directory or
compiled test file.
@@ -950,7 +950,7 @@
</p><pre class="programlisting">
make -C testsuite/movies.all check
</pre><p>
- </p></div></div><div class="sect2" lang="en"><div
class="titlepage"><div><div><h3 class="title"><a name="manually"></a>Running
The Tests Manually</h3></div></div></div><p>
+ </p></div></div><div class="sect2" title="Running The Tests
Manually"><div class="titlepage"><div><div><h3 class="title"><a
name="manually"></a>Running The Tests Manually</h3></div></div></div><p>
You may also run test cases by hand, which can be useful if you
want to see all the debugging output from the test case. Often
the messages which come from deep within <span
class="application">Gnash</span> are most useful for
@@ -963,20 +963,20 @@
</p><pre class="programlisting">
make XML-v{5,6,7,8}.swf
</pre><p>
- </p><div class="sect4" lang="en"><div class="titlepage"><div><div><h5
class="title"><a name="manual_compiled_tests"></a>Movie
tests</h5></div></div></div><p>
+ </p><div class="sect4" title="Movie tests"><div
class="titlepage"><div><div><h5 class="title"><a
name="manual_compiled_tests"></a>Movie tests</h5></div></div></div><p>
This creates a SWF movie version of the test case, which
can be run with a standalone SWF player. For instance,
the target for SWF version 6 could be run with <span
class="application">Gnash</span>:
</p><pre class="programlisting">
gnash -v XML-v6.swf
</pre><p>
- </p></div><div class="sect4" lang="en"><div
class="titlepage"><div><div><h5 class="title"><a
name="manual_actionscript_tests"></a>ActionScript Unit
Tests</h5></div></div></div><p>
+ </p></div><div class="sect4" title="ActionScript Unit Tests"><div
class="titlepage"><div><div><h5 class="title"><a
name="manual_actionscript_tests"></a>ActionScript Unit
Tests</h5></div></div></div><p>
Unit tests for ActionScript classes in <span
class="command"><strong>testsuite/actionscript.all</strong></span>
are run without a graphical display:
</p><pre class="programlisting">
gprocessor -v XML-v6.swf
</pre><p>
- </p></div></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="install"></a>Installation</h2></div></div></div><p>
+ </p></div></div><div class="sect1" title="Installation"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="install"></a>Installation</h2></div></div></div><p>
Now that <span class="application">Gnash</span> has been compiled and
tested, use the following command to install it:
</p><pre class="programlisting">
make install
@@ -1005,7 +1005,7 @@
<a class="link" href="#custompath" title="Specifying Custom
Paths">configuration option</a>
<span class="emphasis"><em>--exec-prefix</em></span> may be used to
specify where
platform-dependent executables and libraries are installed.
- </p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3
class="title"><a name="libinstall"></a>Libraries</h3></div></div></div><p>
+ </p><div class="sect2" title="Libraries"><div
class="titlepage"><div><div><h3 class="title"><a
name="libinstall"></a>Libraries</h3></div></div></div><p>
Installed libraries are located in
<code class="filename">/usr/local/lib</code> by default.
If the <span class="emphasis"><em>--prefix</em></span> option was used
during the
@@ -1026,7 +1026,7 @@
<code class="filename">/etc/ld.so.conf</code>. After adding the path,
run <span class="emphasis"><em>ldconfig</em></span> as root to update
the runtime
cache.
- </p></div><div class="sect2" lang="en"><div
class="titlepage"><div><div><h3 class="title"><a
name="appinstall"></a>Executables</h3></div></div></div><p>
+ </p></div><div class="sect2" title="Executables"><div
class="titlepage"><div><div><h3 class="title"><a
name="appinstall"></a>Executables</h3></div></div></div><p>
The Mozilla plugin is built from headers (the Mozilla SDK) provided with
Gnash and
does not need extra development packages to be installed. By default, the
plugin is installed to <code
class="filename">~/.mozilla/plugins/</code>. To enable
@@ -1042,7 +1042,7 @@
subdirectory of the directory specified by during configuration.
If no path was specified, the default is
<code class="filename">/usr/local/bin</code>.
- </p></div><div class="sect2" lang="en"><div
class="titlepage"><div><div><h3 class="title"><a
name="docinstall"></a>Documentation</h3></div></div></div><p>
+ </p></div><div class="sect2" title="Documentation"><div
class="titlepage"><div><div><h3 class="title"><a
name="docinstall"></a>Documentation</h3></div></div></div><p>
Documentation is not built by default; please refer to the
<a class="link" href="#processdoc" title="Creating the
Documentation">section on documentation</a> for
more information on building documentation.
@@ -1059,7 +1059,7 @@
<code class="filename">doc/C/gnash.omf</code> is used to specify under
which menu item <span class="application">Gnash</span> appears in the
<span class="emphasis"><em>GNOME help</em></span>
system.
- </p></div></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="cross"></a>Cross Configuring</h2></div></div></div><p>
+ </p></div></div><div class="sect1" title="Cross Configuring"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="cross"></a>Cross Configuring</h2></div></div></div><p>
To cross configure and compile <span class="application">Gnash</span>,
begin by building a target system
on your workstation. This includes cross compilers for the target
architecture, and some system headers.
@@ -1127,7 +1127,7 @@
./configure -target=arm-unknown-linux-gnu --prefix=/usr/arm \
--host=arm-unknown-linux-gnu --build=i686-pc-linux-gnu --disable-plugin
</pre><p>
- </p></div></div></div><div class="chapter" lang="en"><div
class="titlepage"><div><div><h2 class="title"><a
name="internals"></a>Chapter?3.?Software Internals</h2></div></div></div><div
class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a
href="#tour">A Tour of Gnash</a></span></dt><dd><dl><dt><span class="sect2"><a
href="#The%20Libraries">The Libraries</a></span></dt><dt><span class="sect2"><a
href="#apps">The Applications</a></span></dt><dt><span class="sect2"><a
href="#plugin">The Plugin</a></span></dt><dt><span class="sect2"><a
href="#logging">The Message Logging System</a></span></dt></dl></dd><dt><span
class="sect1"><a href="#soundhandlers">Sound handling in
Gnash</a></span></dt><dd><dl><dt><span class="sect2"><a
href="#soundtypes">Sound types</a></span></dt><dt><span class="sect2"><a
href="#soundparsing">Sound parsing</a></span></dt><dt><span class="sect2"><a
href="#soundplayback">Sound playback</a></span></dt><dt><span class="sect2"><a
href="#sdlsound">The SDL sound backend</a></span></dt><dt><span
class="sect2"><a href="#gstreamer">The Gstreamer
backend</a></span></dt><dt><span class="sect2"><a href="#audio-future">Future
audio backends</a></span></dt><dt><span class="sect2"><a
href="#gstreamer-details">Detailed description of the Gstreamer
backend</a></span></dt></dl></dd><dt><span class="sect1"><a
href="#testing">Testing </a></span></dt><dd><dl><dt><span class="sect2"><a
href="#testtools">Testing Tools</a></span></dt><dt><span class="sect2"><a
href="#testcases">Test Cases</a></span></dt><dt><span class="sect2"><a
href="#writeastests">Writing ActionScript Tests</a></span></dt><dt><span
class="sect2"><a href="#writemingtests">Writing Ming-based self-contained SWF
tests</a></span></dt><dt><span class="sect2"><a
href="#writing_dejagnu_so_tests">Writing self-contained SWF tests with other
compilers</a></span></dt><dt><span class="sect2"><a
href="#writing_test_runners">Writing Test
Runners</a></span></dt></dl></dd></dl></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="tour"></a>A Tour of Gnash</h2></div></div></div><p>
+ </p></div></div></div><div class="chapter" title="Chapter?3.?Software
Internals"><div class="titlepage"><div><div><h2 class="title"><a
name="internals"></a>Chapter?3.?Software Internals</h2></div></div></div><div
class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a
href="#tour">A Tour of Gnash</a></span></dt><dd><dl><dt><span class="sect2"><a
href="#The%20Libraries">The Libraries</a></span></dt><dt><span class="sect2"><a
href="#apps">The Applications</a></span></dt><dt><span class="sect2"><a
href="#plugin">The Plugin</a></span></dt><dt><span class="sect2"><a
href="#logging">The Message Logging System</a></span></dt></dl></dd><dt><span
class="sect1"><a href="#soundhandlers">Sound handling in
Gnash</a></span></dt><dd><dl><dt><span class="sect2"><a
href="#soundtypes">Sound types</a></span></dt><dt><span class="sect2"><a
href="#soundparsing">Sound parsing</a></span></dt><dt><span class="sect2"><a
href="#soundplayback">Sound playback</a></span></dt><dt><span class="sect2"><a
href="#sdlsound">The SDL sound backend</a></span></dt><dt><span
class="sect2"><a href="#gstreamer">The Gstreamer
backend</a></span></dt><dt><span class="sect2"><a href="#audio-future">Future
audio backends</a></span></dt><dt><span class="sect2"><a
href="#gstreamer-details">Detailed description of the Gstreamer
backend</a></span></dt></dl></dd><dt><span class="sect1"><a
href="#testing">Testing </a></span></dt><dd><dl><dt><span class="sect2"><a
href="#testtools">Testing Tools</a></span></dt><dt><span class="sect2"><a
href="#testcases">Test Cases</a></span></dt><dt><span class="sect2"><a
href="#writeastests">Writing ActionScript Tests</a></span></dt><dt><span
class="sect2"><a href="#writemingtests">Writing Ming-based self-contained SWF
tests</a></span></dt><dt><span class="sect2"><a
href="#writing_dejagnu_so_tests">Writing self-contained SWF tests with other
compilers</a></span></dt><dt><span class="sect2"><a
href="#writing_test_runners">Writing Test
Runners</a></span></dt></dl></dd></dl></div><div class="sect1" title="A Tour of
Gnash"><div class="titlepage"><div><div><h2 class="title" style="clear:
both"><a name="tour"></a>A Tour of Gnash</h2></div></div></div><p>
The top level of Gnash has several libraries, <span
class="emphasis"><em>libgnashbase</em></span>,
<span class="emphasis"><em>libgnashserver</em></span>,
<span class="emphasis"><em>libgnashmedia</em></span>,
@@ -1136,7 +1136,7 @@
included for debug parsing and processing of SWF movie files,
and other useful utilities for examining local Shared Objects and
sniffing LocalConnections.
- </p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3
class="title"><a name="The%20Libraries"></a>The
Libraries</h3></div></div></div><div class="sect3" lang="en"><div
class="titlepage"><div><div><h4 class="title"><a
name="libbase"></a>libgnashbase</h4></div></div></div><p>
+ </p><div class="sect2" title="The Libraries"><div
class="titlepage"><div><div><h3 class="title"><a name="The%20Libraries"></a>The
Libraries</h3></div></div></div><div class="sect3" title="libgnashbase"><div
class="titlepage"><div><div><h4 class="title"><a
name="libbase"></a>libgnashbase</h4></div></div></div><p>
Libgnashbase contains support classes used by the rest of the
code.This library has no dependencies on any of the other
<span class="application">Gnash</span> libraries.
@@ -1144,60 +1144,60 @@
<span class="application">Gnash</span> makes heavy use of smart
pointers, so memory allocations
are freed up automatically by the interpreter. Both STL and
Boost smart pointers are used.
- </p></div><div class="sect3" lang="en"><div
class="titlepage"><div><div><h4 class="title"><a
name="libgnashserver"></a>libgnashserver</h4></div></div></div><p>
+ </p></div><div class="sect3" title="libgnashserver"><div
class="titlepage"><div><div><h4 class="title"><a
name="libgnashserver"></a>libgnashserver</h4></div></div></div><p>
Libgnashserver is the guts of the interpreter itself. This is where
the main code for the interpreter lives. Includes in
libserver are the two support libraries for the parser and
the core of the virtual machine.
- </p></div><div class="sect3" lang="en"><div
class="titlepage"><div><div><h4 class="title"><a
name="libgnashmedia"></a>libgnashmedia</h4></div></div></div><p>
+ </p></div><div class="sect3" title="libgnashmedia"><div
class="titlepage"><div><div><h4 class="title"><a
name="libgnashmedia"></a>libgnashmedia</h4></div></div></div><p>
Libgnashmedia handles Gnash's audio and video capabilities,
dealing with streamed video and sound as well as decoding
embedded media frames. Besides the standard SWF formats
FLV, MPEG4, Nellymoser, ADPCM, MP3 and RAW, <span
class="application">Gnash</span> can
decode other formats supports by Gstreamer or FFmpeg,
including the free OGG container and free codecs.
- </p></div><div class="sect3" lang="en"><div
class="titlepage"><div><div><h4 class="title"><a
name="libgnashamf"></a>libgnashamf</h4></div></div></div><p>
+ </p></div><div class="sect3" title="libgnashamf"><div
class="titlepage"><div><div><h4 class="title"><a
name="libgnashamf"></a>libgnashamf</h4></div></div></div><p>
AMF is the data format used internally by SWF files. This is
Gnash's support library to handle AMF data. This is used by
the ActionScript classes SharedObject and
LocalConnection. This is also used by the NetStream class
when using thre RTMP streaming network protocol.
- </p></div><div class="sect3" lang="en"><div
class="titlepage"><div><div><h4 class="title"><a
name="libgnashbackend"></a>libgnashbackend</h4></div></div></div><p>
+ </p></div><div class="sect3" title="libgnashbackend"><div
class="titlepage"><div><div><h4 class="title"><a
name="libgnashbackend"></a>libgnashbackend</h4></div></div></div><p>
Libgnashbackend is a library containing the rendering
code that glues this display to the Gnash. Supported
rendering backends are OpenGL, Cairo, and AGG.
- </p></div><div class="sect3" lang="en"><div
class="titlepage"><div><div><h4 class="title"><a
name="libgnashpluin"></a>libgnashplugin</h4></div></div></div><p>
+ </p></div><div class="sect3" title="libgnashplugin"><div
class="titlepage"><div><div><h4 class="title"><a
name="libgnashpluin"></a>libgnashplugin</h4></div></div></div><p>
Libgnashplugin is the Mozilla/Firefox plugin.
- </p></div><div class="sect3" lang="en"><div
class="titlepage"><div><div><h4 class="title"><a
name="libklashpart"></a>libklashpart</h4></div></div></div><p>
+ </p></div><div class="sect3" title="libklashpart"><div
class="titlepage"><div><div><h4 class="title"><a
name="libklashpart"></a>libklashpart</h4></div></div></div><p>
Libklashpart is the Konqueror plugin.
- </p></div></div><div class="sect2" lang="en"><div
class="titlepage"><div><div><h3 class="title"><a name="apps"></a>The
Applications</h3></div></div></div><p>
+ </p></div></div><div class="sect2" title="The Applications"><div
class="titlepage"><div><div><h3 class="title"><a name="apps"></a>The
Applications</h3></div></div></div><p>
There are currently a few standalone programs in Gnash,
which serve either to assist with Gnash development or to play SWF
movies.
- </p><div class="sect3" lang="en"><div class="titlepage"><div><div><h4
class="title"><a name="Gnash"></a>The Standalone
Player</h4></div></div></div><p>
+ </p><div class="sect3" title="The Standalone Player"><div
class="titlepage"><div><div><h4 class="title"><a name="Gnash"></a>The
Standalone Player</h4></div></div></div><p>
This is the standalone OpenGL backend used to play
movies. There are several command line options and keyboard
control keys used by Gnash.
- </p></div><div class="sect3" lang="en"><div
class="titlepage"><div><div><h4 class="title"><a
name="processor"></a>Gprocessor</h4></div></div></div><p>
+ </p></div><div class="sect3" title="Gprocessor"><div
class="titlepage"><div><div><h4 class="title"><a
name="processor"></a>Gprocessor</h4></div></div></div><p>
Gprocessor is used to print out the actions (using the -va
option) or the parsing (using the -vp option) of a SWF
movie. It is also used to produce the <span
class="emphasis"><em>.gsc</em></span>
files that Gnash uses to cache data, thereby speeding up the
loading of files.
- </p></div><div class="sect3" lang="en"><div
class="titlepage"><div><div><h4 class="title"><a
name="soldumper"></a>SOLdumper</h4></div></div></div><p>
+ </p></div><div class="sect3" title="SOLdumper"><div
class="titlepage"><div><div><h4 class="title"><a
name="soldumper"></a>SOLdumper</h4></div></div></div><p>
SOLDumper is a utility program used to find and dump the
content of <span class="emphasis"><em>Local Shared
Objects</em></span>, also
called "Flash Cookies" by some.
- </p></div><div class="sect3" lang="en"><div
class="titlepage"><div><div><h4 class="title"><a
name="dumpshm"></a>Dumpshm</h4></div></div></div><p>
+ </p></div><div class="sect3" title="Dumpshm"><div
class="titlepage"><div><div><h4 class="title"><a
name="dumpshm"></a>Dumpshm</h4></div></div></div><p>
Dumpshm is a program used to find and dump the contents of
the <span class="emphasis"><em>LocalConnection</em></span> shared
memory segment.
- </p></div></div><div class="sect2" lang="en"><div
class="titlepage"><div><div><h3 class="title"><a name="plugin"></a>The
Plugin</h3></div></div></div><p>
+ </p></div></div><div class="sect2" title="The Plugin"><div
class="titlepage"><div><div><h3 class="title"><a name="plugin"></a>The
Plugin</h3></div></div></div><p>
The plugin is designed to work within Mozilla or Firefox,
although there is Konqueror support as well. The plugin uses
the Mozilla plugin API (NPAPI) to be cross platform, and is
portable, as well as being well integrated into Mozilla based
browsers.
- </p><div class="sect3" lang="en"><div class="titlepage"><div><div><h4
class="title"><a name="pluginstatus"></a>Current
Implementation</h4></div></div></div><p>
+ </p><div class="sect3" title="Current Implementation"><div
class="titlepage"><div><div><h4 class="title"><a
name="pluginstatus"></a>Current Implementation</h4></div></div></div><p>
The plugin works in a
fashion similar to MozPlugger: the standalone player
is used instead of using a thread. This gets around the
@@ -1207,7 +1207,7 @@
</p><p>
As of Jan, 2007, streaming video, ala "YouTube"
works, along with other video sharing sites.
- </p></div><div class="sect3" lang="en"><div
class="titlepage"><div><div><h4 class="title"><a name="gui"></a>GUI
Support</h4></div></div></div><p>
+ </p></div><div class="sect3" title="GUI Support"><div
class="titlepage"><div><div><h4 class="title"><a name="gui"></a>GUI
Support</h4></div></div></div><p>
Any plugin that wants to display in a browser window needs
to be tied into the windowing system of the platform being
used. On GNU/Linux systems, Firefox is a GTK2+ application.
@@ -1242,7 +1242,7 @@
fashion for now. There is a right mouse button menu that
allows the user to control the movie being player the same
way the existing keyboard commands do.
- </p></div><div class="sect3" lang="en"><div
class="titlepage"><div><div><h4 class="title"><a
name="mozplugger"></a>Mozplugger</h4></div></div></div><p>
+ </p></div><div class="sect3" title="Mozplugger"><div
class="titlepage"><div><div><h4 class="title"><a
name="mozplugger"></a>Mozplugger</h4></div></div></div><p>
<a class="ulink" href="http://mozplugger.mozdev.org/"
target="_top">Mozplugger</a> is a
<span class="emphasis"><em>Mozilla/Firefox</em></span> plugin that
uses external
programs to play video, audio, and other multimedia content
@@ -1284,7 +1284,7 @@
<span class="emphasis"><em>about:plugins</em></span> into the URL
entry of the browser
window. The output will also contain information about the
mozplugger. You should see an entry for Gnash now.
- </p></div><div class="sect3" lang="en"><div
class="titlepage"><div><div><h4 class="title"><a
name="Klash"></a>Klash</h4></div></div></div><p>
+ </p></div><div class="sect3" title="Klash"><div
class="titlepage"><div><div><h4 class="title"><a
name="Klash"></a>Klash</h4></div></div></div><p>
Klash is MozPlugger type support for KDE's Konqueror web
browser. Klash makes Gnash a <span
class="emphasis"><em>kpart</em></span>, so it's
integrated into KDE better than when using MozPlugger. Klash
@@ -1295,7 +1295,7 @@
use the <span class="emphasis"><em>--enable-klash</em></span> option
when
configuring. Other than installing, there is nothing else
that needs to be done to install Klash.
- </p></div></div><div class="sect2" lang="en"><div
class="titlepage"><div><div><h3 class="title"><a name="logging"></a>The Message
Logging System</h3></div></div></div><p>
+ </p></div></div><div class="sect2" title="The Message Logging
System"><div class="titlepage"><div><div><h3 class="title"><a
name="logging"></a>The Message Logging System</h3></div></div></div><p>
<span class="application">Gnash</span>'s common message logging system
uses a <span class="emphasis"><em>printf()</em></span>
style format. Despite the C-like appearance, however, <span
class="application">Gnash</span>'s LogFile class
by default does not use <span class="emphasis"><em>printf()</em></span>
for formatting the
@@ -1321,7 +1321,7 @@
home directory, since that's considered the current directory. A file name
can be specified using either <span
class="emphasis"><em>gnashrc</em></span> or a
call to the LogFile instance itself.
- </p><div class="sect3" lang="en"><div class="titlepage"><div><div><h4
class="title"><a name="api"></a>Logging System API</h4></div></div></div><p>
+ </p><div class="sect3" title="Logging System API"><div
class="titlepage"><div><div><h4 class="title"><a name="api"></a>Logging System
API</h4></div></div></div><p>
<span class="application">Gnash</span> provides 9 specialized logging
calls, each using the <span class="emphasis"><em>printf()</em></span>-style
call similar to this:
</p><pre class="programlisting">log_error(const char* fmt,
...)</pre><p>
@@ -1378,7 +1378,7 @@
This is printed at a
verbosity level of 1 or more
only if AS coding error logging is enabled.
- </p></dd></dl></div></div><div class="sect3" lang="en"><div
class="titlepage"><div><div><h4 class="title"><a name="logfileinstance"></a>The
LogFile Instance</h4></div></div></div><p>
+ </p></dd></dl></div></div><div class="sect3" title="The LogFile
Instance"><div class="titlepage"><div><div><h4 class="title"><a
name="logfileinstance"></a>The LogFile Instance</h4></div></div></div><p>
This is the main API for initializing and manipulating the logging
output.
By default, the log will be written to <span
class="emphasis"><em>gnash-dbg.log</em></span>
file whenever a verbose option is
@@ -1410,7 +1410,7 @@
If <span class="emphasis"><em>flag</em></span> is <span
class="emphasis"><em>true</em></span>, then create the
disk file. If <span class="emphasis"><em>flag</em></span> is <span
class="emphasis"><em>false</em></span>,
then don't create the disk file.
- </p></dd></dl></div></div></div></div><div class="sect1"
lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear:
both"><a name="soundhandlers"></a>Sound handling in
Gnash</h2></div></div></div><p>
+ </p></dd></dl></div></div></div></div><div class="sect1" title="Sound
handling in Gnash"><div class="titlepage"><div><div><h2 class="title"
style="clear: both"><a name="soundhandlers"></a>Sound handling in
Gnash</h2></div></div></div><p>
When a SWF-file contains audio Gnash uses its sound handlers to play it.
At the moment there are two sound handlers, but it is likely that more
will be made.
@@ -1419,28 +1419,28 @@
<span class="emphasis"><em>pluginsound</em></span> and <span
class="emphasis"><em>sound</em></span>.
This was done in order to allow the plugin to be independently
configured, for instance to block sound from advertisements.
- </p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3
class="title"><a name="soundtypes"></a>Sound types</h3></div></div></div><p>
+ </p><div class="sect2" title="Sound types"><div
class="titlepage"><div><div><h3 class="title"><a name="soundtypes"></a>Sound
types</h3></div></div></div><p>
Sounds can be divided into two groups: event-sounds and soundstreams.
Event-sounds are contained in a single SWF frame, but the playtime can
span multiple frames. Soundstreams can be (and normally are) divided
between the SWF frames the soundstreams spans. This means that if a
gotoframe-action jumps to a frame which contains data for a soundstream,
playback of the stream can be picked up from there.
- </p></div><div class="sect2" lang="en"><div
class="titlepage"><div><div><h3 class="title"><a name="soundparsing"></a>Sound
parsing</h3></div></div></div><p>
+ </p></div><div class="sect2" title="Sound parsing"><div
class="titlepage"><div><div><h3 class="title"><a name="soundparsing"></a>Sound
parsing</h3></div></div></div><p>
When Gnash parses a SWF-file, it creates a sound handler if possible
and hands over the sounds to it. Since the event-sounds are contained
in one frame, the entire event-sound is retrieved at once, while a
soundstream maybe not be completely retrieved before the entire
SWF-file has been parsed. But since the entire soundstream doesn't need
to be present when playback starts, it is not necessary to wait.
- </p></div><div class="sect2" lang="en"><div
class="titlepage"><div><div><h3 class="title"><a name="soundplayback"></a>Sound
playback</h3></div></div></div><p>
+ </p></div><div class="sect2" title="Sound playback"><div
class="titlepage"><div><div><h3 class="title"><a name="soundplayback"></a>Sound
playback</h3></div></div></div><p>
When a sound is about to be played Gnash calls the sound handler, which
then starts to play the sound and return. All the playing is done by
threads (in both SDL and Gstreamer), so once
started the audio and graphics are not sync'ed with each other, which
means that we have to trust both the graphic backend and the audio
backend to play at correct speed.
- </p></div><div class="sect2" lang="en"><div
class="titlepage"><div><div><h3 class="title"><a name="sdlsound"></a>The SDL
sound backend</h3></div></div></div><p>
+ </p></div><div class="sect2" title="The SDL sound backend"><div
class="titlepage"><div><div><h3 class="title"><a name="sdlsound"></a>The SDL
sound backend</h3></div></div></div><p>
The current SDL sound backend has replaced the original sound
handler, based on SDL_mixer, which by design had some limitations,
making it difficult to implement needed features such as support
@@ -1459,7 +1459,7 @@
The advantages of the SDL sound handler is speed, and ease of use,
while its only real disadvantage is that it has to be compiled with
MP3 support, which some Linux distributions will probably not like...
- </p></div><div class="sect2" lang="en"><div
class="titlepage"><div><div><h3 class="title"><a name="gstreamer"></a>The
Gstreamer backend</h3></div></div></div><p>
+ </p></div><div class="sect2" title="The Gstreamer backend"><div
class="titlepage"><div><div><h3 class="title"><a name="gstreamer"></a>The
Gstreamer backend</h3></div></div></div><p>
The Gstreamer backend, though not complete, supports both soundstreams
and event-sounds. When receiving sound data it stores it compressed,
unless if it's ADPCM event-sounds, which it decodes by the parser.
@@ -1472,12 +1472,12 @@
should be relatively easy to add VORBIS support. The drawbacks are that
it has longer "reply delay" when starting the playback of a sound, and
it suffers under some bugs in Gstreamer that are yet to be fixed.
- </p></div><div class="sect2" lang="en"><div
class="titlepage"><div><div><h3 class="title"><a name="audio-future"></a>Future
audio backends</h3></div></div></div><p>
+ </p></div><div class="sect2" title="Future audio backends"><div
class="titlepage"><div><div><h3 class="title"><a name="audio-future"></a>Future
audio backends</h3></div></div></div><p>
It would probably be desirable to make more backends in the future,
either because other and better backend systems are brought to our
attention, or perhaps because an internal sound handling is better
suited for embedded platform with limited software installed.
- </p></div><div class="sect2" lang="en"><div
class="titlepage"><div><div><h3 class="title"><a
name="gstreamer-details"></a>Detailed description of the Gstreamer
backend</h3></div></div></div><p>
+ </p></div><div class="sect2" title="Detailed description of the
Gstreamer backend"><div class="titlepage"><div><div><h3 class="title"><a
name="gstreamer-details"></a>Detailed description of the Gstreamer
backend</h3></div></div></div><p>
Gstreamer uses pipelines, bins and elements. Pipelines are the
main bin, where all other bins or elements are places. Visually the
audio pipeline in Gnash looks like this:
@@ -1525,10 +1525,10 @@
Gstreamer also contains a bug concerning linking multiple elements to
the adder in rapid succession, which causes to adder to "die" and stop
the playback.
- </p></div></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="testing"></a>Testing </h2></div></div></div><p>
+ </p></div></div><div class="sect1" title="Testing"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="testing"></a>Testing </h2></div></div></div><p>
<a class="link" href="#runtests" title="Running the Tests">Instructions
on running tests</a>
can be found in the section on building Gnash.
- </p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3
class="title"><a name="testtools"></a>Testing Tools</h3></div></div></div><p>
+ </p><div class="sect2" title="Testing Tools"><div
class="titlepage"><div><div><h3 class="title"><a name="testtools"></a>Testing
Tools</h3></div></div></div><p>
Currently Gnash uses three other tools to help with
testing. Two of these are free compilers for the SWF
format. This lets us write simple test cases for Gnash to test
@@ -1545,7 +1545,7 @@
manner. <span class="emphasis"><em>DejaGnu</em></span> is used by many
other <a class="ulink" href="http://www.gnu.org" target="_top">GNU</a> projects
like
<a class="ulink" href="http://gcc.gnu.org" target="_top">GCC</a> and
<a class="ulink" href="http://www.samba.org" target="_top">Samba</a>.
- </p></div><div class="sect2" lang="en"><div
class="titlepage"><div><div><h3 class="title"><a name="testcases"></a>Test
Cases</h3></div></div></div><p>
+ </p></div><div class="sect2" title="Test Cases"><div
class="titlepage"><div><div><h3 class="title"><a name="testcases"></a>Test
Cases</h3></div></div></div><p>
ActionScript test cases are located under testsuite/actionscript.all/;
these are organized in one file for the ActionScript class.
Other Ming-generated tests are under testsuite/ming-misc.all/;
@@ -1554,7 +1554,7 @@
sample movies are found in testsuite/samples/.
Other directories in testsuite/ are (or shall be) used for other
kind of tests.
- </p></div><div class="sect2" lang="en"><div
class="titlepage"><div><div><h3 class="title"><a
name="writeastests"></a>Writing ActionScript Tests</h3></div></div></div><p>
+ </p></div><div class="sect2" title="Writing ActionScript Tests"><div
class="titlepage"><div><div><h3 class="title"><a
name="writeastests"></a>Writing ActionScript Tests</h3></div></div></div><p>
Writing ActionScript tests is very simple. The
<span class="emphasis"><em>makeswf</em></span> compiler makes use of
the C preprocessor,
thus allowing the inclusion of definitions for macros and external
@@ -1621,7 +1621,7 @@
#endif
</pre><p>
- </p></div><div class="sect2" lang="en"><div
class="titlepage"><div><div><h3 class="title"><a
name="writemingtests"></a>Writing Ming-based self-contained SWF
tests</h3></div></div></div><p>
+ </p></div><div class="sect2" title="Writing Ming-based self-contained
SWF tests"><div class="titlepage"><div><div><h3 class="title"><a
name="writemingtests"></a>Writing Ming-based self-contained SWF
tests</h3></div></div></div><p>
Ming-based test cases are located in testsuite/misc-ming.all
and contain a test generator and a test runner.
The test generator (usually a C program) is used to produce the SWF
@@ -1637,7 +1637,7 @@
provided by the Gnash testing framework to easily run tests.
</p><p>
For generic Ming API documentation, see <a class="ulink"
href="http://www.libming.org/" target="_top">http://www.libming.org</a>.
- </p><div class="sect3" lang="en"><div class="titlepage"><div><div><h4
class="title"><a name="ming_testgenerator_facilities"></a>Using Ming-based test
generators facilities</h4></div></div></div><p>
+ </p><div class="sect3" title="Using Ming-based test generators
facilities"><div class="titlepage"><div><div><h4 class="title"><a
name="ming_testgenerator_facilities"></a>Using Ming-based test generators
facilities</h4></div></div></div><p>
Ming-based test generator facilities, which might be moved into
a loadable SWF in the future, can be currently used by your test
generator by including the ming_utils.h file and calling the
@@ -1693,7 +1693,7 @@
</p><p>
See section <a class="link" href="#writing_test_runners" title="Writing
Test Runners">Writing Test Runners</a>
for information about writing SWF test runners.
- </p></div></div><div class="sect2" lang="en"><div
class="titlepage"><div><div><h3 class="title"><a
name="writing_dejagnu_so_tests"></a>Writing self-contained SWF tests with other
compilers</h3></div></div></div><p>
+ </p></div></div><div class="sect2" title="Writing self-contained SWF
tests with other compilers"><div class="titlepage"><div><div><h3
class="title"><a name="writing_dejagnu_so_tests"></a>Writing self-contained SWF
tests with other compilers</h3></div></div></div><p>
If you want/need to use a different compiler for your test cases
(there's
plenty of open source tools for generating SWF out there), you can still
make use of a loadable SWF utility provided as part of the Gnash
testsuite
@@ -1763,7 +1763,7 @@
</p><p>
See section <a class="link" href="#writing_test_runners" title="Writing
Test Runners">Writing Test Runners</a>
for information about writing a test runners for your self-contained
tests.
- </p></div><div class="sect2" lang="en"><div
class="titlepage"><div><div><h3 class="title"><a
name="writing_test_runners"></a>Writing Test Runners</h3></div></div></div><p>
+ </p></div><div class="sect2" title="Writing Test Runners"><div
class="titlepage"><div><div><h3 class="title"><a
name="writing_test_runners"></a>Writing Test Runners</h3></div></div></div><p>
Test runners are executables that run one or more tests,
writing results in Dejagnu form to standard output.
</p><p>
@@ -1825,7 +1825,7 @@
<p>There was some additional information given about
the test.</p>
</td></tr></tbody></table></div><p>
- </p><div class="sect3" lang="en"><div class="titlepage"><div><div><h4
class="title"><a name="generic_test_runner"></a>Using the generic test runner
for self-contained SWF tests</h4></div></div></div><p>
+ </p><div class="sect3" title="Using the generic test runner for
self-contained SWF tests"><div class="titlepage"><div><div><h4 class="title"><a
name="generic_test_runner"></a>Using the generic test runner for self-contained
SWF tests</h4></div></div></div><p>
The simplest test runner is one that simply invokes Gnash
in verbose mode against a self-contained SWF test movie.
Self-contained SWF test movies are the ones that print
@@ -1866,7 +1866,7 @@
chmod +x $@
</pre><p>
When both -f and -r are given, the first exit condition reached will
take effect.
- </p></div><div class="sect3" lang="en"><div
class="titlepage"><div><div><h4 class="title"><a
name="writing_movie_testers"></a>Writing Movie testers</h4></div></div></div><p>
+ </p></div><div class="sect3" title="Writing Movie testers"><div
class="titlepage"><div><div><h4 class="title"><a
name="writing_movie_testers"></a>Writing Movie testers</h4></div></div></div><p>
There are some parts of Gnash that can NOT be tested
by only using ActionScript tests. Examples include: frame
advancements, actual actions execution, gui events and so on.
@@ -1898,7 +1898,7 @@
Note that you do NOT need access to the SWF source code in order
to implement a Movie tester for it. Some knowledge about the
expected behavior suffices.
- </p></div></div></div><div class="chapter" lang="en"><div
class="titlepage"><div><div><h2 class="title"><a
name="newclass"></a>Chapter?4.?Adding New ActionScript
Class</h2></div></div></div><div class="toc"><p><b>Table of
Contents</b></p><dl><dt><span class="sect1"><a
href="#prototype">Prototype</a></span></dt><dt><span class="sect1"><a
href="#declaration">Declaration</a></span></dt><dt><span class="sect1"><a
href="#instantiation">Instantiation</a></span></dt><dt><span class="sect1"><a
href="#methods">Methods</a></span></dt><dt><span class="sect1"><a
href="#properties">Dynamic Properties</a></span></dt><dt><span class="sect1"><a
href="#as_value">The as_value Object Type</a></span></dt><dd><dl><dt><span
class="sect2"><a href="#data_types">Data Types</a></span></dt><dt><span
class="sect2"><a href="#is_methods">Determining the
Type</a></span></dt><dt><span class="sect2"><a href="#to_methods">Fetching the
Value</a></span></dt><dt><span class="sect2"><a href="#set_methods">Setting the
Value and Type</a></span></dt><dt><span class="sect2"><a
href="#further_as_value_reading">Further
Reading</a></span></dt></dl></dd><dt><span class="sect1"><a
href="#asobject">Object ActionScript Class</a></span></dt><dd><dl><dt><span
class="sect2"><a href="#objectmethods">The Methods of the
Class</a></span></dt><dt><span class="sect2"><a href="#objectprops">The
Properties of the Object Class</a></span></dt><dt><span class="sect2"><a
href="#objectconf">Object Class
Conformance</a></span></dt></dl></dd></dl></div><p>
+ </p></div></div></div><div class="chapter" title="Chapter?4.?Adding New
ActionScript Class"><div class="titlepage"><div><div><h2 class="title"><a
name="newclass"></a>Chapter?4.?Adding New ActionScript
Class</h2></div></div></div><div class="toc"><p><b>Table of
Contents</b></p><dl><dt><span class="sect1"><a
href="#prototype">Prototype</a></span></dt><dt><span class="sect1"><a
href="#declaration">Declaration</a></span></dt><dt><span class="sect1"><a
href="#instantiation">Instantiation</a></span></dt><dt><span class="sect1"><a
href="#methods">Methods</a></span></dt><dt><span class="sect1"><a
href="#properties">Dynamic Properties</a></span></dt><dt><span class="sect1"><a
href="#as_value">The <span class="emphasis"><em>as_value</em></span> Object
Type</a></span></dt><dd><dl><dt><span class="sect2"><a href="#data_types">Data
Types</a></span></dt><dt><span class="sect2"><a href="#is_methods">Determining
the Type</a></span></dt><dt><span class="sect2"><a href="#to_methods">Fetching
the Value</a></span></dt><dt><span class="sect2"><a href="#set_methods">Setting
the Value and Type</a></span></dt><dt><span class="sect2"><a
href="#further_as_value_reading">Further
Reading</a></span></dt></dl></dd><dt><span class="sect1"><a
href="#asobject">Object ActionScript Class</a></span></dt><dd><dl><dt><span
class="sect2"><a href="#objectmethods">The Methods of the
Class</a></span></dt><dt><span class="sect2"><a href="#objectprops">The
Properties of the Object Class</a></span></dt><dt><span class="sect2"><a
href="#objectconf">Object Class
Conformance</a></span></dt></dl></dd></dl></div><p>
In this document, the term 'ActionScript class' refers to the
C++ class which is instantiated by Gnash when some ActionScript
code instantiates a corresponding class. The C++ class
@@ -1916,7 +1916,7 @@
implementation. The name is usually the name of the
class as it is called in the ActionScript specifications;
for instance <span class="emphasis"><em>Boolean.cpp</em></span> for the
Boolean class.
- </p><div class="sect1" lang="en"><div class="titlepage"><div><div><h2
class="title" style="clear: both"><a
name="prototype"></a>Prototype</h2></div></div></div><p>
+ </p><div class="sect1" title="Prototype"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="prototype"></a>Prototype</h2></div></div></div><p>
In ActionScript, a prototype is a base object which contains
all the methods that an instantiated object will contain.
In short, it contains every part of the class except for
@@ -1952,10 +1952,10 @@
trace("MATCHED");
}
</pre><p>
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="declaration"></a>Declaration</h2></div></div></div><p>
+ </p></div><div class="sect1" title="Declaration"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="declaration"></a>Declaration</h2></div></div></div><p>
A new class should derive from <span
class="emphasis"><em>as_object</em></span>,
which is the base class of every ActionScript object in Gnash.
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="instantiation"></a>Instantiation</h2></div></div></div><p>
+ </p></div><div class="sect1" title="Instantiation"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="instantiation"></a>Instantiation</h2></div></div></div><p>
When a new object is needed, instance data is added to
the methods and properties inherited from the prototype.
</p><p>
@@ -1966,11 +1966,11 @@
<span class="emphasis"><em>as_object</em></span>. In addition, the
method
registers the constructor to be used for future object creation,
and attaches methods and properties to the prototype.
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="methods"></a>Methods</h2></div></div></div><p>
+ </p></div><div class="sect1" title="Methods"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="methods"></a>Methods</h2></div></div></div><p>
Every method you implement and
<a class="link" href="#prototype" title="Prototype">attach</a> will
receive an
<span class="emphasis"><em>fn_call</em></span> data structure as an
argument when it is called.
- </p><div class="sect3" lang="en"><div class="titlepage"><div><div><h4
class="title"><a name="arguments"></a>Accessing
Arguments</h4></div></div></div><p>
+ </p><div class="sect3" title="Accessing Arguments"><div
class="titlepage"><div><div><h4 class="title"><a name="arguments"></a>Accessing
Arguments</h4></div></div></div><p>
The arguments stored in <span class="emphasis"><em>fn_call</em></span>
should be accessed using <span class="emphasis"><em>arg()</em></span>.
For
instance, the first element can be popped with
@@ -1979,14 +1979,14 @@
The element popped off the stack is an
<a class="link" href="#as_value" title="The as_value Object Type"><span
class="emphasis"><em>as_value</em></span>
object</a>.
- </p></div><div class="sect3" lang="en"><div
class="titlepage"><div><div><h4 class="title"><a name="return"></a>Returning a
Value to ActionScript</h4></div></div></div><p>
+ </p></div><div class="sect3" title="Returning a Value to
ActionScript"><div class="titlepage"><div><div><h4 class="title"><a
name="return"></a>Returning a Value to ActionScript</h4></div></div></div><p>
The return value should be an
<a class="link" href="#as_value" title="The as_value Object Type"><span
class="emphasis"><em>as_value</em></span>
object</a>. For example:
</p><pre class="programlisting">
return as_value('Goodbye, cruel world.');
</pre><p>
- </p></div><div class="sect3" lang="en"><div
class="titlepage"><div><div><h4 class="title"><a
name="additional_fn_call"></a>Additional <span
class="emphasis"><em>fn_call</em></span> Members</h4></div></div></div><p>
+ </p></div><div class="sect3" title="Additional fn_call Members"><div
class="titlepage"><div><div><h4 class="title"><a
name="additional_fn_call"></a>Additional <span
class="emphasis"><em>fn_call</em></span> Members</h4></div></div></div><p>
There are two other useful members of the <span
class="emphasis"><em>fn_call</em></span>
structure, namely <span class="emphasis"><em>this_ptr</em></span> and
<span class="emphasis"><em>nargs</em></span>. The former points to the
@@ -2005,7 +2005,7 @@
is one method of note. <span
class="emphasis"><em>dump_args()</em></span>
can be used in debugging to output the entire argument
stack.
- </p></div></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="properties"></a>Dynamic Properties</h2></div></div></div><p>
+ </p></div></div><div class="sect1" title="Dynamic Properties"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="properties"></a>Dynamic Properties</h2></div></div></div><p>
This section describes accessors to dynamic properties.
Read-only properties are described
in the <a class="link" href="#prototype" title="Prototype">prototype</a>
section.
@@ -2047,10 +2047,10 @@
gettersetter = new builtin_function(&MyClass::myProperty_getset,
NULL);
o.init_property("myProperty", *gettersetter, *gettersetter);
</pre><p>
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="as_value"></a>The <span class="emphasis"><em>as_value</em></span> Object
Type</h2></div></div></div><p>
+ </p></div><div class="sect1" title="The as_value Object Type"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="as_value"></a>The <span class="emphasis"><em>as_value</em></span> Object
Type</h2></div></div></div><p>
The <span class="emphasis"><em>as_value</em></span> class is used
throughout
the interpreter to create generic objects to hold data.
- </p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3
class="title"><a name="data_types"></a>Data Types</h3></div></div></div><p>
+ </p><div class="sect2" title="Data Types"><div
class="titlepage"><div><div><h3 class="title"><a name="data_types"></a>Data
Types</h3></div></div></div><p>
The following data types are supported:
<span class="emphasis"><em>NULLTYPE</em></span>,
<span class="emphasis"><em>BOOLEAN</em></span>, <span
class="emphasis"><em>STRING</em></span>,
@@ -2058,7 +2058,7 @@
<span class="emphasis"><em>AS_FUNCTION</em></span>, and
<span class="emphasis"><em>MOVIECLIP</em></span> (sprite).
The type <span class="emphasis"><em>C_FUNCTION</em></span> is being
deprecated.
- </p></div><div class="sect2" lang="en"><div
class="titlepage"><div><div><h3 class="title"><a
name="is_methods"></a>Determining the Type</h3></div></div></div><p>
+ </p></div><div class="sect2" title="Determining the Type"><div
class="titlepage"><div><div><h3 class="title"><a
name="is_methods"></a>Determining the Type</h3></div></div></div><p>
Several methods allow you to determine if a value stored in
<span class="emphasis"><em>as_value</em></span> is of a specific type.
These
follow the form of <span class="emphasis"><em>is_TYPE</em></span>, for
example
@@ -2067,7 +2067,7 @@
match the <a class="link" href="#data_types" title="Data Types">data
types</a> listed
above, with the exception of the type <span
class="emphasis"><em>MOVIECLIP</em></span>
which has a method <span class="emphasis"><em>is_sprite()</em></span>.
- </p></div><div class="sect2" lang="en"><div
class="titlepage"><div><div><h3 class="title"><a name="to_methods"></a>Fetching
the Value</h3></div></div></div><p>
+ </p></div><div class="sect2" title="Fetching the Value"><div
class="titlepage"><div><div><h3 class="title"><a name="to_methods"></a>Fetching
the Value</h3></div></div></div><p>
Another set of methods will return a representation of
the value as a particular type. They follow the
<span class="emphasis"><em>to_TYPE</em></span> naming convention.
Examples
@@ -2076,7 +2076,7 @@
<a class="link" href="#data_types" title="Data Types">listed</a>
earlier, except for
<span class="emphasis"><em>MOVIECLIP</em></span>, which uses
<span class="emphasis"><em>to_sprite()</em></span>.
- </p></div><div class="sect2" lang="en"><div
class="titlepage"><div><div><h3 class="title"><a name="set_methods"></a>Setting
the Value and Type</h3></div></div></div><p>
+ </p></div><div class="sect2" title="Setting the Value and Type"><div
class="titlepage"><div><div><h3 class="title"><a name="set_methods"></a>Setting
the Value and Type</h3></div></div></div><p>
Finally, there is the <span class="emphasis"><em>set_TYPE</em></span>
series
of methods. They change the type to the type specified in
the method name, and set the value to the one given as an
@@ -2085,16 +2085,16 @@
match those <a class="link" href="#data_types" title="Data Types">named
earlier</a>,
except in the case of <span class="emphasis"><em>MOVIECLASS</em></span>.
Its
method is called <span class="emphasis"><em>set_sprite()</em></span>.
- </p></div><div class="sect2" lang="en"><div
class="titlepage"><div><div><h3 class="title"><a
name="further_as_value_reading"></a>Further Reading</h3></div></div></div><p>
+ </p></div><div class="sect2" title="Further Reading"><div
class="titlepage"><div><div><h3 class="title"><a
name="further_as_value_reading"></a>Further Reading</h3></div></div></div><p>
Please refer to <span class="emphasis"><em>as_value.h</em></span> or the
Doxygen documentation (see 'Processing The Documentation'
in the Gnash manual for instructions on generating
documents with Doxygen) for more information
about which methods are available for the
<span class="emphasis"><em>as_value</em></span> object.
- </p></div></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="asobject"></a>Object ActionScript Class</h2></div></div></div><p>
+ </p></div></div><div class="sect1" title="Object ActionScript Class"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="asobject"></a>Object ActionScript Class</h2></div></div></div><p>
This class implements an Object object.
- </p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3
class="title"><a name="objectmethods"></a>The Methods of the
Class</h3></div></div></div><p>
+ </p><div class="sect2" title="The Methods of the Class"><div
class="titlepage"><div><div><h3 class="title"><a name="objectmethods"></a>The
Methods of the Class</h3></div></div></div><p>
</p><div class="variablelist"><dl><dt><span
class="term">addProperty()</span></dt><dd><p>
</p></dd><dt><span class="term">registerClass()</span></dt><dd><p>
</p></dd><dt><span class="term">toString()</span></dt><dd><p>
@@ -2106,14 +2106,14 @@
</p></dd><dt><span class="term">SharedgetLocal()</span></dt><dd><p>
</p></dd><dt><span class="term">SharedgetSize()</span></dt><dd><p>
</p></dd></dl></div><p>
- </p></div><div class="sect2" lang="en"><div
class="titlepage"><div><div><h3 class="title"><a name="objectprops"></a>The
Properties of the Object Class</h3></div></div></div><p>
+ </p></div><div class="sect2" title="The Properties of the Object
Class"><div class="titlepage"><div><div><h3 class="title"><a
name="objectprops"></a>The Properties of the Object
Class</h3></div></div></div><p>
</p><div class="variablelist"><dl><dt><span
class="term">constructor</span></dt><dd><p>
</p></dd><dt><span class="term">__proto__</span></dt><dd><p>
</p></dd><dt><span class="term">__resolve</span></dt><dd><p>
</p></dd><dt><span class="term">Shareddata</span></dt><dd><p>
</p></dd><dt><span class="term">SharedonStatus</span></dt><dd><p>
</p></dd></dl></div><p>
- </p></div><div class="sect2" lang="en"><div
class="titlepage"><div><div><h3 class="title"><a name="objectconf"></a>Object
Class Conformance</h3></div></div></div><p>
+ </p></div><div class="sect2" title="Object Class Conformance"><div
class="titlepage"><div><div><h3 class="title"><a name="objectconf"></a>Object
Class Conformance</h3></div></div></div><p>
</p><div class="informaltable"><table border="1"
width="75%"><colgroup><col><col></colgroup><thead><tr><th valign="top">
<p>Class Name</p>
</th><th valign="top">
@@ -2209,7 +2209,7 @@
This property has an unknown status.
</p>
</td></tr></tbody></table></div><p>
- </p></div></div></div></div><div class="chapter" lang="en"><div
class="titlepage"><div><div><h2 class="title"><a
name="bugreport"></a>Chapter?5.?Reporting Bugs</h2></div></div></div><div
class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a
href="#bugstep_package">Get a Fresh Binary Package</a></span></dt><dt><span
class="sect1"><a href="#bugstep_search">Determine if the bug was previously
reported</a></span></dt><dt><span class="sect1"><a
href="#bugstep_guidelines">Review the bug writing
guidelines</a></span></dt><dt><span class="sect1"><a
href="#bugstep_file">Filing a bug report</a></span></dt></dl></div><p>
+ </p></div></div></div></div><div class="chapter"
title="Chapter?5.?Reporting Bugs"><div class="titlepage"><div><div><h2
class="title"><a name="bugreport"></a>Chapter?5.?Reporting
Bugs</h2></div></div></div><div class="toc"><p><b>Table of
Contents</b></p><dl><dt><span class="sect1"><a href="#bugstep_package">Get a
Fresh Binary Package</a></span></dt><dt><span class="sect1"><a
href="#bugstep_search">Determine if the bug was previously
reported</a></span></dt><dt><span class="sect1"><a
href="#bugstep_guidelines">Review the bug writing
guidelines</a></span></dt><dt><span class="sect1"><a
href="#bugstep_file">Filing a bug report</a></span></dt></dl></div><p>
The Gnash project relies on the community of Gnash users to test
the player. Feedback is critical to any successful project. Not
only does it let us know that people use Gnash, but it helps us
@@ -2222,7 +2222,7 @@
be asked to provide this information anyway. Adding
critical details, like the Operating System you are on, its
version, and any relevant error messages from Gnash that you get.
- </p><div class="sect1" lang="en"><div class="titlepage"><div><div><h2
class="title" style="clear: both"><a name="bugstep_package"></a>Get a Fresh
Binary Package</h2></div></div></div><p>
+ </p><div class="sect1" title="Get a Fresh Binary Package"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="bugstep_package"></a>Get a Fresh Binary Package</h2></div></div></div><p>
For starters, it's a good idea to obtain a copy of the latest
snapshot. Although Gnash is primarily released as source, the
Gnash build infrastructure allows the automated building of
@@ -2236,7 +2236,7 @@
<a class="ulink" href="http://www.getgnash.org/packages/" target="_top">
http://www.getgnash.org/packages
</a>.
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="bugstep_search"></a>Determine if the bug was previously
reported</h2></div></div></div><p>
+ </p></div><div class="sect1" title="Determine if the bug was previously
reported"><div class="titlepage"><div><div><h2 class="title" style="clear:
both"><a name="bugstep_search"></a>Determine if the bug was previously
reported</h2></div></div></div><p>
Search the <a class="ulink"
href="https://savannah.gnu.org/bugs/?group=gnash" target="_top">Gnash
bug tracker</a> to see if the bug has already been identified.
</p><p>
@@ -2247,35 +2247,35 @@
on Ubuntu GNU/Linux, and you noticed the same problem on OpenBSD,
your stacktrace would be useful. Conversely, adding a "me too"
note to a feature request is not helpful.
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="bugstep_guidelines"></a>Review the bug writing
guidelines</h2></div></div></div><p>
+ </p></div><div class="sect1" title="Review the bug writing
guidelines"><div class="titlepage"><div><div><h2 class="title" style="clear:
both"><a name="bugstep_guidelines"></a>Review the bug writing
guidelines</h2></div></div></div><p>
A good bug report should be precise, explicit, and discrete.
This means that there should be just one bug per ticket, and
that a ticket should contain the following information:
- </p><div class="itemizedlist"><ul type="opencircle"><li
style="list-style-type: circle"><p>
+ </p><div class="itemizedlist"><ul class="itemizedlist"
type="opencircle"><li class="listitem" style="list-style-type: circle"><p>
An overview of the problem;
- </p></li><li style="list-style-type: circle"><p>
+ </p></li><li class="listitem" style="list-style-type: circle"><p>
Instructions on how to replicate the bug;
- </p></li><li style="list-style-type: circle"><p>
+ </p></li><li class="listitem" style="list-style-type: circle"><p>
A description of what happened when you performed the steps
to replicate the bug, and what you expected to happen;
- </p></li><li style="list-style-type: circle"><p>
+ </p></li><li class="listitem" style="list-style-type: circle"><p>
Your system information: operating system name and version, as
well as the versions of major development dependencies;
- </p></li><li style="list-style-type: circle"><p>
+ </p></li><li class="listitem" style="list-style-type: circle"><p>
The release number or checkout timestamp for the version of Gnash
where you observe the problem;
- </p></li><li style="list-style-type: circle"><p>
+ </p></li><li class="listitem" style="list-style-type: circle"><p>
The file <code class="filename">config.log</code>, which should be
attached as a file;
- </p></li><li style="list-style-type: circle"><p>
+ </p></li><li class="listitem" style="list-style-type: circle"><p>
A descriptive title.
</p></li></ul></div><p>
Include any additional information that you feel might be useful
to the developers.
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="bugstep_file"></a>Filing a bug report</h2></div></div></div><p>
+ </p></div><div class="sect1" title="Filing a bug report"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="bugstep_file"></a>Filing a bug report</h2></div></div></div><p>
After following the steps described above, you can file a bug report at
<a class="ulink" href="https://savannah.gnu.org/bugs/?group=gnash"
target="_top">https://savannah.gnu.org/bugs/?group=gnash</a>.
- </p></div></div><div class="chapter" lang="en"><div
class="titlepage"><div><div><h2 class="title"><a
name="extensions"></a>Chapter?6.?Gnash Extensions</h2></div></div></div><div
class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a
href="#newext">Creating A New Extension</a></span></dt><dd><dl><dt><span
class="sect2"><a href="#craftext">Crafting an
Extension</a></span></dt></dl></dd><dt><span class="sect1"><a
href="#debuext">Debugging An Extension</a></span></dt><dt><span
class="sect1"><a href="#inclext">Included
Extensions</a></span></dt></dl></div><p>
+ </p></div></div><div class="chapter" title="Chapter?6.?Gnash
Extensions"><div class="titlepage"><div><div><h2 class="title"><a
name="extensions"></a>Chapter?6.?Gnash Extensions</h2></div></div></div><div
class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a
href="#newext">Creating A New Extension</a></span></dt><dd><dl><dt><span
class="sect2"><a href="#craftext">Crafting an
Extension</a></span></dt></dl></dd><dt><span class="sect1"><a
href="#debuext">Debugging An Extension</a></span></dt><dt><span
class="sect1"><a href="#inclext">Included
Extensions</a></span></dt></dl></div><p>
Gnash supports extending the SWF specification by creating
custom ActionScript classes that are compiled code, as opposed to
the existing method of defining custom classes as
@@ -2315,7 +2315,7 @@
advantage is the class itself is compiled code, and runs much
faster than the equivalent byte codes which all have to be
interpreted..
- </p><div class="sect1" lang="en"><div class="titlepage"><div><div><h2
class="title" style="clear: both"><a name="newext"></a>Creating A New
Extension</h2></div></div></div><p>
+ </p><div class="sect1" title="Creating A New Extension"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="newext"></a>Creating A New Extension</h2></div></div></div><p>
Each new extension should live in it's own directory. The
extensions included in Gnash are all in the
<span class="emphasis"><em>gnash/extensions</em></span> directory.
Creating an extension
@@ -2345,7 +2345,7 @@
abstractions. Higher-level classes that offer a lot of new
functionality are fine, but is different than wrapping a library
so it can be used from within Gnash.
- </p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3
class="title"><a name="craftext"></a>Crafting an
Extension</h3></div></div></div><p>
+ </p><div class="sect2" title="Crafting an Extension"><div
class="titlepage"><div><div><h3 class="title"><a name="craftext"></a>Crafting
an Extension</h3></div></div></div><p>
All extensions have the same requirements, namely setting up a
few defined function callbacks, which the Gnash VM then uses
to do the right thing. The initial two function callbacks are
@@ -2459,7 +2459,7 @@
return as_value(ret);
}
}
- </pre></div></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="debuext"></a>Debugging An Extension</h2></div></div></div><p>
+ </pre></div></div><div class="sect1" title="Debugging An Extension"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="debuext"></a>Debugging An Extension</h2></div></div></div><p>
As extensions are loaded dynamically at runtime, debugging one
can be difficult. You can use GDB, but you have the problem of
not being able to set a breakpoint in Gnash until
@@ -2498,12 +2498,12 @@
</p><pre class="programlisting">
(gdb) set variable stall = false;
continue
- </pre></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="inclext"></a>Included Extensions</h2></div></div></div><p>
+ </pre></div><div class="sect1" title="Included Extensions"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="inclext"></a>Included Extensions</h2></div></div></div><p>
Gnash has some extensions included in the distribution. This is
mostly because they were written by the Gnash team. Extensions
can be external to gnash, Gnash needs no compiled in knowledge
to load an extension file.
- </p><div class="sect3" lang="en"><div class="titlepage"><div><div><h4
class="title"><a name="gtkext"></a>Gtk Extension</h4></div></div></div><p>
+ </p><div class="sect3" title="Gtk Extension"><div
class="titlepage"><div><div><h4 class="title"><a name="gtkext"></a>Gtk
Extension</h4></div></div></div><p>
The GTK ActionScript class follows the same API as Gtk2, even down
to the same arguments to the same function names. This means
you're actually programming GTK,you're just using ActionScript
@@ -2526,7 +2526,7 @@
Display the widget on the screen.
</p></dd><dt><span class="term">main</span></dt><dd><p>
Start the main GTK event loop. This function does not return.
- </p></dd></dl></div></div><div class="sect3" lang="en"><div
class="titlepage"><div><div><h4 class="title"><a name="fileioext"></a>File I/O
Extension</h4></div></div></div><p>
+ </p></dd></dl></div></div><div class="sect3" title="File I/O
Extension"><div class="titlepage"><div><div><h4 class="title"><a
name="fileioext"></a>File I/O Extension</h4></div></div></div><p>
Flash movies are traditionally forbidden from accessing the
filesystem, but this may be necessary for some embedded
applications. Especially in the case of a user console, currently
@@ -2561,7 +2561,7 @@
Report the current position within the opened file.
</p></dd><dt><span class="term">fclose</span></dt><dd><p>
Close the opened file.
- </p></dd></dl></div></div><div class="sect3" lang="en"><div
class="titlepage"><div><div><h4 class="title"><a name="mysqlext"></a>MySQL
Extension</h4></div></div></div><p>
+ </p></dd></dl></div></div><div class="sect3" title="MySQL
Extension"><div class="titlepage"><div><div><h4 class="title"><a
name="mysqlext"></a>MySQL Extension</h4></div></div></div><p>
The MySQL ActionScript class follows the same API as MySQL, even down
to the same arguments to the same function names. This enables a
Flash movie to have direct access to a MySQL
@@ -2583,7 +2583,7 @@
Free the results of a query.
</p></dd><dt><span class="term">store_results</span></dt><dd><p>
Store the results of a query.
- </p></dd></dl></div></div></div></div><div class="chapter"
lang="en"><div class="titlepage"><div><div><h2 class="title"><a
name="rtmp"></a>Chapter?7.?RTMP Protocol</h2></div></div></div><div
class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a
href="#amf">AMF Format</a></span></dt></dl></div><p>
+ </p></dd></dl></div></div></div></div><div class="chapter"
title="Chapter?7.?RTMP Protocol"><div class="titlepage"><div><div><h2
class="title"><a name="rtmp"></a>Chapter?7.?RTMP
Protocol</h2></div></div></div><div class="toc"><p><b>Table of
Contents</b></p><dl><dt><span class="sect1"><a href="#amf">AMF
Format</a></span></dt></dl></div><p>
This document is based mostly on my own reverse engineering of the
RTMP protocol and AMF format. <span
class="emphasis"><em>tcpdump</em></span> and
<span class="emphasis"><em>ethereal</em></span> are your friend. Some
additional info that got
@@ -2844,7 +2844,7 @@
connection.
</p></dd></dl></div><p>
- </p><div class="sect1" lang="en"><div class="titlepage"><div><div><h2
class="title" style="clear: both"><a name="amf"></a>AMF
Format</h2></div></div></div><p>
+ </p><div class="sect1" title="AMF Format"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="amf"></a>AMF Format</h2></div></div></div><p>
The AMF format is used in the LocalConnection, SharedObject,
NetConnection, and NetStream ActionScript classes. This is a means
of binary data interchange between SWF movies, or between a
@@ -2872,7 +2872,7 @@
since the length is specified.
</p></dd></dl></div><p>
- </p></div></div><div class="chapter" lang="en"><div
class="titlepage"><div><div><h2 class="title"><a
name="nsapi"></a>Chapter?8.?Mozilla/Firefox NPAPI
Plugin</h2></div></div></div><div class="toc"><p><b>Table of
Contents</b></p><dl><dt><span class="sect1"><a href="#plugincapi">Plugin C
API</a></span></dt><dt><span class="sect1"><a href="#plugincppapi">Plugin C++
API</a></span></dt><dt><span class="sect1"><a href="#glthread">OpenGL and
Threads</a></span></dt><dt><span class="sect1"><a href="#eventhandle">Plugin
Event Handling</a></span></dt></dl></div><p>
+ </p></div></div><div class="chapter" title="Chapter?8.?Mozilla/Firefox NPAPI
Plugin"><div class="titlepage"><div><div><h2 class="title"><a
name="nsapi"></a>Chapter?8.?Mozilla/Firefox NPAPI
Plugin</h2></div></div></div><div class="toc"><p><b>Table of
Contents</b></p><dl><dt><span class="sect1"><a href="#plugincapi">Plugin C
API</a></span></dt><dt><span class="sect1"><a href="#plugincppapi">Plugin C++
API</a></span></dt><dt><span class="sect1"><a href="#glthread">OpenGL and
Threads</a></span></dt><dt><span class="sect1"><a href="#eventhandle">Plugin
Event Handling</a></span></dt></dl></div><p>
The Mozilla SDK has two API layers for plugins. The older layer is
documented in the <a class="ulink"
href="http://www.gnu.org/software/gnash/manual/plugin.pdf" target="_top">
Geeko Plugin API Reference</a>, and the newer layer doesn't
@@ -2888,7 +2888,7 @@
When initializing or destroying a plugin, no matter how many
instances are being used, the C API is used. These functions are
typically called once for each plugin that is loaded.
- </p><div class="sect1" lang="en"><div class="titlepage"><div><div><h2
class="title" style="clear: both"><a name="plugincapi"></a>Plugin C
API</h2></div></div></div><p>
+ </p><div class="sect1" title="Plugin C API"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="plugincapi"></a>Plugin C API</h2></div></div></div><p>
The lower layer is a C based API which is used by Firefox to
initialize and destroy a plugin. This is so a plugin can be
portable across multiple systems, since C++ emphasis is not portable
@@ -2926,7 +2926,7 @@
This is used by Firefox to query information from the
plugin, like the supported MIME type, the version number,
and a description.
- </p></dd></dl></div></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="plugincppapi"></a>Plugin C++ API</h2></div></div></div><p>
+ </p></dd></dl></div></div><div class="sect1" title="Plugin C++
API"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="plugincppapi"></a>Plugin C++ API</h2></div></div></div><p>
The higher level layer is the one we are most concerned
with. This is an instantiation of the
<span class="emphasis"><em>nsPluginInstanceBase</em></span> class, as
defined by the
@@ -2988,7 +2988,7 @@
This returns information to the browser about the plugin's
name and description.
</p></dd><dt><span
class="term">nsPluginInstance::URLNotify</span></dt><dd><p>
- </p></dd></dl></div></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="glthread"></a>OpenGL and Threads</h2></div></div></div><p>
+ </p></dd></dl></div></div><div class="sect1" title="OpenGL and
Threads"><div class="titlepage"><div><div><h2 class="title" style="clear:
both"><a name="glthread"></a>OpenGL and Threads</h2></div></div></div><p>
Neither OpenGL nor X11 has any built-in support for threads. Most
actions aren't even atomic, so care has to be made to not corrupt
any internal data. While it is difficult to render OpenGL from
@@ -3014,7 +3014,7 @@
</p><p>
All the emphasis that directly accesses a GLX context or the X11
display must be wrapped with a mutex.
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="eventhandle"></a>Plugin Event Handling</h2></div></div></div><p>
+ </p></div><div class="sect1" title="Plugin Event Handling"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="eventhandle"></a>Plugin Event Handling</h2></div></div></div><p>
Firefox on most UNIX systems is a GTK+ application, so it is
possible to have the plugin hook into the X11 event handling via
GLX or GTK. Since Firefox uses GTK, so does Gnash. This also
@@ -3032,7 +3032,7 @@
<span class="emphasis"><em>--disable-glext</em></span>
</p><p>
- </p></div></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="appendix"></a>Appendix</h2></div></div></div><div class="sect2"
lang="en"><div class="titlepage"><div><div><h3 class="title"><a
name="codestyle"></a>Code Style</h3></div></div></div><p>
+ </p></div></div><div class="sect1" title="Appendix"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="appendix"></a>Appendix</h2></div></div></div><div class="sect2"
title="Code Style"><div class="titlepage"><div><div><h3 class="title"><a
name="codestyle"></a>Code Style</h3></div></div></div><p>
I know any discussion of coding styles leads to strong opinions,
so I'll state simply I follow the <a class="ulink"
href="http://www.gnu.org/prep/standards/standards.html" target="_top">GNU
Coding Standards</a>. Where there is some flexibility as to
@@ -3137,7 +3137,7 @@
when listing all the classes on the generated web pages. The
text after the blank link becomes the detailed description which
appears on the generated web page for that class and method.
- </p></div></div><div class="chapter" lang="en"><div
class="titlepage"><div><div><h2 class="title"><a
name="authors"></a>Chapter?9.?Authors</h2></div></div></div><p>
+ </p></div></div><div class="chapter" title="Chapter?9.?Authors"><div
class="titlepage"><div><div><h2 class="title"><a
name="authors"></a>Chapter?9.?Authors</h2></div></div></div><p>
<span class="application">Gnash</span> is maintained by Rob Savoye.
Other active developers
are: Sandro Santilli, Bastiaan Jacques, Udo Giacomozzi, Chad
Musick, Benjamin Wolsey, Zou Lunkai, and Russ Nelson. Please
@@ -3152,15 +3152,15 @@
Mike Shaver, Thierry Berger-Perrin,
Ignacio Casta?o, Willem Kokke, Vitaly Alexeev, Alexander Streit,
and Rob Savoye.
- </p></div><div class="appendix" lang="en"><div
class="titlepage"><div><div><h2 class="title"><a name="fdl"></a>Appendix?A.?GNU
Free Documentation License</h2></div><div><p class="releaseinfo">
+ </p></div><div class="appendix" title="Appendix?A.?GNU Free Documentation
License"><div class="titlepage"><div><div><h2 class="title"><a
name="fdl"></a>Appendix?A.?GNU Free Documentation License</h2></div><div><p
class="releaseinfo">
Version 1.1, March 2000
- </p></div><div><p class="copyright">Copyright ? 2000 Free Software
Foundation, Inc.</p></div><div><div class="legalnotice"><a
name="fdl-legalnotice"></a><p>
+ </p></div><div><p class="copyright">Copyright ? 2000 Free Software
Foundation, Inc.</p></div><div><div class="legalnotice" title="Legal Notice"><a
name="fdl-legalnotice"></a><p>
</p><div class="address"><p>Free?Software?Foundation,?Inc.?<span
class="street">59?Temple?Place,?<br>
????????Suite?330</span>,?<span class="city">Boston</span>,?<span
class="state">MA</span>??<br>
????????<span class="postcode">02111-1307</span>??<span
class="country">USA</span></p></div><p>
Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.
- </p></div></div></div></div><div class="toc"><p><b>Table of
Contents</b></p><dl><dt><span class="sect1"><a href="#fdl-preamble">0.
PREAMBLE</a></span></dt><dt><span class="sect1"><a href="#fdl-section1">1.
APPLICABILITY AND DEFINITIONS</a></span></dt><dt><span class="sect1"><a
href="#fdl-section2">2. VERBATIM COPYING</a></span></dt><dt><span
class="sect1"><a href="#fdl-section3">3. COPYING IN
QUANTITY</a></span></dt><dt><span class="sect1"><a href="#fdl-section4">4.
MODIFICATIONS</a></span></dt><dt><span class="sect1"><a href="#fdl-section5">5.
COMBINING DOCUMENTS</a></span></dt><dt><span class="sect1"><a
href="#fdl-section6">6. COLLECTIONS OF DOCUMENTS</a></span></dt><dt><span
class="sect1"><a href="#fdl-section7">7. AGGREGATION WITH INDEPENDENT
WORKS</a></span></dt><dt><span class="sect1"><a href="#fdl-section8">8.
TRANSLATION</a></span></dt><dt><span class="sect1"><a href="#fdl-section9">9.
TERMINATION</a></span></dt><dt><span class="sect1"><a href="#fdl-section10">10.
FUTURE REVISIONS OF THIS LICENSE</a></span></dt><dt><span class="sect1"><a
href="#fdl-using">Addendum</a></span></dt></dl></div><div class="sect1"
lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear:
both"><a name="fdl-preamble"></a>0. PREAMBLE</h2></div></div></div><p>
+ </p></div></div></div></div><div class="toc"><p><b>Table of
Contents</b></p><dl><dt><span class="sect1"><a href="#fdl-preamble">0.
PREAMBLE</a></span></dt><dt><span class="sect1"><a href="#fdl-section1">1.
APPLICABILITY AND DEFINITIONS</a></span></dt><dt><span class="sect1"><a
href="#fdl-section2">2. VERBATIM COPYING</a></span></dt><dt><span
class="sect1"><a href="#fdl-section3">3. COPYING IN
QUANTITY</a></span></dt><dt><span class="sect1"><a href="#fdl-section4">4.
MODIFICATIONS</a></span></dt><dt><span class="sect1"><a href="#fdl-section5">5.
COMBINING DOCUMENTS</a></span></dt><dt><span class="sect1"><a
href="#fdl-section6">6. COLLECTIONS OF DOCUMENTS</a></span></dt><dt><span
class="sect1"><a href="#fdl-section7">7. AGGREGATION WITH INDEPENDENT
WORKS</a></span></dt><dt><span class="sect1"><a href="#fdl-section8">8.
TRANSLATION</a></span></dt><dt><span class="sect1"><a href="#fdl-section9">9.
TERMINATION</a></span></dt><dt><span class="sect1"><a href="#fdl-section10">10.
FUTURE REVISIONS OF THIS LICENSE</a></span></dt><dt><span class="sect1"><a
href="#fdl-using">Addendum</a></span></dt></dl></div><div class="sect1"
title="0. PREAMBLE"><div class="titlepage"><div><div><h2 class="title"
style="clear: both"><a name="fdl-preamble"></a>0.
PREAMBLE</h2></div></div></div><p>
The purpose of this License is to make a manual, textbook, or
other written document "free" in the sense of
freedom: to assure everyone the effective freedom to copy and
@@ -3183,7 +3183,7 @@
regardless of subject matter or whether it is published as a
printed book. We recommend this License principally for works
whose purpose is instruction or reference.
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-section1"></a>1. APPLICABILITY AND
DEFINITIONS</h2></div></div></div><p><a name="fdl-document"></a>
+ </p></div><div class="sect1" title="1. APPLICABILITY AND DEFINITIONS"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-section1"></a>1. APPLICABILITY AND
DEFINITIONS</h2></div></div></div><p><a name="fdl-document"></a>
This License applies to any manual or other work that contains a
notice placed by the copyright holder saying it can be
distributed under the terms of this License. The
@@ -3249,7 +3249,7 @@
page as such, "Title Page" means the text near the
most prominent appearance of the work's title, preceding the
beginning of the body of the text.
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-section2"></a>2. VERBATIM COPYING</h2></div></div></div><p>
+ </p></div><div class="sect1" title="2. VERBATIM COPYING"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-section2"></a>2. VERBATIM COPYING</h2></div></div></div><p>
You may copy and distribute the <a class="link"
href="#fdl-document">Document</a> in any medium, either
commercially or noncommercially, provided that this License, the
copyright notices, and the license notice saying this License
@@ -3263,7 +3263,7 @@
</p><p>
You may also lend copies, under the same conditions stated
above, and you may publicly display copies.
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-section3"></a>3. COPYING IN QUANTITY</h2></div></div></div><p>
+ </p></div><div class="sect1" title="3. COPYING IN QUANTITY"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-section3"></a>3. COPYING IN QUANTITY</h2></div></div></div><p>
If you publish printed copies of the <a class="link"
href="#fdl-document">Document</a> numbering more than 100,
and the Document's license notice requires <a class="link"
href="#fdl-cover-texts">Cover Texts</a>, you must enclose
the copies in covers that carry, clearly and legibly, all these
@@ -3302,7 +3302,7 @@
of the <a class="link" href="#fdl-document">Document</a> well before
redistributing any large number of copies, to give them a chance
to provide you with an updated version of the Document.
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-section4"></a>4. MODIFICATIONS</h2></div></div></div><p>
+ </p></div><div class="sect1" title="4. MODIFICATIONS"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-section4"></a>4. MODIFICATIONS</h2></div></div></div><p>
You may copy and distribute a <a class="link"
href="#fdl-modified">Modified Version</a> of the <a class="link"
href="#fdl-document">Document</a> under the conditions of
sections <a class="link" href="#fdl-section2" title="2. VERBATIM
COPYING">2</a> and <a class="link" href="#fdl-section3" title="3. COPYING IN
QUANTITY">3</a> above, provided that you release
the Modified Version under precisely this License, with the
@@ -3310,7 +3310,7 @@
licensing distribution and modification of the Modified Version
to whoever possesses a copy of it. In addition, you must do
these things in the Modified Version:
- </p><div class="itemizedlist"><ul type="opencircle"><li
style="list-style-type: circle"><p><b>A.?</b>
+ </p><div class="itemizedlist"><ul class="itemizedlist"
type="opencircle"><li class="listitem" style="list-style-type: circle"><p
title="A"><b>A.?</b>
Use in the <a class="link" href="#fdl-title-page">Title
Page</a> (and on the covers, if any) a title distinct
from that of the <a class="link" href="#fdl-document">Document</a>,
and from those of
@@ -3318,7 +3318,7 @@
listed in the History section of the Document). You may
use the same title as a previous version if the original
publisher of that version gives permission.
- </p></li><li style="list-style-type: circle"><p><b>B.?</b>
+ </p></li><li class="listitem" style="list-style-type: circle"><p
title="B"><b>B.?</b>
List on the <a class="link" href="#fdl-title-page">Title
Page</a>, as authors, one or more persons or entities
responsible for authorship of the modifications in the
@@ -3326,28 +3326,28 @@
together with at least five of the principal authors of
the <a class="link" href="#fdl-document">Document</a> (all of
its principal authors, if it has less than five).
- </p></li><li style="list-style-type: circle"><p><b>C.?</b>
+ </p></li><li class="listitem" style="list-style-type: circle"><p
title="C"><b>C.?</b>
State on the <a class="link" href="#fdl-title-page">Title
Page</a> the name of the publisher of the <a class="link"
href="#fdl-modified">Modified Version</a>, as the
publisher.
- </p></li><li style="list-style-type: circle"><p><b>D.?</b>
+ </p></li><li class="listitem" style="list-style-type: circle"><p
title="D"><b>D.?</b>
Preserve all the copyright notices of the <a class="link"
href="#fdl-document">Document</a>.
- </p></li><li style="list-style-type: circle"><p><b>E.?</b>
+ </p></li><li class="listitem" style="list-style-type: circle"><p
title="E"><b>E.?</b>
Add an appropriate copyright notice for your modifications
adjacent to the other copyright notices.
- </p></li><li style="list-style-type: circle"><p><b>F.?</b>
+ </p></li><li class="listitem" style="list-style-type: circle"><p
title="F"><b>F.?</b>
Include, immediately after the copyright notices, a
license notice giving the public permission to use the
<a class="link" href="#fdl-modified">Modified Version</a> under
the terms of this License, in the form shown in the
Addendum below.
- </p></li><li style="list-style-type: circle"><p><b>G.?</b>
+ </p></li><li class="listitem" style="list-style-type: circle"><p
title="G"><b>G.?</b>
Preserve in that license notice the full lists of <a class="link"
href="#fdl-invariant"> Invariant Sections</a> and
required <a class="link" href="#fdl-cover-texts">Cover
Texts</a> given in the <a class="link"
href="#fdl-document">Document's</a> license notice.
- </p></li><li style="list-style-type: circle"><p><b>H.?</b>
+ </p></li><li class="listitem" style="list-style-type: circle"><p
title="H"><b>H.?</b>
Include an unaltered copy of this License.
- </p></li><li style="list-style-type: circle"><p><b>I.?</b>
+ </p></li><li class="listitem" style="list-style-type: circle"><p
title="I"><b>I.?</b>
Preserve the section entitled "History", and
its title, and add to it an item stating at least the
title, year, new authors, and publisher of the <a class="link"
href="#fdl-modified">Modified Version </a>as given on
@@ -3358,7 +3358,7 @@
Document as given on its Title Page, then add an item
describing the Modified Version as stated in the previous
sentence.
- </p></li><li style="list-style-type: circle"><p><b>J.?</b>
+ </p></li><li class="listitem" style="list-style-type: circle"><p
title="J"><b>J.?</b>
Preserve the network location, if any, given in the <a class="link"
href="#fdl-document">Document</a> for public access
to a <a class="link" href="#fdl-transparent">Transparent</a>
copy of the Document, and likewise the network locations
@@ -3368,23 +3368,23 @@
was published at least four years before the Document
itself, or if the original publisher of the version it
refers to gives permission.
- </p></li><li style="list-style-type: circle"><p><b>K.?</b>
+ </p></li><li class="listitem" style="list-style-type: circle"><p
title="K"><b>K.?</b>
In any section entitled "Acknowledgements" or
"Dedications", preserve the section's title,
and preserve in the section all the substance and tone of
each of the contributor acknowledgements and/or
dedications given therein.
- </p></li><li style="list-style-type: circle"><p><b>L.?</b>
+ </p></li><li class="listitem" style="list-style-type: circle"><p
title="L"><b>L.?</b>
Preserve all the <a class="link" href="#fdl-invariant">Invariant
Sections</a> of the <a class="link"
href="#fdl-document">Document</a>, unaltered in their
text and in their titles. Section numbers or the
equivalent are not considered part of the section titles.
- </p></li><li style="list-style-type: circle"><p><b>M.?</b>
+ </p></li><li class="listitem" style="list-style-type: circle"><p
title="M"><b>M.?</b>
Delete any section entitled
"Endorsements". Such a section may not be
included in the <a class="link" href="#fdl-modified">Modified
Version</a>.
- </p></li><li style="list-style-type: circle"><p><b>N.?</b>
+ </p></li><li class="listitem" style="list-style-type: circle"><p
title="N"><b>N.?</b>
Do not retitle any existing section as
"Endorsements" or to conflict in title with
any <a class="link" href="#fdl-invariant">Invariant
@@ -3421,7 +3421,7 @@
The author(s) and publisher(s) of the <a class="link"
href="#fdl-document">Document</a> do not by this License
give permission to use their names for publicity for or to
assert or imply endorsement of any <a class="link"
href="#fdl-modified">Modified Version </a>.
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-section5"></a>5. COMBINING DOCUMENTS</h2></div></div></div><p>
+ </p></div><div class="sect1" title="5. COMBINING DOCUMENTS"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-section5"></a>5. COMBINING DOCUMENTS</h2></div></div></div><p>
You may combine the <a class="link" href="#fdl-document">Document</a>
with other documents released under this License, under the
terms defined in <a class="link" href="#fdl-section4" title="4.
MODIFICATIONS">section 4</a>
@@ -3448,7 +3448,7 @@
combine any sections entitled "Acknowledgements",
and any sections entitled "Dedications". You must
delete all sections entitled "Endorsements."
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-section6"></a>6. COLLECTIONS OF DOCUMENTS</h2></div></div></div><p>
+ </p></div><div class="sect1" title="6. COLLECTIONS OF DOCUMENTS"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-section6"></a>6. COLLECTIONS OF DOCUMENTS</h2></div></div></div><p>
You may make a collection consisting of the <a class="link"
href="#fdl-document">Document</a> and other documents
released under this License, and replace the individual copies
of this License in the various documents with a single copy that
@@ -3461,7 +3461,7 @@
insert a copy of this License into the extracted document, and
follow this License in all other respects regarding verbatim
copying of that document.
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-section7"></a>7. AGGREGATION WITH INDEPENDENT
WORKS</h2></div></div></div><p>
+ </p></div><div class="sect1" title="7. AGGREGATION WITH INDEPENDENT
WORKS"><div class="titlepage"><div><div><h2 class="title" style="clear:
both"><a name="fdl-section7"></a>7. AGGREGATION WITH INDEPENDENT
WORKS</h2></div></div></div><p>
A compilation of the <a class="link" href="#fdl-document">Document</a>
or its derivatives with
other separate and independent documents or works, in or on a
volume of a storage or distribution medium, does not as a whole
@@ -3477,7 +3477,7 @@
be placed on covers that surround only the Document within the
aggregate. Otherwise they must appear on covers around the whole
aggregate.
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-section8"></a>8. TRANSLATION</h2></div></div></div><p>
+ </p></div><div class="sect1" title="8. TRANSLATION"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-section8"></a>8. TRANSLATION</h2></div></div></div><p>
Translation is considered a kind of modification, so you may
distribute translations of the <a class="link"
href="#fdl-document">Document</a> under the terms of <a class="link"
href="#fdl-section4" title="4. MODIFICATIONS">section 4</a>. Replacing <a
class="link" href="#fdl-invariant"> Invariant Sections</a> with
translations requires special permission from their copyright
@@ -3488,7 +3488,7 @@
version of this License. In case of a disagreement between the
translation and the original English version of this License,
the original English version will prevail.
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-section9"></a>9. TERMINATION</h2></div></div></div><p>
+ </p></div><div class="sect1" title="9. TERMINATION"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-section9"></a>9. TERMINATION</h2></div></div></div><p>
You may not copy, modify, sublicense, or distribute the <a class="link"
href="#fdl-document">Document</a> except as expressly
provided for under this License. Any other attempt to copy,
modify, sublicense or distribute the Document is void, and will
@@ -3496,7 +3496,7 @@
parties who have received copies, or rights, from you under this
License will not have their licenses terminated so long as such
parties remain in full compliance.
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-section10"></a>10. FUTURE REVISIONS OF THIS
LICENSE</h2></div></div></div><p>
+ </p></div><div class="sect1" title="10. FUTURE REVISIONS OF THIS
LICENSE"><div class="titlepage"><div><div><h2 class="title" style="clear:
both"><a name="fdl-section10"></a>10. FUTURE REVISIONS OF THIS
LICENSE</h2></div></div></div><p>
The <a class="ulink" href="http://www.gnu.org/fsf/fsf.html"
target="_top">Free Software
Foundation</a> may publish new, revised versions of the GNU
Free Documentation License from time to time. Such new versions
@@ -3513,7 +3513,7 @@
the Document does not specify a version number of this License,
you may choose any version ever published (not as a draft) by
the Free Software Foundation.
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-using"></a>Addendum</h2></div></div></div><p>
+ </p></div><div class="sect1" title="Addendum"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-using"></a>Addendum</h2></div></div></div><p>
To use this License in a document you have written, include a copy of
the License in the document and put the following copyright and
license notices just after the title page:
=== modified file 'doc/C/preformatted/gnashuser.html.in'
--- a/doc/C/preformatted/gnashuser.html.in 2009-03-19 08:36:28 +0000
+++ b/doc/C/preformatted/gnashuser.html.in 2010-01-01 20:41:28 +0000
@@ -1,6 +1,6 @@
-<html><head><meta http-equiv="Content-Type" content="text/html;
charset=ISO-8859-1"><title>Gnash User Manual</title><meta name="generator"
content="DocBook XSL Stylesheets V1.73.2"></head><body bgcolor="white"
text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="book"
lang="en"><div class="titlepage"><div><div><h1 class="title"><a
name="index"></a>Gnash User Manual</h1></div><div><p class="releaseinfo">
- This manual describes version 0.8.5 of Gnash.
- </p></div><div><p class="copyright">Copyright ? 2005, 2006, 2007, 2008
Free Software Foundation</p></div><div><div class="legalnotice"><a
name="legalnotice"></a><p>
+<html><head><meta http-equiv="Content-Type" content="text/html;
charset=ISO-8859-1"><title>Gnash User Manual</title><meta name="generator"
content="DocBook XSL Stylesheets V1.75.2"></head><body bgcolor="white"
text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div lang="en"
class="book" title="Gnash User Manual"><div class="titlepage"><div><div><h1
class="title"><a name="index"></a>Gnash User Manual</h1></div><div><p
class="releaseinfo">
+ This manual describes version 0.8.6 of Gnash.
+ </p></div><div><p class="copyright">Copyright ? 2005, 2006, 2007, 2008,
2009, 2010 Free Software Foundation</p></div><div><div class="legalnotice"
title="Legal Notice"><a name="legalnotice"></a><p>
Permission is granted to copy, distribute and/or modify this document
under the terms of the <a class="link" href="#fdl" title="Appendix?A.?GNU
Free Documentation License"><em class="citetitle">GNU
Free Documentation License</em></a>, Version 1.1 or any later
@@ -9,7 +9,7 @@
a copy of the GFDL at this
<a class="link" href="#fdl" title="Appendix?A.?GNU Free Documentation
License">link</a> or in the file COPYING-DOCS
distributed with this manual.
- </p></div></div><div><div class="revhistory"><table border="1" width="100%"
summary="Revision history"><tr><th align="left" valign="top"
colspan="2"><b>Revision History</b></th></tr><tr><td align="left">Revision
Gnash User Manual version 0.1</td><td align="left">Feb 2008</td></tr><tr><td
align="left" colspan="2">
+ </p></div></div><div><div class="revhistory"><table border="1" width="100%"
summary="Revision history"><tr><th align="left" valign="top"
colspan="2"><b>Revision History</b></th></tr><tr><td align="left">Revision
Gnash User Manual version 0.1</td><td align="left">Jan 2010</td></tr><tr><td
align="left" colspan="2">
<p class="author">Rob Savoye
<code class="email"><<a class="email"
href="mailto:address@hidden">address@hidden</a>></code>
The end user parts of the manual have been pulled out of
@@ -17,7 +17,7 @@
</p>
<p class="publisher">Open Media Now! Foundation</p>
- </td></tr></table></div></div></div><hr></div><div class="toc"><p><b>Table
of Contents</b></p><dl><dt><span class="chapter"><a href="#intro">1.
Introduction</a></span></dt><dd><dl><dt><span class="sect1"><a
href="#audience">Audience</a></span></dt><dt><span class="sect1"><a
href="#runs-on">What Is Supported?</a></span></dt></dl></dd><dt><span
class="chapter"><a href="#usage">2. Using <span
class="application">Gnash</span></a></span></dt><dd><dl><dt><span
class="sect1"><a href="#options"><span class="application">Gnash</span> Command
Line Options</a></span></dt><dt><span class="sect1"><a href="#keys"><span
class="application">Gnash</span> Interactive Control
Keys</a></span></dt><dt><span class="sect1"><a href="#gnashrc">User
Configuration File</a></span></dt></dl></dd><dt><span class="chapter"><a
href="#build">3. Installing and Configuring
Gnash</a></span></dt><dd><dl><dt><span class="sect1"><a
href="#requirements">Requirements</a></span></dt><dd><dl><dt><span
class="sect2"><a href="#hardware">Hardware
Requirements</a></span></dt><dt><span class="sect2"><a
href="#software">Software Requirements</a></span></dt></dl></dd><dt><span
class="sect1"><a href="#downloading">Downloading
Gnash</a></span></dt><dd><dl><dt><span class="sect2"><a
href="#gettingsource">Getting the Source</a></span></dt><dt><span
class="sect2"><a href="#getcodecs">Getting Codec
Support</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a
href="#bugreport">4. Reporting Bugs</a></span></dt><dd><dl><dt><span
class="sect1"><a href="#bugstep_package">Get a Fresh Binary
Package</a></span></dt><dt><span class="sect1"><a
href="#bugstep_search">Determine if the bug was previously
reported</a></span></dt><dt><span class="sect1"><a
href="#bugstep_guidelines">Review the bug writing
guidelines</a></span></dt><dt><span class="sect1"><a
href="#bugstep_file">Filing a bug report</a></span></dt></dl></dd><dt><span
class="glossary"><a href="#glossary">Glossary</a></span></dt><dt><span
class="chapter"><a href="#authors">5. Authors</a></span></dt><dt><span
class="appendix"><a href="#fdl">A. GNU Free Documentation
License</a></span></dt><dd><dl><dt><span class="sect1"><a
href="#fdl-preamble">0. PREAMBLE</a></span></dt><dt><span class="sect1"><a
href="#fdl-section1">1. APPLICABILITY AND DEFINITIONS</a></span></dt><dt><span
class="sect1"><a href="#fdl-section2">2. VERBATIM
COPYING</a></span></dt><dt><span class="sect1"><a href="#fdl-section3">3.
COPYING IN QUANTITY</a></span></dt><dt><span class="sect1"><a
href="#fdl-section4">4. MODIFICATIONS</a></span></dt><dt><span class="sect1"><a
href="#fdl-section5">5. COMBINING DOCUMENTS</a></span></dt><dt><span
class="sect1"><a href="#fdl-section6">6. COLLECTIONS OF
DOCUMENTS</a></span></dt><dt><span class="sect1"><a href="#fdl-section7">7.
AGGREGATION WITH INDEPENDENT WORKS</a></span></dt><dt><span class="sect1"><a
href="#fdl-section8">8. TRANSLATION</a></span></dt><dt><span class="sect1"><a
href="#fdl-section9">9. TERMINATION</a></span></dt><dt><span class="sect1"><a
href="#fdl-section10">10. FUTURE REVISIONS OF THIS
LICENSE</a></span></dt><dt><span class="sect1"><a
href="#fdl-using">Addendum</a></span></dt></dl></dd></dl></div><div
class="list-of-tables"><p><b>List of Tables</b></p><dl><dt>2.1. <a
href="#tb-command-line-options">Gnash Command Line Options</a></dt><dt>2.2. <a
href="#tb-control-keys">Gnash Interactive Control Keys</a></dt><dt>2.3. <a
href="#tb-config-variables">User Configuration Variables</a></dt><dt>3.1. <a
href="#tb-os-cpu">Build Matrix</a></dt></dl></div><div class="chapter"
lang="en"><div class="titlepage"><div><div><h2 class="title"><a
name="intro"></a>Chapter?1.?Introduction</h2></div></div></div><div
class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a
href="#audience">Audience</a></span></dt><dt><span class="sect1"><a
href="#runs-on">What Is Supported?</a></span></dt></dl></div><p>
+ </td></tr></table></div></div></div><hr></div><div class="toc"><p><b>Table
of Contents</b></p><dl><dt><span class="chapter"><a href="#intro">1.
Introduction</a></span></dt><dd><dl><dt><span class="sect1"><a
href="#audience">Audience</a></span></dt><dt><span class="sect1"><a
href="#runs-on">What Is Supported?</a></span></dt></dl></dd><dt><span
class="chapter"><a href="#usage">2. Using <span
class="application">Gnash</span></a></span></dt><dd><dl><dt><span
class="sect1"><a href="#options"><span class="application">Gnash</span> Command
Line Options</a></span></dt><dt><span class="sect1"><a href="#keys"><span
class="application">Gnash</span> Interactive Control
Keys</a></span></dt><dt><span class="sect1"><a href="#gnashrc">User
Configuration File</a></span></dt></dl></dd><dt><span class="chapter"><a
href="#build">3. Installing and Configuring
Gnash</a></span></dt><dd><dl><dt><span class="sect1"><a
href="#requirements">Requirements</a></span></dt><dd><dl><dt><span
class="sect2"><a href="#hardware">Hardware
Requirements</a></span></dt><dt><span class="sect2"><a
href="#software">Software Requirements</a></span></dt></dl></dd><dt><span
class="sect1"><a href="#downloading">Downloading
Gnash</a></span></dt><dd><dl><dt><span class="sect2"><a
href="#gettingsource">Getting the Source</a></span></dt><dt><span
class="sect2"><a href="#getcodecs">Getting Codec
Support</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a
href="#bugreport">4. Reporting Bugs</a></span></dt><dd><dl><dt><span
class="sect1"><a href="#bugstep_package">Get a Fresh Binary
Package</a></span></dt><dt><span class="sect1"><a
href="#bugstep_search">Determine if the bug was previously
reported</a></span></dt><dt><span class="sect1"><a
href="#bugstep_guidelines">Review the bug writing
guidelines</a></span></dt><dt><span class="sect1"><a
href="#bugstep_file">Filing a bug report</a></span></dt></dl></dd><dt><span
class="glossary"><a href="#glossary">Glossary</a></span></dt><dt><span
class="chapter"><a href="#authors">5. Authors</a></span></dt><dt><span
class="appendix"><a href="#fdl">A. GNU Free Documentation
License</a></span></dt><dd><dl><dt><span class="sect1"><a
href="#fdl-preamble">0. PREAMBLE</a></span></dt><dt><span class="sect1"><a
href="#fdl-section1">1. APPLICABILITY AND DEFINITIONS</a></span></dt><dt><span
class="sect1"><a href="#fdl-section2">2. VERBATIM
COPYING</a></span></dt><dt><span class="sect1"><a href="#fdl-section3">3.
COPYING IN QUANTITY</a></span></dt><dt><span class="sect1"><a
href="#fdl-section4">4. MODIFICATIONS</a></span></dt><dt><span class="sect1"><a
href="#fdl-section5">5. COMBINING DOCUMENTS</a></span></dt><dt><span
class="sect1"><a href="#fdl-section6">6. COLLECTIONS OF
DOCUMENTS</a></span></dt><dt><span class="sect1"><a href="#fdl-section7">7.
AGGREGATION WITH INDEPENDENT WORKS</a></span></dt><dt><span class="sect1"><a
href="#fdl-section8">8. TRANSLATION</a></span></dt><dt><span class="sect1"><a
href="#fdl-section9">9. TERMINATION</a></span></dt><dt><span class="sect1"><a
href="#fdl-section10">10. FUTURE REVISIONS OF THIS
LICENSE</a></span></dt><dt><span class="sect1"><a
href="#fdl-using">Addendum</a></span></dt></dl></dd></dl></div><div
class="list-of-tables"><p><b>List of Tables</b></p><dl><dt>2.1. <a
href="#tb-command-line-options">Gnash Command Line Options</a></dt><dt>2.2. <a
href="#tb-control-keys">Gnash Interactive Control Keys</a></dt><dt>2.3. <a
href="#tb-config-variables">User Configuration Variables</a></dt><dt>3.1. <a
href="#tb-os-cpu">Build Matrix</a></dt></dl></div><div class="chapter"
title="Chapter?1.?Introduction"><div class="titlepage"><div><div><h2
class="title"><a
name="intro"></a>Chapter?1.?Introduction</h2></div></div></div><div
class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a
href="#audience">Audience</a></span></dt><dt><span class="sect1"><a
href="#runs-on">What Is Supported?</a></span></dt></dl></div><p>
<span class="application">Gnash</span> is a free SWF movie player. It is
available as a
stand-alone application or as a plugin for several popular
web browsers. It supports playing media from a disk or streaming
@@ -30,12 +30,12 @@
extending ActionScript by creating your own classes. You can write
wrappers for any development library, and import them into the
player much like Perl or Python does.
- </p><div class="sect1" lang="en"><div class="titlepage"><div><div><h2
class="title" style="clear: both"><a
name="audience"></a>Audience</h2></div></div></div><p>
+ </p><div class="sect1" title="Audience"><div class="titlepage"><div><div><h2
class="title" style="clear: both"><a
name="audience"></a>Audience</h2></div></div></div><p>
This manual is primarily focused on users interested in how to
get Gnash installed from a package, and basic usage as a web
browser plugin. For more technical details, please refer to the
Gnash Reference manual.
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="runs-on"></a>What Is Supported?</h2></div></div></div><p>
+ </p></div><div class="sect1" title="What Is Supported?"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="runs-on"></a>What Is Supported?</h2></div></div></div><p>
Gnash is known to compile for most any POSIX and ANSI C++
conforming system if you have all the dependent libraries
installed. Systems we test on, and which Gnash is known to
@@ -77,13 +77,13 @@
at: <a class="ulink" href="http://www.gnashdev.org/dev_snapshots/"
target="_top">
http://www.gnashdev.org/dev_snapshots</a>.
</p><p>
- Gnash uses ffmpeg for codecs, so any file supported by Mplayer
+ Gnash uses FFmpeg for codecs, so any file supported by Mplayer
should work with Gnash. Gnash supports the loading of patent
free codecs like Ogg Vorbis or Theora from disk based files,
while work is being done to support these codecs when embedded
- in a SWF file. Ffmpeg contains the codecs used by the current
+ in a SWF file. FFmpeg contains the codecs used by the current
SWF defintion, FLV, VP6 (ON2), H.263, H.264, and MP3.
- </p></div></div><div class="chapter" lang="en"><div
class="titlepage"><div><div><h2 class="title"><a
name="usage"></a>Chapter?2.?Using <span
class="application">Gnash</span></h2></div></div></div><div
class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a
href="#options"><span class="application">Gnash</span> Command Line
Options</a></span></dt><dt><span class="sect1"><a href="#keys"><span
class="application">Gnash</span> Interactive Control
Keys</a></span></dt><dt><span class="sect1"><a href="#gnashrc">User
Configuration File</a></span></dt></dl></div><p>
+ </p></div></div><div class="chapter" title="Chapter?2.?Using Gnash"><div
class="titlepage"><div><div><h2 class="title"><a
name="usage"></a>Chapter?2.?Using <span
class="application">Gnash</span></h2></div></div></div><div
class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a
href="#options"><span class="application">Gnash</span> Command Line
Options</a></span></dt><dt><span class="sect1"><a href="#keys"><span
class="application">Gnash</span> Interactive Control
Keys</a></span></dt><dt><span class="sect1"><a href="#gnashrc">User
Configuration File</a></span></dt></dl></div><p>
When used as a standalone player, you can play any SWF file from
the command line by entering a command of the format:
</p><pre class="programlisting">
@@ -120,7 +120,7 @@
</pre><p>
Note that this will not work with every website; some embedded
Flash files are difficult to play.
- </p><div class="sect1" lang="en"><div class="titlepage"><div><div><h2
class="title" style="clear: both"><a name="options"></a><span
class="application">Gnash</span> Command Line Options</h2></div></div></div><p>
+ </p><div class="sect1" title="Gnash Command Line Options"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="options"></a><span class="application">Gnash</span> Command Line
Options</h2></div></div></div><p>
No options are required for <span class="application">Gnash</span>'s
default behavior. However,
there are many options that can be used to change that behavior.
</p><p>
@@ -199,13 +199,13 @@
</td></tr><tr><td align="left">
<code class="option">-r, --render-mode</code> <em
class="replaceable"><code><0|1|2|3></code></em>
</td><td align="left">
- <div class="itemizedlist"><ul type="disc"><li><p>
+ <div class="itemizedlist"><ul class="itemizedlist"
type="disc"><li class="listitem"><p>
0 disables rendering and sound (good for batch tests).
- </p></li><li><p>
+ </p></li><li class="listitem"><p>
1 enables rendering and disables sound.
- </p></li><li><p>
+ </p></li><li class="listitem"><p>
2 enables sound and disables rendering.
- </p></li><li><p>
+ </p></li><li class="listitem"><p>
3 enables rendering and sound (default).
</p></li></ul></div>
</td></tr><tr><td align="left">
@@ -261,7 +261,7 @@
</td><td align="left">
Start <span class="application">Gnash</span> in fullscreen mode as
long as the GUI and window
manager support this.
- </td></tr></tbody></table></div></div><br
class="table-break"></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="keys"></a><span class="application">Gnash</span> Interactive Control
Keys</h2></div></div></div><p>
+ </td></tr></tbody></table></div></div><br
class="table-break"></div><div class="sect1" title="Gnash Interactive Control
Keys"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="keys"></a><span class="application">Gnash</span> Interactive Control
Keys</h2></div></div></div><p>
While a movie is playing, there are several control
keys. These can be used to step through frames, pause the
playing, and control other actions.
@@ -301,7 +301,7 @@
<code class="option">CTRL-M</code>
</td><td align="left">
Debug. Test the call_method() function.
- </td></tr></tbody></table></div></div><br
class="table-break"></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="gnashrc"></a>User Configuration File</h2></div></div></div><p>
+ </td></tr></tbody></table></div></div><br
class="table-break"></div><div class="sect1" title="User Configuration
File"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="gnashrc"></a>User Configuration File</h2></div></div></div><p>
Individual user preferences may be set by editing variables with
the <code class="filename">.gnashrc</code> file:
</p><pre class="programlisting">
@@ -375,7 +375,9 @@
player when running as a browser plugin. By default, sound
is enabled when using <span class="application">Gnash</span> as a
browser plugin.</td></tr><tr><td align="left">EnableExtensions</td><td
align="left">on/off</td><td align="left">Set to <span
class="emphasis"><em>on</em></span> to enable extensions. This option is <span
class="emphasis"><em>off</em></span> by default</td></tr><tr><td
align="left">StartStopped</td><td align="left">on/off</td><td align="left">Set
to <span class="emphasis"><em>on</em></span> to have the GUI start in "stop"
mode. This is useful in particular
for the plugin, so you have to explicitly start any movie on a
webpage. This option is <span class="emphasis"><em>off</em></span> by default.
- </td></tr><tr><td align="left">flashVersionString</td><td
align="left">string</td><td align="left">Set the string returned by $version
and System.capabilities.version.
+ </td></tr><tr><td align="left">webcamDevice</td><td
align="left">integer</td><td align="left">The integer value (index into vector
of video devices) that represents the default webcam.
+ To easily get this entry run utilities/findwebcams (only works with
Gstreamer right now)</td></tr><tr><td align="left">microphoneDevice</td><td
align="left">integer</td><td align="left">The integer value (index into vector
of microphone devices) that represents the default microphone.
+ To easily get this entry run utilities/findmicrophones (only works with
Gstreamer right now)</td></tr><tr><td align="left">flashVersionString</td><td
align="left">string</td><td align="left">Set the string returned by $version
and System.capabilities.version.
Useful to get around some flash version detection movies.
Note that the version advertised by the plugin is NOT affected by
this setting,
instead you need to set the GNASH_FLASH_VERSION environment variable
for
@@ -388,7 +390,8 @@
certificate could be invalid, may not belong to the host, or both.
Equivalent
to curl --insecure. By default, this option is <span
class="emphasis"><em>off</em></span> and
connections will fail when a host cannot be
verified.</td></tr><tr><td align="left">SOLsafedir</td><td
align="left">Absolute path</td><td align="left">The full path to a directory
where <span class="application">Gnash</span> should store Shared Object files
("flash cookies") if
- they are enabled.</td></tr><tr><td align="left">SOLreadonly</td><td
align="left">on/off</td><td align="left">If set to <span
class="emphasis"><em>on</em></span>, <span class="application">Gnash</span>
will not write Shared Object files.</td></tr><tr><td
align="left">ignoreFSCommand</td><td align="left">on/off</td><td
align="left">If set to on (default), <span class="application">Gnash</span>
will ignore fscommands in standalone mode.
+ they are enabled.</td></tr><tr><td
align="left">solLocalDomain</td><td align="left">on/off</td><td align="left">If
set to <span class="emphasis"><em>on</em></span>, allow the loading of
+ Shared Objects only on the localhost.</td></tr><tr><td
align="left">SOLreadonly</td><td align="left">on/off</td><td align="left">If
set to <span class="emphasis"><em>on</em></span>, <span
class="application">Gnash</span> will not write Shared Object
files.</td></tr><tr><td align="left">ignoreFSCommand</td><td
align="left">on/off</td><td align="left">If set to on (default), <span
class="application">Gnash</span> will ignore fscommands in standalone mode.
Fscommands are requests from the playing movie to the operating
system or
user interface: the most common are quit, fullscreen, showmenu and
exec. <span class="application">Gnash</span>
always ignores fscommands when running as a plugin.
@@ -463,25 +466,25 @@
# Use firefox to open urls
set urlOpenerFormat firefox -remote 'openurl(%u)'
- </pre></div></div><div class="chapter" lang="en"><div
class="titlepage"><div><div><h2 class="title"><a
name="build"></a>Chapter?3.?Installing and Configuring
Gnash</h2></div></div></div><div class="toc"><p><b>Table of
Contents</b></p><dl><dt><span class="sect1"><a
href="#requirements">Requirements</a></span></dt><dd><dl><dt><span
class="sect2"><a href="#hardware">Hardware
Requirements</a></span></dt><dt><span class="sect2"><a
href="#software">Software Requirements</a></span></dt></dl></dd><dt><span
class="sect1"><a href="#downloading">Downloading
Gnash</a></span></dt><dd><dl><dt><span class="sect2"><a
href="#gettingsource">Getting the Source</a></span></dt><dt><span
class="sect2"><a href="#getcodecs">Getting Codec
Support</a></span></dt></dl></dd></dl></div><p>
+ </pre></div></div><div class="chapter" title="Chapter?3.?Installing and
Configuring Gnash"><div class="titlepage"><div><div><h2 class="title"><a
name="build"></a>Chapter?3.?Installing and Configuring
Gnash</h2></div></div></div><div class="toc"><p><b>Table of
Contents</b></p><dl><dt><span class="sect1"><a
href="#requirements">Requirements</a></span></dt><dd><dl><dt><span
class="sect2"><a href="#hardware">Hardware
Requirements</a></span></dt><dt><span class="sect2"><a
href="#software">Software Requirements</a></span></dt></dl></dd><dt><span
class="sect1"><a href="#downloading">Downloading
Gnash</a></span></dt><dd><dl><dt><span class="sect2"><a
href="#gettingsource">Getting the Source</a></span></dt><dt><span
class="sect2"><a href="#getcodecs">Getting Codec
Support</a></span></dt></dl></dd></dl></div><p>
There are two ways of installing Gnash:
using a package manager, or <a class="link" href="#gettingsource"
title="Getting the Source">installing from source</a>.
- </p><div class="sect1" lang="en"><div class="titlepage"><div><div><h2
class="title" style="clear: both"><a
name="requirements"></a>Requirements</h2></div></div></div><p>
+ </p><div class="sect1" title="Requirements"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="requirements"></a>Requirements</h2></div></div></div><p>
Before downloading and installing Gnash, check that your
hardware and software meet the following requirements.
- </p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3
class="title"><a name="hardware"></a>Hardware
Requirements</h3></div></div></div><p>
+ </p><div class="sect2" title="Hardware Requirements"><div
class="titlepage"><div><div><h3 class="title"><a name="hardware"></a>Hardware
Requirements</h3></div></div></div><p>
One of the goals of Gnash is to make it portable enough to
install on small devices. As a result, the hardware
requirements are minimal. Gnash has even run on an ARM9 at 200
MHz with 32 MB of RAM! (It ran without video support in this
case.) While firm minimums have not been established, Gnash
has been shown to run successfully with the following:
- </p><div class="itemizedlist"><ul type="disc"><li><p>
+ </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li
class="listitem"><p>
336 MHz processor
- </p></li><li><p>
+ </p></li><li class="listitem"><p>
128 MB RAM
- </p></li><li><p>
+ </p></li><li class="listitem"><p>
Gnash will run on anything from a raw frame
buffer up to an OpenGL-supporting graphics card.
</p></li></ul></div><p>
@@ -508,8 +511,8 @@
</td><td align="left">MIPS R10K
</td></tr><tr><td align="left">Darwin (MacOS X)
</td><td align="left">PowerPC and x86-32
- </td></tr><tr><td align="left">Windows XP, Windows Vista</td><td
align="left">x86-32</td></tr></tbody></table></div></div><br
class="table-break"></div><div class="sect2" lang="en"><div
class="titlepage"><div><div><h3 class="title"><a name="software"></a>Software
Requirements</h3></div></div></div><p>
- The 0.8.5 release of Gnash has been designed to run on
+ </td></tr><tr><td align="left">Windows XP, Windows Vista</td><td
align="left">x86-32</td></tr></tbody></table></div></div><br
class="table-break"></div><div class="sect2" title="Software Requirements"><div
class="titlepage"><div><div><h3 class="title"><a name="software"></a>Software
Requirements</h3></div></div></div><p>
+ The 0.8.6 release of Gnash has been designed to run on
UNIX/Linux variants, and has been run on most of the free ones.
However, Gnash has successfully run on Windows, Darwin (Mac OS X),
Irix, Solaris, BeOs, OS/2, and Haiku. Gnash has also run on the
@@ -520,7 +523,7 @@
dependencies may be solved by the package manager. Otherwise, you
must first verify that each of these dependencies are installed on the
target system.
- </p></div></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="downloading"></a>Downloading Gnash</h2></div></div></div><p>
+ </p></div></div><div class="sect1" title="Downloading Gnash"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="downloading"></a>Downloading Gnash</h2></div></div></div><p>
There are two ways to download Gnash: using a package manager or by
downloading the source code and building it on your system. If
possible, it is advisable to use a package manager to download Gnash,
@@ -528,12 +531,12 @@
very latest features, or a Gnash package is not available for your
operating system, it is better to download the source code and build
Gnash locally.
- </p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3
class="title"><a name="gettingsource"></a>Getting the
Source</h3></div></div></div><p>
+ </p><div class="sect2" title="Getting the Source"><div
class="titlepage"><div><div><h3 class="title"><a
name="gettingsource"></a>Getting the Source</h3></div></div></div><p>
Gnash is available as a <a class="link" href="#sourcereleases"
title="Releases">release
tarball</a>, a <a class="link" href="#sourcerepo"
title="Repository">development
checkout</a>, or a <a class="link" href="#sourcesnapshot"
title="Snapshot">development
snapshot</a>.
- </p><div class="sect3" lang="en"><div class="titlepage"><div><div><h4
class="title"><a name="sourcereleases"></a>Releases</h4></div></div></div><p>
+ </p><div class="sect3" title="Releases"><div
class="titlepage"><div><div><h4 class="title"><a
name="sourcereleases"></a>Releases</h4></div></div></div><p>
The source can be acquired from a
<a class="ulink" href="http://www.gnu.org/prep/ftp.html"
target="_top">GNU FTP
Mirror</a>. The release version is intended to be
@@ -545,14 +548,14 @@
</p><p>
To download, select a mirror near you, then choose the
<code class="filename">gnash</code> directory.
- </p></div><div class="sect3" lang="en"><div
class="titlepage"><div><div><h4 class="title"><a
name="sourcesnapshot"></a>Snapshot</h4></div></div></div><p>
+ </p></div><div class="sect3" title="Snapshot"><div
class="titlepage"><div><div><h4 class="title"><a
name="sourcesnapshot"></a>Snapshot</h4></div></div></div><p>
The daily development snapshot can be downloaded from
<a class="ulink" href="http://www.gnashdev.org/dev_snapshots/"
target="_top">http://www.gnashdev.org/dev_snapshots/</a>.
This is the best option if you need changes which were introduced
after the <a class="link" href="#sourcereleases"
title="Releases">last release</a> of
Gnash, but are unable to <a class="link" href="#sourcerepo"
title="Repository">download
directly from the repository.</a>
- </p></div><div class="sect3" lang="en"><div
class="titlepage"><div><div><h4 class="title"><a
name="sourcerepo"></a>Repository</h4></div></div></div><p>
+ </p></div><div class="sect3" title="Repository"><div
class="titlepage"><div><div><h4 class="title"><a
name="sourcerepo"></a>Repository</h4></div></div></div><p>
The latest development sources are available via
anonymous CVS. This is recommended
if you need features or bug fixes which were introduced after
@@ -570,7 +573,7 @@
</pre><p>
It is also possible to browse the repository
<a class="ulink"
href="http://cvs.savannah.gnu.org/viewcvs/gnash/?root=gnash"
target="_top">http://cvs.savannah.gnu.org/viewcvs/gnash/?root=gnash</a> on the
web.
- </p></div></div><div class="sect2" lang="en"><div
class="titlepage"><div><div><h3 class="title"><a name="getcodecs"></a>Getting
Codec Support</h3></div></div></div><p>
+ </p></div></div><div class="sect2" title="Getting Codec Support"><div
class="titlepage"><div><div><h3 class="title"><a name="getcodecs"></a>Getting
Codec Support</h3></div></div></div><p>
Gnash requires codec support to handle audio and video
correctly. Some platforms like Ubuntu or Fedora under the
GNOME desktop will automatically notify the user that the
@@ -581,7 +584,7 @@
likely you need to install the proper codecs. For most
platforms, this is the Gstreamer-ffmpeg plugin, available
from your distributions repository.
- </p></div></div></div><div class="chapter" lang="en"><div
class="titlepage"><div><div><h2 class="title"><a
name="bugreport"></a>Chapter?4.?Reporting Bugs</h2></div></div></div><div
class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a
href="#bugstep_package">Get a Fresh Binary Package</a></span></dt><dt><span
class="sect1"><a href="#bugstep_search">Determine if the bug was previously
reported</a></span></dt><dt><span class="sect1"><a
href="#bugstep_guidelines">Review the bug writing
guidelines</a></span></dt><dt><span class="sect1"><a
href="#bugstep_file">Filing a bug report</a></span></dt></dl></div><p>
+ </p></div></div></div><div class="chapter" title="Chapter?4.?Reporting
Bugs"><div class="titlepage"><div><div><h2 class="title"><a
name="bugreport"></a>Chapter?4.?Reporting Bugs</h2></div></div></div><div
class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a
href="#bugstep_package">Get a Fresh Binary Package</a></span></dt><dt><span
class="sect1"><a href="#bugstep_search">Determine if the bug was previously
reported</a></span></dt><dt><span class="sect1"><a
href="#bugstep_guidelines">Review the bug writing
guidelines</a></span></dt><dt><span class="sect1"><a
href="#bugstep_file">Filing a bug report</a></span></dt></dl></div><p>
The Gnash project relies on the community of Gnash users to test
the player. Feedback is critical to any successful project. Not
only does it let us know that people use Gnash, but it helps us
@@ -594,7 +597,7 @@
be asked to provide this information anyway. Adding
critical details, like the Operating System you are on, its
version, and any relevant error messages from Gnash that you get.
- </p><div class="sect1" lang="en"><div class="titlepage"><div><div><h2
class="title" style="clear: both"><a name="bugstep_package"></a>Get a Fresh
Binary Package</h2></div></div></div><p>
+ </p><div class="sect1" title="Get a Fresh Binary Package"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="bugstep_package"></a>Get a Fresh Binary Package</h2></div></div></div><p>
For starters, it's a good idea to obtain a copy of the latest
snapshot. Although Gnash is primarily released as source, the
Gnash build infrastructure allows the automated building of
@@ -608,7 +611,7 @@
<a class="ulink" href="http://www.getgnash.org/packages/" target="_top">
http://www.getgnash.org/packages
</a>.
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="bugstep_search"></a>Determine if the bug was previously
reported</h2></div></div></div><p>
+ </p></div><div class="sect1" title="Determine if the bug was previously
reported"><div class="titlepage"><div><div><h2 class="title" style="clear:
both"><a name="bugstep_search"></a>Determine if the bug was previously
reported</h2></div></div></div><p>
Search the <a class="ulink"
href="https://savannah.gnu.org/bugs/?group=gnash" target="_top">Gnash
bug tracker</a> to see if the bug has already been identified.
</p><p>
@@ -619,35 +622,35 @@
on Ubuntu GNU/Linux, and you noticed the same problem on OpenBSD,
your stacktrace would be useful. Conversely, adding a "me too"
note to a feature request is not helpful.
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="bugstep_guidelines"></a>Review the bug writing
guidelines</h2></div></div></div><p>
+ </p></div><div class="sect1" title="Review the bug writing
guidelines"><div class="titlepage"><div><div><h2 class="title" style="clear:
both"><a name="bugstep_guidelines"></a>Review the bug writing
guidelines</h2></div></div></div><p>
A good bug report should be precise, explicit, and discrete.
This means that there should be just one bug per ticket, and
that a ticket should contain the following information:
- </p><div class="itemizedlist"><ul type="opencircle"><li
style="list-style-type: circle"><p>
+ </p><div class="itemizedlist"><ul class="itemizedlist"
type="opencircle"><li class="listitem" style="list-style-type: circle"><p>
An overview of the problem;
- </p></li><li style="list-style-type: circle"><p>
+ </p></li><li class="listitem" style="list-style-type: circle"><p>
Instructions on how to replicate the bug;
- </p></li><li style="list-style-type: circle"><p>
+ </p></li><li class="listitem" style="list-style-type: circle"><p>
A description of what happened when you performed the steps
to replicate the bug, and what you expected to happen;
- </p></li><li style="list-style-type: circle"><p>
+ </p></li><li class="listitem" style="list-style-type: circle"><p>
Your system information: operating system name and version, as
well as the versions of major development dependencies;
- </p></li><li style="list-style-type: circle"><p>
+ </p></li><li class="listitem" style="list-style-type: circle"><p>
The release number or checkout timestamp for the version of Gnash
where you observe the problem;
- </p></li><li style="list-style-type: circle"><p>
+ </p></li><li class="listitem" style="list-style-type: circle"><p>
The file <code class="filename">config.log</code>, which should be
attached as a file;
- </p></li><li style="list-style-type: circle"><p>
+ </p></li><li class="listitem" style="list-style-type: circle"><p>
A descriptive title.
</p></li></ul></div><p>
Include any additional information that you feel might be useful
to the developers.
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="bugstep_file"></a>Filing a bug report</h2></div></div></div><p>
+ </p></div><div class="sect1" title="Filing a bug report"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="bugstep_file"></a>Filing a bug report</h2></div></div></div><p>
After following the steps described above, you can file a bug report at
<a class="ulink" href="https://savannah.gnu.org/bugs/?group=gnash"
target="_top">https://savannah.gnu.org/bugs/?group=gnash</a>.
- </p></div></div><div class="glossary"><div class="titlepage"><div><div><h2
class="title"><a name="glossary"></a>Glossary</h2></div></div></div><div
class="glossdiv"><h3 class="title">A</h3><dl><dt>
+ </p></div></div><div class="glossary" title="Glossary"><div
class="titlepage"><div><div><h2 class="title"><a
name="glossary"></a>Glossary</h2></div></div></div><div class="glossdiv"
title="A"><h3 class="title">A</h3><dl><dt>
ActionScript
</dt><dd><p>
<span class="emphasis"><em>ActionScript</em></span>, or "AS", is the
scripting
@@ -675,7 +678,7 @@
characters and values which are in the immediate environment
of the current fn_call. Please refer to the Gnash
ActionScript manual for more information.
- </p></dd></dl></div><div class="glossdiv"><h3
class="title">C</h3><dl><dt>
+ </p></dd></dl></div><div class="glossdiv" title="C"><h3
class="title">C</h3><dl><dt>
Cairo
</dt><dd><p>
Cairo is a 2D graphics library with support for multiple
@@ -683,7 +686,7 @@
feature of Cairo is that it will automatically use graphic
card acceleration when available. Cairo has an experimental
OpenGL backend.
- </p></dd></dl></div><div class="glossdiv"><h3
class="title">D</h3><dl><dt>
+ </p></dd></dl></div><div class="glossdiv" title="D"><h3
class="title">D</h3><dl><dt>
DejaGNU
</dt><dd><p>
DejaGNU is a framework for testing software.
@@ -704,7 +707,7 @@
Drupal
</dt><dd><p>
Drupal is a CMS/blog system used for the main Gnash website.
- </p></dd></dl></div><div class="glossdiv"><h3
class="title">E</h3><dl><dt>
+ </p></dd></dl></div><div class="glossdiv" title="E"><h3
class="title">E</h3><dl><dt>
extensions
</dt><dd><p>
A <span class="application">Gnash</span> <span
class="emphasis"><em>extension</em></span> is a plugin (not a
@@ -712,10 +715,10 @@
beyond what is covered by the <span
class="emphasis"><em>SWF</em></span>
specification. These are shared libraries which are loaded
at runtime.
- </p></dd></dl></div><div class="glossdiv"><h3
class="title">F</h3><dl><dt>
- ffmpeg
+ </p></dd></dl></div><div class="glossdiv" title="F"><h3
class="title">F</h3><dl><dt>
+ FFmpeg
</dt><dd><p>
- ffmpeg is an audio and video decoding library which can be
+ FFmpeg is an audio and video decoding library which can be
used by Gnash to decode mp3, FLV and other media types.
</p></dd><dt>
Flash
@@ -743,7 +746,7 @@
Linux Frame Buffer and so does not need a window system to
run. This makes it particularly suitable for use on small
devices.
- </p></dd></dl></div><div class="glossdiv"><h3
class="title">G</h3><dl><dt>
+ </p></dd></dl></div><div class="glossdiv" title="G"><h3
class="title">G</h3><dl><dt>
Gnash
</dt><dd><p>
Gnash is the GNU Flash movie player.
@@ -774,7 +777,7 @@
menus, windowing (where available) and a drawing area.
You must choose a GUI library during the
configuration stage of building Gnash.
- </p></dd></dl></div><div class="glossdiv"><h3
class="title">K</h3><dl><dt>
+ </p></dd></dl></div><div class="glossdiv" title="K"><h3
class="title">K</h3><dl><dt>
kde-gnash
</dt><dd><p>
<span class="emphasis"><em>kde-gnash</em></span> is the name given to
the stand-alone
@@ -786,7 +789,7 @@
</dt><dd><p>
<span class="emphasis"><em>Kparts</em></span> is a plugin for
Konqueror which is
enabled with the configuration option --enable-kparts.
- </p></dd></dl></div><div class="glossdiv"><h3
class="title">M</h3><dl><dt>
+ </p></dd></dl></div><div class="glossdiv" title="M"><h3
class="title">M</h3><dl><dt>
Mesa
</dt><dd><p>
<span class="emphasis"><em>Mesa</em></span> is the free software
OpenGL
@@ -798,13 +801,13 @@
Ming is a C library for generating <span
class="emphasis"><em>SWF</em></span> format
movies, plus a set of wrappers for using the library. It is
used by the Gnash project for generating testcases.
- </p></dd></dl></div><div class="glossdiv"><h3
class="title">N</h3><dl><dt>
+ </p></dd></dl></div><div class="glossdiv" title="N"><h3
class="title">N</h3><dl><dt>
Nellymoser
</dt><dd><p>
Nellymoser is a proprietary audio codec introduced in the
Flash Player in version 6. For more information, please see
Wikipedia.
- </p></dd></dl></div><div class="glossdiv"><h3
class="title">O</h3><dl><dt>
+ </p></dd></dl></div><div class="glossdiv" title="O"><h3
class="title">O</h3><dl><dt>
OpenGL
</dt><dd><p>
OpenGL (Open Graphics Library) is a standard specification
@@ -819,7 +822,7 @@
ORM
</dt><dd><p>
ORM is a system for ensuring the rights of the creator over a piece
of digital content. It is more passive than DRM.
- </p></dd></dl></div><div class="glossdiv"><h3
class="title">P</h3><dl><dt>
+ </p></dd></dl></div><div class="glossdiv" title="P"><h3
class="title">P</h3><dl><dt>
plugin
</dt><dd><p>
The glossterm <span class="emphasis"><em>plugin</em></span> is used
in <span class="application">Gnash</span> to
@@ -828,13 +831,13 @@
<span class="emphasis"><em>Kpart</em></span>. Sometimes, the term is
used in
an even more generic sense to refer to
<span class="emphasis"><em>extensions</em></span>.
- </p></dd></dl></div><div class="glossdiv"><h3
class="title">Q</h3><dl><dt>
+ </p></dd></dl></div><div class="glossdiv" title="Q"><h3
class="title">Q</h3><dl><dt>
Qt
</dt><dd><p>
Qt is a GUI library which is used by KDE. The plugin version
of Gnash using this GUI library is Kpart. The standalone
version is enabled with --enable-gui=kde.
- </p></dd></dl></div><div class="glossdiv"><h3
class="title">R</h3><dl><dt>
+ </p></dd></dl></div><div class="glossdiv" title="R"><h3
class="title">R</h3><dl><dt>
renderer
</dt><dd><p>
The <span class="emphasis"><em>renderer</em></span> is the subsystem
of <span class="application">Gnash</span>
@@ -867,7 +870,7 @@
</dt><dd><p>
RTMPTS is the same as RTMPT, but instead of being a HTTP
wrapper, it is a HTTP SSL wrapper (HTTP secure connection).
- </p></dd></dl></div><div class="glossdiv"><h3
class="title">S</h3><dl><dt>
+ </p></dd></dl></div><div class="glossdiv" title="S"><h3
class="title">S</h3><dl><dt>
SDL
</dt><dd><p>
Simple DirectMedia Layer is a cross-platform multimedia free
@@ -877,7 +880,7 @@
are independent of each other: you can use it for a task and
not for the other if you wish. This version of Gnash does not
implement menus in the SDL GUI; the SDL sound handler is the
- most feature rich, supporting video through ffmpeg.
+ most feature rich, supporting video through FFmpeg.
</p></dd><dt>
sound handler
</dt><dd><p>
@@ -888,7 +891,7 @@
configuration of Gnash when compiling.
</p><p>
There are currently two sound handlers available in <span
class="application">Gnash</span>:
- ffmpeg and Gstreamer. The ffmpeg sound handler uses SDL for
+ FFmpeg and Gstreamer. The ffmpeg sound handler uses SDL for
mixing.
The Gstreamer-sound handler uses the available
plugins to decode the audio, so it might not work if some
@@ -910,7 +913,7 @@
</dt><dd><p>
<span class="emphasis"><em>SWF</em></span> is the generic name for
<span class="emphasis"><em>Flash</em></span> movies.
- </p></dd></dl></div><div class="glossdiv"><h3
class="title">T</h3><dl><dt>
+ </p></dd></dl></div><div class="glossdiv" title="T"><h3
class="title">T</h3><dl><dt>
Tamarin
</dt><dd><p>
The Tamarin project seeks to create an open source
@@ -927,12 +930,12 @@
independently controlled (STOP or PLAY). At regular intervals
(FPS) the player advances all timelines in PLAY mode to the
next frame, looping back when last frame is reached.
- </p></dd></dl></div><div class="glossdiv"><h3
class="title">X</h3><dl><dt>
+ </p></dd></dl></div><div class="glossdiv" title="X"><h3
class="title">X</h3><dl><dt>
X.org
</dt><dd><p>
X.org is the most commonly used X server; it was forked from
XFree86.
- </p></dd></dl></div></div><div class="chapter" lang="en"><div
class="titlepage"><div><div><h2 class="title"><a
name="authors"></a>Chapter?5.?Authors</h2></div></div></div><p>
+ </p></dd></dl></div></div><div class="chapter"
title="Chapter?5.?Authors"><div class="titlepage"><div><div><h2
class="title"><a name="authors"></a>Chapter?5.?Authors</h2></div></div></div><p>
<span class="application">Gnash</span> is maintained by Rob Savoye.
Other active developers
are: Sandro Santilli, Bastiaan Jacques, Udo Giacomozzi, Chad
Musick, Benjamin Wolsey, Zou Lunkai, and Russ Nelson. Please
@@ -947,15 +950,15 @@
Mike Shaver, Thierry Berger-Perrin,
Ignacio Casta?o, Willem Kokke, Vitaly Alexeev, Alexander Streit,
and Rob Savoye.
- </p></div><div class="appendix" lang="en"><div
class="titlepage"><div><div><h2 class="title"><a name="fdl"></a>Appendix?A.?GNU
Free Documentation License</h2></div><div><p class="releaseinfo">
+ </p></div><div class="appendix" title="Appendix?A.?GNU Free Documentation
License"><div class="titlepage"><div><div><h2 class="title"><a
name="fdl"></a>Appendix?A.?GNU Free Documentation License</h2></div><div><p
class="releaseinfo">
Version 1.1, March 2000
- </p></div><div><p class="copyright">Copyright ? 2000 Free Software
Foundation, Inc.</p></div><div><div class="legalnotice"><a
name="fdl-legalnotice"></a><p>
+ </p></div><div><p class="copyright">Copyright ? 2000 Free Software
Foundation, Inc.</p></div><div><div class="legalnotice" title="Legal Notice"><a
name="fdl-legalnotice"></a><p>
</p><div class="address"><p>Free?Software?Foundation,?Inc.?<span
class="street">59?Temple?Place,?<br>
????????Suite?330</span>,?<span class="city">Boston</span>,?<span
class="state">MA</span>??<br>
????????<span class="postcode">02111-1307</span>??<span
class="country">USA</span></p></div><p>
Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.
- </p></div></div></div></div><div class="toc"><p><b>Table of
Contents</b></p><dl><dt><span class="sect1"><a href="#fdl-preamble">0.
PREAMBLE</a></span></dt><dt><span class="sect1"><a href="#fdl-section1">1.
APPLICABILITY AND DEFINITIONS</a></span></dt><dt><span class="sect1"><a
href="#fdl-section2">2. VERBATIM COPYING</a></span></dt><dt><span
class="sect1"><a href="#fdl-section3">3. COPYING IN
QUANTITY</a></span></dt><dt><span class="sect1"><a href="#fdl-section4">4.
MODIFICATIONS</a></span></dt><dt><span class="sect1"><a href="#fdl-section5">5.
COMBINING DOCUMENTS</a></span></dt><dt><span class="sect1"><a
href="#fdl-section6">6. COLLECTIONS OF DOCUMENTS</a></span></dt><dt><span
class="sect1"><a href="#fdl-section7">7. AGGREGATION WITH INDEPENDENT
WORKS</a></span></dt><dt><span class="sect1"><a href="#fdl-section8">8.
TRANSLATION</a></span></dt><dt><span class="sect1"><a href="#fdl-section9">9.
TERMINATION</a></span></dt><dt><span class="sect1"><a href="#fdl-section10">10.
FUTURE REVISIONS OF THIS LICENSE</a></span></dt><dt><span class="sect1"><a
href="#fdl-using">Addendum</a></span></dt></dl></div><div class="sect1"
lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear:
both"><a name="fdl-preamble"></a>0. PREAMBLE</h2></div></div></div><p>
+ </p></div></div></div></div><div class="toc"><p><b>Table of
Contents</b></p><dl><dt><span class="sect1"><a href="#fdl-preamble">0.
PREAMBLE</a></span></dt><dt><span class="sect1"><a href="#fdl-section1">1.
APPLICABILITY AND DEFINITIONS</a></span></dt><dt><span class="sect1"><a
href="#fdl-section2">2. VERBATIM COPYING</a></span></dt><dt><span
class="sect1"><a href="#fdl-section3">3. COPYING IN
QUANTITY</a></span></dt><dt><span class="sect1"><a href="#fdl-section4">4.
MODIFICATIONS</a></span></dt><dt><span class="sect1"><a href="#fdl-section5">5.
COMBINING DOCUMENTS</a></span></dt><dt><span class="sect1"><a
href="#fdl-section6">6. COLLECTIONS OF DOCUMENTS</a></span></dt><dt><span
class="sect1"><a href="#fdl-section7">7. AGGREGATION WITH INDEPENDENT
WORKS</a></span></dt><dt><span class="sect1"><a href="#fdl-section8">8.
TRANSLATION</a></span></dt><dt><span class="sect1"><a href="#fdl-section9">9.
TERMINATION</a></span></dt><dt><span class="sect1"><a href="#fdl-section10">10.
FUTURE REVISIONS OF THIS LICENSE</a></span></dt><dt><span class="sect1"><a
href="#fdl-using">Addendum</a></span></dt></dl></div><div class="sect1"
title="0. PREAMBLE"><div class="titlepage"><div><div><h2 class="title"
style="clear: both"><a name="fdl-preamble"></a>0.
PREAMBLE</h2></div></div></div><p>
The purpose of this License is to make a manual, textbook, or
other written document "free" in the sense of
freedom: to assure everyone the effective freedom to copy and
@@ -978,7 +981,7 @@
regardless of subject matter or whether it is published as a
printed book. We recommend this License principally for works
whose purpose is instruction or reference.
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-section1"></a>1. APPLICABILITY AND
DEFINITIONS</h2></div></div></div><p><a name="fdl-document"></a>
+ </p></div><div class="sect1" title="1. APPLICABILITY AND DEFINITIONS"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-section1"></a>1. APPLICABILITY AND
DEFINITIONS</h2></div></div></div><p><a name="fdl-document"></a>
This License applies to any manual or other work that contains a
notice placed by the copyright holder saying it can be
distributed under the terms of this License. The
@@ -1044,7 +1047,7 @@
page as such, "Title Page" means the text near the
most prominent appearance of the work's title, preceding the
beginning of the body of the text.
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-section2"></a>2. VERBATIM COPYING</h2></div></div></div><p>
+ </p></div><div class="sect1" title="2. VERBATIM COPYING"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-section2"></a>2. VERBATIM COPYING</h2></div></div></div><p>
You may copy and distribute the <a class="link"
href="#fdl-document">Document</a> in any medium, either
commercially or noncommercially, provided that this License, the
copyright notices, and the license notice saying this License
@@ -1058,7 +1061,7 @@
</p><p>
You may also lend copies, under the same conditions stated
above, and you may publicly display copies.
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-section3"></a>3. COPYING IN QUANTITY</h2></div></div></div><p>
+ </p></div><div class="sect1" title="3. COPYING IN QUANTITY"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-section3"></a>3. COPYING IN QUANTITY</h2></div></div></div><p>
If you publish printed copies of the <a class="link"
href="#fdl-document">Document</a> numbering more than 100,
and the Document's license notice requires <a class="link"
href="#fdl-cover-texts">Cover Texts</a>, you must enclose
the copies in covers that carry, clearly and legibly, all these
@@ -1097,7 +1100,7 @@
of the <a class="link" href="#fdl-document">Document</a> well before
redistributing any large number of copies, to give them a chance
to provide you with an updated version of the Document.
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-section4"></a>4. MODIFICATIONS</h2></div></div></div><p>
+ </p></div><div class="sect1" title="4. MODIFICATIONS"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-section4"></a>4. MODIFICATIONS</h2></div></div></div><p>
You may copy and distribute a <a class="link"
href="#fdl-modified">Modified Version</a> of the <a class="link"
href="#fdl-document">Document</a> under the conditions of
sections <a class="link" href="#fdl-section2" title="2. VERBATIM
COPYING">2</a> and <a class="link" href="#fdl-section3" title="3. COPYING IN
QUANTITY">3</a> above, provided that you release
the Modified Version under precisely this License, with the
@@ -1105,7 +1108,7 @@
licensing distribution and modification of the Modified Version
to whoever possesses a copy of it. In addition, you must do
these things in the Modified Version:
- </p><div class="itemizedlist"><ul type="opencircle"><li
style="list-style-type: circle"><p><b>A.?</b>
+ </p><div class="itemizedlist"><ul class="itemizedlist"
type="opencircle"><li class="listitem" style="list-style-type: circle"><p
title="A"><b>A.?</b>
Use in the <a class="link" href="#fdl-title-page">Title
Page</a> (and on the covers, if any) a title distinct
from that of the <a class="link" href="#fdl-document">Document</a>,
and from those of
@@ -1113,7 +1116,7 @@
listed in the History section of the Document). You may
use the same title as a previous version if the original
publisher of that version gives permission.
- </p></li><li style="list-style-type: circle"><p><b>B.?</b>
+ </p></li><li class="listitem" style="list-style-type: circle"><p
title="B"><b>B.?</b>
List on the <a class="link" href="#fdl-title-page">Title
Page</a>, as authors, one or more persons or entities
responsible for authorship of the modifications in the
@@ -1121,28 +1124,28 @@
together with at least five of the principal authors of
the <a class="link" href="#fdl-document">Document</a> (all of
its principal authors, if it has less than five).
- </p></li><li style="list-style-type: circle"><p><b>C.?</b>
+ </p></li><li class="listitem" style="list-style-type: circle"><p
title="C"><b>C.?</b>
State on the <a class="link" href="#fdl-title-page">Title
Page</a> the name of the publisher of the <a class="link"
href="#fdl-modified">Modified Version</a>, as the
publisher.
- </p></li><li style="list-style-type: circle"><p><b>D.?</b>
+ </p></li><li class="listitem" style="list-style-type: circle"><p
title="D"><b>D.?</b>
Preserve all the copyright notices of the <a class="link"
href="#fdl-document">Document</a>.
- </p></li><li style="list-style-type: circle"><p><b>E.?</b>
+ </p></li><li class="listitem" style="list-style-type: circle"><p
title="E"><b>E.?</b>
Add an appropriate copyright notice for your modifications
adjacent to the other copyright notices.
- </p></li><li style="list-style-type: circle"><p><b>F.?</b>
+ </p></li><li class="listitem" style="list-style-type: circle"><p
title="F"><b>F.?</b>
Include, immediately after the copyright notices, a
license notice giving the public permission to use the
<a class="link" href="#fdl-modified">Modified Version</a> under
the terms of this License, in the form shown in the
Addendum below.
- </p></li><li style="list-style-type: circle"><p><b>G.?</b>
+ </p></li><li class="listitem" style="list-style-type: circle"><p
title="G"><b>G.?</b>
Preserve in that license notice the full lists of <a class="link"
href="#fdl-invariant"> Invariant Sections</a> and
required <a class="link" href="#fdl-cover-texts">Cover
Texts</a> given in the <a class="link"
href="#fdl-document">Document's</a> license notice.
- </p></li><li style="list-style-type: circle"><p><b>H.?</b>
+ </p></li><li class="listitem" style="list-style-type: circle"><p
title="H"><b>H.?</b>
Include an unaltered copy of this License.
- </p></li><li style="list-style-type: circle"><p><b>I.?</b>
+ </p></li><li class="listitem" style="list-style-type: circle"><p
title="I"><b>I.?</b>
Preserve the section entitled "History", and
its title, and add to it an item stating at least the
title, year, new authors, and publisher of the <a class="link"
href="#fdl-modified">Modified Version </a>as given on
@@ -1153,7 +1156,7 @@
Document as given on its Title Page, then add an item
describing the Modified Version as stated in the previous
sentence.
- </p></li><li style="list-style-type: circle"><p><b>J.?</b>
+ </p></li><li class="listitem" style="list-style-type: circle"><p
title="J"><b>J.?</b>
Preserve the network location, if any, given in the <a class="link"
href="#fdl-document">Document</a> for public access
to a <a class="link" href="#fdl-transparent">Transparent</a>
copy of the Document, and likewise the network locations
@@ -1163,23 +1166,23 @@
was published at least four years before the Document
itself, or if the original publisher of the version it
refers to gives permission.
- </p></li><li style="list-style-type: circle"><p><b>K.?</b>
+ </p></li><li class="listitem" style="list-style-type: circle"><p
title="K"><b>K.?</b>
In any section entitled "Acknowledgements" or
"Dedications", preserve the section's title,
and preserve in the section all the substance and tone of
each of the contributor acknowledgements and/or
dedications given therein.
- </p></li><li style="list-style-type: circle"><p><b>L.?</b>
+ </p></li><li class="listitem" style="list-style-type: circle"><p
title="L"><b>L.?</b>
Preserve all the <a class="link" href="#fdl-invariant">Invariant
Sections</a> of the <a class="link"
href="#fdl-document">Document</a>, unaltered in their
text and in their titles. Section numbers or the
equivalent are not considered part of the section titles.
- </p></li><li style="list-style-type: circle"><p><b>M.?</b>
+ </p></li><li class="listitem" style="list-style-type: circle"><p
title="M"><b>M.?</b>
Delete any section entitled
"Endorsements". Such a section may not be
included in the <a class="link" href="#fdl-modified">Modified
Version</a>.
- </p></li><li style="list-style-type: circle"><p><b>N.?</b>
+ </p></li><li class="listitem" style="list-style-type: circle"><p
title="N"><b>N.?</b>
Do not retitle any existing section as
"Endorsements" or to conflict in title with
any <a class="link" href="#fdl-invariant">Invariant
@@ -1216,7 +1219,7 @@
The author(s) and publisher(s) of the <a class="link"
href="#fdl-document">Document</a> do not by this License
give permission to use their names for publicity for or to
assert or imply endorsement of any <a class="link"
href="#fdl-modified">Modified Version </a>.
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-section5"></a>5. COMBINING DOCUMENTS</h2></div></div></div><p>
+ </p></div><div class="sect1" title="5. COMBINING DOCUMENTS"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-section5"></a>5. COMBINING DOCUMENTS</h2></div></div></div><p>
You may combine the <a class="link" href="#fdl-document">Document</a>
with other documents released under this License, under the
terms defined in <a class="link" href="#fdl-section4" title="4.
MODIFICATIONS">section 4</a>
@@ -1243,7 +1246,7 @@
combine any sections entitled "Acknowledgements",
and any sections entitled "Dedications". You must
delete all sections entitled "Endorsements."
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-section6"></a>6. COLLECTIONS OF DOCUMENTS</h2></div></div></div><p>
+ </p></div><div class="sect1" title="6. COLLECTIONS OF DOCUMENTS"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-section6"></a>6. COLLECTIONS OF DOCUMENTS</h2></div></div></div><p>
You may make a collection consisting of the <a class="link"
href="#fdl-document">Document</a> and other documents
released under this License, and replace the individual copies
of this License in the various documents with a single copy that
@@ -1256,7 +1259,7 @@
insert a copy of this License into the extracted document, and
follow this License in all other respects regarding verbatim
copying of that document.
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-section7"></a>7. AGGREGATION WITH INDEPENDENT
WORKS</h2></div></div></div><p>
+ </p></div><div class="sect1" title="7. AGGREGATION WITH INDEPENDENT
WORKS"><div class="titlepage"><div><div><h2 class="title" style="clear:
both"><a name="fdl-section7"></a>7. AGGREGATION WITH INDEPENDENT
WORKS</h2></div></div></div><p>
A compilation of the <a class="link" href="#fdl-document">Document</a>
or its derivatives with
other separate and independent documents or works, in or on a
volume of a storage or distribution medium, does not as a whole
@@ -1272,7 +1275,7 @@
be placed on covers that surround only the Document within the
aggregate. Otherwise they must appear on covers around the whole
aggregate.
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-section8"></a>8. TRANSLATION</h2></div></div></div><p>
+ </p></div><div class="sect1" title="8. TRANSLATION"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-section8"></a>8. TRANSLATION</h2></div></div></div><p>
Translation is considered a kind of modification, so you may
distribute translations of the <a class="link"
href="#fdl-document">Document</a> under the terms of <a class="link"
href="#fdl-section4" title="4. MODIFICATIONS">section 4</a>. Replacing <a
class="link" href="#fdl-invariant"> Invariant Sections</a> with
translations requires special permission from their copyright
@@ -1283,7 +1286,7 @@
version of this License. In case of a disagreement between the
translation and the original English version of this License,
the original English version will prevail.
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-section9"></a>9. TERMINATION</h2></div></div></div><p>
+ </p></div><div class="sect1" title="9. TERMINATION"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-section9"></a>9. TERMINATION</h2></div></div></div><p>
You may not copy, modify, sublicense, or distribute the <a class="link"
href="#fdl-document">Document</a> except as expressly
provided for under this License. Any other attempt to copy,
modify, sublicense or distribute the Document is void, and will
@@ -1291,7 +1294,7 @@
parties who have received copies, or rights, from you under this
License will not have their licenses terminated so long as such
parties remain in full compliance.
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-section10"></a>10. FUTURE REVISIONS OF THIS
LICENSE</h2></div></div></div><p>
+ </p></div><div class="sect1" title="10. FUTURE REVISIONS OF THIS
LICENSE"><div class="titlepage"><div><div><h2 class="title" style="clear:
both"><a name="fdl-section10"></a>10. FUTURE REVISIONS OF THIS
LICENSE</h2></div></div></div><p>
The <a class="ulink" href="http://www.gnu.org/fsf/fsf.html"
target="_top">Free Software
Foundation</a> may publish new, revised versions of the GNU
Free Documentation License from time to time. Such new versions
@@ -1308,7 +1311,7 @@
the Document does not specify a version number of this License,
you may choose any version ever published (not as a draft) by
the Free Software Foundation.
- </p></div><div class="sect1" lang="en"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-using"></a>Addendum</h2></div></div></div><p>
+ </p></div><div class="sect1" title="Addendum"><div
class="titlepage"><div><div><h2 class="title" style="clear: both"><a
name="fdl-using"></a>Addendum</h2></div></div></div><p>
To use this License in a document you have written, include a copy of
the License in the document and put the following copyright and
license notices just after the title page:
=== modified file 'doc/C/preformatted/gprocessor.1.in'
--- a/doc/C/preformatted/gprocessor.1.in 2009-09-24 16:32:22 +0000
+++ b/doc/C/preformatted/gprocessor.1.in 2010-01-01 20:41:28 +0000
@@ -5,7 +5,7 @@
\\$2 \(la\\$1\(ra\\$3
..
.if \n(.g .mso www.tmac
-.TH gprocessor 1 "12 September 2009" "" ""
+.TH gprocessor 1 "20 December 2009" "" ""
.SH NAME
gprocessor \- Gnash SWF Processor
.SH Synopsis
=== modified file 'doc/C/preformatted/rtmpget.1.in'
--- a/doc/C/preformatted/rtmpget.1.in 2009-11-16 12:57:54 +0000
+++ b/doc/C/preformatted/rtmpget.1.in 2010-01-01 20:41:28 +0000
@@ -5,7 +5,7 @@
\\$2 \(la\\$1\(ra\\$3
..
.if \n(.g .mso www.tmac
-.TH rtmpget 1 "16 November 2009" "" ""
+.TH rtmpget 1 "20 December 2009" "" ""
.SH NAME
rtmpget \- Gnash Utility For Fetching RTMP-data
.SH Synopsis
=== modified file 'doc/C/preformatted/soldumper.1.in'
--- a/doc/C/preformatted/soldumper.1.in 2008-06-23 04:34:05 +0000
+++ b/doc/C/preformatted/soldumper.1.in 2010-01-01 20:41:28 +0000
@@ -1,11 +1,11 @@
-'\" -*- coding: us-ascii -*-
+.\" -*- coding: us-ascii -*-
.if \n(.g .ds T< \\FC
.if \n(.g .ds T> \\F[\n[.fam]]
.de URL
\\$2 \(la\\$1\(ra\\$3
..
.if \n(.g .mso www.tmac
-.TH soldumper 1 "20 June 2008" "" ""
+.TH soldumper 1 "20 December 2009" "" ""
.SH NAME
soldumper \- Gnash Local Shared Object (LSO) File Dumper
.SH Synopsis
@@ -17,12 +17,12 @@
Dump information about the .sol files used by the SharedObject
ActionScript class.
.PP
-When a Flash player, including the Gnash player, plays a Flash "movie",
+When a SWF player, including Gnash, plays a SWF "movie",
the movie can contain
scripts. These scripts can call ActionScript classes. One such class
is SharedObject. SharedObject creates shared objects, which end up
-stored in your computer's file system. For example, a Flash game might
-store its score file in a SharedObject; or a privacy-invading Flash
+stored in your computer's file system. For example, a SWF game might
+store its score file in a SharedObject; or a privacy-invading SWF
movie might store "cookies" in a SharedObject. Before soldumper was
written, these bits of stored information were hard for users to
notice or investigate.
=== modified file 'doc/C/usermanual/gnashrc.xml'
--- a/doc/C/usermanual/gnashrc.xml 2009-08-07 20:51:26 +0000
+++ b/doc/C/usermanual/gnashrc.xml 2010-01-01 20:41:28 +0000
@@ -170,19 +170,21 @@
</entry>
</row>
- <entry>webcamDevice</entry>
+ <row>
+ <entry>webcamDevice</entry>
<entry>integer</entry>
<entry>The integer value (index into vector of video devices) that
represents the default webcam.
To easily get this entry run utilities/findwebcams (only works with
Gstreamer right now)</entry>
- </row>
+ </row>
- <entry>microphoneDevice</entry>
- <entry>integer</entry>
- <entry>The integer value (index into vector of microphone devices)
that represents the default microphone.
+ <row>
+ <entry>microphoneDevice</entry>
+ <entry>integer</entry>
+ <entry>The integer value (index into vector of microphone devices) that
represents the default microphone.
To easily get this entry run utilities/findmicrophones (only works with
Gstreamer right now)</entry>
- </row>
+ </row>
- <row>
+ <row>
<entry>flashVersionString</entry>
<entry>string</entry>
<entry>Set the string returned by $version and
System.capabilities.version.
=== modified file 'libamf/amf.cpp'
--- a/libamf/amf.cpp 2010-01-01 17:48:26 +0000
+++ b/libamf/amf.cpp 2010-01-01 20:41:28 +0000
@@ -182,11 +182,14 @@
// GNASH_REPORT_FUNCTION;
boost::uint32_t length;
length = data.propertySize();
- // log_debug("Encoded data size has %d properties", length);
+ log_debug("Encoded data size has %d properties", length);
boost::shared_ptr<amf::Buffer> buf;
if (length) {
buf.reset(new amf::Buffer);
+ } else {
+ return buf;
}
+
*buf = Element::OBJECT_AMF0;
if (data.propertySize() > 0) {
vector<boost::shared_ptr<amf::Element> >::const_iterator ait;
@@ -1242,7 +1245,7 @@
length = tooFar - tmpptr;
}
#else
- if (length > SANE_STR_SIZE) {
+ if (length >= SANE_STR_SIZE) {
log_error("%d bytes for a string is over the safe limit of %d. Putting
the rest of the buffer into the string, line %d", length, SANE_STR_SIZE,
__LINE__);
}
#endif
=== modified file 'libamf/amf.h'
--- a/libamf/amf.h 2010-01-01 17:48:26 +0000
+++ b/libamf/amf.h 2010-01-01 20:41:28 +0000
@@ -70,7 +70,7 @@
/// for the following value is bogus. Although the length field is a short, it
/// seems silly to assume we'll ever see a string 65,000 characters long.
Still,
/// it makes sense to make this an adjustable thing.
-const int SANE_STR_SIZE = 65535;
+const boost::uint16_t SANE_STR_SIZE = 65535;
/// Binary representation of an ActionScript object.
//
=== modified file 'libamf/buffer.cpp'
--- a/libamf/buffer.cpp 2010-01-01 17:48:26 +0000
+++ b/libamf/buffer.cpp 2010-01-01 20:41:28 +0000
@@ -200,15 +200,16 @@
Buffer::copy(boost::uint8_t *data, size_t nbytes)
{
// GNASH_REPORT_FUNCTION;
- _seekptr =_data.get();
if (_data) {
- std::copy(data, data + nbytes, _data.get());
- _seekptr = _data.get() + nbytes;
- } else {
- boost::format msg("Not enough storage was allocated to hold the "
- "copied data! Needs %1%, only has %2% bytes");
- msg % nbytes % _nbytes;
+ if (_nbytes >= nbytes) {
+ std::copy(data, data + nbytes, _data.get());
+ _seekptr = _data.get() + nbytes;
+ } else {
+ boost::format msg("Not enough storage was allocated to hold the "
+ "copied data! Needs %1%, only has %2% bytes");
+ msg % nbytes % _nbytes;
throw GnashException(msg.str());
+ }
}
return *this;
}
@@ -230,9 +231,9 @@
std::copy(data, data + nbytes, _seekptr);
_seekptr += nbytes;
} else {
- boost::format msg("Not enough storage was allocated to hold the "
- "appended data! Needs %1%, only has %2% bytes");
- msg % nbytes % _nbytes;
+ boost::format msg("Not enough storage was allocated to hold the "
+ "appended data! Needs %1%, only has %2% bytes");
+ msg % nbytes % spaceLeft();
throw GnashException(msg.str());
}
}
=== modified file 'libamf/flv.cpp'
--- a/libamf/flv.cpp 2010-01-01 17:48:26 +0000
+++ b/libamf/flv.cpp 2010-01-01 20:41:28 +0000
@@ -85,11 +85,11 @@
// Decode a Buffer into a header
boost::shared_ptr<Flv::flv_header_t>
-Flv::decodeHeader(boost::shared_ptr<amf::Buffer> buf)
+Flv::decodeHeader(boost::uint8_t *data)
{
// GNASH_REPORT_FUNCTION;
boost::shared_ptr<flv_header_t> header(new flv_header_t);
- memcpy(header.get(), buf->reference(), sizeof(flv_header_t));
+ memcpy(header.get(), data, sizeof(flv_header_t));
// std::copy(buf->begin(), buf->begin() + sizeof(flv_header_t),
header.get());
// test the magic number
@@ -164,13 +164,13 @@
ptr += length;
// Extract the properties for this metadata object.
- boost::shared_ptr<amf::Element> el = amf.extractAMF(ptr, tooFar);
- if (el.get()) {
- ptr += amf.totalsize();
- el->setName(name.c_str(), length);
+ _metadata = amf.extractAMF(ptr, tooFar);
+ if (_metadata.get()) {
+ ptr += amf.totalsize();
+ _metadata->setName(name.c_str(), length);
}
- return el;
+ return _metadata;
}
boost::shared_ptr<Flv::flv_audio_t>
@@ -292,10 +292,10 @@
// Decode the tag header
boost::shared_ptr<Flv::flv_tag_t>
-Flv::decodeTagHeader(boost::shared_ptr<amf::Buffer> &buf)
+Flv::decodeTagHeader(boost::uint8_t *buf)
{
// GNASH_REPORT_FUNCTION;
- flv_tag_t *data = reinterpret_cast<flv_tag_t *>(buf->reference());
+ flv_tag_t *data = reinterpret_cast<flv_tag_t *>(buf);
boost::shared_ptr<flv_tag_t> tag(new flv_tag_t);
memcpy(tag.get(), data, sizeof(flv_tag_t));
=== modified file 'libamf/flv.h'
--- a/libamf/flv.h 2010-01-01 17:48:26 +0000
+++ b/libamf/flv.h 2010-01-01 20:41:28 +0000
@@ -26,6 +26,7 @@
//#include "buffer.h"
#include "element.h"
+#include "buffer.h"
#include "dsodefs.h" // DSOEXPORT
/// \namespace amf
@@ -172,7 +173,8 @@
/// @param buf a smart pointer to a Buffer containing the data.
///
/// @return a smart pointer to data structure that contains the data.
- boost::shared_ptr<flv_header_t>
decodeHeader(boost::shared_ptr<amf::Buffer> buf);
+ boost::shared_ptr<flv_header_t>
decodeHeader(boost::shared_ptr<amf::Buffer> buf) { return
decodeHeader(buf->reference()); };
+ boost::shared_ptr<flv_header_t> decodeHeader(boost::uint8_t *data);
/// \brief Decode a MetaData object.
/// This is after the header, but before all the other tags
usually
@@ -211,7 +213,8 @@
/// @param flags The data to deserialize.
///
/// @return a smart pointer to an video data structure that contains the
data.
- boost::shared_ptr<flv_tag_t>
decodeTagHeader(boost::shared_ptr<amf::Buffer> &buf);
+ boost::shared_ptr<flv_tag_t>
decodeTagHeader(boost::shared_ptr<amf::Buffer> &buf) { return
decodeTagHeader(buf->reference()); };
+ boost::shared_ptr<flv_tag_t> decodeTagHeader(boost::uint8_t *data);
/// \brief Find the named property for this Object.
///
@@ -255,6 +258,11 @@
/// The array of properties for this Flv file, which is
/// populated by the data from the first onMetaTag block.
std::vector<boost::shared_ptr<amf::Element> > _properties;
+
+ /// \var _metadata
+ /// The data contained in the first onMetaData tag from
+ /// the FLV file.
+ boost::shared_ptr<amf::Element> _metadata;
}; // end of class definition
=== modified file 'libbase/sharedlib.cpp'
--- a/libbase/sharedlib.cpp 2010-01-01 17:48:26 +0000
+++ b/libbase/sharedlib.cpp 2010-01-01 20:41:28 +0000
@@ -132,6 +132,7 @@
SharedLib::initentry *
SharedLib::getInitEntry (const std::string& symbol)
{
+ // GNASH_REPORT_FUNCTION;
lt_ptr run = NULL;
scoped_lock lock(_libMutex);
=== modified file 'libnet/cache.cpp'
--- a/libnet/cache.cpp 2010-01-01 17:48:26 +0000
+++ b/libnet/cache.cpp 2010-01-01 20:41:28 +0000
@@ -89,14 +89,17 @@
{
// GNASH_REPORT_FUNCTION;
boost::mutex::scoped_lock lock(cache_mutex);
+
_responses[name] = response;
}
void
Cache::addFile(const std::string &name, boost::shared_ptr<DiskStream> &file)
{
-// GNASH_REPORT_FUNCTION;
+ // GNASH_REPORT_FUNCTION;
+
boost::mutex::scoped_lock lock(cache_mutex);
+ log_network("Adding file %s to cache.", name);
_files[name] = file;
}
@@ -134,10 +137,12 @@
return _responses[name];
}
-boost::shared_ptr<DiskStream>
+boost::shared_ptr<DiskStream> &
Cache::findFile(const std::string &name)
{
// GNASH_REPORT_FUNCTION;
+
+ log_network("Trying to find %s in the cache.", name);
boost::mutex::scoped_lock lock(cache_mutex);
#ifdef USE_STATS_CACHE
clock_gettime (CLOCK_REALTIME, &_last_access);
@@ -247,28 +252,31 @@
void
Cache::dump(std::ostream& os) const
{
-// GNASH_REPORT_FUNCTION;
+ GNASH_REPORT_FUNCTION;
boost::mutex::scoped_lock lock(cache_mutex);
// Dump all the pathnames
+ os << "Pathname cache has " << _pathnames.size() << " files." << endl;
map<string, string>::const_iterator name;
for (name = _pathnames.begin(); name != _pathnames.end(); name++) {
os << "Full path for \"" << name->first << "\" is: " << name->second
<< endl;
}
// Dump the responses
+ os << "Responses cache has " << _responses.size() << " files." << endl;
for (name = _responses.begin(); name != _responses.end(); name++) {
os << "Response for \"" << name->first << "\" is: " << name->second <<
endl;
}
-
-#if 1
+
+ os << "DiskStream cache has " << _files.size() << " files." << endl;
+
map<std::string, boost::shared_ptr<DiskStream> >::const_iterator data;
for (data = _files.begin(); data != _files.end(); data++) {
boost::shared_ptr<DiskStream> filedata = data->second;
- os << "File info for \"" << data->first << "\" is: ";
-// filedata.dump(os) << endl;
+ os << "file info for \"" << data->first << "\" is: " << endl;
+ filedata->dump();
+ os << "-----------------------------" << endl;
}
-#endif
#ifdef USE_STATS_CACHE
this->stats(false);
=== modified file 'libnet/cache.h'
--- a/libnet/cache.h 2010-01-01 17:48:26 +0000
+++ b/libnet/cache.h 2010-01-01 20:41:28 +0000
@@ -60,7 +60,7 @@
void removeResponse(const std::string &name);
void addFile(const std::string &name, boost::shared_ptr<DiskStream >
&file);
- boost::shared_ptr<DiskStream> DSOEXPORT findFile(const std::string &name);
+ boost::shared_ptr<DiskStream> &DSOEXPORT findFile(const std::string &name);
void removeFile(const std::string &name);
/// \brief Dump the internal data of this class in a human readable form.
=== modified file 'libnet/diskstream.cpp'
--- a/libnet/diskstream.cpp 2010-01-01 17:48:26 +0000
+++ b/libnet/diskstream.cpp 2010-01-01 20:41:28 +0000
@@ -54,6 +54,7 @@
#include <boost/thread/mutex.hpp>
static boost::mutex io_mutex;
+static boost::mutex mem_mutex;
using namespace gnash;
using namespace std;
@@ -301,7 +302,9 @@
DiskStream::~DiskStream()
{
-// GNASH_REPORT_FUNCTION;
+ GNASH_REPORT_FUNCTION;
+ log_debug("Deleting %s on fd #%d", _filespec, _filefd);
+
if (_filefd) {
::close(_filefd);
}
@@ -310,21 +313,54 @@
}
}
-/// \brief Close the open disk file and it's associated stream.
+/// \brief copy another DiskStream into ourselves, so they share data
+/// in memory.
+DiskStream &
+DiskStream::operator=(DiskStream *stream)
+{
+ GNASH_REPORT_FUNCTION;
+
+ _filespec = stream->getFilespec();
+ _filetype = stream->getFileType();
+ _filefd = stream->getFileFd();
+ _netfd = stream->getNetFd();
+ _dataptr = stream->get();
+ _state = stream->getState();
+
+ return *this;
+}
+
+bool
+DiskStream::fullyPopulated()
+{
+ // GNASH_REPORT_FUNCTION;
+
+ if ((_filesize < _max_memload) && (_dataptr != 0)) {
+ return true;
+ }
+ return false;
+};
+
+/// \brief Close the open disk file, but stay resident in memory.
void
DiskStream::close()
{
-// GNASH_REPORT_FUNCTION;
+ // GNASH_REPORT_FUNCTION;
log_debug("Closing %s on fd #%d", _filespec, _filefd);
if (_filefd) {
::close(_filefd);
}
-
- _filesize = 0;
+
+ // reset everything in case we get reopened.
+ _filefd = 0;
+ _netfd = 0;
_offset = 0;
-
+ _seekptr = _dataptr + _pagesize;
+ _state = CLOSED;
+
+#if 0 // FIXME: don't unmap the memory for debugging
#ifdef _WIN32
UnmapViewOfFile(_dataptr);
#elif defined(__amigaos4__)
@@ -332,14 +368,10 @@
#else
if ((_dataptr != MAP_FAILED) && (_dataptr != 0)) {
munmap(_dataptr, _pagesize);
-// delete[] _dataptr;
}
#endif
+#endif
- _dataptr = 0;
- _filefd = 0;
- _state = CLOSED;
-// _filespec.clear();
}
/// \brief Load a chunk (pagesize) of the file into memory.
@@ -358,13 +390,15 @@
boost::uint8_t *
DiskStream::loadToMem(off_t offset)
{
+ // GNASH_REPORT_FUNCTION;
+
return loadToMem(_filesize, offset);
}
boost::uint8_t *
DiskStream::loadToMem(size_t filesize, off_t offset)
{
-// GNASH_REPORT_FUNCTION;
+ GNASH_REPORT_FUNCTION;
log_debug("%s: offset is: %d", __FUNCTION__, offset);
@@ -432,6 +466,10 @@
// size = _filesize;
// }
+ // lock in case two threads try to load the same file at the
+ // same time.
+ boost::mutex::scoped_lock lock(mem_mutex);
+
#ifdef _WIN32
HANDLE handle = CreateFileMapping((HANDLE)_get_osfhandle(_filefd), NULL,
PAGE_WRITECOPY, 0, 0, NULL);
@@ -460,12 +498,49 @@
log_debug (_("File %s a offset %d mapped to: %p"), _filespec, offset,
(void *)dataptr);
clock_gettime (CLOCK_REALTIME, &_last_access);
_dataptr = dataptr;
- _seekptr = _dataptr + offset;
+ // map the seekptr to the end of data
+ _seekptr = _dataptr + _pagesize;
_state = OPEN;
- }
-
- return _seekptr;
-
+ _offset = 0;
+ }
+
+ boost::uint8_t *ptr = dataptr;
+ if (_filetype == FILETYPE_FLV) {
+ // FIXME: for now, assume all media files are in FLV format
+ _flv.reset(new amf::Flv);
+ boost::shared_ptr<amf::Flv::flv_header_t> head =
_flv->decodeHeader(ptr);
+ ptr += sizeof(amf::Flv::flv_header_t);
+ ptr += sizeof(amf::Flv::previous_size_t);
+ boost::shared_ptr<amf::Flv::flv_tag_t> tag =
_flv->decodeTagHeader(ptr);
+ ptr += sizeof(amf::Flv::flv_tag_t);
+ size_t bodysize = _flv->convert24(tag->bodysize);
+ if (tag->type == amf::Flv::TAG_METADATA) {
+ boost::shared_ptr<amf::Element> metadata =
_flv->decodeMetaData(ptr, bodysize);
+ if (metadata) {
+ metadata->dump();
+ }
+ }
+ }
+
+ if (filesize < _max_memload) {
+ close();
+ }
+
+ // The data pointer points to the real data past all the header bytes.
+ _dataptr = ptr;
+
+ return _seekptr;
+}
+
+/// \brief Write the existing data to the Network.
+///
+/// @return true is the write suceeded, false if it failed.
+bool
+DiskStream::writeToNet(int /* start */, int /* bytes */)
+{
+ GNASH_REPORT_FUNCTION;
+
+ return false;
}
/// \brief Write the data in memory to disk
@@ -557,7 +632,7 @@
bool
DiskStream::open(const string &filespec, int netfd, Statistics &statistics)
{
-// GNASH_REPORT_FUNCTION;
+ GNASH_REPORT_FUNCTION;
// the file is already open
if (_state == OPEN) {
@@ -566,6 +641,13 @@
#endif
return true;
}
+
+ // If DONE, then we were previously open, but not closed, so we
+ // just reopen the same stream.
+ if ((_state == DONE) || (_state == CLOSED)) {
+ _state = OPEN;
+ return true;
+ }
_netfd = netfd;
_statistics = statistics;
@@ -579,8 +661,12 @@
log_debug (_("Opening file %s (fd #%d), %lld bytes in size."),
_filespec, _filefd,
(long long int) _filesize);
+ _state = OPEN;
+ _filetype = determineFileType(filespec);
+ loadToMem(0); // load the first page into memory
} else {
log_error (_("File %s doesn't exist"), _filespec);
+ _state = DONE;
return false;
}
@@ -588,12 +674,6 @@
clock_gettime (CLOCK_REALTIME, &_first_access);
#endif
-// // The pagesize is how much of the file to load. As all memory is
-// // only mapped in multiples of pages, we use that for the default size.
-// if (_pagesize == 0) {
-// _pagesize = pageSize;
-// }
-
return true;
}
@@ -605,29 +685,100 @@
{
// GNASH_REPORT_FUNCTION;
- return play(_netfd);
+ return play(_netfd, true);
+}
+
+bool
+DiskStream::play(bool flag)
+{
+// GNASH_REPORT_FUNCTION;
+
+ return play(_netfd, flag);
}
/// \brief Stream the file that has been loaded,
///
-/// @param netfd An optional file descriptor to read data from
+/// @param netfd The file descriptor to use for operations
+///
+/// @param flag True to only send the first packet, False plays entire file.
///
/// @return True if the data was streamed sucessfully, false if not.
bool
-DiskStream::play(int netfd)
+DiskStream::play(int netfd, bool flag)
{
-// GNASH_REPORT_FUNCTION;
+ GNASH_REPORT_FUNCTION;
+ bool done = false;
+// dump();
+
_netfd = netfd;
- _state = PLAY;
- log_unimpl("%s", __PRETTY_FUNCTION__);
-
- while (_state != DONE) {
+ while (!done) {
+ // If flag is false, only play the one page of the file.
+ if (!flag) {
+ done = true;
+ }
switch (_state) {
+ case NO_STATE:
+ log_network("No Diskstream open %s for net fd #%d", _filespec,
netfd);
+ break;
+ case CREATED:
+ case CLOSED:
+ if (_dataptr) {
+ log_network("Diskstream %s is closed on net fd #%d.",
_filespec, netfd);
+ }
+ done = true;
+ continue;
+ case OPEN:
+ loadToMem(0);
+ _offset = 0;
+ _state = PLAY;
+ // continue;
case PLAY:
- _state = DONE;
- break;
+ {
+ size_t ret;
+ Network net;
+ if ((_filesize - _offset) < _pagesize) {
+#ifdef HAVE_SENDFILE_XX
+ ret = sendfile(netfd, _filefd, &_offset, _filesize - _offset);
+#else
+ ret = net.writeNet(netfd, (_dataptr + _offset), (_filesize -
_offset));
+ if (ret != (_filesize - _offset)) {
+ log_error("In %s(%d): couldn't write %d bytes to net fd
#%d! %s",
+ __FUNCTION__, __LINE__, (_filesize - _offset),
+ netfd, strerror(errno));
+ }
+#endif
+ log_debug("Done playing file %s, size was: %d", _filespec,
_filesize);
+ close();
+ done = true;
+ // reset to the beginning of the file
+ _offset = 0;
+ } else {
+ log_debug("\tPlaying part of file %s, offset is: %d",
_filespec, _offset);
+#ifdef HAVE_SENDFILE_XX
+ ret = sendfile(netfd, _filefd, &_offset, _pagesize);
+#else
+ ret = net.writeNet(netfd, (_dataptr + _offset), _pagesize);
+ if (ret != _pagesize) {
+ log_error("In %s(%d): couldn't write %d of bytes of data
to net fd #%d! Got %d, %s",
+ __FUNCTION__, __LINE__, _pagesize, netfd,
+ ret, strerror(errno));
+ }
+ _offset += _pagesize;
+#endif
+ }
+ switch (errno) {
+ case EINVAL:
+ case ENOSYS:
+ case EFAULT:
+ log_network("ERROR: %s", strerror(errno));
+ break;
+ default:
+ break;
+ }
+ break;
+ }
case PREVIEW:
break;
case THUMBNAIL:
@@ -641,7 +792,13 @@
case MULTICAST:
break;
case DONE:
- break;
+ log_debug("Restarting Disk Stream from the beginning");
+ _offset = 0;
+ _filefd = 0;
+ _state = PLAY;
+ _seekptr = _dataptr + _pagesize;
+ _netfd = netfd;
+ continue;
default:
break;
}
@@ -657,20 +814,8 @@
#ifdef USE_STATS_FILE
_statistics->addBytes(nbytes);
_bytes += nbytes;
- _seekptr += nbytes;
-#endif
-
- log_debug("Done...");
-
-#ifdef _WIN32
- UnmapViewOfFile(_dataptr);
-#elif defined(__amigaos4__)
- if (_dataptr) free(_dataptr);
-#else
- munmap(_dataptr, _filesize);
-#endif
-
- _seekptr = 0;
+ // _seekptr += nbytes;
+#endif
return true;
}
@@ -783,9 +928,6 @@
return(determineFileType(_filespec));
}
-
-
-
// Get the file type, so we know how to set the
// Content-type in the header.
bool
@@ -843,10 +985,14 @@
if (pos != string::npos) {
string suffix = filespec.substr(pos+1, filespec.size());
_filetype = FILETYPE_NONE;
- if (suffix == "html") {
+ if (suffix == "htm") {
+ _filetype = FILETYPE_HTML;
+ } else if (suffix == "html") {
_filetype = FILETYPE_HTML;
} else if (suffix == "ogg") {
_filetype = FILETYPE_OGG;
+ } else if (suffix == "ogv") {
+ _filetype = FILETYPE_OGG;
} else if (suffix == "swf") {
_filetype = FILETYPE_SWF;
} else if (suffix == "flv") {
@@ -865,6 +1011,8 @@
_filetype = FILETYPE_XML;
} else if (suffix == "mp4") {
_filetype = FILETYPE_MP4;
+ } else if (suffix == "mpeg") {
+ _filetype = FILETYPE_MP4;
} else if (suffix == "png") {
_filetype = FILETYPE_PNG;
} else if (suffix == "gif") {
@@ -942,9 +1090,11 @@
DiskStream::dump()
{
// GNASH_REPORT_FUNCTION;
- //state_e _state;
const char *state_str[] = {
"NO_STATE",
+ "CREATED",
+ "CLOSED",
+ "OPEN",
"PLAY",
"PREVIEW",
"THUMBNAIL",
@@ -954,14 +1104,39 @@
"MULTICAST",
"DONE"
};
+
+ const char *type_str[] = {
+ "NONE",
+ "AMF",
+ "SWF",
+ "HTML",
+ "PNG",
+ "JPEG",
+ "GIF",
+ "MP3",
+ "MP4",
+ "OGG",
+ "VORBIS",
+ "THEORA",
+ "DIRAC",
+ "TEXT",
+ "FLV",
+ "VP6",
+ "XML",
+ "FLAC",
+ "ENCODED"
+ };
cerr << "State is \"" << state_str[_state] << "\"" << endl;
+ cerr << "File type is \"" << type_str[_filetype] << "\"" << endl;
cerr << "Filespec is \"" << _filespec << "\"" << endl;
cerr << "Disk file descriptor is fd #" << _filefd << endl;
- cerr << "Network file descritor is fd #" << _netfd << endl;
+ cerr << "Network file descriptor is fd #" << _netfd << endl;
cerr << "File size is " << _filesize << endl;
cerr << "Memory Page size is " << _pagesize << endl;
cerr << "Memory Offset is " << _offset << endl;
+ cerr << "Base Memory Address is " << (void *)_dataptr << endl;
+ cerr << "Seek Pointer Memory Address is " << (void *)_seekptr << endl;
// dump timing related data
struct timespec now;
=== modified file 'libnet/diskstream.h'
--- a/libnet/diskstream.h 2010-01-01 17:48:26 +0000
+++ b/libnet/diskstream.h 2010-01-01 20:41:28 +0000
@@ -28,6 +28,7 @@
#include "amf.h"
#include "buffer.h"
+#include "flv.h"
#include "cque.h"
#include "statistics.h"
#include "getclocktime.hpp"
@@ -49,6 +50,7 @@
/// This represents the state of the current stream.
typedef enum {
NO_STATE,
+ CREATED,
CLOSED,
OPEN,
PLAY,
@@ -112,9 +114,12 @@
///
/// @param netfd An optional file descriptor to read data from
///
+ /// @param flag True to play the entire file, false to play part.
+ ///
/// @return True if the data was streamed sucessfully, false if not.
bool play();
- bool play(int netfd);
+ bool play(bool flag);
+ bool play(int netfd, bool flag);
/// \brief Stream a preview of the file.
/// A preview is a series of video frames from
@@ -201,7 +206,7 @@
/// \brief Write the existing data to the Network.
///
/// @return true is the write suceeded, false if it failed.
- bool writeToNet();
+ bool writeToNet(int start, int bytes);
/// \brief Get the memory page size
/// This is a cached value of the system configuration
@@ -218,7 +223,11 @@
///
/// @return nothing.
void setPagesize(size_t size) { _pagesize = size; };
-
+
+ /// \brief copy another DiskStream into ourselves, so they share data
+ /// in memory.
+ DiskStream &operator=(DiskStream *stream);
+
/// \brief Dump the internal data of this class in a human readable form.
/// @remarks This should only be used for debugging purposes.
void dump();
@@ -226,8 +235,11 @@
/// \brief Get the base address for the memory page.
///
- /// @return A real pointer to the base address.
+ /// @return A real pointer to the base address data in the file, but after
+ /// the header bytes.
boost::uint8_t *get() { return _dataptr; };
+ bool fullyPopulated();
+// bool fullyPopulated() { return ((_seekptr - _filesize) == _dataptr); };
/// \brief Get the size of the file.
///
@@ -237,6 +249,7 @@
DiskStream::filetype_e getFileType() { return _filetype; };
std::string &getFilespec() { return _filespec; }
+ void setFilespec(std::string filespec) { _filespec = filespec; }
/// \brief Get the time of the last access.
///
@@ -244,6 +257,10 @@
struct timespec *getLastAccessTime() { return &_last_access; };
state_e getState() { return _state; };
+ void setState(state_e state) { _state = state; };
+
+ int getFileFd() { return _filefd; };
+ int getNetFd() { return _netfd; };
#ifdef USE_STATS_CACHE
/// \brief Get the time of the first access.
@@ -292,7 +309,8 @@
size_t _max_memload;
/// \var DiskStream::_seekptr
- /// The current location within the current memory page.
+ /// The current location within the current memory page
where
+ /// the data ends, which is in increments of the empry page
size.
boost::uint8_t *_seekptr;
/// \var DiskStream::_filesize
@@ -320,8 +338,6 @@
// Get the file stats, so we know how to set the
// Content-Length in the header.
bool getFileStats(const std::string &filespec);
-
-
DiskStream::filetype_e _filetype;
struct timespec _last_access;
@@ -334,6 +350,9 @@
#ifdef USE_STATS_FILE
int _bytes;
#endif
+
+ // The header, tag, and onMetaData from the FLV file.
+ boost::shared_ptr<amf::Flv> _flv;
};
/// \brief Dump to the specified output stream.
=== modified file 'libnet/http.cpp'
--- a/libnet/http.cpp 2010-01-01 17:48:26 +0000
+++ b/libnet/http.cpp 2010-01-01 20:41:28 +0000
@@ -84,7 +84,8 @@
// _handler(0),
_clientid(0),
_index(0),
- _max_requests(0)
+ _max_requests(0),
+ _close(false)
{
// GNASH_REPORT_FUNCTION;
// struct status_codes *status = new struct status_codes;
@@ -101,7 +102,9 @@
_keepalive(false),
_clientid(0),
_index(0),
- _max_requests(0)
+ _max_requests(0),
+ _close(false)
+
{
// GNASH_REPORT_FUNCTION;
// _handler = hand;
@@ -137,10 +140,10 @@
boost::uint8_t *
-HTTP::processHeaderFields(amf::Buffer &buf)
+HTTP::processHeaderFields(amf::Buffer *buf)
{
// GNASH_REPORT_FUNCTION;
- string head(reinterpret_cast<const char *>(buf.reference()));
+ string head(reinterpret_cast<const char *>(buf->reference()));
// The end of the header block is always followed by a blank line
string::size_type end = head.find("\r\n\r\n", 0);
@@ -160,7 +163,7 @@
_keepalive = true;
if ((value != "on") && (value != "off")) {
_max_requests = strtol(value.c_str(), NULL, 0);
- log_debug("Setting Max Requests for Keep-Alive to %d",
_max_requests);
+ // log_debug("Setting Max Requests for Keep-Alive to %d",
_max_requests);
}
}
if (name == "connection") {
@@ -204,7 +207,7 @@
// in it. It's actually two separate integers.
_version.major = i->at(pos+5) - '0';
_version.minor = i->at(pos+7) - '0';
- log_debug (_("Version: %d.%d"), _version.major,
_version.minor);
+ // log_debug (_("Version: %d.%d"), _version.major,
_version.minor);
// the filespec in the request is the middle field,
deliminated
// by a space on each end.
if (params != string::npos) {
@@ -228,7 +231,7 @@
}
}
- return buf.reference() + end + 4;
+ return buf->reference() + end + 4;
}
// // Parse an Echo Request message coming from the Red5 echo_test. This
@@ -388,11 +391,7 @@
}
}
- if (result) {
- return _cmd;
- } else {
- return HTTP::HTTP_NONE;
- }
+ return _cmd;
}
// A GET request asks the server to send a file to the client
@@ -941,10 +940,14 @@
formatLastModified();
formatAcceptRanges("bytes");
formatContentLength(size);
+
// Apache closes the connection on GET requests, so we do the same.
// This is a bit silly, because if we close after every GET request,
// we're not really handling the persistance of HTTP 1.1 at all.
- formatConnection("close");
+ if (_close) {
+ formatConnection("close");
+ _keepalive = false;
+ }
formatContentType(type);
// All HTTP messages are followed by a blank line.
@@ -1125,7 +1128,6 @@
return formatLastModified(date.str());
}
-
amf::Buffer &
HTTP::formatEchoResponse(const std::string &num, amf::Buffer &data)
{
@@ -1247,7 +1249,7 @@
HTTP::http_method_e
HTTP::extractCommand(boost::uint8_t *data)
{
- GNASH_REPORT_FUNCTION;
+ // GNASH_REPORT_FUNCTION;
// string body = reinterpret_cast<const char *>(data);
HTTP::http_method_e cmd = HTTP::HTTP_NONE;
@@ -1291,7 +1293,7 @@
// This is fine as long as end is within the buffer.
_filespec = std::string(start, end);
}
- log_debug("Requesting file: \"%s\"", _filespec);
+ // log_debug("Requesting file: \"%s\"", _filespec);
// The third field is always the HTTP version
// The version is the last field and is the protocol name
@@ -1300,7 +1302,7 @@
// in it. It's actually two separate integers.
_version.major = *(end+6) - '0';
_version.minor = *(end+8) - '0';
- log_debug (_("Version: %d.%d"), _version.major, _version.minor);
+ // log_debug (_("Version: %d.%d"), _version.major, _version.minor);
}
return cmd;
@@ -1484,7 +1486,8 @@
int
HTTP::recvMsg(int fd, size_t size)
{
- GNASH_REPORT_FUNCTION;
+ // GNASH_REPORT_FUNCTION;
+
size_t ret = 0;
if (size == 0) {
@@ -1537,7 +1540,7 @@
} while (ret);
// We're done. Notify the other threads the socket is closed, and tell
them to die.
- log_debug("Handler done for fd #%d...", fd);
+ log_debug("Done receiving data for fd #%d...", fd);
return ret;
}
=== modified file 'libnet/http.h'
--- a/libnet/http.h 2010-01-01 17:48:26 +0000
+++ b/libnet/http.h 2010-01-01 20:41:28 +0000
@@ -145,12 +145,13 @@
// process all the header fields in the Buffer, storing them internally
// in _fields. The address returned is the address where the Content data
// starts, and is "Content-Length" bytes long, of "Content-Type" data.
- boost::uint8_t *processHeaderFields(amf::Buffer &buf);
+ boost::uint8_t *processHeaderFields(amf::Buffer *buf);
// Get the field for header 'name' that was stored by processHeaderFields()
std::string &getField(const std::string &name) { return _fields[name]; };
size_t NumOfFields() { return _fields.size(); };
void clearFields() { _fields.clear(); };
+ std::map<std::string, std::string> &getFields() { return _fields; };
// Get an array of values for header field 'name'.
boost::shared_ptr<std::vector<std::string> > getFieldItem(const
std::string &name);
@@ -280,6 +281,8 @@
// These accessors are used mostly just for debugging.
bool keepAlive() { return _keepalive; }
+ void keepAlive(bool x) { _keepalive = x; };
+
int getMaxRequests() { return _max_requests; }
int getFileSize() { return _filesize; }
std::string &getFilespec() { return _filespec; }
@@ -335,6 +338,8 @@
int _index;
int _max_requests;
std::string _docroot;
+
+ bool _close;
};
// This is the thread for all incoming HTTP connections for the server
=== modified file 'libnet/network.cpp'
--- a/libnet/network.cpp 2010-01-01 17:48:26 +0000
+++ b/libnet/network.cpp 2010-01-01 20:41:28 +0000
@@ -40,6 +40,7 @@
# include <io.h>
# include <ws2tcpip.h>
#else
+# include <sys/ioctl.h>
# include <sys/time.h>
# include <unistd.h>
# include <sys/select.h>
@@ -67,6 +68,10 @@
#define MAXHOSTNAMELEN 256
#endif
+#ifndef FIONREAD
+#define FIONREAD 0
+#endif
+
using namespace std;
/// \namespace gnash
@@ -788,6 +793,18 @@
}
int
+Network::readNet(int fd, amf::Buffer *buffer)
+{
+// GNASH_REPORT_FUNCTION;
+ int ret = readNet(fd, buffer->reference(), buffer->size(), _timeout);
+ if (ret > 0) {
+ buffer->setSeekPointer(buffer->reference() + ret);
+ }
+
+ return ret;
+}
+
+int
Network::readNet(amf::Buffer &buffer)
{
// GNASH_REPORT_FUNCTION;
@@ -1251,7 +1268,7 @@
boost::shared_ptr<std::vector<struct pollfd> >
Network::waitForNetData(int limit, struct pollfd *fds)
{
- // GNASH_REPORT_FUNCTION;
+// GNASH_REPORT_FUNCTION;
boost::shared_ptr<vector<struct pollfd> > hits(new vector<struct pollfd>);
@@ -1366,19 +1383,22 @@
{
// GNASH_REPORT_FUNCTION;
- int max = 0;
-
fd_set fdset;
FD_ZERO(&fdset);
-
- for (size_t i = 0; i<data.size(); i++) {
- FD_SET(data[i], &fdset);
- if (data[i] > max) {
- max = data[i];
+
+ if (data.size()) {
+ int max = 0;
+
+ for (size_t i = 0; i<data.size(); i++) {
+ FD_SET(data[i], &fdset);
+ if (data[i] > max) {
+ max = data[i];
+ }
}
+ return waitForNetData(max+1, fdset);
}
- return waitForNetData(max+1, fdset);
+ return fdset;
}
fd_set
@@ -1428,14 +1448,23 @@
if (ret == -1) {
log_error (_("Waiting for data for fdset, was never available for
reading"));
+ FD_ZERO(&fdset);
+ FD_SET(0, &fdset);
+ return fdset;
}
if (ret == 0) {
// log_debug (_("Waiting for data for fdset, timed out waiting for
data"));
FD_ZERO(&fdset);
+ FD_SET(0, &fdset);
+ return fdset;
}
- if (ret) {
+ if (ret < 0) {
+ log_error("select() got an error: %s.", strerror(errno));
+ FD_ZERO(&fdset);
+ FD_SET(0, &fdset);
+ } else {
log_network("select() saw activity on %d file descriptors.", ret);
}
@@ -1561,10 +1590,26 @@
}
#endif
+// Use an ioctl() to see how many bytes are in the network buffers.
+size_t
+Network::sniffBytesReady(int fd)
+{
+ // GNASH_REPORT_FUNCTION;
+
+ int bytes;
+
+ ioctl(fd, FIONREAD, &bytes);
+
+ log_network("#%d bytes waiting in kernel network buffer.", bytes);
+
+ return bytes;
+}
+
// Trap Control-C so we can cleanly exit
static void
cntrlc_handler (int sig)
{
+ GNASH_REPORT_FUNCTION;
sig_number = sig;
log_debug(_("Got an %d interrupt while blocked on pselect()"), sig);
exit(EXIT_FAILURE);
=== modified file 'libnet/network.h'
--- a/libnet/network.h 2010-01-01 17:48:26 +0000
+++ b/libnet/network.h 2010-01-01 20:41:28 +0000
@@ -137,6 +137,7 @@
int netfd;
void *entry;
void *handler;
+ amf::Buffer *buffer;
std::string filespec;
protocols_supported_e protocol;
} thread_params_t;
@@ -205,6 +206,7 @@
boost::shared_ptr<amf::Buffer> readNet();
int readNet(amf::Buffer &buffer);
int readNet(int fd, amf::Buffer &buffer);
+ int readNet(int fd, amf::Buffer *buffer);
int readNet(amf::Buffer &buffer, int timeout);
int readNet(int fd, amf::Buffer &buffer, int timeout);
int readNet(byte_t *data, int nbytes);
@@ -320,6 +322,9 @@
std::string &keyfile, std::string &calist,
std::string &rootpath, bool auth);
#endif
+
+ // Use an ioctl() to see how many bytes are in the network buffers.
+ size_t sniffBytesReady(int fd);
protected:
in_addr_t _ipaddr;
=== modified file 'libnet/rtmp.cpp'
--- a/libnet/rtmp.cpp 2010-01-01 17:48:26 +0000
+++ b/libnet/rtmp.cpp 2010-01-01 20:41:28 +0000
@@ -170,17 +170,16 @@
int
RTMP::headerSize(boost::uint8_t header)
{
-// GNASH_REPORT_FUNCTION;
+ // GNASH_REPORT_FUNCTION;
+ int headersize = header & RTMP_HEADSIZE_MASK;
- int headersize = -1;
-
- if ((header & RTMP_HEADSIZE_MASK) == 0) {
+ if (headersize == 0) {
headersize = 12;
- } else if (header & 0x80) {
+ } else if (headersize == 0x80) {
headersize = 4;
- } else if (header & 0x40) {
+ } else if (headersize == 0x40) {
headersize = 8;
- } else if (header & 0xc0) {
+ } else if (headersize == 0xc0) {
headersize = 1;
} else {
log_error(_("AMF Header size bits (0x%X) out of range"),
@@ -277,7 +276,7 @@
// log_network (_("The header size is %d"), head->head_size);
// cerr << "FIXME(" << __FUNCTION__ << "): " << hexify(in,
- // head->head_size, false) << endl;
+ // head->head_size, false) << endl;
// Make sure the header size is in range, it has to be between
// 1-12 bytes.
@@ -287,7 +286,7 @@
head.reset();
return head;
} else if (head->head_size == 0) {
- log_error("RTMP Header size can't be zaero!");
+ log_error("RTMP Header size can't be zero!");
head.reset();
return head;
}
@@ -296,12 +295,11 @@
_mystery_word = *tmpptr++;
_mystery_word = (_mystery_word << 8) + *tmpptr++;
_mystery_word = (_mystery_word << 8) + *tmpptr++;
-// log_network(_("The mystery word is: %d"), _mystery_word);
+ // log_network(_("The mystery word is: %d"), _mystery_word);
} else {
_mystery_word = 0;
}
-
if (head->head_size >= 8) {
head->bodysize = *tmpptr++;
head->bodysize = (head->bodysize << 8) + *tmpptr++;
@@ -345,7 +343,7 @@
}
#endif
} else {
- if ((_type[head->channel] >= RTMP::NONE) && (_type[head->channel] <=
RTMP::FLV_DATA)) {
+ if (_type[head->channel] <= RTMP::FLV_DATA) {
log_network("Using previous type of %d for channel %d",
head->type, head->channel);
head->type = _type[head->channel];
@@ -380,6 +378,7 @@
{
// GNASH_REPORT_FUNCTION;
boost::shared_ptr<amf::Buffer> buf(new Buffer(1));
+ buf->clear();
boost::uint8_t *ptr = buf->reference();
// Make the channel index & header size byte
@@ -437,17 +436,26 @@
// The type is a one byte field
*ptr = type;
ptr++;
- }
-
- // Add the routing of the message if the header size is 12, the maximum.
- if (head_size == HEADER_12) {
- boost::uint32_t swapped = htonl(routing);
- memcpy(ptr, &swapped, 4);
- ptr += 4;
+
+ // Add the routing of the message if the header size is 12, the maximum.
+ if (head_size == HEADER_12 && type != RTMP::USER) {
+ if (type != RTMP::AUDIO_DATA && type != RTMP::VIDEO_DATA) {
+ // log_network(_("The routing is: 0x%x"), routing);
+ boost::uint32_t swapped = htonl(routing);
+ memcpy(ptr, &swapped, 4);
+ } else {
+ // FIXME: I have no idea why these two empty messages
+ // don't handle the routing field for 12 byte headers
+ // the same as all the other types.
+ boost::uint8_t swapped = 0x1;
+ *ptr = swapped;
+ }
+ ptr += 4;
+ }
}
// Manually adjust the seek pointer since we added the data by
- // walking ou own temporary pointer, so none of the regular ways
+ // walking our own temporary pointer, so none of the regular ways
// of setting the seek pointer are appropriate.
buf->setSeekPointer(buf->reference() + buf->size());
@@ -615,7 +623,14 @@
}
boost::shared_ptr<RTMP::user_event_t>
-RTMP::decodeUser(boost::uint8_t *data)
+RTMP::decodeUserControl(amf::Buffer &buf)
+{
+// GNASH_REPORT_FUNCTION;
+ return decodeUserControl(buf.reference());
+}
+
+boost::shared_ptr<RTMP::user_event_t>
+RTMP::decodeUserControl(boost::uint8_t *data)
{
// GNASH_REPORT_FUNCTION;
@@ -659,11 +674,55 @@
return user;
}
-boost::shared_ptr<RTMP::user_event_t>
-RTMP::decodeUser(amf::Buffer &buf)
+
+// Stream Live -
+// 02 00 00 00 00 00 06 04 00 00 00 00 00 04 00 00 00 01
+// Stream Start -
+// 02 00 00 00 00 00 06 04 00 00 00 00 00 00 00 00 00 01
+boost::shared_ptr<amf::Buffer>
+RTMP::encodeUserControl(user_control_e eventid, boost::uint32_t data)
{
// GNASH_REPORT_FUNCTION;
- return decodeUser(buf.reference());
+
+ boost::uint32_t swapped = 0;
+ boost::shared_ptr<amf::Buffer> buf;
+ if (eventid == STREAM_BUFFER) {
+ buf.reset(new Buffer(sizeof(boost::uint16_t) * 5));
+ } else {
+ buf.reset(new Buffer(sizeof(boost::uint16_t) * 3));
+ }
+
+ // Set the type of this ping message
+ boost::uint16_t typefield = htons(eventid);
+ *buf = typefield;
+
+ // All events have only 4 bytes of data, except Set Buffer, which
+ // uses 8 bytes. The 4 bytes is usually the Stream ID except for
+ // Ping and Pong events, which carry a time stamp instead. We
+ // don't actually do anything here, we just parse the data.
+ switch (eventid) {
+ case STREAM_START:
+ case STREAM_EOF:
+ case STREAM_NODATA:
+ swapped = data;
+ swapBytes(&swapped, sizeof(boost::uint32_t));
+ *buf += swapped;
+ break;
+ case STREAM_BUFFER:
+ buf.reset(new Buffer(sizeof(boost::uint16_t) * 5));
+ break;
+ case STREAM_LIVE:
+ case STREAM_PING:
+ case STREAM_PONG:
+ swapped = data;
+ swapBytes(&swapped, sizeof(boost::uint32_t));
+ *buf += swapped;
+ break;
+ default:
+ break;
+ };
+
+ return buf;
}
boost::shared_ptr<RTMPMsg>
@@ -708,7 +767,7 @@
double swapped = streamid->to_number();
// swapBytes(&swapped, amf::AMF0_NUMBER_SIZE);
- msg->setStreamID(swapped);
+ msg->setTransactionID(swapped);
if ((msg->getMethodName() == "_result") || (msg->getMethodName() ==
"_error") || (msg->getMethodName() == "onStatus")) {
status = true;
@@ -740,18 +799,27 @@
return decodeMsgBody(buf.reference(), buf.allocated());
}
+// 02 00 00 00 00 00 04 01 00 00 00 00 00 00 10 00
+// id=2 timestamp=0 body_size=4 content_type=0x01 dest=0
+// Set chunk size 4096
boost::shared_ptr<amf::Buffer>
-RTMP::encodeChunkSize()
+RTMP::encodeChunkSize(int size)
{
GNASH_REPORT_FUNCTION;
- log_unimpl(__PRETTY_FUNCTION__);
- return boost::shared_ptr<amf::Buffer>((amf::Buffer*)0);
+
+ boost::uint32_t swapped = htonl(size);
+ boost::shared_ptr<amf::Buffer> buf(new
amf::Buffer(sizeof(boost::uint32_t)));
+ *buf += swapped;
+
+ return buf;
}
void
RTMP::decodeChunkSize()
{
GNASH_REPORT_FUNCTION;
+ // _chunksize[rthead->channel] = ntohl(*reinterpret_cast<boost::uint32_t
*>(ptr + rthead->head_size));
+ // log_network("Setting packet chunk size to %d.", _chunksize);
log_unimpl(__PRETTY_FUNCTION__);
}
@@ -913,13 +981,15 @@
{
// GNASH_REPORT_FUNCTION;
int ret = 0;
-
+
+#if 0
// We got some bogus parameters
- if (total_size == 0) {
+ if (total_size || size 0) {
log_error("Bogus size parameter in %s!", __PRETTY_FUNCTION__);
return false;
}
-
+#endif
+
// FIXME: This is a temporary hack to make it easier to read hex
// dumps from network packet sniffing so all the data is in one
// buffer. This matches the Adobe behaviour, but for Gnash/Cygnal,
@@ -961,6 +1031,7 @@
*bigbuf = head;
#endif
+ // if (data && size) {
// now send the data
while (nbytes <= size) {
// The last bit of data is usually less than the packet size,
@@ -983,6 +1054,8 @@
*bigbuf += cont_head;
#endif
}
+ // }
+
// write the data to the client
#if 0
ret = writeNet(fd, data + nbytes, partial);
@@ -994,7 +1067,9 @@
ret, size-nbytes);
}
#else
- bigbuf->append(data + nbytes, partial);
+ if (data != 0) {
+ bigbuf->append(data + nbytes, partial);
+ }
#endif
// adjust the accumulator.
nbytes += _chunksize[channel];
@@ -1272,6 +1347,11 @@
if (rthead->channel == RTMP_SYSTEM_CHANNEL) {
log_network("Got a message on the system channel!", __FUNCTION__);
}
+ // If the header size is 4 bytes or less, then reuse the body size
+ // of the last message for this channel.
+ if (rthead->head_size <= 4) {
+ rthead->bodysize = _lastsize[rthead->channel];
+ }
// Make sure the header size we just got is in range. We can
// proceed as long as it is in range, but if it is out of
// range, we can't really continue.
@@ -1279,10 +1359,7 @@
// Any packet with a header size greater than 1 is a
// always a new RTMP message, so create a new Buffer to
// hold all the data.
- if (rthead->head_size <= 4) {
- rthead->bodysize = _lastsize[rthead->channel];
- }
- if ((rthead->head_size > 1) || (ptr == data)) {
+ if ((rthead->head_size >= 1) || (ptr == data)) {
// cerr << "New packet for channel #" << rthead->channel << "
of size "
// << (rthead->head_size + rthead->bodysize) << endl;
// give it some memory to store data in. We store
=== modified file 'libnet/rtmp.h'
--- a/libnet/rtmp.h 2010-01-01 17:48:26 +0000
+++ b/libnet/rtmp.h 2010-01-01 20:41:28 +0000
@@ -321,9 +321,13 @@
// Decode
boost::shared_ptr<rtmp_head_t> decodeHeader(boost::uint8_t *header);
boost::shared_ptr<rtmp_head_t> decodeHeader(amf::Buffer &data);
- boost::shared_ptr<amf::Buffer> encodeHeader(int amf_index,
rtmp_headersize_e head_size,
- size_t total_size, content_types_e type,
RTMPMsg::rtmp_source_e routing);
- boost::shared_ptr<amf::Buffer> encodeHeader(int amf_index,
rtmp_headersize_e head_size);
+
+ boost::shared_ptr<amf::Buffer> encodeHeader(int amf_index,
+ rtmp_headersize_e head_size,
+ size_t total_size, content_types_e type,
+ RTMPMsg::rtmp_source_e routing);
+ boost::shared_ptr<amf::Buffer> encodeHeader(int amf_index,
+ rtmp_headersize_e head_size);
void addProperty(amf::Element &el);
void addProperty(char *name, amf::Element &el);
@@ -347,13 +351,15 @@
virtual boost::shared_ptr<rtmp_ping_t> decodePing(boost::uint8_t *data);
boost::shared_ptr<rtmp_ping_t> decodePing(amf::Buffer &buf);
- virtual boost::shared_ptr<user_event_t> decodeUser(boost::uint8_t *data);
- boost::shared_ptr<user_event_t> decodeUser(amf::Buffer &buf);
+ virtual boost::shared_ptr<user_event_t> decodeUserControl(boost::uint8_t
*data);
+ boost::shared_ptr<user_event_t> decodeUserControl(amf::Buffer &buf);
+ virtual boost::shared_ptr<amf::Buffer> encodeUserControl(user_control_e,
boost::uint32_t data);
+
// These are handlers for the various types
- virtual boost::shared_ptr<amf::Buffer> encodeChunkSize();
+ virtual boost::shared_ptr<amf::Buffer> encodeChunkSize(int size);
virtual void decodeChunkSize();
-
+
virtual boost::shared_ptr<amf::Buffer> encodeBytesRead();
virtual void decodeBytesRead();
virtual boost::shared_ptr<amf::Buffer> encodeServer();
=== modified file 'libnet/rtmp_msg.cpp'
--- a/libnet/rtmp_msg.cpp 2010-01-01 17:48:26 +0000
+++ b/libnet/rtmp_msg.cpp 2010-01-01 20:41:28 +0000
@@ -49,7 +49,7 @@
RTMPMsg::RTMPMsg()
: _routing(FROM_SERVER),
_status(APP_SHUTDOWN),
- _streamid(0),
+ _transid(0),
_channel(0)
{
// GNASH_REPORT_FUNCTION;
@@ -211,8 +211,8 @@
// cerr << "Length: " << _header.length << endl;
cerr << "Method Name:\t" << _method << endl;
-// cerr << "Stream ID:\t" << hexify((const unsigned char *)&_streamid, 8,
false) << endl;
- cerr << "Stream ID:\t" << _streamid << endl;
+// cerr << "Transaction ID:\t" << hexify((const unsigned char *)&_transid,
8, false) << endl;
+ cerr << "Transaction ID:\t" << _transid << endl;
vector<boost::shared_ptr<amf::Element> >::iterator ait;
cerr << "# of Elements in file: " << _amfobjs.size() << endl;
=== modified file 'libnet/rtmp_msg.h'
--- a/libnet/rtmp_msg.h 2010-01-01 17:48:26 +0000
+++ b/libnet/rtmp_msg.h 2010-01-01 20:41:28 +0000
@@ -98,8 +98,8 @@
void setMethodName(const std::string &name) { _method = name; } ;
std::string &getMethodName() { return _method; };
- void setStreamID(double num) { _streamid = num; };
- double getStreamID() { return _streamid; };
+ void setTransactionID(double num) { _transid = num; };
+ double getTransactionID() { return _transid; };
rtmp_status_e checkStatus(boost::shared_ptr<amf::Element> el);
void setStatus(rtmp_status_e st) { _status = st; };
@@ -128,7 +128,7 @@
rtmp_source_e _routing;
rtmp_status_e _status;
std::string _method;
- double _streamid;
+ double _transid;
std::vector<boost::shared_ptr<amf::Element> > _amfobjs;
boost::uint8_t _channel;
};
=== modified file 'testsuite/libamf.all/test_amf.cpp'
--- a/testsuite/libamf.all/test_amf.cpp 2010-01-01 17:48:26 +0000
+++ b/testsuite/libamf.all/test_amf.cpp 2010-01-01 20:41:28 +0000
@@ -52,9 +52,9 @@
// Prototypes for test cases
static void test_encoding();
-static void test_string();
+// static void test_string();
static void test_object();
-static void test_boolean();
+// static void test_boolean();
static void test_array();
// Enable the display of memory allocation and timing data
=== modified file 'testsuite/libamf.all/test_buffer.cpp'
--- a/testsuite/libamf.all/test_buffer.cpp 2010-01-01 17:48:26 +0000
+++ b/testsuite/libamf.all/test_buffer.cpp 2010-01-01 20:41:28 +0000
@@ -337,7 +337,9 @@
}
const char *sub = "fgh";
+#if 0
Network::byte_t *ptr2 = const_cast<Network::byte_t
*>(reinterpret_cast<const Network::byte_t *>(sub));
+#endif
fptr = std::search(buf1.begin(), buf1.end(), sub, sub+3);
if (fptr == (ptr1 + 5)) {
runtest.pass ("Buffer::find(Network::byte_t *, size_t)");
@@ -432,8 +434,8 @@
}
buf7 += buf6;
- Network::byte_t *ptr1 = buf7.reference() + 10 + sizeof(boost::uint16_t);
- Network::byte_t *ptr2 = buf6.reference();
+ // Network::byte_t *ptr1 = buf7.reference() + 10 + sizeof(boost::uint16_t);
+ // Network::byte_t *ptr2 = buf6.reference();
if (memcmp(buf7.reference() + 10 + sizeof(boost::uint16_t),
buf6.reference(), 30) == 0) {
runtest.pass ("Buffer::operator+=(Buffer &)");
} else {
=== modified file 'testsuite/libnet.all/test_diskstream.cpp'
--- a/testsuite/libnet.all/test_diskstream.cpp 2010-01-01 17:48:26 +0000
+++ b/testsuite/libnet.all/test_diskstream.cpp 2010-01-01 20:41:28 +0000
@@ -55,7 +55,7 @@
static void create_file(const std::string &, size_t);
// Enable the display of memory allocation and timing data
-static bool memdebug = false;
+// static bool memdebug = false;
TestState runtest;
LogFile& dbglogfile = LogFile::getDefaultInstance();
@@ -170,8 +170,8 @@
if ((ds2.get() == MAP_FAILED) || (ds2.get() == 0)) {
runtest.unresolved("loadToMem(6789)");
} else {
- if ((memcmp(ds2.get(), buf+4, range-4) == 0)
- && (memcmp(ptr, buf+4, range-4) == 0)) {
+ if ((memcmp(ds2.get(), buf, range-4) == 0)
+ && (memcmp(ptr, buf, range-4) == 0)) {
runtest.pass("loadToMem(6789)");
} else {
runtest.fail("loadToMem(6789)");
@@ -183,8 +183,8 @@
if ((ds2.get() == MAP_FAILED) || (ds2.get() == 0)) {
runtest.unresolved("seek(5100)");
} else {
- if ((memcmp(ds2.get(), buf+4, range-4) == 0)
- && (memcmp(ptr, buf+82, range-82) == 0)) {
+ if ((memcmp(ds2.get(), buf, range-4) == 0)
+ && (memcmp(ptr, buf+78, range-78) == 0)) {
runtest.pass("seek(5100)");
} else {
runtest.fail("seek(5100)");
@@ -220,7 +220,7 @@
runtest.pass("DiskStream::writeToDisk()");
} else {
runtest.fail("DiskStream::writeToDisk()");
- }
+ }
}
/// \brief create a test file to read in later. This lets us create
@@ -237,15 +237,15 @@
}
// Create an array of printable ASCII characters
- int range = '~' - '!';
+ size_t range = '~' - '!';
char *buf = new char[range];
- for (int j=0; j<range; j++) {
+ for (size_t j=0; j<range; j++) {
buf[j] = '!' + j;
}
// Write the false data to disk
- int total = 0;
- int ret = 0;
+ size_t total = 0;
+ size_t ret = 0;
for (size_t i=0; i<size; i+=range) {
if ((size - total) < range) {
ret = write(fd, buf, (size - total));
=== modified file 'testsuite/libnet.all/test_http.cpp'
--- a/testsuite/libnet.all/test_http.cpp 2010-01-01 17:48:26 +0000
+++ b/testsuite/libnet.all/test_http.cpp 2010-01-01 20:41:28 +0000
@@ -57,7 +57,7 @@
static void usage (void);
static void tests (void);
static void test_post (void);
-static void test_rtmpt (void);
+// static void test_rtmpt (void);
static TestState runtest;
@@ -349,6 +349,7 @@
// Decoding tests for HTTP
//
http.clearHeader();
+#if 0
boost::uint8_t *buffer = (boost::uint8_t *)"GET
/software/gnash/tests/flvplayer.swf?file=http://localhost/software/gnash/tests/Ouray_Ice_Festival_Climbing_Competition.flv
HTTP/1.1\r\n"
"User-Agent: Gnash/0.8.1-cvs (X11; Linux i686; U; en)\r\n"
"Host: localhost:4080\r\n"
@@ -362,7 +363,8 @@
"Referer: http://localhost/software/gnash/tests/index.html\r\n"
"TE: deflate, gzip, chunked, identity, trailers\r\n"
"\r\n";
-
+#endif
+
// GET /software/gnash/tests/ HTTP/1.1
// Host: localhost:4080
// User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.5)
Gecko/20070718 Fedora/2.0.0.5-1.fc7 Firefox/2.0.0.5
@@ -601,7 +603,7 @@
// FIXME: should be moved to server side only test case
// Check the Server field
AMF amf;
- boost::uint8_t *data1 = http.processHeaderFields(ptr1);
+ boost::uint8_t *data1 = http.processHeaderFields(&ptr1);
boost::shared_ptr<amf::Element> el1 = amf.extractAMF(data1, data1 + 15);
string str1 = el1->to_string();
@@ -630,7 +632,7 @@
ptr2 += *encnum;
ptr2.resize(); // shrink the buffer to be the exact size of
the data
- boost::uint8_t *data2 = http.processHeaderFields(ptr2);
+ boost::uint8_t *data2 = http.processHeaderFields(&ptr2);
boost::shared_ptr<amf::Element> el2 = amf.extractAMF(data2, data2 + 15);
if ((http.getField("host") == "localhost:5080")
&& (el2->to_number() == 1.2345)
=== modified file 'testsuite/libnet.all/test_rtmp.cpp'
--- a/testsuite/libnet.all/test_rtmp.cpp 2010-01-01 17:48:26 +0000
+++ b/testsuite/libnet.all/test_rtmp.cpp 2010-01-01 20:41:28 +0000
@@ -635,7 +635,6 @@
// props[3]->getName(), props[3]->to_string());
if ((msg1->getStatus() == RTMPMsg::NC_CONNECT_SUCCESS)
&& (msg1->getMethodName() == "_result")
- && (msg1->getStreamID() == 1)
&& (msg1->size() >= 1)) { // the msg has one element, which has 4
properties
runtest.pass("Decoded RTMP Result(NC_CONNECT_SUCCESS) message");
} else {
@@ -666,7 +665,6 @@
if (msg2) {
if ((msg2->getStatus() == RTMPMsg::NC_CONNECT_FAILED)
&& (msg2->getMethodName() == "_result")
- && (msg2->getStreamID() == 1)
&& (msg2->size() >= 1)) {
runtest.pass("Decoded RTMP result(NC_CONNECT_FAILED(as result)");
} else {
@@ -700,7 +698,6 @@
// std::vector<amf::Element *> hell4 = msg4->getElements();
if ((msg4->getStatus() == RTMPMsg::NS_PLAY_RESET)
&& (msg4->getMethodName() == "onStatus")
- && (msg4->getStreamID() == 0)
&& (msg4->size() >= 1)) {
runtest.pass("Encoded/Decoded RTMP onStatus(Play Reset)");
} else {
@@ -715,7 +712,6 @@
boost::shared_ptr<RTMPMsg> msg5 = rtmp.decodeMsgBody(*hex5);
if ((msg5->getStatus() == RTMPMsg::NS_DATA_START)
&& (msg5->getMethodName() == "onStatus")
- && (msg5->getStreamID() == -1)
&& (msg5->size() == 1)) {
runtest.pass("Encoded/Decoded RTMP onStatus(Data Start)");
} else {
@@ -735,7 +731,6 @@
boost::shared_ptr<RTMPMsg> msg6 = rtmp.decodeMsgBody(*hex6);
if ((msg6->getStatus() == RTMPMsg::NS_PLAY_START)
&& (msg6->getMethodName() == "onStatus")
- && (msg6->getStreamID() == 0)
&& (msg6->size() >= 1)) {
runtest.pass("Encoded/Decoded RTMP onStatus(Play Start)");
} else {
=== modified file 'testsuite/network.all/Makefile.am'
--- a/testsuite/network.all/Makefile.am 2010-01-01 17:48:26 +0000
+++ b/testsuite/network.all/Makefile.am 2010-01-01 20:41:28 +0000
@@ -61,14 +61,21 @@
$(OPENGL_LIBS) \
$(BOOST_LIBS) \
$(PTHREAD_LIBS)
+ $(MING_LIBS) \
$(NULL)
+if BUILD_SSL
+TEST_SSL = test_ssl
+endif
+if BUILD_SSH
+TEST_SSH = test_ssh
+endif
check_PROGRAMS = \
Dejagnu \
Dejagnu.swf \
- test_ssl \
test_allowDomain \
- test_ssh \
+ $(TEST_SSL) \
+ $(TEST_SSH) \
$(NULL)
check_SCRIPTS = \
@@ -85,6 +92,7 @@
libgnashmingutils_la_SOURCES = \
$(top_srcdir)/testsuite/misc-ming.all/ming_utils.h \
$(top_srcdir)/testsuite/misc-ming.all/ming_utils.c
+libgnashmingutils_la_LIBADD = $(MING_LIBS)
http.swf: $(srcdir)/http.as Dejagnu.swf Makefile ../actionscript.all/check.as
../actionscript.all/utils.as
$(MAKESWF) -n network -r12 -o $@ -v7 -DRED5_HOST='\"$(RED5_HOST)\"'
-DUSE_DEJAGNU_MODULE -DOUTPUT_VERSION=7 Dejagnu.swf $(srcdir)/http.as
$(srcdir)/../actionscript.all/dejagnu_so_fini.as
@@ -115,20 +123,23 @@
Dejagnu.swf: Dejagnu
./Dejagnu $(top_srcdir)/testsuite/media
+if BUILD_SSL
test_ssl_SOURCES = test_ssl.cpp
test_ssl_LDADD = \
$(top_builddir)/libbase/libgnashbase.la \
$(top_builddir)/libamf/libgnashamf.la \
$(top_builddir)/libnet/libgnashnet.la
+test_ssl_DEPENDENCIES = site-update
+endif
+if BUILD_SSH
test_ssh_SOURCES = test_ssh.cpp
test_ssh_LDADD = \
$(top_builddir)/libbase/libgnashbase.la \
$(top_builddir)/libamf/libgnashamf.la \
$(top_builddir)/libnet/libgnashnet.la
-
-test_ssl_DEPENDENCIES = site-update
-
+test_ssh_DEPENDENCIES = site-update
+endif
test_allowDomain_SOURCES = test_allowDomain.cpp
test_allowDomain_LDADD = \
=== modified file 'testsuite/network.all/test_ssl.cpp'
--- a/testsuite/network.all/test_ssl.cpp 2010-01-01 17:48:26 +0000
+++ b/testsuite/network.all/test_ssl.cpp 2010-01-01 20:41:28 +0000
@@ -91,6 +91,7 @@
exit(EXIT_FAILURE);
}
+#ifdef USE_SSL
bool servermode = false;
for( int i = 0; i < parser.arguments(); ++i ) {
@@ -164,14 +165,16 @@
cerr << _("This is a Gnash bug.") << endl;
}
}
-
+
if (servermode) {
test_server();
} else {
test_client();
}
+#endif
}
+#ifdef USE_SSL
static void test_client()
{
size_t ret;
@@ -265,6 +268,7 @@
server.sslAccept(net.getFileFd());
}
+#endif
static void
usage (void)
=== modified file 'utilities/flvdumper.cpp'
--- a/utilities/flvdumper.cpp 2010-01-01 17:48:26 +0000
+++ b/utilities/flvdumper.cpp 2010-01-01 20:41:28 +0000
@@ -189,7 +189,7 @@
Flv::previous_size_t previous = 0;
boost::shared_ptr<Flv::flv_tag_t> tag;
- // Make sure it's an SOL file
+ // Make sure it's an FLV file
if (stat(filespec.c_str(), &st) == 0) {
try {
// Open the binary file
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Gnash-commit] /srv/bzr/gnash/trunk r11741: Regenertated preformatted documentation after updating the copyright.,
Rob Savoye <=