[请教] linux C/C++, 使用libflashplayer.so, 控制flash文件的播放

chenglong365 2009-01-04 04:53:28
各位高手,请教一下。

我现在需要在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;
}



Makefile

CC=gcc
MOZSDK_INC=./mozilla-sucks
LD_LIBS=-DDEBUG -DMOZ_X11 -lflashplayer -ldl `pkg-config --cflags --libs gtk+-2.0`

all: foo.c
$(CC) $(LD_LIBS) -I$(MOZSDK_INC) -o foo foo.c

clean:
rm -f foo
...全文
4703 30 打赏 收藏 转发到动态 举报
写回复
用AI写文章
30 条回复
切换为时间正序
请发表友善的回复…
发表回复
挨踢大侠 2012-10-25
  • 打赏
  • 举报
回复
2012年了, 又有一位程序员遇到了这个问题; 看到前人走过的路, 兴奋不已呀。
mooncreek 2012-03-23
  • 打赏
  • 举报
回复
我最近也是用gtk做这个东西 楼主成功了吗
droplight 2010-04-23
  • 打赏
  • 举报
回复
最近我也在关注这个功能。都一年多了,不知楼主成功了没有?
xiaobaiwen 2010-02-10
  • 打赏
  • 举报
回复
mark mark mark
amhzy406 2010-01-28
  • 打赏
  • 举报
回复
mark
jxfengzi 2009-10-16
  • 打赏
  • 举报
回复
mark
haihua_880 2009-03-16
  • 打赏
  • 举报
回复
兄弟,你的问题解决了吗?

我也正在做一个Flash播放器,

窗口已经出来了,但就是看来看不多Flash的画面,无法渲染?

这是为什么?
chenglong365 2009-02-18
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 frankpzh 的回复:]
Netscape Client Plugin API和libflashplayer是什么关系啊?
我觉得NPNFuncs是flash的回调函数,你自己实现了提供给libflashplayer用的,不应该是由你来调用的
如果要向flashplayer提供流,应该是libflashplayer API的函数才是
[/Quote]

libflashplayer.so是给你提供的库,Netscape提供了一套实现客户端插件的API函数,NPNFuns应该像是提供的接口,需要自己来实现,供插件调用。在浏览器端,像firefox,已经提供了实现,libflashplayer就可以正确的调用来渲染播放flash。

过程应该是:
1. Load flash plugin
使用dlopen打开libflashplayer.so库, 获得库提供的API函数指针,主要有:NP_GetMIMEDescription,NP_Initialize, NP_Shutdown, NP_GetValue.

2. InitializeFuncs
初始化NPNetscapeFuncs函数列表的函数指针,对应的函数需要自己实现,供插件调用

3. Play Swf
调用libflashplayer.so提供的API函数指针,播放swf文件。
主要有:NP_Initialize, NPP_NewProc, NPP_SetWindow, Writing SWF file四个步骤。分别是初始化插件函数列表;创建插件实例,设置基本参数;创建插件渲染的窗口;创建流并使用流进行读写swf文件。

4. 播放完成退出

这是我的理解,具体可以参考上面提供的代码。
chenglong365 2009-02-18
  • 打赏
  • 举报
回复
这是在和其他朋友交流时,得到的google代码里的一份,和现在做的是一个思路,这个已经能够显示出flash的画面,但是播放有问题,支持flash 7,需要的朋友可以以这个为基础进行开发,我现在的那个flash画面还是没有渲染出来,搁浅了一段时间,这个使用右键才能渲染出画面,但是好像播放还有问题。

链接:http://www.google.cn/codesearch/p?hl=zh-CN#7dyAN_vlVX0/flasher-0.2/flasher.c&q=libflashplayer.so%20lang:c
frankpzh 2009-02-12
  • 打赏
  • 举报
回复
楼主,我也在做和你一样的工作,一起交流一下吧
Netscape Client Plugin API和libflashplayer是什么关系啊?
我觉得NPNFuncs是flash的回调函数,你自己实现了提供给libflashplayer用的,不应该是由你来调用的
如果要向flashplayer提供流,应该是libflashplayer API的函数才是

分享一下工程吧,谢谢 frankpzh@gmail.com
chenglong365 2009-02-03
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 ahmy_0 的回复:]
先请教一下:就是如果你/我成功在gtk上加载了flash插件,且能正确的加载swf文件,那么与swf如果实现通信呢?
windows上有CallFunction,回调有fscommand以及flashcall,当然这都得益与adobe在(IE)插件提供的com接口,
当然,在网页中可以通过js与swf交互,包括回调。
我的疑问:如果是自己加载,与swf通信该如何做?

[/Quote]

我的理解是,如果自己加载的话,会创建一个流NPStream,包含了swf文件的url,end,lastmotified等信息。
之后打开swf文件,将读到流中的数据,写入缓冲区中。然后将缓冲区中的数据显示在NPwindow中。
我现在思路是这样的,不过这样很快就读完了,感觉还有些问题。
不过通过读取swf文件,使用NPStream流与swf文件进行通信应该是没问题的。

我觉得应该按帧对swf文件进行控制,不过现在还不是很清楚怎么弄。

代码我给你发了一份,希望能一起交流,将这个搞定。
chenglong365 2009-02-03
  • 打赏
  • 举报
回复
有个问题,在调用NPPFuncs.newstream(*plugin, type, &stream, 0, &stype)时,
会去调用NPN_GetURL(NPP instance, const char* url, const char* target),
让浏览器创建一个指定URL的流,我现在的打印信息是:

NPN_GetURL instance=0xbffa8850, url=javascript:top.location+"__flashplugin_unique__", target=

我不大清楚输出的url信息是否正确,后面javascript:top.location和"__flashplugin_unique__"怎么解释,有人知道么?

我现在对url的处理,就是在调用newstream之前,对stream进行相应赋值:
stream.url = ...
stream.end = ...
stream.lastmodified = ....
chenglong365 2009-02-03
  • 打赏
  • 举报
回复
我的和前面说的那样“在函数SendSrcStream中,在调用NPPFuncs.write时,返回值一直是-1”,能运行,但是界面上也是没有把flash渲染出来。今天刚回来,得尽快弄出来才行。
ahmy_0 2009-02-03
  • 打赏
  • 举报
回复
先请教一下:就是如果你/我成功在gtk上加载了flash插件,且能正确的加载swf文件,那么与swf如果实现通信呢?
windows上有CallFunction,回调有fscommand以及flashcall,当然这都得益与adobe在(IE)插件提供的com接口,
当然,在网页中可以通过js与swf交互,包括回调。
我的疑问:如果是自己加载,与swf通信该如何做?

愿意分享的话: jengju@gmail.com
非常乐意贡献自己的一点力
sunjianpin 2009-02-02
  • 打赏
  • 举报
回复
lz,我编译通过了,也运行了,但是界面上什么东西也没有,不知道为什么,你自己的运行成功了吗
ahmy_0 2009-02-01
  • 打赏
  • 举报
回复
能否分享一下楼主的代码?

chenglong365 2009-01-20
  • 打赏
  • 举报
回复
问题继续

在函数SendSrcStream中,在调用NPPFuncs.write时,返回值一直是-1,知道可能是什么原因么。

这段代码如下:

if((stype == NP_NORMAL) || (stype == NP_ASFILE)) {
swf_fd = fopen(swf_file, "rb");
write_idx = 0;

while(stream.end > 0) {

write_max = NPPFuncs.writeready(*plugin, &stream);

#ifdef DEBUG
printf("NPP_WriteReady: write_max = %d, end = %d, sizeof(data): %d\n", \
write_max, stream.end, sizeof(data));
#endif //DEBUG

if(write_max <= 0) break;

bytes_read = ((sizeof(data) > stream.end) ? stream.end : sizeof(data));
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, byte_written: %d\n", write_idx, stream.end,
bytes_read, bytes_written);
#endif //DEBUG

if(bytes_written <= 0) break;

write_idx += bytes_written;
stream.end -= bytes_written;
}

fclose(swf_fd);
}



部分调试信息如下:

146 printf("newstream ok, type:%d\n", stype);
(gdb) n
newstream ok, type:1
...
(gdb) n
160 printf("NPP_WriteReady: write_max = %d, end = %d, sizeof(data): %d\n", \
(gdb) n
NPP_WriteReady: write_max = 268435455, end = 1196834, sizeof(data): 10241
...
167 fread(data, sizeof(data), bytes_read, swf_fd);
(gdb) p bytes_read
$7 = 10241
(gdb) n
170 printf("fread: bytes_read = %d\n", bytes_read);
(gdb) p data
$8 = '\0' <repeats 1472 times>, "\036\000\002\000\005zh_CN", '\0' <repeats 266 times>, " \000\000\000\211�,\006��5\006p-\020\b\000\000\000\000����\235�,\006\000\000\000\000\005", '\0' <repeats 19 times>, "@�,\006\\*%\000(\037\016\b0�������\024\232#\000p-\020\b|�\017\bP\000\000\000pR$\0000���", '\0' <repeats 20 times>, "p-\020\b\\*%\0000���(\037\016\b\030����\026\"\000(\037\016\b\000\000\000\000\002\000\000\0000���\b���z�,\006l\026\"\000�\f\"\000\\*%\000(\037\016\bX����\023\"\000("...
(gdb) n
fread: bytes_read = 10241
173 bytes_written = NPPFuncs.write(*plugin, \
(gdb) n
...
(gdb) n
NPP_Write: offset = 0, end = 1196834, written = 10241, byte_written: -1
184 if(bytes_written <= 0) break;
(gdb) p stream
$10 = {pdata = 0x1, ndata = 0x0, url = 0x804a79c "CS_startup.swf", end = 1196834, lastmodified = 1232324044,
notifyData = 0x0}
sunjianpin 2009-01-19
  • 打赏
  • 举报
回复
你好,工程已收到,谢谢
不过编译过程出错,
/usr/bin/ld: cannot find -lflashplayer
collect2: ld return 1 exit status
make: *** [all] Error 1

这个应该怎么处理阿
chenglong365 2009-01-19
  • 打赏
  • 举报
回复
还没阿, 你说的这个,我改了,现在newp好歹通过了。

继续努力,楼上之前是否做过这个阿,如果是的话,可要多多帮忙,先谢过。
wheel_wang 2009-01-19
  • 打赏
  • 举报
回复
LZ搞定没? 还是给你提个初始化是可能出现的问题。NPP在这里是个指针,不是一个struct, 所以需要你给它提前分配内存,NPP plugin = malloc...
加载更多回复(10)

23,110

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧