2 // Copyright (C) 2010, 2011 Free Software Foundation, Inc
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 3 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 #include "gnashconfig.h"
33 #include <sys/types.h>
35 #if defined(HAVE_WINSOCK_H) && !defined(__OS2__)
36 # include <winsock2.h>
38 # include <sys/stat.h>
40 # include <ws2tcpip.h>
43 # include <sys/ioctl.h>
45 # include <sys/select.h>
46 # include <netinet/in.h>
47 # include <arpa/inet.h>
48 # include <sys/socket.h>
51 #include "npruntime.h"
53 #include "callbacks.h"
55 #include "pluginScriptObject.h"
57 extern NPNetscapeFuncs NPNFuncs
;
61 // NPClass of GnashPluginScriptObject
62 static NPClass GnashPluginScriptObjectClass
= {
63 NP_CLASS_STRUCT_VERSION
,
64 GnashPluginScriptObject::marshalAllocate
,
65 GnashPluginScriptObject::marshalDeallocate
,
66 GnashPluginScriptObject::marshalInvalidate
,
67 GnashPluginScriptObject::marshalHasMethod
,
68 GnashPluginScriptObject::marshalInvoke
,
69 GnashPluginScriptObject::marshalInvokeDefault
,
70 GnashPluginScriptObject::marshalHasProperty
,
71 GnashPluginScriptObject::marshalGetProperty
,
72 GnashPluginScriptObject::marshalSetProperty
,
73 GnashPluginScriptObject::marshalRemoveProperty
,
74 GnashPluginScriptObject::marshalEnumerate
,
75 GnashPluginScriptObject::marshalConstruct
78 /// The HostFD is the file descriptor for the socket connection
79 /// to the standalone player. This is used by this plugin when reading
80 /// messages from the standalone player.
81 static int hostfd
= -1;
83 /// The ControlFD is the file descriptor for the socket connection
84 /// to the standalone player. This is used when writing to the
85 /// standalone player from this plugin.
86 static int controlfd
= -1;
89 printNPVariant(const NPVariant
*value
)
91 if (NPVARIANT_IS_DOUBLE(*value
)) {
92 double num
= NPVARIANT_TO_DOUBLE(*value
);
93 log_debug("is double, value %g", num
);
94 } else if (NPVARIANT_IS_STRING(*value
)) {
95 std::string str
= NPStringToString(NPVARIANT_TO_STRING(*value
));
96 log_debug("is string, value %s", str
);
97 } else if (NPVARIANT_IS_BOOLEAN(*value
)) {
98 bool flag
= NPVARIANT_TO_BOOLEAN(*value
);
99 log_debug("is boolean, value %d", flag
);
100 } else if (NPVARIANT_IS_INT32(*value
)) {
101 int num
= NPVARIANT_TO_INT32(*value
);
102 log_debug("is int, value %d", num
);
103 } else if (NPVARIANT_IS_NULL(*value
)) {
104 log_debug("value is null");
105 } else if (NPVARIANT_IS_VOID(*value
)) {
106 log_debug("value is void");
107 } else if (NPVARIANT_IS_OBJECT(*value
)) {
108 log_debug("value is object");
113 // The methods for GnashPluginScriptObject start here.
117 GnashPluginScriptObject::AddProperty(const std::string
&name
,
118 const std::string
&val
)
120 NPIdentifier id
= NPN_GetStringIdentifier(name
.c_str());
123 STRINGN_TO_NPVARIANT(val
.c_str(), static_cast<int>(val
.size()), strvar
);
124 SetProperty(id
, strvar
);
128 GnashPluginScriptObject::AddProperty(const std::string
&name
, double num
)
130 NPIdentifier id
= NPN_GetStringIdentifier(name
.c_str());
132 DOUBLE_TO_NPVARIANT(num
, value
);
133 SetProperty(id
, value
);
137 GnashPluginScriptObject::AddProperty(const std::string
&name
, int num
)
139 NPIdentifier id
= NPN_GetStringIdentifier(name
.c_str());
141 INT32_TO_NPVARIANT(num
, value
);
142 SetProperty(id
, value
);
145 // Sets up the property and method identifier arrays used by the browser
146 // via the hasProperty and hasMethod fuction pointers
148 GnashPluginScriptObject::initializeIdentifiers()
150 // log_debug("initializeIdentifiers");
152 // NPN_Status(_nppinstance, __FUNCTION__);
154 // http://www.adobe.com/support/flash/publishexport/scriptingwithflash/scriptingwithflash_04.html
156 // We maintain an internal property for our version number, rather
157 // than asking the player.
158 AddProperty("$version", "10,1,r999");
159 // id and name appear to be the same tag, but differeing browsers access
160 // one or the other, or both.
161 // name=send_this_page_swf
162 AddProperty("name", "Hello World");
163 // id=send_this_page_swf
164 AddProperty("id", "Hello World");
166 // http://s.ytimg.com/yt/swf/watch-vfl161193.swf
167 AddProperty("src", "example");
168 AddProperty("align", "middle");
169 AddProperty("quality", "high");
170 AddProperty("bgcolor", "#FFFFFF");
171 AddProperty("allowScriptAccess", "sameDomain");
172 AddProperty("type", "application/x-shockwave-flash");
173 AddProperty("codebase", "http://www.getgnash.org");
174 AddProperty("pluginspage", "http://www.getgnash.org");
176 AddProperty("classid", "2b70f2b1-fc72-4734-bb81-4eb2a7713e49");
177 AddProperty("movie", "unknown");
178 AddProperty("width", 0);
179 AddProperty("height", 0);
180 AddProperty("vspace", 0);
181 AddProperty("hspace", 0);
182 AddProperty("class", "class unknown");
183 AddProperty("title", "title unknown");
184 AddProperty("accesskey", 0);
185 AddProperty("name", "name unknown");
186 AddProperty("tabindex", 8);
187 AddProperty("FlashVars", "flashVars unknown");
189 // Javascript and flash events
190 AddProperty("onafterupdate", "unknown");
191 AddProperty("onbeforeupdate", "unknown");
192 AddProperty("onblur", "unknown");
193 AddProperty("oncellchange", "unknown");
194 AddProperty("onclick", "unknown");
195 AddProperty("ondblClick", "unknown");
196 AddProperty("ondrag", "unknown");
197 AddProperty("ondragend", "unknown");
198 AddProperty("ondragenter", "unknown");
199 AddProperty("ondragleave", "unknown");
200 AddProperty("ondragover", "unknown");
201 AddProperty("ondrop", "unknown");
202 AddProperty("onfinish", "unknown");
203 AddProperty("onfocus", "unknown");
204 AddProperty("onhelp", "unknown");
205 AddProperty("onmousedown", "unknown");
206 AddProperty("onmouseup", "unknown");
207 AddProperty("onmouseover", "unknown");
208 AddProperty("onmousemove", "unknown");
209 AddProperty("onmouseout", "unknown");
210 AddProperty("onkeypress", "unknown");
211 AddProperty("onkeydown", "unknown");
212 AddProperty("onkeyup", "unknown");
213 AddProperty("onload", "unknown");
214 AddProperty("onlosecapture", "unknown");
215 AddProperty("onpropertychange", "unknown");
216 AddProperty("onreadystatechange", "unknown");
217 AddProperty("onrowsdelete", "unknown");
218 AddProperty("onrowenter", "unknown");
219 AddProperty("onrowexit", "unknown");
220 AddProperty("onrowsinserted", "unknown");
221 AddProperty("onstart", "");
222 AddProperty("onscroll", "unknown");
223 AddProperty("onbeforeeditfocus", "unknown");
224 AddProperty("onactivate", "unknown");
225 AddProperty("onbeforedeactivate", "unknown");
226 AddProperty("ondeactivate", "unknown");
228 // Add the default methods
229 NPIdentifier id
= NPN_GetStringIdentifier("SetVariable");
230 AddMethod(id
, SetVariableCallback
);
232 id
= NPN_GetStringIdentifier("GetVariable");
233 AddMethod(id
, GetVariableCallback
);
235 id
= NPN_GetStringIdentifier("GotoFrame");
236 AddMethod(id
, GotoFrame
);
238 id
= NPN_GetStringIdentifier("IsPlaying");
239 AddMethod(id
, IsPlaying
);
241 id
= NPN_GetStringIdentifier("LoadMovie");
242 AddMethod(id
, LoadMovie
);
244 id
= NPN_GetStringIdentifier("Pan");
247 id
= NPN_GetStringIdentifier("PercentLoaded");
248 AddMethod(id
, PercentLoaded
);
250 id
= NPN_GetStringIdentifier("Play");
253 id
= NPN_GetStringIdentifier("Rewind");
254 AddMethod(id
, Rewind
);
256 id
= NPN_GetStringIdentifier("SetZoomRect");
257 AddMethod(id
, SetZoomRect
);
259 id
= NPN_GetStringIdentifier("StopPlay");
260 AddMethod(id
, StopPlay
);
262 id
= NPN_GetStringIdentifier("Zoom");
265 id
= NPN_GetStringIdentifier("TotalFrames");
266 AddMethod(id
, TotalFrames
);
268 // id = NPN_GetStringIdentifier("TestASMethod");
269 // AddMethod(id, remoteCallback);
273 GnashPluginScriptObject::GnashPluginScriptObject()
276 // log_debug(__PRETTY_FUNCTION__);
278 initializeIdentifiers();
280 _sockfds
[READFD
] = 0;
281 _sockfds
[WRITEFD
] = 0;
285 GnashPluginScriptObject::GnashPluginScriptObject(NPP npp
)
288 // log_debug(__PRETTY_FUNCTION__);
290 initializeIdentifiers();
292 _sockfds
[READFD
] = 0;
293 _sockfds
[WRITEFD
] = 0;
297 GnashPluginScriptObject::~GnashPluginScriptObject()
299 // log_debug(__PRETTY_FUNCTION__);
300 // Should be automatically shutdown by GIO
306 GnashPluginScriptObject::marshalGetNPClass()
308 // log_debug(__PRETTY_FUNCTION__);
309 return &GnashPluginScriptObjectClass
;
313 GnashPluginScriptObject::marshalAllocate (NPP npp
, NPClass */
* aClass */
)
315 // log_debug(__PRETTY_FUNCTION__);
317 GnashPluginScriptObject
*npobj
= reinterpret_cast<GnashPluginScriptObject
*>
318 (NPN_MemAlloc(sizeof(GnashPluginScriptObject
)));
319 npobj
->setInstance(npp
);
322 return new GnashPluginScriptObject(npp
);
328 GnashPluginScriptObject::marshalDeallocate (NPObject
*npobj
)
330 // log_debug(__PRETTY_FUNCTION__);
332 NPN_MemFree(reinterpret_cast<void *>(npobj
));
334 delete (GnashPluginScriptObject
*)npobj
;
339 GnashPluginScriptObject::marshalInvalidate (NPObject */
* npobj */
)
341 // log_debug(__PRETTY_FUNCTION__);
343 // gpso->Invalidate();
347 GnashPluginScriptObject::marshalHasMethod (NPObject
*npobj
, NPIdentifier name
)
349 // log_debug(__PRETTY_FUNCTION__);
351 GnashPluginScriptObject
*gpso
= (GnashPluginScriptObject
*)npobj
;
354 log_debug("Checking for Method: ");
355 if (NPN_IdentifierIsString(name
)) {
356 log_debug("%s", NPN_UTF8FromIdentifier(name
));
358 log_debug("%d", NPN_IntFromIdentifier(name
));
362 return gpso
->HasMethod(name
);
366 GnashPluginScriptObject::marshalInvoke (NPObject
*npobj
, NPIdentifier name
,
367 const NPVariant
*args
, uint32_t argCount
,
370 GnashPluginScriptObject
*gpso
= (GnashPluginScriptObject
*)npobj
;
372 return gpso
->Invoke(npobj
, name
, args
, argCount
, result
);
376 GnashPluginScriptObject::marshalInvokeDefault (NPObject
*npobj
,
377 const NPVariant
*args
,
381 GnashPluginScriptObject
*gpso
= (GnashPluginScriptObject
*)npobj
;
383 return gpso
->InvokeDefault(args
, argCount
, result
);
387 GnashPluginScriptObject::marshalHasProperty (NPObject
*npobj
, NPIdentifier name
)
389 GnashPluginScriptObject
*gpso
= (GnashPluginScriptObject
*)npobj
;
391 return gpso
->HasProperty(name
);
395 GnashPluginScriptObject::marshalGetProperty (NPObject
*npobj
, NPIdentifier name
,
398 GnashPluginScriptObject
*gpso
= (GnashPluginScriptObject
*)npobj
;
400 return gpso
->GetProperty(name
, result
);
404 GnashPluginScriptObject::marshalSetProperty (NPObject
*npobj
, NPIdentifier name
,
405 const NPVariant
*value
)
407 GnashPluginScriptObject
*gpso
= (GnashPluginScriptObject
*)npobj
;
408 return gpso
->SetProperty(name
, *value
);
412 GnashPluginScriptObject::marshalRemoveProperty (NPObject
*npobj
, NPIdentifier name
)
414 GnashPluginScriptObject
*gpso
= (GnashPluginScriptObject
*)npobj
;
415 return gpso
->RemoveProperty(name
);
419 GnashPluginScriptObject::marshalEnumerate (NPObject
*npobj
, void***identifier
,
422 log_debug(__PRETTY_FUNCTION__
);
424 GnashPluginScriptObject
*gpso
= (GnashPluginScriptObject
*)npobj
;
425 return gpso
->Enumerate(identifier
, count
);
431 GnashPluginScriptObject::marshalConstruct (NPObject
*npobj
, const NPVariant
*data
,
432 uint32_t count
, NPVariant
*result
)
434 log_debug(__PRETTY_FUNCTION__
);
436 GnashPluginScriptObject
*gpso
= (GnashPluginScriptObject
*)npobj
;
437 return gpso
->Construct(data
, count
, result
);
443 GnashPluginScriptObject::HasProperty(NPIdentifier name
)
446 log_debug("Checking for Property \"");
447 if (NPN_IdentifierIsString(name
)) {
448 log_debug("%s\"...", NPN_UTF8FromIdentifier(name
));
450 log_debug("%d\"...", NPN_IntFromIdentifier(name
));
454 return _properties
.find(name
) != _properties
.end();
458 GnashPluginScriptObject::GetProperty(NPIdentifier name
, NPVariant
*result
)
460 if (NPN_IdentifierIsString(name
)) {
461 log_debug("Getting Property \"%s\"...", NPN_UTF8FromIdentifier(name
));
463 log_debug("Getting Property \"%d\"...", NPN_IntFromIdentifier(name
));
466 std::map
<NPIdentifier
, GnashNPVariant
>::const_iterator it
;
467 it
= _properties
.find(name
);
468 if (it
== _properties
.end()) {
472 const GnashNPVariant
& val
= it
->second
;
479 GnashPluginScriptObject::SetProperty(NPIdentifier name
, const NPVariant
& value
)
481 _properties
[name
] = value
;
487 GnashPluginScriptObject::RemoveProperty(NPIdentifier name
)
489 std::map
<NPIdentifier
, GnashNPVariant
>::iterator it
;
490 it
= _properties
.find(name
);
491 if (it
!= _properties
.end()) {
492 _properties
.erase(it
);
500 GnashPluginScriptObject::Enumerate(NPIdentifier
**/
*identifier */
, uint32_t */
* count */
)
502 log_debug(__PRETTY_FUNCTION__
);
508 GnashPluginScriptObject::Construct(const NPVariant */
* args */
, uint32_t /* argCount */,
509 NPVariant */
* result */
)
511 log_debug(__PRETTY_FUNCTION__
);
517 GnashPluginScriptObject::HasMethod(NPIdentifier name
)
520 log_debug("Checking for Method \"");
521 if (NPN_IdentifierIsString(name
)) {
522 log_debug("%s\"...", NPN_UTF8FromIdentifier(name
));
524 log_debug("%d\"...", NPN_IntFromIdentifier(name
));
528 return _methods
.find(name
) != _methods
.end();
532 GnashPluginScriptObject::Invoke(NPObject */
* npobj */
, NPIdentifier name
,
533 const NPVariant
*args
, uint32_t argCount
,
536 // log_debug(__PRETTY_FUNCTION__);
539 if (NPN_IdentifierIsString(name
)) {
540 log_debug("Invoking Method \"%s\"...", NPN_UTF8FromIdentifier(name
));
542 log_debug("Invoking Method: \"%d\"...", NPN_IntFromIdentifier(name
));
544 // log_debug("SCRIPT OBJECT invoke %s: %x", NPN_UTF8FromIdentifier(name),
548 std::map
<NPIdentifier
, NPInvokeFunctionPtr
>::iterator it
;
549 it
= _methods
.find(name
);
550 if (it
!= _methods
.end()) {
551 // log_debug("FOUND Method \"%s\"!", NPN_UTF8FromIdentifier(name));
552 NPInvokeFunctionPtr func
= it
->second
;
553 return func(NULL
, name
, args
, argCount
, result
);
555 log_error("Couldn't find Method \"%s\"", NPN_UTF8FromIdentifier(name
));
560 // return NPN_Invoke(_nppinstance, this, name, args, argCount, result);
564 GnashPluginScriptObject::InvokeDefault(const NPVariant */
* args */
,
565 uint32_t /* argCount */, NPVariant */
* result */
)
567 log_debug(__PRETTY_FUNCTION__
);
569 log_debug("Invoking Default Method \"");
570 if (NPN_IdentifierIsString(name
)) {
571 log_debug("%s\"...", NPN_UTF8FromIdentifier(name
));
573 log_debug("%d\"...", NPN_IntFromIdentifier(name
));
581 GnashPluginScriptObject::AddMethod(NPIdentifier name
, NPInvokeFunctionPtr func
)
583 // log_debug(__PRETTY_FUNCTION__);
586 if (NPN_IdentifierIsString(name
)) {
587 log_debug("Adding Method \"%s\"...", NPN_UTF8FromIdentifier(name
));
589 log_debug("Adding Method \"%d\"...", NPN_IntFromIdentifier(name
));
593 _methods
[name
] = func
;
598 // SetVariable sends a message to the player that looks like this:
599 // "Command Name Type value\n", ie... "SetVariable var1 string value1\n"
601 GnashPluginScriptObject::SetVariable(const std::string
&name
,
602 const NPVariant
& value
)
604 std::vector
<std::string
> iargs
;
605 std::string str
= plugin::ExternalInterface::makeString(name
);
606 iargs
.push_back(str
);
607 str
= plugin::ExternalInterface::convertNPVariant(&value
);
608 iargs
.push_back(str
);
609 str
= plugin::ExternalInterface::makeInvoke("SetVariable", iargs
);
611 log_debug("Trying to set a value for %s.", name
);
613 // Write the message to the Control FD.
614 size_t ret
= writePlayer(str
);
615 // Unless we wrote the same amount of data as the message contained,
616 // something went wrong.
617 if (ret
!= str
.size()) {
618 log_error("Couldn't set the variable, network problems.");
625 // GetVariable sends a message to the player that looks like this:
626 // "Command Name\n", ie... "GetVariable var1\n". Then it waits
627 // for the response with the type and value.
629 GnashPluginScriptObject::GetVariable(const std::string
&name
)
631 std::vector
<std::string
> iargs
;
632 std::string str
= plugin::ExternalInterface::makeString(name
);
633 iargs
.push_back(str
);
634 str
= plugin::ExternalInterface::makeInvoke("GetVariable", iargs
);
636 log_debug("Trying to get a value for %s.", name
);
638 size_t ret
= writePlayer(str
);
639 if (ret
!= str
.size()) {
640 // If all the browser wants is the version, we don't need to
641 // ask the standalone player for this value. YouTube at
642 // least depends on this for some pages which want this to
643 // be greater than 8.0.0. This appears to potentially be
644 // Google's way of trying to revent downloaders, as this requires
647 if (name
== "$version") {
648 STRINGN_TO_NPVARIANT("LNX 10,0,r999", 13, value
);
650 log_error("Couldn't send GetVariable request, network problems.");
651 NULL_TO_NPVARIANT(value
);
656 // Have the read function allocate the memory
657 std::string data
= readPlayer();
659 return GnashNPVariant();
662 GnashNPVariant parsed
= plugin::ExternalInterface::parseXML(data
);
664 printNPVariant(&parsed
.get());
670 GnashPluginScriptObject::setControlFD(int x
)
672 // log_debug("%s: %d", __FUNCTION__, x);
675 _iochan
[WRITEFD
] = g_io_channel_unix_new(x
);
678 controlfd
= x
; // FIXME: this should go away
682 GnashPluginScriptObject::getControlFD()
684 // log_debug("getControlFD: %d", controlfd);
687 return g_io_channel_unix_get_fd (_iochan
);
693 GnashPluginScriptObject::setHostFD(int x
)
695 // log_debug("%s: %d", __FUNCTION__, x);
698 _iochan
[WRITEFD
] = g_io_channel_unix_new(x
);
701 hostfd
= x
; // FIXME: this should go away
705 GnashPluginScriptObject::getHostFD()
707 // log_debug("getControlFD: %d", controlfd);
710 return g_io_channel_unix_get_fd (_iochan
);
716 // Write to the standalone player over the control socket
718 GnashPluginScriptObject::writePlayer(const std::string
&data
)
720 return writePlayer(controlfd
, data
);
724 GnashPluginScriptObject::writePlayer(int fd
, const std::string
&data
)
726 // log_debug(__PRETTY_FUNCTION__);
728 // log_debug("Writing data to fd #%d:\n %s", fd, data);
731 return ::write(fd
, data
.c_str(), data
.size());
738 GnashPluginScriptObject::readPlayer()
740 return readPlayer(hostfd
);
744 GnashPluginScriptObject::readPlayer(int fd
)
746 // log_debug(__PRETTY_FUNCTION__);
751 log_error("Invalid fd passed");
755 // Wait for some data from the player
763 // log_debug("Waiting for data... ");
764 if (select(fd
+1, &fdset
, NULL
, NULL
, &tval
)) {
765 // log_debug("There is data in the network");
767 ioctl(fd
, FIONREAD
, &bytes
);
769 ioctlSocket(fd
, FIONREAD
, &bytes
);
778 log_debug("There are %d bytes in the network buffer", bytes
);
780 std::string
buf(bytes
, '\0');
782 int ret
= ::read(fd
, &buf
[0], bytes
);
797 GnashPluginScriptObject::closePipe(int fd
)
799 // log_debug(__FUNCTION__);
802 // Send a Quit message to the player before closing the pipe.
803 std::vector
<std::string
> args
;
804 std::string str
= plugin::ExternalInterface::makeInvoke("Quit", args
);
805 writePlayer(fd
, str
);
807 ::shutdown(fd
, SHUT_RDWR
);
814 // Create a socket so we can talk to the player.
816 GnashPluginScriptObject::createPipe()
818 log_debug(__PRETTY_FUNCTION__
);
822 int p2c_controlpipe
[2];
824 int ret
= socketpair(AF_UNIX
, SOCK_STREAM
, 0, p2c_pipe
);
826 gnash::log_error("ERROR: socketpair(p2c) failed: %s", strerror(errno
));
829 _streamfd
= p2c_pipe
[1];
831 ret
= socketpair(AF_UNIX
, SOCK_STREAM
, 0, c2p_pipe
);
833 gnash::log_error("ERROR: socketpair(c2p) failed: %s", strerror(errno
));
837 ret
= socketpair(AF_UNIX
, SOCK_STREAM
, 0, p2c_controlpipe
);
839 gnash::log_error("ERROR: socketpair(control) failed: %s", strerror(errno
));
842 _controlfd
= p2c_controlpipe
[1];
846 if ((_sockfds
[READFD
] == 0) && (_sockfds
[WRITEFD
] == 0)) {
847 int ret
= socketpair(AF_UNIX
, SOCK_STREAM
, 0, _sockfds
);
850 // Set up the Glib IO Channel for reading from the plugin
851 // log_debug("Read fd for socketpair is: %d", _sockfds[READFD]);
853 _iochan
[READFD
] = g_io_channel_unix_new(_sockfds
[READFD
]);
854 g_io_channel_set_close_on_unref(_iochan
[READFD
], true);
855 _watchid
= g_io_add_watch(_iochan
[READFD
],
856 (GIOCondition
)(G_IO_IN
|G_IO_HUP
),
857 (GIOFunc
)handleInvokeWrapper
, this);
859 // Set up the Glib IO Channel for writing to the plugin
860 // log_debug("Write fd for socketpair is: %d", _sockfds[WRITEFD]);
861 _iochan
[WRITEFD
] = g_io_channel_unix_new(_sockfds
[WRITEFD
]);
862 g_io_channel_set_close_on_unref(_iochan
[WRITEFD
], true);
869 std::stringstream ss
;
870 static int count
= 0;
871 ss
<< "/tmp/gnash-" << getpid() << count
++;
873 return createPipe(ss
.str());
881 GnashPluginScriptObject::createPipe(const std::string
&name
)
883 log_debug(__PRETTY_FUNCTION__
);
885 mode_t mode
= S_IRUSR
|S_IWUSR
;
887 int ret
= mkfifo(name
.c_str(), mode
);
889 _sockfd
= ::open(name
.c_str(), O_RDWR
|O_NONBLOCK
, mode
);
891 log_error("Couldn't open the pipe: \"%s\"", strerror(errno
));
894 log_error("Couldn't create fifo: s\n", strerror(errno
));
905 // Close the socketpair
907 GnashPluginScriptObject::closePipe()
909 // log_debug(__FUNCTION__);
911 bool ret
= closePipe(_sockfds
[READFD
]);
913 ret
= closePipe(_sockfds
[WRITEFD
]);
919 GIOStatus rstatus
= g_io_channel_shutdown(_iochan
[READFD
], true, &error
);
920 GIOStatus wstatus
= g_io_channel_shutdown(_iochan
[WRITEFD
], true, &error
);
921 if ((rstatus
== G_IO_STATUS_NORMAL
)
922 && (wstatus
== G_IO_STATUS_NORMAL
)) {
931 // Check the pipe to see if it's ready, ie... is gnash connected yet ?
933 GnashPluginScriptObject::checkPipe()
935 return checkPipe(_sockfds
[WRITEFD
]);
939 GnashPluginScriptObject::checkPipe(int fd
)
941 // log_debug(__PRETTY_FUNCTION__);
952 int ret
= select(fd
+1, &fdset
, NULL
, NULL
, &tval
);
954 log_debug ("The pipe for #fd %d timed out waiting to read", fd
);
956 } else if (ret
== 1) {
957 log_debug ("The pipe for #fd is ready", fd
);
961 log_error("The pipe has this error: %s", strerror(errno
));
969 GnashPluginScriptObject::handleInvoke(GIOChannel
*iochan
, GIOCondition cond
)
971 log_debug(__PRETTY_FUNCTION__
);
973 if ( cond
& G_IO_HUP
) {
974 log_debug("Player control channel hang up");
975 // Returning false here will cause the "watch" to be removed. This watch
976 // is the only reference held to the GIOChannel, so it will be
977 // destroyed. We must make sure we don't attempt to destroy it again.
982 assert(cond
& G_IO_IN
);
984 log_debug("Checking player requests on fd #%d",
985 g_io_channel_unix_get_fd(iochan
));
991 GIOStatus status
= g_io_channel_read_line(iochan
, &request
,
992 &requestSize
, NULL
, &error
);
995 case G_IO_STATUS_ERROR
:
996 log_error("Error reading request line: %s", error
->message
);
1000 case G_IO_STATUS_EOF
:
1001 log_error("EOF (error: %s", error
->message
);
1003 case G_IO_STATUS_AGAIN
:
1004 log_error("Read again(error: %s", error
->message
);
1006 case G_IO_STATUS_NORMAL
:
1008 log_debug("Normal read: %s" + std::string(request
));
1011 log_error("Abnormal status!");
1016 // process request..
1017 processPlayerRequest(request
, requestSize
);
1020 } while (g_io_channel_get_buffer_condition(iochan
) & G_IO_IN
);
1026 GnashPluginScriptObject::processPlayerRequest(gchar */
* buf */
, gsize
/* len */)
1028 log_debug(__PRETTY_FUNCTION__
);
1034 GnashPluginScriptObject::handleInvokeWrapper(GIOChannel
*iochan
,
1036 GnashPluginScriptObject
* plugin
)
1038 log_debug(__PRETTY_FUNCTION__
);
1040 return plugin
->handleInvoke(iochan
, cond
);
1043 } // end of gnash namespace
1047 // indent-tabs-mode: nil