|
发表于 2010-7-19 23:21:02
|
显示全部楼层
But IMHO, the most convenient and crossplatform way to embed Flash into application written in Pascal is to write a web application. If you want to deploy to the desktop you can use embedded web server (that can be based e.g. on Ararat Synapse examples) and something like Mozilla Prism as a frontend
如果你是在浏览器上运行,可以试一下下面的demo:
- program dgtkflasher;
- {$mode delphi}{$H+}
- uses
- cthreads,
- Classes, SysUtils, libc, gtk2, gdk2, glib2, math,
- MozillaPluginAPI, gdk2x, x;
- var
- window, button, vbox, socket, fixed: pGtkWidget;
- plugin_funcs: TNPPluginFuncs;
- mozilla_funcs: TNPNetscapeFuncs;
- gNP_GetMIMEDescription: TNPP_GetMIMEDescription;
- //gNP_Initialize: TNPP_Initialize;
- gNP_Initialize: TNP_InitializeProc;
- gNP_Shutdown: TNPP_Shutdown;
- gNP_GetValue: TNPP_GetValue;
- plugin: TNPP;
- type
- { TPCharArgs }
- TArrayPtr = array[0..16383] of PChar;
- PArrayPtr = ^TArrayPtr;
- TPCharArgs = class
- private
- FCount: Integer;
- FData: PArrayPtr;
- public
- constructor Create;
- destructor Destroy;
- procedure Add(AValue: string);
- property Data: PArrayPtr read FData;
- property Count: Integer read FCount;
- end;
- { TPCharArgs }
- constructor TPCharArgs.Create;
- begin
- inherited;
- GetMem(FData, SizeOf(PChar) * 50);
- FCount := 0;
- FillChar(FData^, SizeOf(PChar) * 50, 0);
- end;
- destructor TPCharArgs.Destroy;
- var
- I: Integer;
- begin
- for I := 0 to FCount-1 do
- Dispose(FData^[I]);
- inherited;
- end;
- procedure TPCharArgs.Add(AValue: string);
- begin
- GetMem(FData^[FCount], Length(AValue)+1);
- StrPLCopy(FData^[FCount], AValue, Length(AValue));
- Inc(FCount);
- end;
- procedure Debug(msg: string; fmt: array of const);
- begin
- WriteLn(Format(msg, fmt));
- end;
- {/*==========================================================================*\\
- * Browser-side functions...
- \\*==========================================================================*/}
- //* Closes and deletes a stream */
- function NPN_DestroyStream(instance: PNPP; stream: PNPStream; reason: TNPError): TNPError; cdecl;
- begin
- Debug('NPN_DestroyStream instance=%p, stream=%p, reason=%d\\n',
- [instance, stream, reason]);
- Result := NPERR_GENERIC_ERROR;
- {$IF 0}
- CURLStream *s = stream->ndata;
- if (!s) {
- return NPERR_GENERIC_ERROR;
- }
- CURLStreamDestroy(s, reason);
- return NPERR_NO_ERROR;
- {$ENDIF}
- end;
- ///* Forces a repaint message for a windowless plug-in */
- procedure NPN_ForceRedraw(instance: PNPP); cdecl;
- begin
- Debug('NPN_ForceRedraw instance=%p\\n', [instance]);
- //NOT_IMPLEMENTED();
- end;
- ///* Asks the browser to create a stream for the specified URL */
- function NPN_GetURL(instance: PNPP; const url: PChar; const target: PChar): TNPError; cdecl;
- begin
- Debug('NPN_GetURL instance=%p, url=%s, target=%s\\n',
- [instance, url, target]);
- if (target <> nil) then
- begin
- //NOT_IMPLEMENTED();
- Result := NPERR_INVALID_PARAM;
- Exit;
- end;
- Result := NPERR_GENERIC_ERROR;
- {$IF 0}
- CURLStream *s = CURLStreamNew(instance, url, False, NULL);
- return s ? NPERR_NO_ERROR : NPERR_GENERIC_ERROR;
- {$ENDIF}
- end;
- ///* Requests creation of a new stream for the specified URL */
- function NPN_GetURLNotify(instance: PNPP;
- const url: Pchar;
- const target: PChar;
- notifyData: Pointer): TNPError; cdecl;
- begin
- Debug('NPN_GetURLNotify instance=%p, url=%s, target=%s\\n',
- [instance, url, target]);
- if (target <> nil) then
- begin
- //NOT_IMPLEMENTED();
- Result := NPERR_INVALID_PARAM;
- Exit;
- end;
- Result := NPERR_GENERIC_ERROR;
- {$IF 0}
- CURLStream *s = CURLStreamNew(instance, url, True, notifyData);
- return s ? NPERR_NO_ERROR : NPERR_GENERIC_ERROR;
- {$ENDIF}
- end;
- ///* Allows the plug-in to query the browser for information */
- function NPN_GetValue(instance: PNPP; variable: TNPNVariable; value: Pointer): TNPError; cdecl;
- begin
- Debug('NPN_GetValue instance=%p, variable=%d [%08x]\\n',
- [instance, variable and $ffff, variable]);
- case (variable) of
- NPNVSupportsXEmbedBool:
- PNPBool(value)^ := true;
- {NPNVxDisplay:
- Pointer(Pointer(value)^) := x_display;
- //*(void **)value = x_display;
- NPNVxtAppContext:
- Pointer(Pointer(value)^) := XtDisplayToApplicationContext(x_display);}
- NPNVToolkit:
- PNPNToolkitType(value)^ := NPNVGtk2;
- else
- begin
- Debug('Unhandled variable %d for NPN_GetValue\\n',
- [variable]);
- Result := NPERR_INVALID_PARAM;
- Exit;
- end;
- end;
- Result := NPERR_NO_ERROR;
- end;
- {/*
- * Invalidates specified drawing area prior to repainting or refreshing a
- * windowless plug-in
- */}
- procedure NPN_InvalidateRect(instance: PNPP; invalidRect: PNPRect); cdecl;
- begin
- Debug('NPN_InvalidateRect top=%d, left=%d, bottom=%d, right=%d\\n',
- [invalidRect^.top, invalidRect^.left, invalidRect^.bottom,
- invalidRect^.right]);
- //NOT_IMPLEMENTED();
- end;
- {/*
- * Invalidates specified region prior to repainting or refreshing a
- * windowless plug-in.
- */}
- procedure NPN_InvalidateRegion(instance: PNPP; invalidRegion: Pointer {TNPRegion}); cdecl;
- {var
- rect: TXRectangle;}
- begin
- //XClipBox(invalidRegion, @rect);
- Debug('NPN_InvalidateRegion', []);
- {Debug('NPN_InvalidateRegion x=%d, y=%d, width=%d, height=%d\\n',
- [rect.x, rect.y, rect.width, rect.height]);}
- //NOT_IMPLEMENTED();
- end;
- //* Allocates memory from the browser's memory space. */
- function NPN_MemAlloc(size: LongWord): Pointer; cdecl;
- begin
- Debug('NPN_MemAlloc size=%d\\n', [size]);
- Result := GetMem(size);
- end;
- //* Requests that the browser free a specified amount of memory. */
- function NPN_MemFlush(size: LongWord): LongWord; cdecl;
- begin
- Debug('NPN_MemFlush size=%d\\n', [size]);
- Result := 0;
- end;
- ///* Deallocates a block of allocated memory. */
- procedure NPN_MemFree(ptr: Pointer); cdecl;
- begin
- Debug('NPN_MemFree ptr=%p\\n', [ptr]);
- FreeMem(ptr);
- end;
- {/*
- * Requests the creation of a new data stream produced by the plug-in and
- * consumed by the browser.
- */}
- type PPNPStream = ^PNPStream;
- function NPN_NewStream(instance: PNPP;
- _type: TNPMIMEType;
- const target: PChar;
- stream: PPNPStream): TNPError; cdecl;
- begin
- Debug('NPN_NewStream instance=%p, type=%s, target=%s\\n',
- [instance, _type, target]);
- //NOT_IMPLEMENTED();
- Result := NPERR_GENERIC_ERROR;
- end;
- ///* Posts data to a URL. */
- function NPN_PostURL(instance: PNPP;
- const url: PChar;
- const target: PChar;
- len: LongWord;
- const buf: PChar;
- _file: TNPBool): TNPError; cdecl;
- begin
- Debug('NPN_PostURL instance=%p, url=%s, target=%s, len=%d, file=%d\\n',
- [instance, url, target, len,_file]);
- if (target <> NULL) then
- begin
- //NOT_IMPLEMENTED();
- Result := NPERR_INVALID_PARAM;
- Exit;
- end;
- Result := NPERR_GENERIC_ERROR;
- {$IF 0}
- CURLStream *s = CURLStreamNewPost(instance, url, False, NULL, buf,
- len, file);
- return s ? NPERR_NO_ERROR : NPERR_GENERIC_ERROR;
- {$ENDIF}
- end;
- ///* Posts data to a URL, and receives notification of the result. */
- function NPN_PostURLNotify(instance: PNPP;
- const url: PChar;
- const target: PChar;
- len: LongWord;
- const buf: PChar;
- _file: TNPBool;
- notifyData: Pointer): TNPError; cdecl;
- begin
- Debug('NPN_PostURLNotify instance=%p, url=%s, target=%s, len=%d, file=%d\\n',
- [instance, url, target, len, _file]);
- if (target <> NULL) then
- begin
- //NOT_IMPLEMENTED();
- Result := NPERR_INVALID_PARAM;
- Exit;
- end;
- Result := NPERR_GENERIC_ERROR;
- {$IF 0}
- CURLStream *s = CURLStreamNewPost(instance, url, True, notifyData, buf,
- len, file);
- return s ? NPERR_NO_ERROR : NPERR_GENERIC_ERROR;
- {$ENDIF}
- end;
- ///* Supposed to flush all plugins and reload. */
- procedure NPN_ReloadPlugins(reloadPages: TNPBool); cdecl;
- begin
- Debug('NPN_ReloadPlugins reloadPages=%d\\n', [reloadPages]);
- //NOT_IMPLEMENTED();
- end;
- ///* Returns the Java execution environment. */
- function NPN_GetJavaEnv(): PJRIEnv; cdecl;
- begin
- Debug('NPN_GetJavaEnv\\n', []);
- Result := nil;
- end;
- //* Returns the Java object associated with the plug-in instance. */
- function NPN_GetJavaPeer(instance: PNPP): Tjref; cdecl;
- begin
- Debug('NPN_GetJavaPeer instance=%p\\n', [instance]);
- Result := nil;
- end;
- ///* Requests a range of bytes for a seekable stream. */
- function NPN_RequestRead(stream: PNPStream; rangeList: PNPByteRange): TNPError; cdecl;
- begin
- Debug('NPN_RequestRead stream=%p\\n', [stream]);
- //NOT_IMPLEMENTED();
- Result := NPERR_GENERIC_ERROR;
- end;
- //* Sets various modes of plug-in operation. */
- function NPN_SetValue(instance: PNPP; variable: TNPPVariable; value: Pointer): TNPError; cdecl;
- begin
- Debug('NPN_SetValue instance=%p, variable=%d\\n', [instance, variable]);
- //NOT_IMPLEMENTED();
- Result := NPERR_GENERIC_ERROR;
- end;
- //* Displays a message on the status line of the browser window. */
- procedure NPN_Status(instance: PNPP; const message: PChar); cdecl;
- begin
- Debug('NPN_Status instance=%p, message=%s\\n', [instance, message]);
- //NOT_IMPLEMENTED();
- end;
- ///* Returns the browser's user agent field. */
- function NPN_UserAgent(instance: PNPP): PChar; cdecl;
- begin
- Result := 'Mozilla/5.0 (X11; U; Linux i686; en-US) Flasher/0.2';
- end;
- {/*
- * Pushes data into a stream produced by the plug-in and consumed by the
- * browser.
- */}
- function NPN_Write(instance: PNPP; stream: PNPStream; len: LongWord; buf: Pointer): LongWord; cdecl;
- begin
- Debug('NPN_Write instance=%p, stream=%p, len=%d\\n',
- [instance, stream, len]);
- //NOT_IMPLEMENTED();
- Result := -1;
- end;
- {/*==========================================================================*\\
- * Plugin instance creation, window creation, file reading...
- \\*==========================================================================*/}
- ///* Create a new plugin instance, passing some very basic arguments */
- function CallNew(plugin: PNPP; swf_file: string; width, height: Integer): TNPError;
- var
- width_s, height_s: string;
- //args, values: array[0..4] of string;
- args, values: TPCharArgs;
-
- xembed: TNPBool;
- err: TNPError;
- begin
- ///* FIXME: Store window state. */
- plugin.ndata := nil;
- width_s := IntToStr(width);
- height_s := IntToStr(height);
- args := TPCharArgs.Create;
- values := TPCharArgs.Create;
- args.Add('SRC');
- args.Add('WIDTH');
- args.Add('HEIGHT');
- args.Add('MENU');
- args.Add('LOOP');
- values.Add(swf_file);
- values.Add(width_s);
- values.Add(height_s);
- values.Add('FALSE');
- values.Add('TRUE');
- //SetLength(args, 5);
- //SetLength(values, 5);
- {args[0] := 'SRC';
- args[1] := 'WIDTH';
- args[2] := 'HEIGHT';
- args[3] := 'MENU';
- args[4] := 'LOOP';
- values[0] := swf_file;
- values[1] := width_s;
- values[2] := height_s;
- values[3] := 'FALSE';
- values[4] := 'TRUE';}
- Result := plugin_funcs.New('application/x-shockwave-flash', plugin,
- Word(NP_EMBED), args.Count, PArrayPchar(args.Data), PArrayPchar(values.Data), nil);
- args.Free;
- values.Free;
-
- {xembed := true;
- err := plugin_funcs.GetValue(plugin, NPPVpluginNeedsXEmbed, @xembed);
- if err <> NPERR_NO_ERROR then
- writeln('ouch');}
- end;
- //* Create a new Xt window and pass it to the plugin. */
- function CallSetWindow(plugin: PNPP; width, height: Integer): TNPError;
- var
- ws_info: TNPSetWindowCallbackStruct;
- win: TNPWindow;
-
- draw: PGdkDrawable;
- window: TWindow;
-
- {screen: Integer;
- attr: TXSetWindowAttributes;
- mask: LongWord;
- x_root_win: TWindow;
- x_win: TWindow;
- top_widget: PWidget;
- args: array[0..6] of TArg;
- n: Integer;
- form: PWidget;}
- begin
- draw := PGdkDrawable(socket^.window);
- //draw := PGdkDrawable(fixed^.window);
- //draw := gtk_widget_get_parent_window(socket);
- window := GDK_WINDOW_XWINDOW(draw);
- FillChar(ws_info, sizeof(ws_info), 0);
- FillChar(win, sizeof(win), 0);
- ws_info._type := NP_SETWINDOW;
- ws_info.display := GDK_DRAWABLE_XDISPLAY (draw);
- ws_info.visual := GDK_VISUAL_XVISUAL (gdk_drawable_get_visual(draw));
- ws_info.colormap := GDK_COLORMAP_XCOLORMAP (gdk_drawable_get_colormap(draw));
- ws_info.depth := gdk_drawable_get_depth (draw);
- win._type := NPWindowTypeDrawable;
- win.x := 0;
- win.y := 0;
- win.width := width;
- win.height := height;
- win.ws_info := @ws_info;
- //win.window := gtk_socket_get_id(GTK_SOCKET(socket));
- win.window := window;
- //gtk_widget_realize(window);
- //win.window := GDK_WINDOW_XWINDOW(PGdkDrawable(window^.window));
- plugin_funcs.setwindow(plugin, @win);
- end;
- function SearchFileSize(AFilename: string): Integer;
- var
- S: TSearchRec;
- begin
- Result := 0;
- if FindFirst(AFilename, faAnyFile, S) = 0 then
- Result := S.Size;
- FindClose(S);
- end;
- //* Open, read, and write the contents of swf_file to the plugin instance. */
- function SendSrcStream(plugin: PNPP; swf_file: string): TNPError;
- var
- err: TNPError;
- stream: TNPStream;
- stype: Word;
- swf_fd: TFileStream;
- write_idx: Integer;
- data: array[0..1024*10] of char;
- write_max, bytes_read, bytes_written: Integer;
- pfn: PChar;
- reason: TNPError;
- begin
- err := NPERR_NO_ERROR;
- FillChar(stream, sizeof(stream), 0);
- stype := 0;
- if not FileExists(swf_file) then
- begin
- Result := NPERR_FILE_NOT_FOUND;
- Exit;
- end;
- stream.url := PChar(swf_file);
- stream._end := SearchFileSize(swf_file);
- stream.lastmodified := FileAge(swf_file);
- err := plugin_funcs.newstream(plugin,
- 'application/x-shockwave-flash', @stream,
- True, stype);
- if (err <> NPERR_NO_ERROR) then
- begin
- Result := err;
- end;
- if ((stype = NP_NORMAL) or (stype = NP_ASFILE)) then
- begin
- swf_fd := TFileStream.Create(swf_file, fmOpenRead);
- write_idx := 0;
- while (stream._end > 0) do
- begin
- write_max :=
- plugin_funcs.writeready(plugin, @stream);
- {Debug("NPP_WriteReady: write_max = %d, end = %d\\n",
- write_max, stream.end);}
- if (write_max <= 0) then
- break;
- bytes_read := MIN(sizeof(data), stream._end);
- bytes_read := swf_fd.Read(data, bytes_read);
- //Debug("fread: bytes_read = %d\\n", bytes_read);
- bytes_written := plugin_funcs.write(plugin,
- @stream, write_idx,
- bytes_read,
- @data);
- {Debug("NPP_Write: offset = %d, end = %d, "
- "written = %d\\n", write_idx, stream.end,
- bytes_read);}
- if (bytes_written <= 0) then
- break;
- Inc(write_idx, bytes_written);
- Dec(stream._end, bytes_written);
- end;
- swf_fd.Free;
- end;
- if ((stype = NP_ASFILE) or (stype = NP_ASFILEONLY)) then
- begin
- if stream._end = 0 then
- pfn := PChar(swf_file)
- else
- pfn := nil;
- plugin_funcs.asfile(plugin, @stream, pfn);
- end;
- if (stype <> NP_SEEK) then
- begin
- if stream._end = 0 then
- reason := NPRES_DONE
- else
- reason := NPRES_NETWORK_ERR;
- err := plugin_funcs.destroystream(plugin, @stream, reason);
- end;
- Result := err;
- end;
- {/*==========================================================================*\\
- * Play utility, cmdline parsing, main...
- \\*==========================================================================*/}
- procedure LoadFlashPlugin();
- var
- user_plugin_path: string;
- plugin_path: string;
- dlobj: Pointer;
- begin
- //user_plugin_path := '/home/rreale/prog/MozillaPluginPanel/Plugins/flash7/';
- user_plugin_path := '/usr/lib/firefox/plugins/';
- plugin_path := user_plugin_path + 'libflashplayer.so';
- //user_plugin_path := '/home/rreale/.mozilla/plugins/';
- //plugin_path := user_plugin_path + 'libdiamondx.so';
- dlobj := dlopen(PChar(plugin_path), RTLD_LAZY);
- if dlobj = nil then
- raise Exception.Create('Unable to load flash plugin');
- gNP_GetMIMEDescription := dlsym(dlobj, 'NP_GetMIMEDescription');
- gNP_Initialize := dlsym(dlobj, 'NP_Initialize');
- gNP_Shutdown := dlsym(dlobj, 'NP_Shutdown');
- gNP_GetValue := dlsym(dlobj, 'NP_GetValue');
- end;
- FUNCTION delete_event( widget : pGtkWidget ; event : pGdkEvent ; data : gpointer ) :
- gint; cdecl;
- BEGIN
- { Returning FALSE from the function, as we do here, causes the --destroy-- signal to be emitted. }
- delete_event := 0;
- END;
- PROCEDURE destroy( widget : pGtkWidget ; data : gpointer ); cdecl;
- BEGIN
- gtk_main_quit();
- END;
- procedure window_size_allocate(widget: PGtkWidget;
- allocation: PGtkAllocation;
- user_data: gpointer); cdecl;
- begin
- {gtk_widget_set_size_request(fixed,
- allocation.width, allocation.height);}
- {gtk_widget_set_size_request(socket,
- allocation.width, allocation.height);}
- end;
- procedure socket_size_request(widget: PGtkWidget;
- allocation: PGtkRequisition;
- user_data: gpointer); cdecl;
- begin
- //gtk_widget_get_size_request();
- allocation.width := 900;
- allocation.height := 600;
- {gtk_widget_set_size_request(fixed,
- allocation.width, allocation.height);
- gtk_widget_set_size_request(socket,
- allocation.width, allocation.height);}
- end;
- procedure socket_size_allocate(widget: PGtkWidget;
- allocation: PGtkAllocation;
- user_data: gpointer); cdecl;
- begin
- if (socket <> nil) and
- (GTK_WIDGET_REALIZED(socket)) then
- CallSetWindow(@plugin, allocation.width, allocation.height);
- {gtk_widget_set_size_request(fixed,
- allocation.width, allocation.height);}
- {gtk_widget_set_size_request(socket,
- allocation.width, allocation.height);}
- end;
- procedure InitializeGtk(width, height: Integer);
- begin
- window := gtk_window_new(GTK_WINDOW_TOPLEVEL);
- gtk_container_set_border_width(GTK_CONTAINER(window), 10);
- gtk_widget_set_size_request(window, width, height);
- gtk_signal_connect(GTK_OBJECT(window), 'delete_event',
- GTK_SIGNAL_FUNC(@delete_event), NIL);
- gtk_signal_connect(GTK_OBJECT(window), 'destroy',
- GTK_SIGNAL_FUNC(@destroy), NIL);
- gtk_signal_connect(GTK_OBJECT(window), 'size-allocate',
- GTK_SIGNAL_FUNC(@window_size_allocate), NIL);
- {fixed := gtk_fixed_new;
- gtk_fixed_set_has_window(GTK_FIXED(fixed), true);
- gtk_widget_set_size_request(fixed, width, height);
- gtk_container_add(GTK_CONTAINER(window), fixed);}
- //gtk_widget_realize(fixed);
- //vbox := gtk_vbox_new(true, 5);
- {frame := gtk_frame_new('My Frame');
- gtk_box_pack_start(GTK_BOX(vbox), frame, true, false, 0);
- gtk_widget_show(frame);}
- socket := gtk_socket_new;
- //gtk_widget_set_size_request(socket, width, height);
-
- {gtk_signal_connect(GTK_OBJECT(socket), 'size-request',
- GTK_SIGNAL_FUNC(@socket_size_request), NIL);}
- gtk_signal_connect(GTK_OBJECT(socket), 'size-allocate',
- GTK_SIGNAL_FUNC(@socket_size_allocate), NIL);
-
- //gtk_container_add(GTK_CONTAINER(fixed), socket);
- //gtk_box_pack_start(GTK_BOX(vbox), socket, true, false, 0);
- //gtk_widget_realize(socket);
- gtk_container_add(GTK_CONTAINER(window), socket);
- gtk_widget_show(socket);
- //gtk_container_add(GTK_CONTAINER(fixed), vbox);
- //gtk_container_add(GTK_CONTAINER(window), vbox);
- //gtk_widget_show(vbox);
- //gtk_widget_show(fixed);
- gtk_widget_show(window);
- end;
- procedure InitializeFuncs();
- begin
- FillChar(mozilla_funcs, sizeof(mozilla_funcs), 0);
- mozilla_funcs.Size := sizeof(mozilla_funcs);
- mozilla_funcs.Version := (NP_VERSION_MAJOR shl 8) + NP_VERSION_MINOR;
- mozilla_funcs.GetUrl := @NPN_GetURL;
- mozilla_funcs.PostUrl := @NPN_PostURL;
- mozilla_funcs.RequestRead := @NPN_RequestRead;
- mozilla_funcs.NewStream := @NPN_NewStream;
- mozilla_funcs.Write := @NPN_Write;
- mozilla_funcs.DestroyStream := @NPN_DestroyStream;
- mozilla_funcs.Status := @NPN_Status;
- mozilla_funcs.UserAgent := @NPN_UserAgent;
- mozilla_funcs.MemAlloc := @NPN_MemAlloc;
- mozilla_funcs.MemFlush := @NPN_MemFlush;
- mozilla_funcs.MemFlush := @NPN_MemFree;
- mozilla_funcs.ReloadPlugins := @NPN_ReloadPlugins;
- mozilla_funcs.GetJavaEnv := @NPN_GetJavaEnv;
- mozilla_funcs.GetJavaPeer := @NPN_GetJavaPeer;
- mozilla_funcs.GetUrlNotify := @NPN_GetURLNotify;
- mozilla_funcs.PostUrlNotify := @NPN_PostURLNotify;
- mozilla_funcs.GetValue := @NPN_GetValue;
- mozilla_funcs.SetValue := @NPN_SetValue;
- mozilla_funcs.InvalidateRect := @NPN_InvalidateRect;
- FillChar(plugin_funcs, SizeOf(plugin_funcs), 0);
- plugin_funcs.size := SizeOf(plugin_funcs);
- end;
- procedure Error(msg: string; fmt: array of const);
- begin
- raise Exception.CreateFmt(msg, fmt);
- end;
- {/*
- * Helper to manage create a plugin instance, new window, then writing the
- * file contents to the instance.
- */}
- function PlaySwf(plugin: PNPP; swf_file: string; width, height: Integer): TNPError;
- var
- err: TNPError;
- begin
- err := NPERR_NO_ERROR;
- {/*
- * Without this, Flash segfaults attempting to dynamically invoke
- * gtk_major_mode. Linking GTK+ means that Flash uses GTK's mainloop
- * for IO and timeouts, which we don't want.
- *
- * FIXME: Is there a better way?
- */}
- //putenv('FLASH_GTK_LIBRARY=');
- err := gNP_Initialize(@mozilla_funcs, @plugin_funcs);
- if (err <> NPERR_NO_ERROR) then
- Error('NP_Initialize result = %d', [err]);
- err := CallNew(plugin, swf_file, width, height);
- if (err <> NPERR_NO_ERROR) then
- Error('NPP_NewProc result = %d', [err]);
- err := CallSetWindow(plugin, width, height);
- if (err <> NPERR_NO_ERROR) then
- Error('NPP_SetWindow result = %d', [err]);
- //Log("Loading: %s\\n", swf_file);
- err := SendSrcStream(plugin, swf_file);
- if (err <> NPERR_NO_ERROR) then
- Error('Writing SWF file, result = %d', [err]);
- Result := NPERR_NO_ERROR;
- end;
- var
- geometry: string;
- fullscren: Boolean = false;
- baseurl, swf_file: string;
- width: Integer = 700;
- height: Integer = 400;
- begin
- swf_file := 'test.swf';
- // must disable floating point exceptions
- SetExceptionMask([exInvalidOp, exDenormalized,
- exZeroDivide, exOverflow,
- exUnderflow, exPrecision]);
- gtk_init(@argc, @argv);
- LoadFlashPlugin();
- InitializeGtk(width, height);
- InitializeFuncs();
- PlaySwf(@plugin, swf_file, width, height);
- gtk_main();
-
- gNP_Shutdown();
- end.
复制代码 |
|