[请教] linux C/C++, 使用libflashplayer.so, 控制flash文件的播放
各位高手,请教一下。
我现在需要在Linux下实现一个简单的应用程序,用来控制flash文件的播放。编程语言C/C++。
通过网上查找资料,我现在是使用Adobe的libflashplayer.so库。通过阅读mozilla-sdk相关的源码,对该库的使用有了一定的了解,
程序基本写完,但是运行时,总是产生段错误,发现是在调用NPPluginFuncs的函数时(如setwindow, newstream等),出错,
不知是传参有问题,还是其他的问题。
下面是我现在的代码:
foo.c
#define MIN(a,b) ((a) <= (b) ? (a) : (b))#include <sys/stat.h>#include <unistd.h>#include <fcntl.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <dlfcn.h>#include <gtk/gtk.h>#include <gdk/gdkx.h>#include "npapi.h"#include "npupp.h"static void *handle;static GtkWidget *window;static GtkWidget *socket;/* plugin meta member functions */char* (*gNP_GetMIMEDescription)(void);NPError (*gNP_Initialize)(NPNetscapeFuncs* aNPNFuncs, NPPluginFuncs* aNPPFuncs);NPError (*gNP_GetValue)(void* future, NPPVariable variable, void *value);NPError (*gNP_Shutdown)(void);/* Create a new plugin instance, passing some very basic arguments */static NPError CallNew(NPPluginFuncs *NPPFuncs, NPP plugin, char *swf_file, int width, int height){ NPError err = NPERR_NO_ERROR; char width_s[8]; char height_s[8]; int16 argc = 5; char* argn[5]; char* argv[5]; NPBool xembed; sprintf(width_s, "%d", width); sprintf(height_s, "%d", height); argn[0] = "SRC"; argn[1] = "WIDTH"; argn[2] = "HEIGHT"; argn[3] = "MENU"; argn[4] = "LOOP"; argv[0] = swf_file; argv[1] = width_s; argv[2] = height_s; argv[3] = "FALSE"; argv[4] = "TRUE";#ifdef DEBUG printf("swf_file: %s, width_s: %s, height_s: %s\n", swf_file, width_s, height_s);#endif //DEBUG NPPFuncs->newp("application/x-shockwave-flash:swf:Shockwave Flash", \ plugin, NP_EMBED, argc, argn, argv, NULL); xembed = true; err = NPPFuncs->getvalue(plugin, NPPVpluginNeedsXEmbed, &xembed); if(err != NPERR_NO_ERROR) fprintf(stderr, "ouch\n"); return err;}/* Create a new Xt window and pass it to the plugin. */static NPError CallSetWindow(NPPluginFuncs *NPPFuncs, NPP plugin, int width, int height){ NPSetWindowCallbackStruct ws_info; NPWindow win; GdkDrawable *draw = (GdkDrawable *)(socket->window); Window window = GDK_DRAWABLE_XID(draw); memset(&ws_info, 0, sizeof(NPSetWindowCallbackStruct)); memset(&win, 0, sizeof(NPWindow)); 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 = &window; //here out "segment fault"!!! //NPPFuncs->setwindow(plugin, &win);}//* Open, read, and write the contents of swf_file to the plugin instance. */static NPError SendSrcStream(NPPluginFuncs *NPPFuncs, NPP plugin, char *swf_file){ NPError err = NPERR_NO_ERROR; NPMIMEType type = "application/x-shockwave-flash"; struct stat buf; //file state struct NPStream stream; uint16 stype = 0; FILE *swf_fd; char data[1024*10+1]; int write_idx, write_max; int bytes_read, bytes_written; char *pfn; NPError reason; memset(&stream, 0, sizeof(NPStream)); if(access(swf_file, F_OK) != 0) return NPERR_FILE_NOT_FOUND; int fd = open(swf_file, O_RDONLY); fstat(fd, &buf); stream.url = swf_file; stream.end = buf.st_size; stream.lastmodified = buf.st_mtime; //segment default //NPPFuncs->newstream(plugin, type, &stream, TRUE, &stype); //if(err != NPERR_NO_ERROR) // return err;#ifdef DEBUG printf("test newstream : success!\n");#endif //DEBUG if((stype == NP_NORMAL) || (stype == NP_ASFILE)) { swf_fd = fopen(swf_file, "r"); write_idx = 0; while(stream.end > 0) { //write_max = NPPFuncs->writeready(plugin, &stream);#ifdef DEBUG printf("NPP_WriteReady: write_max = %d, end = %d\n", \ write_max, stream.end);#endif //DEBUG if(write_max <= 0) break; bytes_read = MIN(sizeof(data), stream.end); bytes_read = fread(data, sizeof(data), bytes_read, swf_fd);#ifdef DEBUG printf("fread: bytes_read = %d\n", bytes_read);#endif //DEBUG //bytes_written = NPPFuncs->write(plugin, \ &stream, write_idx, \ bytes_read, \ &data);#ifdef DEBUG printf("NPP_Write: offset = %d, end = %d, " \ "written = %d\n", write_idx, stream.end, bytes_read);#endif //DEBUG if(bytes_written <= 0) break; write_idx += bytes_written; stream.end -= bytes_written; } fclose(swf_fd); } if((stype == NP_ASFILE) || (stype == NP_ASFILEONLY)) { if(stream.end == 0) pfn = swf_file; else pfn = NULL; //NPPFuncs->asfile(plugin, &stream, pfn); } if(stype != NP_SEEK) { if(stream.end == 0) reason = NPRES_DONE; else reason = NPRES_NETWORK_ERR; //segment default //err = NPPFuncs->destroystream(plugin, &stream, reason); } return err;}void LoadFlashPlugin(){ handle = dlopen ("libflashplayer.so", RTLD_LAZY); if (!handle) { fprintf (stderr, "%s\n", dlerror()); exit(1); } gNP_GetMIMEDescription = dlsym(handle, "NP_GetMIMEDescription"); gNP_Initialize = dlsym(handle, "NP_Initialize"); gNP_GetValue = dlsym(handle, "NP_GetValue"); gNP_Shutdown = dlsym(handle, "NP_Shutdown"); dlerror(); /* Clear any existing error */}NPError PlaySwf(NPP plugin, char *swf_file, int width, int height){ NPError rv = NPERR_NO_ERROR; NPNetscapeFuncs NPNFuncs; NPPluginFuncs NPPFuncs; rv = (*gNP_Initialize)(&NPNFuncs, &NPPFuncs); if(rv != NPERR_NO_ERROR) printf("NP_Initialize result = %d\n", rv); rv = CallNew(&NPPFuncs, plugin, swf_file, width, height); if(rv != NPERR_NO_ERROR) printf("NPP_NewProc result = %d\n", rv); rv = CallSetWindow(&NPPFuncs, plugin, width, height); if(rv != NPERR_NO_ERROR) printf("NPP_SetWindow result = %d\n", rv); rv = SendSrcStream(&NPPFuncs, plugin, swf_file); if(rv != NPERR_NO_ERROR) printf("Writing SWF file, result = %d\n", rv); return NPERR_NO_ERROR;}void InitializeGtk(int width, int height){ window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_signal_connect(GTK_OBJECT(window), "delete_event", G_CALLBACK(gtk_main_quit), NULL); gtk_window_set_title(GTK_WINDOW(window), "flashplayer"); gtk_container_set_border_width(GTK_CONTAINER(window), 10); gtk_widget_set_size_request(window, width, height); socket = gtk_socket_new(); gtk_widget_show (socket); gtk_container_add(GTK_CONTAINER(window), socket); gtk_widget_show (window);}int main(int argc, char **argv) { char *swf_file = "CS_startup.swf"; int width = 700; int height = 400; NPP plugin; gtk_init(&argc, &argv); LoadFlashPlugin(); InitializeGtk(width, height); /* NP_GetMIMEDescription */ printf("%s\n", (*gNP_GetMIMEDescription)()); PlaySwf(plugin, swf_file, width, height); gtk_main(); /* NP_Shutdown */ (*gNP_Shutdown)(); dlclose(handle); return 0;}