gnash-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Gnash-commit] /srv/bzr/gnash/trunk r12162: partial scriptable support.


From: Rob Savoye
Subject: [Gnash-commit] /srv/bzr/gnash/trunk r12162: partial scriptable support. fixes Go Upgrade YouTube problem.
Date: Mon, 19 Apr 2010 17:46:40 -0600
User-agent: Bazaar (2.0.3)

------------------------------------------------------------
revno: 12162 [merge]
committer: Rob Savoye <address@hidden>
branch nick: trunk
timestamp: Mon 2010-04-19 17:46:40 -0600
message:
  partial scriptable support. fixes Go Upgrade YouTube problem.
modified:
  configure.ac
  gui/Player.cpp
  gui/gnash.cpp
  libcore/movie_root.cpp
  plugin/npapi/callbacks.cpp
  plugin/npapi/external.cpp
  plugin/npapi/external.h
  plugin/npapi/plugin.cpp
  plugin/npapi/plugin.h
  plugin/npapi/pluginScriptObject.cpp
  plugin/npapi/pluginScriptObject.h
  plugin/npapi/scriptable-test.html
  plugin/npapi/test.cpp
=== modified file 'configure.ac'
--- a/configure.ac      2010-04-10 20:59:49 +0000
+++ b/configure.ac      2010-04-16 22:07:49 +0000
@@ -289,7 +289,7 @@
     yes) scriptable=yes ;;
     no)  scriptable=no ;;
     *)   AC_MSG_ERROR([bad value ${enableval} for enable-scriptable option]) ;;
-  esac], scriptable=no
+  esac], scriptable=yes
 )
 AM_CONDITIONAL(SCRIPTABLE, [test x"$scriptable" = xyes])
 if test x$scriptable = xyes; then

=== modified file 'gui/Player.cpp'
--- a/gui/Player.cpp    2010-03-16 18:04:59 +0000
+++ b/gui/Player.cpp    2010-04-17 00:32:12 +0000
@@ -329,8 +329,11 @@
     }
 
     // Set _root._url (either explicit of from infile)
-    if (!url.empty()) _url = url;
-    else _url = infile;
+    if (!url.empty()) {
+        _url = url;
+    } else {
+        _url = infile;
+    }
 
     // Parse player parameters. These are not passed to the SWF, but rather
     // control stage properties etc.
@@ -417,7 +420,9 @@
     root.registerFSCommandCallback(_callbacksHandler.get());
 
     // Set host requests fd (if any)
-    if ( _hostfd != -1 ) root.setHostFD(_hostfd);
+    if ( _hostfd != -1 ) {
+        root.setHostFD(_hostfd);
+    }
 
     if (_controlfd != -1) {
         _gui->setFDCallback(_controlfd, boost::bind(&Gui::quit, 
boost::ref(_gui)));
@@ -433,7 +438,9 @@
     // because the gui window should be properly set up by this point.
     RcInitFile& rcfile = RcInitFile::getDefaultInstance();
 
-    if (rcfile.startStopped()) _gui->stop();
+    if (rcfile.startStopped()) {
+        _gui->stop();
+    }
 
     // Start loader thread
     // NOTE: the loader thread might (in IMPORT tag parsing)

=== modified file 'gui/gnash.cpp'
--- a/gui/gnash.cpp     2010-04-05 19:54:56 +0000
+++ b/gui/gnash.cpp     2010-04-19 22:58:02 +0000
@@ -26,6 +26,9 @@
 #include <iostream>
 #include <ios>
 #include <boost/format.hpp>
+#include <cstdlib>
+#include <sys/types.h>
+#include <fcntl.h>
 #ifdef ENABLE_NLS
 # include <clocale>
 #endif
@@ -118,7 +121,7 @@
     << _("                           1 enable rendering, disable sound\n") 
     << _("                           2 enable sound, disable rendering\n") 
     << _("                           3 enable rendering and sound 
(default)\n") 
-    // Only list the renderes that were configured in for this build
+    // Only list the renderers that were configured in for this build
     << _("  -R,  --Renderer <")
 #ifdef RENDERER_OPENGL
      << _(" opengl")
@@ -140,8 +143,6 @@
             "\"FlashVars=A=1&b=2\")\n") 
     << _("  -F,  --fd <fd>           Filedescriptor to use for external "
             "communications\n") 
-    << _("  -G,  --controlfd <fd>    File descriptor for external application"
-            " control\n")
 #ifdef GNASH_FPS_DEBUG
     << _("  -f,  --debug-fps num     Print FPS every num seconds (float)\n") 
 #endif // def GNASH_FPS_DEBUG
@@ -235,8 +236,7 @@
         { 'g', "debugger",          Arg_parser::no  },
         { 'V', "version",           Arg_parser::no  },        
         { 'f', "debug-fps",         Arg_parser::yes },        
-        { 'F', "fd",                Arg_parser::yes },
-        { 'G', "controlfd",         Arg_parser::yes },
+        { 'F', "fifo",              Arg_parser::yes },
         { 'A', "dump",              Arg_parser::yes },
         { 259, "screenshot",        Arg_parser::yes },
         { 260, "screenshot-file",   Arg_parser::yes },
@@ -322,26 +322,31 @@
                     break;
                 case 'F':
                 {
-                    const int fd = parser.argument<long>(i);
-                    if (fd < 1) {
-                        cerr << boost::format(_("Invalid host communication "
-                                    "filedescriptor %d\n")) % fd << endl;
-                        exit(EXIT_FAILURE);
-                    }
-                    player.setHostFD ( fd );
-                    break;
-                }
-                case 'G':
-                {
-                    const int fd = parser.argument<long>(i);
-                    if (fd < 1) {
-                        cerr << boost::format(_("Invalid host communication "
-                                    "filedescriptor %d\n")) % fd << endl;
-                        exit(EXIT_FAILURE);
-                    }
-                    player.setControlFD ( fd );
-                    break;
-                }
+                   const std::string& fds = parser.argument(i);
+                    fds.find(":");
+                    int hostfd = 0, controlfd = 0;
+                    hostfd = strtol(fds.substr(0, fds.find(":")).c_str(), 
NULL, 0);
+                    std::string csub = fds.substr(fds.find(":")+1, fds.size());
+                    controlfd = strtol(csub.c_str(), 0, 0);
+                    gnash::log_debug(_("Host FD #%d, Control FD #%d\n"), 
+                              hostfd, controlfd);
+                    if (hostfd < 0) {
+                        cerr << boost::format(_("Invalid host communication "
+                                               "filedescriptor %d\n"))
+                            % hostfd << endl;
+                        exit(EXIT_FAILURE);
+                    }
+                    player.setHostFD (hostfd);
+
+                    if (controlfd < 1) {
+                        cerr << boost::format(_("Invalid control communication 
"
+                                    "filedescriptor %d\n")) % controlfd << 
endl;
+//                        exit(EXIT_FAILURE);
+                        controlfd = hostfd + 1;
+                    }
+                    player.setControlFD (controlfd);
+                }
+                break;
                 case 'j':
                     widthGiven = true;
                     player.setWidth(parser.argument<long>(i));

=== modified file 'libcore/movie_root.cpp'
--- a/libcore/movie_root.cpp    2010-04-16 14:44:15 +0000
+++ b/libcore/movie_root.cpp    2010-04-19 23:10:08 +0000
@@ -1968,35 +1968,9 @@
         /// with complex urlOpenerFormats like:
         ///    firefox -remote 'openurl(%u)'
         ///
-        ///
-        /// NOTE: this escaping implementation is far from optimal, but
-        ///       I felt pretty in rush to fix the arbitrary command
-        ///      execution... we'll optimize if needed
-        ///
-        std::string safeurl = url.str(); 
-        boost::replace_all(safeurl, "\\", "\\\\");    // escape backslashes 
first
-        boost::replace_all(safeurl, "'", "\\'");    // then single quotes
-        boost::replace_all(safeurl, "\"", "\\\"");    // double quotes
-        boost::replace_all(safeurl, ";", "\\;");    // colons
-        boost::replace_all(safeurl, " ", "\\ ");    // spaces
-        boost::replace_all(safeurl, ">", "\\>");    // output redirection
-        boost::replace_all(safeurl, "<", "\\<");    // input redirection
-        boost::replace_all(safeurl, "&", "\\&");    // background (sic)
-        boost::replace_all(safeurl, "\n", "\\n");    // newline
-        boost::replace_all(safeurl, "\r", "\\r");    // return
-        boost::replace_all(safeurl, "\t", "\\t");    // tab
-        boost::replace_all(safeurl, "|", "\\|");    // pipe
-        boost::replace_all(safeurl, "`", "\\`");    // backtick
-
-        boost::replace_all(safeurl, "(", "\\(");    // subshell :'(
-        boost::replace_all(safeurl, ")", "\\)");    // 
-        boost::replace_all(safeurl, "}", "\\}");    // 
-        boost::replace_all(safeurl, "{", "\\{");    // 
-
-        boost::replace_all(safeurl, "$", "\\$");    // variable expansions
-
+        std::string safeurl = url.encode(urlstr);
         boost::replace_all(command, "%u", safeurl);
-
+        
         log_debug (_("Launching URL: %s"), command);
         std::system(command.c_str());
         return;

=== modified file 'plugin/npapi/callbacks.cpp'
--- a/plugin/npapi/callbacks.cpp        2010-04-15 20:13:21 +0000
+++ b/plugin/npapi/callbacks.cpp        2010-04-17 02:44:32 +0000
@@ -141,7 +141,7 @@
         varname = NPVARIANT_TO_STRING(args[0]).UTF8Characters;
         value = gpso->GetVariable(varname);
         if (value == 0) {
-            NPVARIANT_IS_NULL(*result);
+            NULL_TO_NPVARIANT(*result);
         } else {
             if (NPVARIANT_IS_DOUBLE(*value)) {
                 double num = NPVARIANT_TO_DOUBLE(*value);
@@ -382,7 +382,7 @@
     
     GnashPluginScriptObject *gpso = (GnashPluginScriptObject *)npobj;
 
-#if 0
+#if 1
     static int counter = 0;
 //    log_error("%s: %d ; %d\n", __FUNCTION__, gpso->getControlFD(), counter);
     INT32_TO_NPVARIANT(counter, *result);

=== modified file 'plugin/npapi/external.cpp'
--- a/plugin/npapi/external.cpp 2010-04-15 20:19:54 +0000
+++ b/plugin/npapi/external.cpp 2010-04-19 23:03:36 +0000
@@ -30,7 +30,9 @@
 #include "npapi.h"
 #include "npruntime.h"
 #include "external.h"
+#include "plugin.h"
 
+#include <boost/algorithm/string/erase.hpp>
 
 ExternalInterface::ExternalInterface ()
 {
@@ -184,7 +186,6 @@
 {
     std::stringstream ss;
     std::map<std::string, std::string>::iterator it;
-    int index = 0;
 
     ss << "<object>";
     for (it = args.begin(); it != args.end(); ++it) {
@@ -195,9 +196,64 @@
     return ss.str();
 }
 
+// An invoke looks like this:
+// <invoke name=\"foobar\" returntype=\"xml\">
+//      <arguments>
+//              <string>barfoo</string>
+//              <number>135.78</number>
+//      </arguments>
+// </invoke>
+ExternalInterface::invoke_t *
+ExternalInterface::parseInvoke(const std::string &xml)
+{
+    if (xml.empty()) {
+        return 0;
+    }
+    
+    ExternalInterface::invoke_t *invoke = new invoke_t;
+    
+    std::string::size_type start = 0;
+    std::string::size_type end;
+    std::string tag;
+
+    // Look for the ending > in the first part of the data for the tag
+    end = xml.find(">");
+    if (end != std::string::npos) {
+        end++;                  // go past the > character
+        tag = xml.substr(start, end);
+        // Look for the easy ones first
+        if (tag.substr(0, 7) == "<invoke") {
+            // extract the name of the method to invoke
+            start = tag.find("name=") + 5;
+            end   = tag.find(" ", start);
+            invoke->name  = tag.substr(start, end-start);
+            // Ignore any quote characters around the string
+            boost::erase_first(invoke->name, "\"");
+            boost::erase_last(invoke->name, "\"");
+
+            // extract the return type of the method
+            start = tag.find("returntype=") + 11;
+            end   = tag.find(">", start);
+            invoke->type  = tag.substr(start, end-start);
+            // Ignore any quote characters around the string
+            boost::erase_first(invoke->type, "\"");
+            boost::erase_last(invoke->type, "\"");
+
+            // extract the arguments to the method
+            start = xml.find("<arguments>");
+            end   = xml.find("</invoke");
+            tag   = xml.substr(start, end-start);
+            invoke->args = parseArguments(tag);
+        }
+    }
+
+    return invoke;
+}
+
 NPVariant *
 ExternalInterface::parseXML(const std::string &xml)
 {
+
     NPVariant *value =  (NPVariant *)NPN_MemAlloc(sizeof(NPVariant));
     NULL_TO_NPVARIANT(*value);
     

=== modified file 'plugin/npapi/external.h'
--- a/plugin/npapi/external.h   2010-04-15 20:19:54 +0000
+++ b/plugin/npapi/external.h   2010-04-18 00:32:42 +0000
@@ -34,6 +34,12 @@
 class ExternalInterface
 {
 public:
+    typedef struct {
+        std::string name;
+        std::string type;
+        std::vector<NPVariant *> args;
+    } invoke_t;
+    
     ExternalInterface ();
     ~ExternalInterface ();
     
@@ -54,6 +60,8 @@
     std::string makeObject (std::map<std::string, std::string> &args);
     
     NPVariant *parseXML(const std::string &xml);
+    invoke_t *parseInvoke(const std::string &xml);
+    
     std::map<std::string, NPVariant *> parseProperties(const std::string &xml);
     std::vector<NPVariant *> parseArguments(const std::string &xml);
     std::string convertNPVariant (const NPVariant *npv);

=== modified file 'plugin/npapi/plugin.cpp'
--- a/plugin/npapi/plugin.cpp   2010-04-15 20:19:54 +0000
+++ b/plugin/npapi/plugin.cpp   2010-04-19 23:01:59 +0000
@@ -62,8 +62,6 @@
   <br>\
   Compatible Shockwave Flash "FLASH_VERSION
 
-//#define WRITE_FILE
-
 // Defining this flag disables the pipe to the standalone player, as well
 // as prevents the standalone Gnash player from being exec'd. Instead it
 // makes a network connection to localhost:1111 so the developer can use
@@ -361,7 +359,7 @@
     }
 
 #ifdef ENABLE_SCRIPTABLE
-    _scriptObject = NPNFuncs.createobject(_instance, 
GnashPluginScriptObject::marshalGetNPClass());
+    _scriptObject = (GnashPluginScriptObject 
*)NPNFuncs.createobject(_instance, 
GnashPluginScriptObject::marshalGetNPClass());
 #endif
 #if defined(ENABLE_SCRIPTABLE) && defined(NETTEST)
     // This is a network testing node switch. This is only used for testing the
@@ -384,8 +382,7 @@
         if (ret == 0) {
             log_debug("Connected to debug server on fd #%d", sockfd);
             _controlfd = sockfd;
-            GnashPluginScriptObject *gpso = (GnashPluginScriptObject 
*)_scriptObject;
-            gpso->setControlFD(_controlfd);
+            _scriptObject->setControlFD(_controlfd);
         } else {
             log_debug("Couldn't connect to debug server: %s", strerror(errno));
         }
@@ -421,7 +418,7 @@
 /// \brief Destructor
 nsPluginInstance::~nsPluginInstance()
 {
-    log_debug("plugin instance destruction");
+//    log_debug("plugin instance destruction");
 
     if ( _ichanWatchId ) {
         g_source_remove(_ichanWatchId);
@@ -496,6 +493,11 @@
             log_error("Gnash plugin failed to close the control socket!");
         }
     }
+
+// #ifdef ENABLE_SCRIPTABLE
+//     _scriptObject->closePipe();
+// #endif
+
 }
 /// \brief Set the window to be used to render in
 ///
@@ -556,7 +558,7 @@
     return NS_PluginGetValue(aVariable, aValue);
 }
 
-#if 1
+#if 0
 // FIXME: debugging stuff, will be gone soon after I figure how this works
 void myfunc(void */* param */)
 {
@@ -602,27 +604,6 @@
     
     log_debug("The full URL is %s", _swf_url);
 
-#ifdef WRITE_FILE
-    size_t start, end;
-    std::string fname;
-    end   = _swf_url.find(".swf", 0) + 4;
-    start = _swf_url.rfind("/", end) + 1;
-    fname = "/tmp/";
-    fname += _swf_url.substr(start, end - start);
-
-    log_debug("The Flash movie name is: %s", fname);
-
-    _filefd = open(fname.c_str(),
-            O_CREAT | O_WRONLY,
-            S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
-    
-    if (_filefd < 0) {
-        _filefd = open(fname.c_str(),
-                O_TRUNC | O_WRONLY,
-                S_IRUSR | S_IRGRP | S_IROTH);
-    }
-#endif
-    
     if (!_swf_url.empty() && _window) {
         startProc();
     }
@@ -643,16 +624,6 @@
         }
     }
 
-#ifdef WRITE_FILE
-    if (_filefd != -1) {
-        if (close(_filefd) == -1) {
-            perror("closing _filefd");
-        } else {
-            _filefd = -1;
-        }
-    }
-#endif
-
     return NPERR_NO_ERROR;
 }
 
@@ -675,9 +646,6 @@
 nsPluginInstance::Write(NPStream* /*stream*/, int32_t /*offset*/, int32_t len,
         void* buffer)
 {
-#ifdef WRITE_FILE
-    write(_filefd, buffer, len);
-#endif
     int written = write(_streamfd, buffer, len);
     return written;
 }
@@ -686,12 +654,16 @@
 nsPluginInstance::handlePlayerRequestsWrapper(GIOChannel* iochan,
         GIOCondition cond, nsPluginInstance* plugin)
 {
+    log_trace(__PRETTY_FUNCTION__);
+    
     return plugin->handlePlayerRequests(iochan, cond);
 }
 
 bool
 nsPluginInstance::handlePlayerRequests(GIOChannel* iochan, GIOCondition cond)
 {
+    log_trace(__PRETTY_FUNCTION__);
+    
     if ( cond & G_IO_HUP ) {
         log_debug("Player request channel hang up");
         // Returning false here will cause the "watch" to be removed. This 
watch
@@ -703,15 +675,15 @@
 
     assert(cond & G_IO_IN);
 
-    log_debug("Checking player requests on fd #%d", 
g_io_channel_unix_get_fd(iochan));
+    log_debug("Checking player requests on fd #%d",
+              g_io_channel_unix_get_fd(iochan));
 
     do {
         GError* error=NULL;
         gchar* request;
         gsize requestSize=0;
         GIOStatus status = g_io_channel_read_line(iochan, &request,
-                &requestSize, NULL, &error);
-
+                           &requestSize, NULL, &error);
         switch ( status ) {
             case G_IO_STATUS_ERROR:
                 log_error(std::string("Error reading request line: ") + 
error->message);
@@ -769,8 +741,7 @@
             return false;
         }
 
-        log_debug("Asked to get URL '%s''", url);
-        log_debug("In target '%s'", target);
+        log_debug("Asked to get URL '%s' in target %s", url, target);
         NPN_GetURL(_instance, url, target);
         return true;
 
@@ -943,17 +914,20 @@
     }
 
     std::stringstream pars;
-    pars << "-x "  <<  _window           // X window ID to render into
-         << " -j " << _width             // Width of window
-         << " -k " << _height            // Height of window
-         << " -F " << hostfd             // Socket to send commands to
-         << " -G " << controlfd;         // Socket determining lifespan
-    {
-        std::string pars_str = pars.str();
-        typedef boost::char_separator<char> char_sep;
-        boost::tokenizer<char_sep> tok(pars_str, char_sep(" "));
-        arg_vec.insert(arg_vec.end(), tok.begin(), tok.end());
+    pars << "-x "  <<  _window          // X window ID to render into
+         << " -j " << _width            // Width of window
+         << " -k " << _height;           // Height of window
+#if GNASH_PLUGIN_DEBUG > 1
+    pars << " -vv ";
+#endif
+    if ((hostfd > 0) && (controlfd)) {
+        pars << " -F " << hostfd            // Socket to send commands to
+             << ":"    << controlfd;        // Socket determining lifespan
     }
+    std::string pars_str = pars.str();
+    typedef boost::char_separator<char> char_sep;
+    boost::tokenizer<char_sep> tok(pars_str, char_sep(" "));
+    arg_vec.insert(arg_vec.end(), tok.begin(), tok.end());
 
     for (std::map<std::string,std::string>::const_iterator it = 
_params.begin(),
         itEnd = _params.end(); it != itEnd; ++it) {
@@ -1020,8 +994,6 @@
 {
     // 0 For reading, 1 for writing.
     int p2c_pipe[2];
-    int c2p_pipe[2];
-    int p2c_controlpipe[2];
     
     int ret = pipe(p2c_pipe);
     if (ret == -1) {
@@ -1030,12 +1002,15 @@
     }
     _streamfd = p2c_pipe[1];
 
+#if 0
+    int c2p_pipe[2];
     ret = pipe(c2p_pipe);
     if (ret == -1) {
         log_error("ERROR: child to parent pipe() failed: " +
                  std::string(std::strerror(errno)));
     }
 
+    int p2c_controlpipe[2];
     ret = pipe(p2c_controlpipe);
     if (ret == -1) {
         log_error("ERROR: parent to child pipe() failed: " +
@@ -1043,20 +1018,22 @@
     }
 
     _controlfd = p2c_controlpipe[1];
+#endif
     
 #ifdef ENABLE_SCRIPTABLE
-    GnashPluginScriptObject *gpso = (GnashPluginScriptObject *)_scriptObject;
+    _scriptObject->createPipe();
+//    _controlfd = _scriptObject->getReadFD();
+//    _scriptObject->checkPipe();
 #ifdef NETTEST
-    gpso->setControlFD(_controlfd);
+    _scriptObject->setControlFD(_controlfd);
 #endif
 #endif
     
-    /*
-    Setup the command line for starting Gnash
-    */
-
-    std::vector<std::string> arg_vec = getCmdLine(c2p_pipe[1],
-                                                  p2c_controlpipe[0]);
+    // Setup the command line for starting Gnash
+
+    std::vector<std::string> arg_vec = getCmdLine(_scriptObject->getReadFD(),
+                                                  _scriptObject->getWriteFD());
+
     if (arg_vec.empty()) {
         log_error("Failed to obtain command line parameters.");
         return;
@@ -1068,9 +1045,7 @@
                    std::mem_fun_ref(&std::string::c_str));
     args.push_back(0);
     
-    /*
-      Argument List prepared, now fork(), close file descriptors and execv()
-    */
+    // Argument List prepared, now fork(), close file descriptors and execv()
     
     _childpid = fork();
     
@@ -1089,7 +1064,7 @@
             log_error("ERROR: p2c_pipe[0] close() failed: " +
                           std::string(strerror(errno)));
         }
-        
+#if 0
         // we want to read from c2p pipe, so close write-fd1
         ret = close (c2p_pipe[1]);
         if (ret == -1) {
@@ -1098,15 +1073,10 @@
         }
         
         ret = close (p2c_controlpipe[0]); // close read descriptor
+#endif
         
         log_debug("Forked successfully, child process PID is %d" , _childpid);
-        
-        GIOChannel* ichan = g_io_channel_unix_new(c2p_pipe[0]);
-        g_io_channel_set_close_on_unref(ichan, true);
-        _ichanWatchId = g_io_add_watch(ichan, 
-                                       (GIOCondition)(G_IO_IN|G_IO_HUP), 
-                                       (GIOFunc)handlePlayerRequestsWrapper, 
this);
-        g_io_channel_unref(ichan);
+      
         return;
     }
     
@@ -1126,7 +1096,7 @@
     // Close all of the browser's file descriptors that we just inherited
     // (including p2c_pipe[0] that we just dup'd to fd 0), but obviously
     // not the file descriptors that we want the child to use.
-    int dontclose[] = {c2p_pipe[1], p2c_controlpipe[0]};
+    int dontclose[] = {_scriptObject->getReadFD(), 
_scriptObject->getWriteFD()};
     close_fds(dontclose);
 
     // Start the desired executable and go away.
@@ -1208,13 +1178,27 @@
     std::cerr << "ERROR: " << fmt.str() << std::endl;
 }
 
+#if GNASH_PLUGIN_DEBUG > 1
 void
 processLog_debug(const boost::format& fmt)
 {
-#if GNASH_PLUGIN_DEBUG > 1
     std::cout << "DEBUG: " << fmt.str() << std::endl;
+}
+
+void
+processLog_trace(const boost::format& fmt)
+{
+    std::cout << "TRACE: " << fmt.str() << std::endl;
+}
+#else
+void
+processLog_debug(const boost::format& fmt)
+{ /* do nothing */ }
+
+void
+processLog_trace(const boost::format& fmt)
+{ /* do nothing */ }
 #endif
-}
 
 // Local Variables:
 // mode: C++

=== modified file 'plugin/npapi/plugin.h'
--- a/plugin/npapi/plugin.h     2010-04-15 20:19:54 +0000
+++ b/plugin/npapi/plugin.h     2010-04-19 23:46:40 +0000
@@ -35,7 +35,7 @@
 #endif
 
 #ifndef HAVE_PRETTY_FUNCTION
-       #define __PRETTY_FUNCTION__ __FUNCTION__
+# define __PRETTY_FUNCTION__ __FUNCTION__
 #endif
 
 /* Xlib/Xt stuff */
@@ -54,6 +54,7 @@
 #include <boost/preprocessor/seq/for_each.hpp>
 
 #include "pluginbase.h"
+#include "pluginScriptObject.h"
 
 extern NPBool      plugInitialized;
 
@@ -71,10 +72,13 @@
     NPError GetValue(NPPVariable variable, void *value);
     NPError SetWindow(NPWindow *aWindow);
 
+    /// Open a new stream. THis is called every time there is swf content.
     NPError NewStream(NPMIMEType type, NPStream *stream, NPBool seekable,
                       uint16_t *stype);
+    /// Destroy the stream
     NPError DestroyStream(NPStream * stream, NPError reason);
 
+    /// Can the stream be written to yet ?
     int32_t WriteReady(NPStream *stream);
     int32_t Write(NPStream *stream, int32_t offset, int32_t len, void *buffer);
 #ifdef ENABLE_SCRIPTABLE
@@ -85,7 +89,6 @@
 private:
     void startProc();
     std::vector<std::string> getCmdLine(int hostfd, int controlfd);
-
     static bool handlePlayerRequestsWrapper(GIOChannel* iochan, GIOCondition 
cond, nsPluginInstance* plugin);
 
     bool handlePlayerRequests(GIOChannel* iochan, GIOCondition cond);
@@ -124,7 +127,7 @@
     /// Name of the plugin instance element in the dom 
     std::string                        _name;
 #ifdef ENABLE_SCRIPTABLE
-    NPObject                            *_scriptObject;
+    GnashPluginScriptObject             *_scriptObject;
 #endif
     
     const char* getCurrentPageURL() const;
@@ -145,6 +148,7 @@
 // memory footprint down.
 DSOEXPORT void processLog_error(const boost::format& fmt);
 DSOEXPORT void processLog_debug(const boost::format& fmt);
+DSOEXPORT void processLog_trace(const boost::format& fmt);
 
 /// This heap of steaming preprocessor code magically converts
 /// printf-style statements into boost::format messages using templates.
@@ -161,10 +165,10 @@
 /// This is a sequence of different log message types to be used in
 /// the code. Append the name to log_ to call the function, e.g. 
 /// log_error, log_unimpl.
-#define LOG_TYPES (error) (debug)
+#define LOG_TYPES (error) (debug) (trace)
 /// The preprocessor generates templates with 1..ARG_NUMBER
 /// arguments.
-#define ARG_NUMBER 2
+#define ARG_NUMBER 4
 #define LOG_TEMPLATES(z, n, data)\
 template<BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(n), typename T)>\
 inline void log_##data(BOOST_PP_REPEAT(BOOST_PP_INC(n), TOKENIZE_ARGS, t)) \

=== modified file 'plugin/npapi/pluginScriptObject.cpp'
--- a/plugin/npapi/pluginScriptObject.cpp       2010-04-15 20:19:54 +0000
+++ b/plugin/npapi/pluginScriptObject.cpp       2010-04-19 23:03:02 +0000
@@ -28,6 +28,10 @@
 #include <fcntl.h>
 #include <cstring>
 #include <cstdlib>
+#include <cstdio>
+#include <cerrno>
+#include <sys/types.h>
+#include <unistd.h>
 #if defined(HAVE_WINSOCK_H) && !defined(__OS2__)
 # include <winsock2.h>
 # include <windows.h>
@@ -35,9 +39,12 @@
 # include <io.h>
 # include <ws2tcpip.h>
 #else
+# include <sys/un.h>
 # include <sys/ioctl.h>
 # include <unistd.h>
 # include <sys/select.h>
+# include <netinet/in.h>
+# include <arpa/inet.h>
 #endif
 #include "npapi.h"
 #include "npruntime.h"
@@ -221,59 +228,46 @@
     AddProperty("onbeforedeactivate", "unknown");
     AddProperty("ondeactivate", "unknown");
     
-#if 0
-   for (int i = 0; i < NUM_METHOD_IDENTIFIERS; i++) {
-       SetProperty(pluginMethodIdentifiers[i], value);
-   }
-   
-   // fill the method identifier array
-   NPNFuncs.getstringidentifiers(pluginMethodIdentifierNames,
-                                 NUM_METHOD_IDENTIFIERS,
-                                 pluginMethodIdentifiers);
-#endif
-//     NPIdentifier id = NPN_GetStringIdentifier("showFoobar");
-//    NPInvokeFunctionPtr func = testfunc;  
-//    AddMethod(id, func);
-
-   NPIdentifier id = NPN_GetStringIdentifier("SetVariable");
-   AddMethod(id, SetVariableCallback);
-
-   id = NPN_GetStringIdentifier("GetVariable");
-   AddMethod(id, GetVariableCallback);
-
-   id = NPN_GetStringIdentifier("GotoFrame");
-   AddMethod(id, GotoFrame);
-
-   id = NPN_GetStringIdentifier("IsPlaying");
-   AddMethod(id, IsPlaying);
-
-   id = NPN_GetStringIdentifier("LoadMovie");
-   AddMethod(id, LoadMovie);
-
-   id = NPN_GetStringIdentifier("Pan");
-   AddMethod(id, Pan);
-
-   id = NPN_GetStringIdentifier("PercentLoaded");
-   AddMethod(id, PercentLoaded);
-
-   id = NPN_GetStringIdentifier("Play");
-   AddMethod(id, Play);
-
-   id = NPN_GetStringIdentifier("Rewind");
-   AddMethod(id, Rewind);
-
-   id = NPN_GetStringIdentifier("SetZoomRect");
-   AddMethod(id, SetZoomRect);
-
-   id = NPN_GetStringIdentifier("StopPlay");
-   AddMethod(id, StopPlay);
-
-   id = NPN_GetStringIdentifier("Zoom");
-   AddMethod(id, Zoom);
-
-   id = NPN_GetStringIdentifier("TotalFrames");
-   AddMethod(id, TotalFrames);
-   
+    // Add the default methods
+    NPIdentifier id = NPN_GetStringIdentifier("SetVariable");
+    AddMethod(id, SetVariableCallback);
+    
+    id = NPN_GetStringIdentifier("GetVariable");
+    AddMethod(id, GetVariableCallback);
+    
+    id = NPN_GetStringIdentifier("GotoFrame");
+    AddMethod(id, GotoFrame);
+    
+    id = NPN_GetStringIdentifier("IsPlaying");
+    AddMethod(id, IsPlaying);
+    
+    id = NPN_GetStringIdentifier("LoadMovie");
+    AddMethod(id, LoadMovie);
+    
+    id = NPN_GetStringIdentifier("Pan");
+    AddMethod(id, Pan);
+    
+    id = NPN_GetStringIdentifier("PercentLoaded");
+    AddMethod(id, PercentLoaded);
+    
+    id = NPN_GetStringIdentifier("Play");
+    AddMethod(id, Play);
+    
+    id = NPN_GetStringIdentifier("Rewind");
+    AddMethod(id, Rewind);
+    
+    id = NPN_GetStringIdentifier("SetZoomRect");
+    AddMethod(id, SetZoomRect);
+    
+    id = NPN_GetStringIdentifier("StopPlay");
+    AddMethod(id, StopPlay);
+    
+    id = NPN_GetStringIdentifier("Zoom");
+    AddMethod(id, Zoom);
+    
+    id = NPN_GetStringIdentifier("TotalFrames");
+    AddMethod(id, TotalFrames);
+    
 };
 
 // Constructor
@@ -282,6 +276,9 @@
 {
 //    log_debug(__PRETTY_FUNCTION__);
     initializeIdentifiers();
+    
+    _sockfds[READFD] = 0;
+    _sockfds[WRITEFD] = 0;
 }
 
 // Constructor
@@ -290,27 +287,31 @@
 {
 //    log_debug(__PRETTY_FUNCTION__);
     initializeIdentifiers();
+
+    _sockfds[READFD] = 0;
+    _sockfds[WRITEFD] = 0;
 }
 
 // Destructor
 GnashPluginScriptObject::~GnashPluginScriptObject() 
 {
-    // log_debug(__PRETTY_FUNCTION__);
-    // do nothing
+//    log_debug(__PRETTY_FUNCTION__);
+// Should be automatically shutdown by GIO
+//    closePipe();
 }
 
 // Marshal Functions
 NPClass *
 GnashPluginScriptObject::marshalGetNPClass() 
 {
-    // log_debug(__PRETTY_FUNCTION__);
+//    log_debug(__PRETTY_FUNCTION__);
     return &GnashPluginScriptObjectClass;
 }
 
 NPObject *
 GnashPluginScriptObject::marshalAllocate (NPP npp, NPClass */* aClass */)
 {
-    log_debug(__PRETTY_FUNCTION__);
+//    log_debug(__PRETTY_FUNCTION__);
 #if 0
     GnashPluginScriptObject *npobj = reinterpret_cast<GnashPluginScriptObject 
*>
         (NPN_MemAlloc(sizeof(GnashPluginScriptObject)));
@@ -325,7 +326,7 @@
 void 
 GnashPluginScriptObject::marshalDeallocate (NPObject *npobj)
 {
-    log_debug(__PRETTY_FUNCTION__);
+//    log_debug(__PRETTY_FUNCTION__);
 #if 0
     NPN_MemFree(reinterpret_cast<void *>(npobj));
 #else
@@ -336,7 +337,7 @@
 void 
 GnashPluginScriptObject::marshalInvalidate (NPObject */* npobj */)
 {
-    log_debug(__PRETTY_FUNCTION__);
+//    log_debug(__PRETTY_FUNCTION__);
 
 //    gpso->Invalidate();
 }
@@ -692,14 +693,27 @@
     iargs.push_back(str);
     str = ei.makeInvoke("GetVariable", iargs);
 
+    log_debug("Trying to get a value for %s.", name);
+    
+    NPVariant *value = 0;
     size_t ret = writePlayer(controlfd, str);
     if (ret != str.size()) {
-        log_error("Couldn't send GetVariable request, network problems.");
-        return false;
+        // If all the browser wants is the version, we don't need to
+        // ask the standalone player for this value. YouTube at
+        // least depends on this for some pages which want this to
+        // be greater than 8.0.0. This appears to potentially be
+        // Google's way of trying to revent downloaders, as this requires
+        // plugin support.
+        if (name == "$version") {
+            value =  (NPVariant *)NPN_MemAlloc(sizeof(NPVariant));
+            STRINGZ_TO_NPVARIANT(strdup("LNX 10,0,r999"), *value);
+        } else {
+            log_error("Couldn't send GetVariable request, network problems.");
+        }
+        return value;
     }
 
     // Have the read function allocate the memory
-    NPVariant *value = 0;
     const char *data = 0;
     char *ptr = 0;
     ptr = const_cast<char *>(data);
@@ -724,24 +738,37 @@
 GnashPluginScriptObject::setControlFD(int x)
 {
 //    log_debug("%s: %d", __FUNCTION__, x);
-    
-    controlfd = x;
+#if 0
+    if (_iochan == 0) {
+        _iochan[WRITEFD] = g_io_channel_unix_new(x);
+    }
+#endif
+    controlfd = x;              // FIXME: this should go away
 }
 
 int
 GnashPluginScriptObject::getControlFD()
 {
-    log_debug("getControlFD: %d", controlfd);
-    
+// log_debug("getControlFD: %d", controlfd);
+
+#if 0
+    return g_io_channel_unix_get_fd (_iochan);
+#endif    
     return controlfd;
 };
 
 
 // Write to the standalone player over the control socket
 int
+GnashPluginScriptObject::writePlayer(const std::string &data)
+{
+    return writePlayer(_sockfds[WRITEFD], data);
+}
+
+int
 GnashPluginScriptObject::writePlayer(int fd, const std::string &data)
 {
-    log_debug(__PRETTY_FUNCTION__);
+//    log_debug(__PRETTY_FUNCTION__);
 
 //    log_debug("Writing data: %s", data);
 
@@ -753,9 +780,15 @@
 }
 
 int
+GnashPluginScriptObject::writePlayer(const char *data, size_t length)
+{
+    return writePlayer(_sockfds[WRITEFD], data, length);
+}
+
+int
 GnashPluginScriptObject::writePlayer(int fd, const char *data, size_t length)
 {
-    log_debug(__PRETTY_FUNCTION__);    
+    // log_debug(__PRETTY_FUNCTION__);    
 
     if (fd > 2) {
         return ::write(fd, data, length);
@@ -768,13 +801,27 @@
 
 // Read the standalone player over the control socket
 int
-GnashPluginScriptObject::readPlayer(int /* fd */, const std::string &/* data 
*/)
-{
-//    log_debug(__PRETTY_FUNCTION__);
-
-//    return readPlayer(fd, data.c_str(), data.size());
-
-    return -1;
+GnashPluginScriptObject::readPlayer(const std::string &data)
+{
+//    log_debug(__PRETTY_FUNCTION__);
+
+    const char *ptr = data.c_str();
+    return readPlayer(_sockfds[READFD], &ptr, data.size());
+}
+
+int
+GnashPluginScriptObject::readPlayer(int fd, const std::string &data)
+{
+//    log_debug(__PRETTY_FUNCTION__);
+
+    const char *ptr = data.c_str();
+    return readPlayer(fd, &ptr, data.size());
+}
+
+int
+GnashPluginScriptObject::readPlayer(const char **data, size_t length)
+{
+    return readPlayer(_sockfds[READFD], data, length);
 }
 
 int
@@ -791,7 +838,7 @@
         struct timeval tval;
         tval.tv_sec = 10;
         tval.tv_usec = 0;
-        log_debug("Waiting for data... ");
+        // log_debug("Waiting for data... ");
         if (select(fd+1, &fdset, NULL, NULL, &tval)) {
             // log_debug("There is data in the network");
 #ifndef _WIN32
@@ -804,11 +851,11 @@
         }
         
 
-        log_debug("There are %d bytes in the network buffer", bytes);
         // No data yet
         if (bytes == 0) {
             return 0;
         }
+        log_debug("There are %d bytes in the network buffer", bytes);
 
         char *buf = 0;
         if (*data == 0) {
@@ -823,11 +870,222 @@
         if (ret == bytes) {
             *data = buf;
         }
+
+        std::cout << buf << std::endl;
         return ret;
     }
     
     return 0;
-}   
+}
+
+
+// Close the socket
+bool
+GnashPluginScriptObject::closePipe(int fd)
+{
+//     log_debug(__FUNCTION__);
+    
+    if (fd > 0) {
+        ::shutdown(fd, SHUT_RDWR);
+        ::close(fd);
+    }
+
+    return true;
+}
+
+// Create a socket so we can talk to the player.
+bool
+GnashPluginScriptObject::createPipe()
+{
+    log_trace(__PRETTY_FUNCTION__);
+
+    if ((_sockfds[READFD] == 0) && (_sockfds[WRITEFD] == 0)) {
+        int ret = socketpair(AF_UNIX, SOCK_STREAM, 0, _sockfds);
+    
+        if (ret == 0) {
+            // Set up the Glib IO Channel for reading from the plugin
+//            log_debug("Read fd for socketpair is: %d", _sockfds[READFD]);
+            
+            _iochan[READFD]  = g_io_channel_unix_new(_sockfds[READFD]);
+            g_io_channel_set_close_on_unref(_iochan[READFD], true);
+            _watchid = g_io_add_watch(_iochan[READFD], 
+                                      (GIOCondition)(G_IO_IN|G_IO_HUP), 
+                                      (GIOFunc)handleInvokeWrapper, this);
+            
+            // Set up the Glib IO Channel for writing to the plugin
+//            log_debug("Write fd for socketpair is: %d", _sockfds[WRITEFD]);
+            _iochan[WRITEFD] = g_io_channel_unix_new(_sockfds[WRITEFD]);
+            g_io_channel_set_close_on_unref(_iochan[WRITEFD], true);
+            return true;
+        }
+    }
+    
+#if 0
+    std::stringstream ss;
+    static int count = 0;
+    ss << "/tmp/gnash-" << getpid() << count++;
+
+    return createPipe(ss.str());
+#endif
+
+    return false;
+}
+
+#if 0
+bool
+GnashPluginScriptObject::createPipe(const std::string &name)
+{
+    log_debug(__PRETTY_FUNCTION__);
+
+    mode_t mode = S_IRUSR|S_IWUSR;
+    if (!name.empty()) {
+        int ret = mkfifo(name.c_str(), mode);
+        if (ret == 0) {
+            _sockfd = ::open(name.c_str(), O_RDWR|O_NONBLOCK, mode);
+            if (_sockfd < 0) {
+                log_error("Couldn't open the pipe: \"%s\"", strerror(errno));
+            }
+        } else {
+            log_error("Couldn't create fifo: s\n", strerror(errno));
+        }
+    }
+
+    _pipename = name;
+    
+    return false;
+}
+#endif
+
+
+// Close the socketpair
+bool
+GnashPluginScriptObject::closePipe()
+{
+//     log_debug(__FUNCTION__);
+
+    bool ret = closePipe(_sockfds[READFD]);
+    if (ret) {
+        ret = closePipe(_sockfds[WRITEFD]);
+    } else {
+        return false;
+    }
+
+    GError *error;
+    GIOStatus rstatus = g_io_channel_shutdown(_iochan[READFD], true, &error);
+    GIOStatus wstatus = g_io_channel_shutdown(_iochan[WRITEFD], true, &error);
+    if ((rstatus == G_IO_STATUS_NORMAL)
+        && (wstatus == G_IO_STATUS_NORMAL)) {
+        return true;
+    } else {
+        return false;
+    }
+
+    return false;
+}
+
+// Check the pipe to see if it's ready, ie... is gnash connected yet ?
+bool
+GnashPluginScriptObject::checkPipe()
+{
+    return checkPipe(_sockfds[WRITEFD]);
+}
+
+bool
+GnashPluginScriptObject::checkPipe(int fd)
+{
+//    log_debug(__PRETTY_FUNCTION__);
+    
+    fd_set fdset;
+        
+    if (fd > 2) {
+        FD_ZERO(&fdset);
+        FD_SET(fd, &fdset);
+       struct timeval tval;
+        tval.tv_sec = 0;
+        tval.tv_usec = 100;
+        errno = 0;
+        int ret = select(fd+1, &fdset, NULL, NULL, &tval);
+        if (ret == 0) {
+            log_debug ("The pipe for #fd %d timed out waiting to read", fd);
+            return false;
+        } else if (ret == 1) {
+            log_debug ("The pipe for #fd is ready", fd);
+            controlfd = fd;
+            return true;
+        } else {
+            log_error("The pipe has this error: %s", strerror(errno));
+        }
+    }
+
+    return false;
+}
+
+bool
+GnashPluginScriptObject::handleInvoke(GIOChannel *iochan, GIOCondition cond)
+{
+    log_trace(__PRETTY_FUNCTION__);
+    
+    if ( cond & G_IO_HUP ) {
+        log_debug("Player request channel hang up");
+        // Returning false here will cause the "watch" to be removed. This 
watch
+        // is the only reference held to the GIOChannel, so it will be
+        // destroyed. We must make sure we don't attempt to destroy it again.
+        _watchid = 0;
+        return false;
+    }
+
+    assert(cond & G_IO_IN);
+
+    log_debug("Checking player requests on fd #%d",
+              g_io_channel_unix_get_fd(iochan));
+
+    do {
+        GError* error=NULL;
+        gchar* request;
+        gsize requestSize=0;
+        GIOStatus status = g_io_channel_read_line(iochan, &request,
+                &requestSize, NULL, &error);
+
+        switch ( status ) {
+          case G_IO_STATUS_ERROR:
+                log_error("Error reading request line: %s", error->message);
+
+                g_error_free(error);
+                return false;
+            case G_IO_STATUS_EOF:
+                log_error("EOF (error: %s", error->message);
+                return false;
+            case G_IO_STATUS_AGAIN:
+                log_error("Read again(error: %s", error->message);
+                break;
+            case G_IO_STATUS_NORMAL:
+                // process request
+                log_debug("Normal read: %s" + std::string(request));
+                break;
+            default:
+                log_error("Abnormal status!");
+                return false;
+            
+        }
+
+        // process request..
+        processPlayerRequest(request, requestSize);
+        g_free(request);
+
+    } while (g_io_channel_get_buffer_condition(iochan) & G_IO_IN);
+
+    return true;
+}
+
+bool
+GnashPluginScriptObject::handleInvokeWrapper(GIOChannel *iochan,
+                                             GIOCondition cond,
+                                             GnashPluginScriptObject* plugin)
+{
+    log_trace(__PRETTY_FUNCTION__);
+    
+    return plugin->handleInvoke(iochan, cond);
+}
 
 // local Variables:
 // mode: C++

=== modified file 'plugin/npapi/pluginScriptObject.h'
--- a/plugin/npapi/pluginScriptObject.h 2010-04-15 20:19:54 +0000
+++ b/plugin/npapi/pluginScriptObject.h 2010-04-18 00:35:41 +0000
@@ -16,9 +16,7 @@
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 //
 
-#ifdef HAVE_CONFIG_H
-#include "gnashconfig.h"
-#endif
+#include <glib.h>
 
 // Test:
 //     Use browser to open plugin/scriptable-test.html.
@@ -44,6 +42,9 @@
 #include "npapi.h"
 #include "npruntime.h"
 
+#define READFD 0
+#define WRITEFD 1
+
 class GnashPluginScriptObject : public NPObject
 {
 public:
@@ -102,12 +103,30 @@
     /// @return the value as returned by the standalone player
     NPVariant *GetVariable(const std::string &name);
 
+    // Create a socketpair so we can talk to the player.
+    bool createPipe();
+    
+    // Close the socket
+    bool closePipe();
+    bool closePipe(int fd);
+
+    // Check the pipe to see if it's ready, ie... is gnash connected yet ?
+    bool checkPipe();
+    bool checkPipe(int fd);
+
+    int getReadFD()  { return _sockfds[READFD]; };
+    int getWriteFD() { return _sockfds[WRITEFD]; };
+    
     // Write to the standalone player over the control socket
+    int writePlayer(const char *data, size_t length);
     int writePlayer(int fd, const char *data, size_t length);
+    int writePlayer(const std::string &data);
     int writePlayer(int fd, const std::string &data);
     
     // Read the standalone player over the control socket
+    int readPlayer(const char **data, size_t length);
     int readPlayer(int fd, const char **data, size_t length);
+    int readPlayer(const std::string &data);
     int readPlayer(int fd, const std::string &data);
     
 protected:
@@ -130,20 +149,41 @@
     bool Enumerate(NPIdentifier **identifier, uint32_t *count);
     bool Construct(const NPVariant *data, uint32_t argCount, NPVariant 
*result);
 
+    bool handleInvoke(GIOChannel* iochan, GIOCondition cond);
     
+    /// Process a null-terminated request line
+    //
+    /// @param buf
+    ///          The single request.
+    ///   Caller is responsible for memory management, but give us
+    ///   permission to modify the string.
+    ///
+    /// @param len
+    ///          Lenght of buffer.
+    ///
+    /// @return true if the request was processed, false otherwise (bogus 
request..)
+    ///
+    bool processPlayerRequest(gchar* buf, gsize len);
+
 private:
+    static bool handleInvokeWrapper(GIOChannel* iochan, GIOCondition cond,
+                                     GnashPluginScriptObject* plugin);
+
     void initializeIdentifiers();
     void setInstance(NPP inst) { _nppinstance = inst; };
     
     // _nppinstance->pdata should be the nsPluginInstance once NPP_New() is 
finished.
-    NPP _nppinstance;
-    
+    NPP         _nppinstance;
     std::map<NPIdentifier, NPVariant *> _properties;
     std::map<NPIdentifier,  NPInvokeFunctionPtr> _methods;
-    // int _control;
+    // 0 for reading, 1 for writing
+    int         _sockfds[2];
+    GIOChannel *_iochan[2];
+    // ID to watch the read channel from the player
+    int         _watchid;
 };
 
-#endif /* GNASH_PLUGIN_SCRIPT_OBJECT_H */
+#endif // GNASH_PLUGIN_SCRIPT_OBJECT_H
 
 // local Variables:
 // mode: C++

=== modified file 'plugin/npapi/scriptable-test.html'
--- a/plugin/npapi/scriptable-test.html 2010-04-15 20:19:54 +0000
+++ b/plugin/npapi/scriptable-test.html 2010-04-19 15:38:17 +0000
@@ -1,282 +1,245 @@
 <html>
   <head>
-    <title>Scriptable Plugin Test</title>
+    <title>Gnash: Scriptable Plugin Test</title>
+    <style type="text/css" media="screen">
+        body, * {font-family:sans-serif;}
+        h1 {text-align:center;}
+        #content {}
+        #test-actions {
+            list-style-type: none;
+            margin: 0;
+            padding: 0;
+        }
+        p {font-family: monospace;}
+        #log {
+            font-family: monospace;
+            width: 800px;
+            float:right;
+        }
+        #log p {
+            margin: 0;
+            border-bottom:1px solid gray;
+        }
+        #log h2 a {
+            font-style: italic;
+            font-weight:normal;
+            font-size:12px;
+        }
+    </style>
   </head>
   <body>
-
-    <center>
-      <h1> Scriptable Plugin </h1>
-    </center>
-    
-    <br><br>
-    
-    <center>
-      
-      <embed type="application/x-shockwave-flash" width=1 height=1 
hidden="true"><br>
+    <h1>Scriptable Plugin testbed</h1>
+    <div id="log">
+        <h2>Log <a href="#" onclick="clearLog(); return false;">Clear</a></h2>
         
-        <script>
+    </div>
+    <div id="content">
+      
+    <embed type="application/x-shockwave-flash" width="1" height="1" 
hidden="true">
+
+    <ul id="test-actions">
+      <li><button onclick='ShowVersion()'>Show Version</button></li>
+      <li><button onclick='ShowFoobar("barfood")'>Show Foobar</button></li>
+      <li><button onclick='FlashSetVariable("var1", 
"value1")'>SetVariable</button></li>
+      <li><button onclick='FlashGetVariable("var1")'>GetVariable</button></li>
+      <li><button onclick='FlashGotoFrame(123)'>GotoFrame</button></li>
+      <li><button onclick='FlashIsPlaying()'>IsPlaying</button></li>
+      <li><button onclick='FlashLoadMovie(2, "bogus")'>LoadMovie</button></li>
+      <li><button onclick='FlashPan(1, 2, 0)'>Pan</button></li>
+      <li><button onclick='FlashPercentLoaded()'>PercentLoaded</button></li>
+      <li><button onclick='FlashPlay()'>Play</button></li>
+      <li><button onclick='FlashRewind()'>Rewind</button></li>
+      <li><button onclick='FlashSetZoomRect(1, 2, 3, 
4)'>SetZoomRect</button></li>
+      <li><button onclick='FlashStopPlay()'>StopPlay</button></li>
+      <li><button onclick='FlashZoom(12)'>Zoom</button></li>
+      <li><button onclick='FlashTotalFrames()'>TotalFrames</button></li>
+    </ul>
+
+</div>
+
+      <script type="text/javascript">
           var embed = document.embeds[0];
-          
-          function ShowVersion()
-          {
-          document.write("Codebase =  = " + embed.codebase + "<br>");
-          document.write("Classid = " + embed.classid + "<br>");
-          document.write("Pluginspage = " + embed.pluginspage + "<br>");
-          document.write("Src = " + embed.src + "<br>");
-          document.write("BG Color = " + embed.bgcolor + "<br>");
-          document.write("Quality = " + embed.quality + "<br>");
-          document.write("movie = " + embed.movie + "<br>");
-          // document.write("onafterupdate = " + embed.onafterupdate + "<br>");
-          // document.write("onbeforeupdate = " + embed.onbeforeupdate + 
"<br>");
-          // document.write("onblur = " + embed.onblur + "<br>");
-          // document.write("oncellchange = " + embed.oncellchange + "<br>");
-          // document.write("onclick = " + embed.onclick + "<br>");
-          // document.write("ondblClick = " + embed.ondblClick + "<br>");
-          // document.write("ondrag = " + embed.ondrag + "<br>");
-          // document.write("ondragend = " + embed.ondragend + "<br>");
-          // document.write("ondragenter = " + embed.ondragenter + "<br>");
-          // document.write("ondragleave = " + embed.ondragleave + "<br>");
-          // document.write("ondragover = " + embed.ondragover + "<br>");
-          // document.write("ondrop = " + embed.ondrop + "<br>");
-          // document.write("onfinish = " + embed.onfinish + "<br>");
-          // document.write("onfocus = " + embed.onfocus + "<br>");
-          // document.write("onhelp = " + embed.onhelp + "<br>");
-          // document.write("onmousedown = " + embed.onmousedown + "<br>");
-          // document.write("onmouseup = " + embed.onmouseup + "<br>");
-          // document.write("onmouseover = " + embed.onmouseover + "<br>");
-          // document.write("onmousemove = " + embed.onmousemove + "<br>");
-          // document.write("onmouseout = " + embed.onmouseout + "<br>");
-          // document.write("onkeypress = " + embed.onkeypress + "<br>");
-          // document.write("onkeydown = " + embed.onkeydown + "<br>");
-          // document.write("onkeyup = " + embed.onkeyup + "<br>");
-          // document.write("onload = " + embed.onload + "<br>");
-          // document.write("onlosecapture = " + embed.onlosecapture + "<br>");
-          // document.write("onpropertychange = " + embed.onpropertychange + 
"<br>");
-          // document.write("onreadystatechange = " + embed.onreadystatechange 
+ "<br>");
-          // document.write("onrowsdelete = " + embed.onrowsdelete + "<br>");
-          // document.write("onrowenter = " + embed.onrowenter + "<br>");
-          // document.write("onrowexit = " + embed.onrowexit + "<br>");
-          // document.write("onrowsinserted = " + embed.onrowsinserted + 
"<br>");
-          // document.write("onstart = " + embed.onstart + "<br>");
-          // document.write("onscroll = " + embed.onscroll + "<br>");
-          // document.write("onbeforeeditfocus = " + embed.onbeforeeditfocus + 
"<br>");
-          // document.write("onactivate = " + embed.onactivate) + "<br>";
-          // document.write("onbeforedeactivate = " + embed.onbeforedeactivate 
+ "<br>");
-          // document.write("ondeactivate = " + embed.ondeactivate + "<br>");
-          document.write("type = " + embed.type + "<br>");
-          document.write("id = " + embed.id + "<br>");
-          document.write("width = " + embed.width + "<br>");
-          document.write("height = " + embed.height + "<br>");
-          document.write("align = " + embed.align + "<br>");
-          document.write("vspace", + embed.vspace + "<br>");
-          document.write("hspace = " + embed.hspace + "<br>");
-          document.write("class = " + embed.class + "<br>");
-          document.write("title = " + embed.title + "<br>");
-         document.write("accesskey = " + embed.accesskey + "<br>");
-         document.write("name = " + embed.name + "<br>");
-          document.write("tabindex = " + embed.tabindex + "<br>");
-          document.write("FlashVars = " + embed.FlashVars + "<br>");
-          
-         alert(embed.version);
-}
-
-function FlashSetVariable(name, value)
-{
-          embed.SetVariable(name, value);
-//          alert("FlashSetVariable");
-}
-
-function FlashGetVariable(name)
-{
-          var value = embed.GetVariable(name);
-//          document.write("Got Variable = " + value + "<br>");          
-          alert(value);
-}
-
-function FlashGotoFrame(num)
-{
-          embed.GotoFrame(num);
-//          document.write("GotoFrame<br>");
-//          alert(value);
-}
-
-function FlashIsPlaying()
-{
-          var value = embed.IsPlaying();
-//          document.write("IsPlaying() = " + value + "<br>");          
-          alert(value);
-}
-
-function FlashLoadMovie(layer, name)
-{
-          embed.LoadMovie(layer, name);
-//          document.write("LoadMovie()<br>");
-//          alert("FlashLoadMovie");
-}
-
-function FlashPan(x, y, mode)
-{
-          embed.Pan(x, y, mode);
-//          document.write("Pan()<br>");
-//          alert("FlashPan");
-}
-
-function FlashPercentLoaded()
-{
-          var value = embed.PercentLoaded();
-//          document.write("PercentLoaded() = " + value + "<br>");          
-          alert(value);
-}
-
-function FlashPlay()
-{
-          embed.Play();
-//          document.write("Play()<br>");
-//        alert("FlashPlay");
-}
-
-function FlashRewind()
-{
-          embed.Rewind();
-//          document.write("Rewind()<br>");
-//        alert("FlashRewind");
-}
-
-function FlashSetZoomRect(left, top, right, bottom)
-{
-          embed.SetZoomRect(left, top, right, bottom);
-//          document.write("SetZoomRect()<br>");
-//        alert("FlashSetZoomRect");
-}
-
-function FlashStopPlay()
-{
-          embed.StopPlay();
-//          document.write("StopPlay()<br>");
-//        alert("FlashStopPlay");
-}
-
-function FlashZoom(zoom)
-{
-          embed.Zoom(zoom);
-//          document.write("Zoom()<br>");
-//        alert("FlashZoom");
-}
-
-function FlashTotalFrames()
-{
-          var value = embed.TotalFrames();
-//          document.write("TotalFrames() = " + value + "<br>");          
-          alert(value);
-}
-
-function ShowFoobar(msg)
-{
-        document.write(embed.SetVariable("foo", "bar") + "<br>");
-        document.write(embed.SetVariable("fuby", 1.1) + "<br>");
-        document.write(embed.GetVariable("foo") + "<br>");
-
-       alert(embed.showFoobar(msg));
-}
+          function clearLog() {
+              var log = document.getElementById("log");
+              log.innerHTML = '<h2>Log <a href="#" onclick="clearLog(); return 
false;">Clear</a></h2>';
+          }
+          function addLog(str) {
+              var p = document.createElement("P");
+              p.innerHTML = str;
+              var log = document.getElementById("log");
+              log.appendChild(p);
+          }
+          
+          function ShowVersion() {
+              var v = '';
+              v += "Codebase = " + embed.codebase + "<br>";
+              v += "Classid = " + embed.classid + "<br>";
+              v += "Plugins page = " + embed.pluginspage + "<br>";
+              v += "Src = " + embed["src"] + "<br>";
+              v += "BG Color = " + embed.bgcolor + "<br>";
+              v += "Quality = " + embed.quality + "<br>";
+              v += "movie = " + embed.movie + "<br>";
+              // v += "onafterupdate = " + embed.onafterupdate + "<br>";
+              // v += "onbeforeupdate = " + embed.onbeforeupdate + "<br>";
+              // v += "onblur = " + embed.onblur + "<br>";
+              // v += "oncellchange = " + embed.oncellchange + "<br>";
+              // v += "onclick = " + embed.onclick + "<br>";
+              // v += "ondblClick = " + embed.ondblClick + "<br>";
+              // v += "ondrag = " + embed.ondrag + "<br>";
+              // v += "ondragend = " + embed.ondragend + "<br>";
+              // v += "ondragenter = " + embed.ondragenter + "<br>";
+              // v += "ondragleave = " + embed.ondragleave + "<br>";
+              // v += "ondragover = " + embed.ondragover + "<br>";
+              // v += "ondrop = " + embed.ondrop + "<br>";
+              // v += "onfinish = " + embed.onfinish + "<br>";
+              // v += "onfocus = " + embed.onfocus + "<br>";
+              // v += "onhelp = " + embed.onhelp + "<br>";
+              // v += "onmousedown = " + embed.onmousedown + "<br>";
+              // v += "onmouseup = " + embed.onmouseup + "<br>";
+              // v += "onmouseover = " + embed.onmouseover + "<br>";
+              // v += "onmousemove = " + embed.onmousemove + "<br>";
+              // v += "onmouseout = " + embed.onmouseout + "<br>";
+              // v += "onkeypress = " + embed.onkeypress + "<br>";
+              // v += "onkeydown = " + embed.onkeydown + "<br>";
+              // v += "onkeyup = " + embed.onkeyup + "<br>";
+              // v += "onload = " + embed.onload + "<br>";
+              // v += "onlosecapture = " + embed.onlosecapture + "<br>";
+              // v += "onpropertychange = " + embed.onpropertychange + "<br>";
+              // v += "onreadystatechange = " + embed.onreadystatechange + 
"<br>";
+              // v += "onrowsdelete = " + embed.onrowsdelete + "<br>";
+              // v += "onrowenter = " + embed.onrowenter + "<br>";
+              // v += "onrowexit = " + embed.onrowexit + "<br>";
+              // v += "onrowsinserted = " + embed.onrowsinserted + "<br>";
+              // v += "onstart = " + embed.onstart + "<br>";
+              // v += "onscroll = " + embed.onscroll + "<br>";
+              // v += "onbeforeeditfocus = " + embed.onbeforeeditfocus + 
"<br>";
+              // v += "onactivate = " + embed.onactivate + "<br>";
+              // v += "onbeforedeactivate = " + embed.onbeforedeactivate + 
"<br>";
+              // v += "ondeactivate = " + embed.ondeactivate + "<br>";
+          
+              v += "type = " + embed.type + "<br>";
+              v += "id = " + embed.id + "<br>";
+              v += "width = " + embed.width + "<br>";
+              v += "height = " + embed.height + "<br>";
+              v += "align = " + embed.align + "<br>";
+              v += "vspace = " + embed.vspace + "<br>";
+              v += "hspace = " + embed.hspace + "<br>";
+              v += "class = " + embed["class"] + "<br>";
+              v += "title = " + embed.title + "<br>";
+              v += "accesskey = " + embed.accesskey + "<br>";
+              v += "name = " + embed.name + "<br>";
+              v += "tabindex = " + embed.tabindex + "<br>";
+              v += "FlashVars = " + embed.FlashVars + "<br>";
+          
+              addLog('Found version is:' + embed.version);
+              addLog(v);
+          
+      }
+
+        function FlashSetVariable(name, value)
+        {
+            embed.SetVariable(name, value);
+        //          addLog("FlashSetVariable");
+        }
+
+        function FlashGetVariable(name)
+        {
+              var value = embed.GetVariable(name);
+        //          addLog("Got Variable = " + value);          
+              addLog(value);
+        }
+
+        function FlashGotoFrame(num)
+        {
+                  embed.GotoFrame(num);
+        //          addLog("GotoFrame<br>");
+        //          addLog(value);
+        }
+
+        function FlashIsPlaying()
+        {
+                  var value = embed.IsPlaying();
+        //          addLog("IsPlaying() = " + value);          
+                  addLog(value);
+        }
+
+        function FlashLoadMovie(layer, name)
+        {
+                  embed.LoadMovie(layer, name);
+        //          addLog("LoadMovie()<br>");
+        //          addLog("FlashLoadMovie");
+        }
+
+        function FlashPan(x, y, mode)
+        {
+                  embed.Pan(x, y, mode);
+        //          addLog("Pan()<br>");
+        //          addLog("FlashPan");
+        }
+
+        function FlashPercentLoaded()
+        {
+                  var value = embed.PercentLoaded();
+        //          addLog("PercentLoaded() = " + value);          
+                  addLog(value);
+        }
+
+        function FlashPlay()
+        {
+                  embed.Play();
+        //          addLog("Play()<br>");
+        //        addLog("FlashPlay");
+        }
+
+        function FlashRewind()
+        {
+                  embed.Rewind();
+        //          addLog("Rewind()<br>");
+        //        addLog("FlashRewind");
+        }
+
+        function FlashSetZoomRect(left, top, right, bottom)
+        {
+                  embed.SetZoomRect(left, top, right, bottom);
+        //          addLog("SetZoomRect()<br>");
+        //        addLog("FlashSetZoomRect");
+        }
+
+        function FlashStopPlay()
+        {
+                  embed.StopPlay();
+        //          addLog("StopPlay()<br>");
+        //        addLog("FlashStopPlay");
+        }
+
+        function FlashZoom(zoom)
+        {
+                  embed.Zoom(zoom);
+        //          addLog("Zoom()<br>");
+        //        addLog("FlashZoom");
+        }
+
+        function FlashTotalFrames()
+        {
+                  var value = embed.TotalFrames();
+        //          addLog("TotalFrames() = " + value);          
+                  addLog(value);
+        }
+
+        function ShowFoobar(msg)
+        {
+            addLog(embed.SetVariable("foo", "bar"));
+            addLog(embed.SetVariable("fuby", 1.1));
+            addLog(embed.GetVariable("foo"));
+            if (typeof embed.showFoobar === 'function') {
+                addLog('Running embed.showFoobar("'+msg+'")');
+                addLog(embed.showFoobar(msg));
+            } else {
+                addLog("Quitting: embed.showFoobar is not a function. Tried 
running embed.showFoobar('"+msg+"')");
+            }
+        }
 </script>
 
-<br>
-<form name="form1">
-<input type=button value="Show Version" onclick='ShowVersion()'>
-</form>
-<br>
-
-<form name="form2">
-<input type=button value="Show Foobar" onclick='ShowFoobar("barfood")'>
-</form>
-
-</center>
-
-<div id="main">
-<table>
-  <tr><td>
-      <form name="form3">
-        <input type=button value="SetVariable" 
onclick='FlashSetVariable("var1", "value1")'>
-      </form>
-    </td>
-
-    <td>
-      <form name="form4">
-        <input type=button value="GetVariable" 
onclick='FlashGetVariable("var1")'>
-      </form>
-    </td>
-
-    <td>
-      <form name="form5">
-        <input type=button value="GotoFrame" onclick='FlashGotoFrame(123)'>
-      </form>
-    </td>
-
-    <td>
-      <form name="form6">
-        <input type=button value="IsPlaying" onclick='FlashIsPlaying()'>
-      </form>
-    </td>
-
-    <td>
-      <form name="form7">
-        <input type=button value="LoadMovie" onclick='FlashLoadMovie(2, 
"bogus")'>
-      </form>
-    </td>
-
-    <td>
-      <form name="form8">
-        <input type=button value="Pan" onclick='FlashPan(1, 2, 0)'>
-      </form>
-      
-    </td>
-
-    <td>
-      <form name="form9">
-        <input type=button value="PercentLoaded" 
onclick='FlashPercentLoaded()'>
-      </form>
-    </td>
-
-  </tr><tr>
-
-    <td>
-      <form name="form10">
-        <input type=button value="Play" onclick='FlashPlay()'>
-      </form>
-    </td>
-
-    <td>
-      <form name="form11">
-        <input type=button value="Rewind" onclick='FlashRewind()'>
-      </form>
-    </td>
-
-    <td>      
-      <form name="form12">
-        <input type=button value="SetZoomRect" onclick='FlashSetZoomRect(1, 2, 
3, 4)'>
-      </form>
-
-    </td>
-
-    <td>
-      <form name="form13">
-        <input type=button value="StopPlay" onclick='FlashStopPlay()'>
-      </form>
-    </td>
-
-    <td>
-      <form name="form14">
-        <input type=button value="Zoom" onclick='FlashZoom(12)'>
-      </form>      
-    </td>
-
-    <td>
-      <form name="form15">
-        <input type=button value="TotalFrames" onclick='FlashTotalFrames()'>
-      </form>
-    </td></tr>
-</table>
-</div>
 
 </body>
 </html>

=== modified file 'plugin/npapi/test.cpp'
--- a/plugin/npapi/test.cpp     2010-04-15 20:19:54 +0000
+++ b/plugin/npapi/test.cpp     2010-04-18 00:32:42 +0000
@@ -265,6 +265,21 @@
     } else {
         runtest.fail("ExternalInterface::parseArguments()");
     }
+
+    // Parse an invoke message
+    xml = "<invoke name=\"barbyfoo\" 
returntype=\"xml\"><arguments><string>barfoo</string><number>135.78</number></arguments></invoke>";
+    ExternalInterface::invoke_t *invoke = ei.parseInvoke(xml);
+    str = NPVARIANT_TO_STRING(*invoke->args[0]).UTF8Characters;
+    if ((invoke->name == "barbyfoo") && (invoke->type == "xml")
+        && (NPVARIANT_IS_STRING(*invoke->args[0]))
+        && (str == "barfoo")
+        && (NPVARIANT_IS_DOUBLE(*invoke->args[1]))
+        && (NPVARIANT_TO_DOUBLE(*invoke->args[1]) == 135.78)
+        ) {
+        runtest.pass("ExternalInterface::parseInvoke()");
+    } else {
+        runtest.fail("ExternalInterface::parseInvoke()");
+    }
 }
 
 // We have to implement these two memory allocation functions as


reply via email to

[Prev in Thread] Current Thread [Next in Thread]