日期:2014-05-16  浏览次数:20697 次

[请教] 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_RDONL