root/applications/osmozilla/osmozilla.cpp

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. Osmozilla_Shutdown
  2. osmozilla_do_log
  3. Osmozilla_EventProc
  4. Osmozilla_Initialize
  5. Osmozilla_SetWindow
  6. Osmozilla_GetVersion
  7. Osmozilla_ConnectTo
  8. Osmozilla_Pause
  9. Osmozilla_Play
  10. Osmozilla_Stop
  11. CreateBitmapInfoStruct
  12. Osmozilla_Print
  13. Osmozilla_Update
  14. Osmozilla_QualitySwitch
  15. Osmozilla_SetURL
  16. Osmozilla_GetDownloadProgress

/*
*                       GPAC - Multimedia Framework C SDK
*
 *                      Authors: Jean Le Feuvre
 *                      Copyright (c) Telecom ParisTech 2000-2012
*                                       All rights reserved
*
*  This file is part of GPAC / Osmozilla NPAPI plugin
*
*  GPAC is free software; you can redistribute it and/or modify
*  it under the terms of the GNU Lesser General Public License as published by
*  the Free Software Foundation; either version 2, or (at your option)
*  any later version.
*
*  GPAC is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU Lesser General Public License for more details.
*
*  You should have received a copy of the GNU Lesser General Public
*  License along with this library; see the file COPYING.  If not, write to
*  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/

#include "osmozilla.h"

#ifdef XP_WIN
#include <windows.h>
#endif

#include <gpac/options.h>
#include <gpac/terminal.h>
#include <gpac/term_info.h>


short Osmozilla_GetURL(NPP instance, const char *url, const char *target);
void Osmozilla_SetStatus(NPP instance, const char *message);


void Osmozilla_Shutdown(Osmozilla *osmo)
{
        if (osmo->url) gf_free(osmo->url);
        osmo->url = NULL;
        if (osmo->term) {
                GF_Terminal *a_term = osmo->term;
                osmo->term = NULL;
                gf_term_del(a_term);
        }
        if (osmo->user) {
                if (osmo->user->modules) gf_modules_del(osmo->user->modules);
                if (osmo->user->config) gf_cfg_del(osmo->user->config);
                gf_free(osmo->user);
                osmo->user = NULL;
        }
}

static void osmozilla_do_log(void *cbk, GF_LOG_Level level, GF_LOG_Tool tool, const char *fmt, va_list list)
{
        FILE *logs = (FILE *) cbk;
        vfprintf(logs, fmt, list);
        fflush(logs);
}


Bool Osmozilla_EventProc(void *opaque, GF_Event *evt)
{
        char msg[1024];
        Osmozilla *osmo = (Osmozilla *)opaque;
        if (!osmo->term) return GF_FALSE;

        switch (evt->type) {
        case GF_EVENT_MESSAGE:
                if (!evt->message.message) return GF_FALSE;
                if (evt->message.error)
                        sprintf((char *)msg, "GPAC: %s (%s)", evt->message.message, gf_error_to_string(evt->message.error));
                else
                        sprintf((char *)msg, "GPAC: %s", evt->message.message);

                Osmozilla_SetStatus(osmo->np_instance, msg);
                break;
        case GF_EVENT_PROGRESS:
                if (evt->progress.done == evt->progress.total) {
                        Osmozilla_SetStatus(osmo->np_instance, "");
                        osmo->download_progress = 100;
                } else {
                        char *szTitle = (char *)"";
                        if (evt->progress.progress_type==0) szTitle = (char *)"Buffer ";
                        else if (evt->progress.progress_type==1)
                        {
                                szTitle = (char *)"Download ";
                                osmo->download_progress = (int) (100.0*evt->progress.done) / evt->progress.total;
                        }
                        else if (evt->progress.progress_type==2) szTitle = (char *)"Import ";

                        sprintf(msg, "(GPAC) %s: %02.2f", szTitle, (100.0*evt->progress.done) / evt->progress.total);
                        Osmozilla_SetStatus(osmo->np_instance, msg);
                }
                break;

        /*IGNORE any scene size, just work with the size allocated in the parent doc*/
        case GF_EVENT_SCENE_SIZE:
                gf_term_set_size(osmo->term, osmo->width, osmo->height);
                break;
        /*window has been resized (full-screen plugin), resize*/
        case GF_EVENT_SIZE:
                osmo->width = evt->size.width;
                osmo->height = evt->size.height;
                gf_term_set_size(osmo->term, osmo->width, osmo->height);
                break;
        case GF_EVENT_CONNECT:
                osmo->is_connected = evt->connect.is_connected;
                break;
        case GF_EVENT_DURATION:
                osmo->can_seek = evt->duration.can_seek;
                osmo->duration = evt->duration.duration;
                break;
        case GF_EVENT_DBLCLICK:
                gf_term_set_option(osmo->term, GF_OPT_FULLSCREEN, !gf_term_get_option(osmo->term, GF_OPT_FULLSCREEN));
                break;
        case GF_EVENT_NAVIGATE_INFO:
                strcpy(msg, evt->navigate.to_url);
                Osmozilla_SetStatus(osmo->np_instance, msg);
                break;
        case GF_EVENT_NAVIGATE:
                if (gf_term_is_supported_url(osmo->term, evt->navigate.to_url, GF_TRUE, osmo->disable_mime ? GF_TRUE : GF_FALSE)) {
                        gf_term_navigate_to(osmo->term, evt->navigate.to_url);
                        return GF_TRUE;
                } else {
                        u32 i;
                        char *target = (char *)"_self";

                        for (i=0; i<evt->navigate.param_count; i++) {
                                if (!strcmp(evt->navigate.parameters[i], "_parent")) target = (char *)"_parent";
                                else if (!strcmp(evt->navigate.parameters[i], "_blank")) target = (char *)"_blank";
                                else if (!strcmp(evt->navigate.parameters[i], "_top")) target = (char *)"_top";
                                else if (!strcmp(evt->navigate.parameters[i], "_new")) target = (char *)"_new";
                                else if (!strnicmp(evt->navigate.parameters[i], "_target=", 8)) target = (char *) evt->navigate.parameters[i]+8;
                        }
                        Osmozilla_GetURL(osmo->np_instance, evt->navigate.to_url, target);
                        return GF_TRUE;
                }
                break;
        }
        return GF_FALSE;
}

int Osmozilla_Initialize(Osmozilla *osmo, signed short argc, char* argn[], char* argv[])
{
        const char *str;
        int i;
        osmo->auto_start = 1;
        osmo->use_gui = 0;

        /*options sent from plugin*/
        for(i=0; i<argc; i++) {
                if (!argn[i] || !argv[i]) continue;
                if (!stricmp(argn[i],"autostart") && (!stricmp(argv[i], "false") || !stricmp(argv[i], "no")) )
                        osmo->auto_start = 0;

                else if (!stricmp(argn[i],"src") ) {
                        if (osmo->url) gf_free(osmo->url);
                        osmo->url = gf_strdup(argv[i]);
                }
                else if (!stricmp(argn[i],"use3d") && (!stricmp(argv[i], "true") || !stricmp(argv[i], "yes") ) ) {
                        osmo->use_3d = 1;
                }
                else if (!stricmp(argn[i],"loop") && (!stricmp(argv[i], "true") || !stricmp(argv[i], "yes") ) ) {
                        osmo->loop = 1;
                }
                else if (!stricmp(argn[i],"aspectratio")) {
                        osmo->aspect_ratio = GF_ASPECT_RATIO_KEEP;
                        if (!stricmp(argv[i], "keep")) osmo->aspect_ratio = GF_ASPECT_RATIO_KEEP;
                        else if (!stricmp(argv[i], "16:9")) osmo->aspect_ratio = GF_ASPECT_RATIO_16_9;
                        else if (!stricmp(argv[i], "4:3")) osmo->aspect_ratio = GF_ASPECT_RATIO_4_3;
                        else if (!stricmp(argv[i], "fill")) osmo->aspect_ratio = GF_ASPECT_RATIO_FILL_SCREEN;
                }
                else if (!stricmp(argn[i],"gui") && (!stricmp(argv[i], "true") || !stricmp(argv[i], "yes") ) )
                        osmo->use_gui = 1;
        }

        /*URL is not absolute, request new stream to mozilla - we don't pass absolute URLs since some may not be
        handled by gecko */
        if (osmo->url) {
                Bool absolute_url = GF_FALSE;
                if (strstr(osmo->url, "://")) absolute_url = GF_TRUE;
                else if (osmo->url[0] == '/') {
                        FILE *test = gf_fopen(osmo->url, "rb");
                        if (test) {
                                absolute_url = GF_TRUE;
                                gf_fclose(test);
                        }
                }
                else if ((osmo->url[1] == ':') && ((osmo->url[2] == '\\') || (osmo->url[2] == '/'))) absolute_url = GF_TRUE;

                if (!absolute_url) {
                        char *url = osmo->url;
                        osmo->url = NULL;
                        Osmozilla_GetURL(osmo->np_instance, url, NULL);
                        gf_free(url);
                }
        }

        GF_SAFEALLOC(osmo->user, GF_User);
        osmo->user->config = gf_cfg_init(NULL, NULL);
        /*need to have a valid cfg file for now*/
        if (!osmo->user->config) {
                gf_free(osmo->user);
                osmo->user = NULL;
#ifdef WIN32
                MessageBox(NULL, "GPAC CONFIGURATION FILE NOT FOUND OR INVALID", "OSMOZILLA FATAL ERROR", MB_OK);
#else
                fprintf(stdout, "OSMOZILLA FATAL ERROR\nGPAC CONFIGURATION FILE NOT FOUND OR INVALID\n");
#endif
                return 0;
        }

        osmo->user->modules = gf_modules_new(NULL, osmo->user->config);
        if (!gf_modules_get_count(osmo->user->modules)) {
                if (osmo->user->modules) gf_modules_del(osmo->user->modules);
                gf_free(osmo->user);
                osmo->user = NULL;
#ifdef WIN32
                MessageBox(NULL, "GPAC MODULES NOT FOUND", "OSMOZILLA FATAL ERROR", MB_OK);
#else
                fprintf(stdout, "OSMOZILLA FATAL ERROR\nGPAC MODULES NOT FOUND\n");
#endif
                return 0;
        }

        osmo->user->opaque = osmo;
        osmo->user->EventProc = Osmozilla_EventProc;

        /*always fetch mime ? Check with anchor examples*/
        osmo->disable_mime = 0;
        str = gf_cfg_get_key(osmo->user->config, "General", "NoMIMETypeFetch");
        if (str && !strcmp(str, "yes")) osmo->disable_mime = 0;
        /*check log file*/
        str = gf_cfg_get_key(osmo->user->config, "General", "LogFile");
        if (str) {
                osmo->logs = gf_fopen(str, "wt");
                if (osmo->logs) gf_log_set_callback(osmo->logs, osmozilla_do_log);
        }

        /*setup logs*/
        if (gf_log_set_tools_levels(gf_cfg_get_key(osmo->user->config, "General", "Logs")) != GF_OK)
                fprintf(stdout, "Osmozilla: invalid log level specified\n");

        fprintf(stdout, "Osmozilla initialized\n");
        return 1;
}

int Osmozilla_SetWindow(Osmozilla *osmo, void *os_wnd_handle, void *os_wnd_display, unsigned int width, unsigned int height)
{
        const char *gui;

        if (!osmo->user) return 0;

        if (osmo->window_set) {
                osmo->width = width;
                osmo->height = height;
                if (osmo->is_connected) gf_term_set_size(osmo->term, osmo->width, osmo->height);
                return 1;
        }
        if (!os_wnd_handle) return 0;

        osmo->width = width;
        osmo->height = height;

        osmo->user->os_window_handler = os_wnd_handle;
        osmo->user->os_display = os_wnd_display;

        /*Everything is now setup, create the terminal*/
        fprintf(stdout, "Creating Osmozilla terminal\n");
        osmo->term = gf_term_new(osmo->user);
        if (!osmo->term) return 0;
        fprintf(stdout, "Osmozilla terminal created\n");

        gf_term_set_option(osmo->term, GF_OPT_ASPECT_RATIO, osmo->aspect_ratio);
        osmo->window_set = 1;

#ifdef XP_WIN
        SetFocus((HWND)os_wnd_handle);
#endif

        /*stream not ready*/
        if (!osmo->url || !osmo->auto_start) {
                fprintf(stdout, "Osmozilla ready - not connecting to %s yet\n", osmo->url);
                return 1;
        }

        /*connect from 0 and pause if not autoplay*/
        gui = gf_cfg_get_key(osmo->user->config, "General", "StartupFile");
        if (gui && osmo->use_gui) {
                gf_cfg_set_key(osmo->user->config, "Temp", "BrowserMode", "yes");
                gf_cfg_set_key(osmo->user->config, "Temp", "GUIStartupFile", osmo->url);
                gf_term_connect(osmo->term, gui);
        } else {
                gf_term_connect(osmo->term, osmo->url);
        }
        fprintf(stdout, "Osmozilla connected to %s\n", osmo->url);
        return 1;
}

char *Osmozilla_GetVersion()
{
        return (char *) "GPAC Plugin " GPAC_FULL_VERSION " for NPAPI compatible Web Browsers. For more information go to <a href=\"http://gpac.sourceforge.net\">GPAC website</a>";
}

void Osmozilla_ConnectTo(Osmozilla *osmo, const char *url)
{
        if (!osmo->user) return;

        if ( osmo->url && !strcmp(url, osmo->url))
                return;

        fprintf(stdout, "Osmozilla connecting to %s\n", url);

        if (osmo->url) gf_free(osmo->url);
        osmo->url = gf_strdup(url);

        /*connect from 0 and pause if not autoplay*/
        if (osmo->auto_start) {
                const char *gui = gf_cfg_get_key(osmo->user->config, "General", "StartupFile");
                if (gui && osmo->use_gui) {
                        gf_cfg_set_key(osmo->user->config, "Temp", "BrowserMode", "yes");
                        gf_cfg_set_key(osmo->user->config, "Temp", "GUIStartupFile", url);
                        gf_term_connect(osmo->term, gui);
                } else {
                        gf_term_connect(osmo->term, url);
                }
        }
        fprintf(stdout, "Osmozilla connected to %s\n", url);
}

void Osmozilla_Pause(Osmozilla *osmo)
{
        if (osmo->term) {
                if (gf_term_get_option(osmo->term, GF_OPT_PLAY_STATE) == GF_STATE_PAUSED) {
                        gf_term_set_option(osmo->term, GF_OPT_PLAY_STATE, GF_STATE_PLAYING);
                } else {
                        gf_term_set_option(osmo->term, GF_OPT_PLAY_STATE, GF_STATE_PAUSED);
                }
        }
}

void Osmozilla_Play(Osmozilla *osmo)
{
        if (!osmo->is_connected) {
                if (osmo->url) gf_term_connect(osmo->term, (const char *) osmo->url);
        } else {
                gf_term_set_option(osmo->term, GF_OPT_PLAY_STATE, GF_STATE_PLAYING);
        }
}

void Osmozilla_Stop(Osmozilla *osmo)
{
        if (osmo->term) gf_term_disconnect(osmo->term);
}

#ifdef XP_WIN
PBITMAPINFO CreateBitmapInfoStruct(GF_VideoSurface *pfb)
{
        PBITMAPINFO pbmi;
        WORD    cClrBits;

        cClrBits = 32;

        pbmi = (PBITMAPINFO) LocalAlloc(LPTR,
                                        sizeof(BITMAPINFOHEADER));

        pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
        pbmi->bmiHeader.biWidth = pfb->width;
        pbmi->bmiHeader.biHeight = 1;
        pbmi->bmiHeader.biPlanes = 1;
        pbmi->bmiHeader.biBitCount = cClrBits;

        pbmi->bmiHeader.biCompression = BI_RGB;
        pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8
                                      * pbmi->bmiHeader.biHeight;
        pbmi->bmiHeader.biClrImportant = 0;
        return pbmi;
}
#endif

void Osmozilla_Print(Osmozilla *osmo, unsigned int is_embed, void *os_print_dc, unsigned int target_x, unsigned int target_y, unsigned int target_width, unsigned int target_height)
{
        if (is_embed) {
#ifdef XP_MACOS
                /*
                os_print_dc contains a THPrint reference on MacOS
                */
        }
#endif  // XP_MACOS
#ifdef XP_UNIX
        /*
        os_print_dc contains a NPPrintCallbackStruct on Unix and
        the plug-in location and size in the NPWindow are in page coordinates (720/ inch), but the printer requires point coordinates (72/inch)
        */
#endif  // XP_UNIX
#ifdef XP_WIN
        /*
        The coordinates for the window rectangle are in TWIPS format.
        This means that you need to convert the x-y coordinates using the Windows API call DPtoLP when you output text
        */
        GF_VideoSurface fb;
        u32 xsrc, ysrc;
        u16 src_16;
        char *src;
        float deltay;
        int     ysuiv = 0;
        char *ligne;
        BITMAPINFO      *infoSrc;
        HDC pDC = (HDC)os_print_dc;
        /*lock the source buffer */
        gf_term_get_screen_buffer(osmo->term, &fb);
        infoSrc = CreateBitmapInfoStruct(&fb);
        deltay = (float)target_height/(float)fb.height;
        ligne = (char *) LocalAlloc(GMEM_FIXED, fb.width*4);
        for (ysrc=0; ysrc<fb.height; ysrc++) {
                int ycrt, delta;
                char *dst = (char*)ligne;
                src = fb.video_buffer + ysrc * fb.pitch_y;
                for (xsrc=0; xsrc<fb.width; xsrc++)
                {
                        switch (fb.pixel_format) {
                        case GF_PIXEL_RGB_32:
                        case GF_PIXEL_ARGB:
                                dst[0] = src[0];
                                dst[1] = src[1];
                                dst[2] = src[2];
                                src+=4;
                                break;
                        case GF_PIXEL_BGR_32:
                        case GF_PIXEL_RGBA:
                                dst[0] = src[3];
                                dst[1] = src[2];
                                dst[2] = src[1];
                                src+=4;
                                break;
                        case GF_PIXEL_RGB_24:
                                dst[0] = src[2];
                                dst[1] = src[1];
                                dst[2] = src[0];
                                src+=3;
                                break;
                        case GF_PIXEL_BGR_24:
                                dst[0] = src[2];
                                dst[1] = src[1];
                                dst[2] = src[0];
                                src+=3;
                                break;
                        case GF_PIXEL_RGB_565:
                                src_16 = * ( (u16 *)src );
                                dst[2] = (src_16 >> 8) & 0xf8;
                                dst[2] += dst[2]>>5;
                                dst[1] = (src_16 >> 3) & 0xfc;
                                dst[1] += dst[1]>>6;
                                dst[0] = (src_16 << 3) & 0xf8;
                                dst[0] += dst[0]>>5;
                                src+=2;
                                break;
                        case GF_PIXEL_RGB_555:
                                src_16 = * (u16 *)src;
                                dst[2] = (src_16 >> 7) & 0xf8;
                                dst[2] += dst[2]>>5;
                                dst[1] = (src_16 >> 2) & 0xf8;
                                dst[1] += dst[1]>>5;
                                dst[0] = (src_16 << 3) & 0xf8;
                                dst[0] += dst[0]>>5;
                                src+=2;
                                break;
                        }
                        dst += 4;
                }
                ycrt = ysuiv;
                ysuiv = (u32) ( ((float)ysrc+1.0)*deltay);
                delta = ysuiv-ycrt;
                StretchDIBits(
                    pDC, target_x, target_y, target_width,
                    delta,
                    0, 0, fb.width, 1,
                    ligne, infoSrc, DIB_RGB_COLORS, SRCCOPY);
        }

        /*unlock GPAC frame buffer */
        gf_term_release_screen_buffer(osmo->term, &fb);
        /* gf_free temporary  objects */
        GlobalFree(ligne);
        LocalFree(infoSrc);
#endif   // XP_WIN

        return;
}

/*TODO - this is full print, present the print dialog and manage the print*/
}

void Osmozilla_Update(Osmozilla *osmo, const char *type, const char *commands)
{
        if (osmo->term) {
                GF_Err e = gf_term_scene_update(osmo->term, (char *) type, (char *) commands);
                if (e) {
                        char szMsg[1024];
                        sprintf((char *)szMsg, "GPAC: Error applying update (%s)", gf_error_to_string(e) );
                        Osmozilla_SetStatus(osmo->np_instance, szMsg);
                }
        }
}

void Osmozilla_QualitySwitch(Osmozilla *osmo, int switch_up)
{
        if (osmo->term)
                gf_term_switch_quality(osmo->term, switch_up ? GF_TRUE : GF_FALSE);
}

void Osmozilla_SetURL(Osmozilla *osmo, const char *url)
{
        if (osmo->term) {
                if (osmo->url) gf_free(osmo->url);
                osmo->url = gf_strdup(url);
                gf_term_connect(osmo->term, osmo->url);
        }
}

int Osmozilla_GetDownloadProgress(Osmozilla *osmo)
{
        if (osmo->term)
                return osmo->download_progress;
        return 0;
}

/* [<][>][^][v][top][bottom][index][help] */