[请教] linux C/C++, 使用libflashplayer.so, 控制flash文件的播放
各位高手,请教一下。
我现在需要在Linux下实现一个简单的应用程序,用来控制flash文件的播放。编程语言C/C++。
通过网上查找资料,我现在是使用Adobe的libflashplayer.so库。通过阅读mozilla-sdk相关的源码,对该库的使用有了一定的了解,
程序基本写完,但是运行时,总是产生段错误,发现是在调用NPPluginFuncs的函数时(如setwindow, newstream等),出错,
不知是传参有问题,还是其他的问题。
下面是我现在的代码:
foo.c
- C/C++ code
#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;}
Makefile
[解决办法]
你的NPNFuncs列表里的函数在哪里赋值的?他们是flashplayer.so能供work的基础。
[解决办法]
mark帮顶
[解决办法]
#include "npapi.h"
#include "npupp.h"
这两个文件没找到阿,我用的是fc10,能不能发给我整个工程或这两个文件(还有他们相关的文件),邮箱sunjianpin@sina.com.cn
十分感谢
[解决办法]
如果是有声音的SWF文件呢。。。 反正我用的FLASH播放器就没播放正常过。。 压根放不出来--外国语教程来着。。。
[解决办法]
你好,工程已收到,谢谢
不过编译过程出错,
/usr/bin/ld: cannot find -lflashplayer
collect2: ld return 1 exit status
make: *** [all] Error 1
这个应该怎么处理阿
[解决办法]
LZ搞定没? 还是给你提个初始化是可能出现的问题。NPP在这里是个指针,不是一个struct, 所以需要你给它提前分配内存,NPP plugin = malloc...
[解决办法]
能否分享一下楼主的代码?
[解决办法]
lz,我编译通过了,也运行了,但是界面上什么东西也没有,不知道为什么,你自己的运行成功了吗
[解决办法]
先请教一下:就是如果你/我成功在gtk上加载了flash插件,且能正确的加载swf文件,那么与swf如果实现通信呢?
windows上有CallFunction,回调有fscommand以及flashcall,当然这都得益与adobe在(IE)插件提供的com接口,
当然,在网页中可以通过js与swf交互,包括回调。
我的疑问:如果是自己加载,与swf通信该如何做?
愿意分享的话: jengju@gmail.com
非常乐意贡献自己的一点力
[解决办法]
楼主,我也在做和你一样的工作,一起交流一下吧
Netscape Client Plugin API和libflashplayer是什么关系啊?
我觉得NPNFuncs是flash的回调函数,你自己实现了提供给libflashplayer用的,不应该是由你来调用的
如果要向flashplayer提供流,应该是libflashplayer API的函数才是
分享一下工程吧,谢谢 frankpzh@gmail.com