ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/Mozilla-Plugin/Plugin.pm
Revision: 1.8
Committed: Sun Feb 25 23:31:25 2001 UTC (23 years, 4 months ago) by root
Branch: MAIN
Changes since 1.7: +102 -7 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 =head1 NAME
2
3 Mozilla::Plugin - embed perl into mozilla/netscape.
4
5 =head1 SYNOPSIS
6
7 use Mozilla::Plugin;
8
9 =head1 DESCRIPTION
10
11 sorry...
12
13 =over 4
14
15 =cut
16
17 package Mozilla::Plugin;
18
19 use base Exporter;
20 use Storable;
21 #use XSLoader;
22
23 $VERSION = 0.01;
24 @EXPORT = qw();
25
26 #XSLoader::load __PACKAGE__, $VERSION;
27 use Data::Dumper;#d#
28
29 my $interface; # Mozilla::Plugin::xxx (design weakness)
30
31 sub NP_VERSION_MAJOR (){ 0 }
32 sub NP_VERSION_MINOR (){ 9 }
33 sub NP_EMBED (){ 1 }
34 sub NP_FULL (){ 2 }
35 sub NP_NORMAL (){ 1 }
36 sub NP_SEEK (){ 2 }
37 sub NP_ASFILE (){ 3 }
38 sub NP_ASFILEONLY (){ 4 }
39 sub NP_MAXREADY (){ 2147483647 }
40 sub NPERR_NO_ERROR (){ 0 }
41 sub NPERR_GENERIC_ERROR (){ 1 }
42 sub NPERR_INVALID_INSTANCE_ERROR (){ 2 }
43 sub NPERR_INVALID_FUNCTABLE_ERROR (){ 3 }
44 sub NPERR_MODULE_LOAD_FAILED_ERROR (){ 4 }
45 sub NPERR_OUT_OF_MEMORY_ERROR (){ 5 }
46 sub NPERR_INVALID_PLUGIN_ERROR (){ 6 }
47 sub NPERR_INVALID_PLUGIN_DIR_ERROR (){ 7 }
48 sub NPERR_INCOMPATIBLE_VERSION_ERROR (){ 8 }
49 sub NPERR_INVALID_PARAM (){ 9 }
50 sub NPERR_INVALID_URL (){ 10 }
51 sub NPERR_FILE_NOT_FOUND (){ 11 }
52 sub NPERR_NO_DATA (){ 12 }
53 sub NPERR_STREAM_NOT_SEEKABLE (){ 13 }
54 sub NPVERS_HAS_STREAMOUTPUT (){ 8 }
55 sub NPVERS_HAS_NOTIFICATION (){ 9 }
56 sub NPVERS_HAS_LIVECONNECT (){ 9 }
57 sub NPVERS_WIN16_HAS_LIVECONNECT (){ 10 }
58
59 my $data;
60
61 sub BIAS() { -2147483647 } # ugliest hack ever seen
62
63 sub snd_cmd($) {
64 $data = pack "NN", 0, ord($_[0]);
65 }
66
67 sub snd_ptr($) {
68 $data .= $_[0];
69 }
70
71 sub snd_u32($) {
72 $data .= pack "N", $_[0];
73 }
74
75 sub snd_i32($) {
76 $data .= pack "N", $_[0] - BIAS;
77 }
78
79 sub snd_blk($) {
80 $data .= pack "NA*", length($_[0]), $_[0];
81 }
82
83 sub snd_snd() {
84 substr ($data, 0, 4) = pack "N", length $data;
85 length ($data) == syswrite FD, $data;
86 }
87
88 sub snd_dyn($) {
89 length ($_[0]) == syswrite FD, $_[0];
90 }
91
92 sub rcv_cmd() {
93 my $buf;
94 4 == sysread FD, $buf, 4 or exit;
95 my $len = unpack "N", $buf;
96 $len -= 4;
97 $len == sysread FD, $buf, $len or die;
98
99 $data = substr $buf, 4;
100
101 substr $buf, 3, 1;
102 }
103
104 sub rcv_ptr() {
105 my $ptr = substr $data, 0, 8;
106 $data = substr $data, 8;
107 $ptr;
108 }
109
110 sub rcv_u32() {
111 my $u32 = unpack "N", $data;
112 $data = substr $data, 4;
113 $u32;
114 }
115
116 sub rcv_i32() {
117 my $i32 = BIAS + unpack "N", $data;
118 $data = substr $data, 4;
119 $i32;
120 }
121
122 sub rcv_blk() {
123 my $len = unpack "N", $data;
124 my $str = substr $data, 4, $len;
125 $data = substr $data, 4 + $len;
126 $str;
127 }
128
129 =item my $fh = server_fh
130
131 The design of this module is event-based. When the plug-in starts (there
132 is always just one interpreter) it spawns one perl interpreter which
133 will immediately go into a even loop. If you want to use your own event
134 loop (e.g. using the Gtk or Event modules) you need to register a file
135 input handler on the filehandle returned by C<server_fh> that calls
136 C<server_event> whenever there is input pending on C<server_fh>. This will
137 ensure proper operation of the plug-in.
138
139 =item server_event
140
141 Call this function whenever there is data available on the C<server_fh>. This function
142 might not return.
143
144 Due to this design (flaw?), sharing of different toolkits using this
145 plug-in is difficult at best. Spawning a new perl interpreter for every
146 plug-in is also not very viable, so in the future one might be able to
147 specify a group on the embed statement (i.e. EMBED GROUP="gtk+").
148
149 =cut
150
151 sub server_fh() { \*FD }
152
153 sub server_event() {
154 my $cmd = rcv_cmd;
155
156 warn "cmd<$cmd>\n";#d#
157
158 if ($cmd eq "I") {
159 rcv_u32 == 1 or die "protocol version mismatch\n";
160 ($IFACE, $OSNAME, $OSVERS) = (rcv_blk, rcv_blk, rcv_blk);
161
162 } elsif ($cmd eq "+") { # New
163 my ($objid, $type, $mode, $save, $argc)
164 = (rcv_ptr, rcv_blk, rcv_u32, rcv_blk, rcv_u32);
165 my %args;
166 while ($argc--) {
167 my ($argn, $argv) = (rcv_blk, rcv_blk);
168 $args{$argn} = $argv;
169 }
170
171 $_OBJ{$objid} = $interface->new(
172 objid => $objid,
173 type => $type,
174 mode => $mode,
175 save => $save,
176 args => \%args,
177 );
178
179 } elsif ($cmd eq "-") { # Destroy
180 my $objid = rcv_ptr;
181 my $save = (delete $_OBJ{$objid})->save;
182 snd_cmd "-";
183 snd_u32 length $save;
184 snd_snd and snd_dyn $save;
185
186 } elsif ($cmd eq "X") { # SetWindow
187 my $objid = rcv_ptr;
188 my %args = (
189 window => rcv_ptr,
190 x => rcv_i32,
191 y => rcv_i32,
192 w => rcv_i32,
193 h => rcv_i32,
194 );
195 if ($IFACE eq "UNIX") {
196 $args{window} = unpack "xxxxN", $args{window};
197 $args{ws_type} = rcv_i32;
198 $args{ws_depth} = rcv_u32;
199 }
200
201 snd_cmd 'X';
202 snd_u32 $_OBJ{$objid}->set_window(\%args);
203 snd_snd;
204
205 } elsif ($cmd eq "N") { # NewStream
206 my $obj = $_OBJ{+rcv_ptr};
207 my %args = (
208 obj => $obj,
209 mimetype => rcv_blk,
210 id => rcv_ptr,
211 url => rcv_blk,
212 end => rcv_u32,
213 lastmodified => rcv_u32,
214 notifydata => rcv_u32,
215 seekable => rcv_u32,
216 );
217 my $str = $_OBJ{$args{id}} = new Mozilla::Stream \%args;
218
219 my ($stype, $err) = $obj->push_stream($str);
220
221 snd_cmd 'W';
222 snd_u32 $err;
223 snd_u32 $stype || NP_NORMAL;
224 snd_snd;
225
226 } elsif ($cmd eq "/") { # StreamAsFile
227 my $obj = $_OBJ{+rcv_ptr};
228 my $str = $_OBJ{+rcv_ptr};
229 my $path = rcv_blk;
230
231 $obj->stream_as_file($obj, $stream, $path);
232
233 } elsif ($cmd eq "R") { # WriteReady
234 my $obj = $_OBJ{+rcv_ptr};
235 my $str = $_OBJ{+rcv_ptr};
236
237 snd_cmd 'R';
238 snd_u32 $obj->write_ready($obj, $str);
239 snd_snd;
240
241 } elsif ($cmd eq "W") { # Write
242 my $obj = $_OBJ{+rcv_ptr};
243 my $str = $_OBJ{+rcv_ptr};
244 my $ofs = rcv_i32;
245 my $len = rcv_i32;
246 my $dta = rcv_dyn $len;
247
248 snd_cmd 'W';
249 snd_i32 $obj->write($str, $ofs, $len, $dta);
250 snd_snd;
251
252 } elsif ($cmd eq "D") { # DestroyStream
253 my $obj = $_OBJ{+rcv_ptr};
254 my $str = delete $_OBJ{+rcv_ptr};
255 my $why = rcv_u32;
256
257 $obj->destroy_stream($obj, $str, $why);
258
259 } else {
260 die "unknown command '$cmd' received";
261 }
262 }
263
264 sub mainloop {
265 server_event while 1;
266 }
267
268 sub init {
269 $interface = shift;
270
271 open FD, "+<&=$_[0]"; binmode FD;
272
273 $interface->mainloop;
274 }
275
276 sub new {
277 my $class = shift;
278 my $self = bless { @_ }, $class;
279 $self->{save} = $self->{save} ne ""
280 ? Storable::thaw $self->{save}
281 : {};
282 $self;
283 }
284
285 sub set_window {
286 my $self = shift;
287 my $new = shift;
288 print "window set calling with $new->{window}, $new->{w}, $new->{h} ($self->{window}\n";#d#
289 if ($self->{window}) {
290 if ($self->{window}{window} ne $new->{window}) {
291 $self->window_delete($self->{window});
292 } elsif ($self->{window}{w} != $new->{w}
293 or $self->{window}{h} != $new->{h}) {
294 $self->window_resize($new->{window}, $new->{w}, $new->{h});
295 }
296 $self->{window} = $new;
297 }
298
299 unless ($self->{window}) {
300 $self->{window} = $new;
301 print "window new calling with $new->{window}, $new->{w}, $new->{h}\n";#d#
302 $self->window_new($new->{window}, $new->{w}, $new->{h});
303 }
304
305 ();
306 }
307
308 sub window_new {}
309 sub window_resize {}
310
311 sub window_delete {
312 my $self = shift;
313 delete $self->{window};
314 }
315
316 sub save {
317 my $self = shift;
318 $self->set_window(undef);
319 $self->{destroy};
320 Storable::nfreeze $self->{save};
321 }
322
323 sub destroy {}
324 sub DESTROY {}
325 sub write_ready { 0xfffff }
326 sub push_stream {}
327 sub stream_as_file {}
328 sub destroy_stream {}
329
330 sub write {
331 my ($self) = shift;
332 shift->write(@_);
333 }
334
335 1;
336
337 =back
338
339 =head1 BUGS
340
341 =head1 SEE ALSO
342
343 L<PApp>.
344
345 =head1 AUTHOR
346
347 Marc Lehmann <pcg@goof.com>
348 http://www.goof.com/pcg/marc/
349
350 =cut
351