Logo
  • Main Page
  • Related Pages
  • Modules
  • Classes
  • Files

mmsflash.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2005-2007 Stefan Schwarzer, Jens Schneider,             *
00003  *                           Matthias Hardt, Guido Madaus                  *
00004  *                                                                         *
00005  *   Copyright (C) 2007-2008 BerLinux Solutions GbR                        *
00006  *                           Stefan Schwarzer & Guido Madaus               *
00007  *                                                                         *
00008  *   Copyright (C) 2009-2013 BerLinux Solutions GmbH                       *
00009  *                                                                         *
00010  *   Authors:                                                              *
00011  *      Stefan Schwarzer   <stefan.schwarzer@diskohq.org>,                 *
00012  *      Matthias Hardt     <matthias.hardt@diskohq.org>,                   *
00013  *      Jens Schneider     <jens.schneider@diskohq.org>,                   *
00014  *      Guido Madaus       <guido.madaus@diskohq.org>,                     *
00015  *      Patrick Helterhoff <patrick.helterhoff@diskohq.org>,               *
00016  *      René Bählkow       <rene.baehlkow@diskohq.org>                     *
00017  *                                                                         *
00018  *   This library is free software; you can redistribute it and/or         *
00019  *   modify it under the terms of the GNU Lesser General Public            *
00020  *   License version 2.1 as published by the Free Software Foundation.     *
00021  *                                                                         *
00022  *   This library is distributed in the hope that it will be useful,       *
00023  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00024  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00025  *   Lesser General Public License for more details.                       *
00026  *                                                                         *
00027  *   You should have received a copy of the GNU Lesser General Public      *
00028  *   License along with this library; if not, write to the                 *
00029  *   Free Software Foundation, Inc.,                                       *
00030  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
00031  **************************************************************************/
00032 
00033 #ifdef __HAVE_MMSFLASH__
00034 
00035 #include "mmsflash/mmsflash.h"
00036 #include "mmsflash/mmsflashthread.h"
00037 
00038 extern "C" {
00039 #include <swfdec/swfdec.h>
00040 #include <swfdec/swfdec_buffer.h>
00041 }
00042 
00043 #include <cairo.h>
00044 #include <cairo-features.h>
00045 
00046 
00047 // static variables
00048 bool MMSFlash::swfdec_initialized = false;
00049 
00050 
00051 MMSFlash::MMSFlash(MMSWindow *window) {
00052     // init the window
00053     this->window = window;
00054     this->window->onHandleInput->connect(sigc::mem_fun(this,&MMSFlash::onHandleInput));
00055 
00056     // init all others
00057     this->ready                 = false;
00058     this->playing               = false;
00059     this->swfdec_player         = NULL;
00060     this->swfdec_rate           = 0;
00061     this->width                 = 0;
00062     this->height                = 0;
00063     this->flash_temp_surface    = NULL;
00064     this->loaderthread          = new MMSFlashThread(this, MMSFLASHTHREAD_MODE_LOADER, "MMSFlashLoaderThread");
00065     this->playerthread          = new MMSFlashThread(this, MMSFLASHTHREAD_MODE_PLAYER, "MMSFlashPlayerThread");
00066 
00067     if (!this->swfdec_initialized) {
00068         DEBUGMSG("MMSFLASH", "initializing swfdec");
00069         swfdec_init();
00070         DEBUGMSG("MMSFLASH", "swfdec initialized");
00071         this->swfdec_initialized = true;
00072     }
00073 }
00074 
00075 MMSFlash::~MMSFlash() {
00076     stopThreads();
00077     if (this->flash_temp_surface)
00078         delete this->flash_temp_surface;
00079     if (this->swfdec_player)
00080         g_object_unref(this->swfdec_player);
00081 }
00082 
00083 
00084 void MMSFlash::loader(bool &stop) {
00085 
00086     // lock me
00087     lock.lock();
00088     this->ready = false;
00089     this->playing = false;
00090 
00091     // new player object
00092     if (this->swfdec_player)
00093         g_object_unref(this->swfdec_player);
00094     DEBUGMSG("MMSFLASH", "creating swfdec player");
00095     this->swfdec_player = swfdec_player_new(NULL);
00096     if (!this->swfdec_player) {
00097         lock.unlock();
00098         DEBUGMSG("MMSFLASH", "Cannot get a new SwfdecPlayer object");
00099         return;
00100     }
00101 
00102     // set url
00103     DEBUGMSG("MMSFLASH", "setting swfdec player url");
00104     SwfdecURL *url = swfdec_url_new(this->filename.c_str());
00105     swfdec_player_set_url((SwfdecPlayer*)this->swfdec_player, url);
00106     swfdec_url_free(url);
00107 
00108     // check if player is initialized
00109     DEBUGMSG("MMSFLASH", "checking swfdec player");
00110     swfdec_player_advance((SwfdecPlayer*)this->swfdec_player, 0);
00111     if (!swfdec_player_is_initialized((SwfdecPlayer*)this->swfdec_player)) {
00112         g_object_unref(this->swfdec_player);
00113         this->swfdec_player = NULL;
00114         lock.unlock();
00115         fprintf(stderr, "Cannot initialize SwfdecPlayer object\n");
00116         return;
00117     }
00118 
00119     // get frame rate
00120     this->swfdec_rate = swfdec_player_get_rate((SwfdecPlayer*)this->swfdec_player);
00121     DEBUGMSG("MMSFLASH", "frame rate = %d", this->swfdec_rate);
00122 
00123     // get size of the flash image
00124     guint ww,hh;
00125     swfdec_player_get_default_size((SwfdecPlayer*)this->swfdec_player, &ww, &hh);
00126     this->width=ww;
00127     this->height=hh;
00128     DEBUGMSG("MMSFLASH", "size = %d x %d", this->width, this->height);
00129 
00130     // (re-)create surface for cairo/swfdec
00131     if (this->flash_temp_surface)
00132         delete flash_temp_surface;
00133     DEBUGMSG("MMSFLASH", "creating surface for cairo/swfdec");
00134     this->window->getLayer()->createSurface(&(this->flash_temp_surface), this->width, this->height, MMSFB_PF_ARGB, 0);
00135     if (!this->flash_temp_surface) {
00136         g_object_unref(this->swfdec_player);
00137         this->swfdec_player = NULL;
00138         lock.unlock();
00139         DEBUGMSG("MMSFLASH", "Cannot create temporary surface");
00140         return;
00141     }
00142     void *ptr;
00143     int pitch;
00144     this->flash_temp_surface->lock(MMSFB_LOCK_WRITE, &ptr, &pitch);
00145     this->flash_temp_surface->unlock();
00146     DEBUGMSG("MMSFLASH", "creating cairo surface");
00147     this->cairosurface = cairo_image_surface_create_for_data((unsigned char*)ptr, CAIRO_FORMAT_ARGB32,
00148                                                                 this->width, this->height, pitch);
00149     if (!this->cairosurface) {
00150         delete this->flash_temp_surface;
00151         this->flash_temp_surface = NULL;
00152         g_object_unref(this->swfdec_player);
00153         this->swfdec_player = NULL;
00154         lock.unlock();
00155         DEBUGMSG("MMSFLASH", "Cannot create cairo surface");
00156         return;
00157     }
00158     DEBUGMSG("MMSFLASH", "creating cairo object");
00159     this->cairo = cairo_create((cairo_surface_t *)cairosurface);
00160     cairo_surface_destroy((cairo_surface_t *)cairosurface);
00161     if (!this->cairo) {
00162         delete this->flash_temp_surface;
00163         this->flash_temp_surface = NULL;
00164         g_object_unref(this->swfdec_player);
00165         this->swfdec_player = NULL;
00166         lock.unlock();
00167         DEBUGMSG("MMSFLASH", "Cannot create cairo object");
00168         return;
00169     }
00170 
00171     // ready for playing
00172     this->ready = true;
00173 
00174     // unlock me
00175     lock.unlock();
00176     DEBUGMSG("MMSFLASH", "loading finished");
00177 }
00178 
00179 void MMSFlash::player(bool &stop) {
00180     // waiting for ready state
00181     this->playing = false;
00182     while ((!stop)&&(!this->ready)) {
00183         msleep(50);
00184         if ((!this->ready)&&(!this->loaderthread->isRunning()))
00185             return;
00186     }
00187     this->playing = true;
00188 
00189     // until stopped
00190     unsigned int sleep_time = (unsigned int)(1000 / this->swfdec_rate);
00191     while (!stop) {
00192         if (!this->window->isShown(true)) {
00193             // window is not shown, so playback is not needed
00194             msleep(500);
00195             continue;
00196         }
00197 
00198         // lock me
00199         lock.lock();
00200 
00201         // get start time
00202         unsigned int start_ts = getMTimeStamp();
00203 
00204         // get background color of the current frame and clear the surface
00205         unsigned int bg = swfdec_player_get_background_color((SwfdecPlayer*)this->swfdec_player);
00206         this->flash_temp_surface->clear( (bg >> 16) & 0xff, (bg >> 8) & 0xff, bg & 0xff, bg >> 24 );
00207 
00208         // let swfdec render to the temporary surface
00209         DEBUGMSG("MMSFLASH", "rendering");
00210         swfdec_player_render((SwfdecPlayer*)this->swfdec_player, (cairo_t *)this->cairo);
00211         DEBUGMSG("MMSFLASH", "finished rendering");
00212 
00213         // unlock me
00214         lock.unlock();
00215 
00216         // do an stretchblit to the window and flip it
00217         this->window->getSurface()->stretchBlit(this->flash_temp_surface, NULL, NULL);
00218         this->window->flip();
00219 
00220         // calc sleep time and sleep
00221         unsigned int end_ts = getMTimeStamp();
00222         end_ts = getMDiff(start_ts, end_ts);
00223         if (end_ts < sleep_time)
00224             msleep(sleep_time - end_ts);
00225     }
00226 
00227     // reset state
00228     this->playing = false;
00229 }
00230 
00231 void MMSFlash::stopThreads(void) {
00232     // stop it all
00233     this->loaderthread->invokeStop();
00234     this->playerthread->invokeStop();
00235     this->loaderthread->waitUntilStopped();
00236     this->playerthread->waitUntilStopped();
00237 
00238     // reset state
00239     this->ready = false;
00240     this->playing = false;
00241 }
00242 
00243 unsigned int MMSFlash::mapKey(MMSKeySymbol key) {
00244     switch (key) {
00245     case MMSKEY_CURSOR_UP:
00246         return SWFDEC_KEY_UP;
00247     case MMSKEY_CURSOR_DOWN:
00248         return SWFDEC_KEY_DOWN;
00249     case MMSKEY_CURSOR_LEFT:
00250         return SWFDEC_KEY_LEFT;
00251     case MMSKEY_CURSOR_RIGHT:
00252         return SWFDEC_KEY_RIGHT;
00253     case MMSKEY_SPACE:
00254         return SWFDEC_KEY_SPACE;
00255     case MMSKEY_BACKSPACE:
00256         return SWFDEC_KEY_BACKSPACE;
00257     case MMSKEY_SLASH:
00258         return SWFDEC_KEY_SLASH;
00259     case MMSKEY_BACKSLASH:
00260         return SWFDEC_KEY_BACKSLASH;
00261     case MMSKEY_TAB:
00262         return SWFDEC_KEY_TAB;
00263     case MMSKEY_CLEAR:
00264         return SWFDEC_KEY_CLEAR;
00265     case MMSKEY_RETURN:
00266         return SWFDEC_KEY_ENTER;
00267     case MMSKEY_SHIFT:
00268         return SWFDEC_KEY_SHIFT;
00269     case MMSKEY_CONTROL:
00270         return SWFDEC_KEY_CONTROL;
00271     case MMSKEY_ALT:
00272         return SWFDEC_KEY_ALT;
00273     case MMSKEY_CAPS_LOCK:
00274         return SWFDEC_KEY_CAPS_LOCK;
00275     case MMSKEY_ESCAPE:
00276         return SWFDEC_KEY_ESCAPE;
00277     case MMSKEY_PAGE_UP:
00278         return SWFDEC_KEY_PAGE_UP;
00279     case MMSKEY_PAGE_DOWN:
00280         return SWFDEC_KEY_PAGE_DOWN;
00281     case MMSKEY_END:
00282         return SWFDEC_KEY_END;
00283     case MMSKEY_HOME:
00284         return SWFDEC_KEY_HOME;
00285     case MMSKEY_INSERT:
00286         return SWFDEC_KEY_INSERT;
00287     case MMSKEY_DELETE:
00288         return SWFDEC_KEY_DELETE;
00289     case MMSKEY_HELP:
00290         return SWFDEC_KEY_HELP;
00291     case MMSKEY_0:
00292         return SWFDEC_KEY_0;
00293     case MMSKEY_1:
00294         return SWFDEC_KEY_1;
00295     case MMSKEY_2:
00296         return SWFDEC_KEY_2;
00297     case MMSKEY_3:
00298         return SWFDEC_KEY_3;
00299     case MMSKEY_4:
00300         return SWFDEC_KEY_4;
00301     case MMSKEY_5:
00302         return SWFDEC_KEY_5;
00303     case MMSKEY_6:
00304         return SWFDEC_KEY_6;
00305     case MMSKEY_7:
00306         return SWFDEC_KEY_7;
00307     case MMSKEY_8:
00308         return SWFDEC_KEY_8;
00309     case MMSKEY_9:
00310         return SWFDEC_KEY_9;
00311     case MMSKEY_CAPITAL_A:
00312     case MMSKEY_SMALL_A:
00313         return SWFDEC_KEY_A;
00314     case MMSKEY_CAPITAL_B:
00315     case MMSKEY_SMALL_B:
00316         return SWFDEC_KEY_B;
00317     case MMSKEY_CAPITAL_C:
00318     case MMSKEY_SMALL_C:
00319         return SWFDEC_KEY_C;
00320     case MMSKEY_CAPITAL_D:
00321     case MMSKEY_SMALL_D:
00322         return SWFDEC_KEY_D;
00323     case MMSKEY_CAPITAL_E:
00324     case MMSKEY_SMALL_E:
00325         return SWFDEC_KEY_E;
00326     case MMSKEY_CAPITAL_F:
00327     case MMSKEY_SMALL_F:
00328         return SWFDEC_KEY_F;
00329     case MMSKEY_CAPITAL_G:
00330     case MMSKEY_SMALL_G:
00331         return SWFDEC_KEY_G;
00332     case MMSKEY_CAPITAL_H:
00333     case MMSKEY_SMALL_H:
00334         return SWFDEC_KEY_H;
00335     case MMSKEY_CAPITAL_I:
00336     case MMSKEY_SMALL_I:
00337         return SWFDEC_KEY_I;
00338     case MMSKEY_CAPITAL_J:
00339     case MMSKEY_SMALL_J:
00340         return SWFDEC_KEY_J;
00341     case MMSKEY_CAPITAL_K:
00342     case MMSKEY_SMALL_K:
00343         return SWFDEC_KEY_K;
00344     case MMSKEY_CAPITAL_L:
00345     case MMSKEY_SMALL_L:
00346         return SWFDEC_KEY_L;
00347     case MMSKEY_CAPITAL_M:
00348     case MMSKEY_SMALL_M:
00349         return SWFDEC_KEY_M;
00350     case MMSKEY_CAPITAL_N:
00351     case MMSKEY_SMALL_N:
00352         return SWFDEC_KEY_N;
00353     case MMSKEY_CAPITAL_O:
00354     case MMSKEY_SMALL_O:
00355         return SWFDEC_KEY_O;
00356     case MMSKEY_CAPITAL_P:
00357     case MMSKEY_SMALL_P:
00358         return SWFDEC_KEY_P;
00359     case MMSKEY_CAPITAL_Q:
00360     case MMSKEY_SMALL_Q:
00361         return SWFDEC_KEY_Q;
00362     case MMSKEY_CAPITAL_R:
00363     case MMSKEY_SMALL_R:
00364         return SWFDEC_KEY_R;
00365     case MMSKEY_CAPITAL_S:
00366     case MMSKEY_SMALL_S:
00367         return SWFDEC_KEY_S;
00368     case MMSKEY_CAPITAL_T:
00369     case MMSKEY_SMALL_T:
00370         return SWFDEC_KEY_T;
00371     case MMSKEY_CAPITAL_U:
00372     case MMSKEY_SMALL_U:
00373         return SWFDEC_KEY_U;
00374     case MMSKEY_CAPITAL_V:
00375     case MMSKEY_SMALL_V:
00376         return SWFDEC_KEY_V;
00377     case MMSKEY_CAPITAL_W:
00378     case MMSKEY_SMALL_W:
00379         return SWFDEC_KEY_W;
00380     case MMSKEY_CAPITAL_X:
00381     case MMSKEY_SMALL_X:
00382         return SWFDEC_KEY_X;
00383     case MMSKEY_CAPITAL_Y:
00384     case MMSKEY_SMALL_Y:
00385         return SWFDEC_KEY_Y;
00386     case MMSKEY_CAPITAL_Z:
00387     case MMSKEY_SMALL_Z:
00388         return SWFDEC_KEY_Z;
00389     case MMSKEY_F1:
00390         return SWFDEC_KEY_F1;
00391     case MMSKEY_F2:
00392         return SWFDEC_KEY_F2;
00393     case MMSKEY_F3:
00394         return SWFDEC_KEY_F3;
00395     case MMSKEY_F4:
00396         return SWFDEC_KEY_F4;
00397     case MMSKEY_F5:
00398         return SWFDEC_KEY_F5;
00399     case MMSKEY_F6:
00400         return SWFDEC_KEY_F6;
00401     case MMSKEY_F7:
00402         return SWFDEC_KEY_F7;
00403     case MMSKEY_F8:
00404         return SWFDEC_KEY_F8;
00405     case MMSKEY_F9:
00406         return SWFDEC_KEY_F9;
00407     case MMSKEY_F10:
00408         return SWFDEC_KEY_F10;
00409     case MMSKEY_F11:
00410         return SWFDEC_KEY_F11;
00411     case MMSKEY_F12:
00412         return SWFDEC_KEY_F12;
00413     case MMSKEY_NUM_LOCK:
00414         return SWFDEC_KEY_NUM_LOCK;
00415     case MMSKEY_SCROLL_LOCK:
00416         return SWFDEC_KEY_SCROLL_LOCK;
00417     case MMSKEY_SEMICOLON:
00418         return SWFDEC_KEY_SEMICOLON;
00419     case MMSKEY_EQUALS_SIGN:
00420         return SWFDEC_KEY_EQUAL;
00421     case MMSKEY_COMMA:
00422         return SWFDEC_KEY_COMMA;
00423     case MMSKEY_MINUS_SIGN:
00424         return SWFDEC_KEY_MINUS;
00425     case MMSKEY_PERIOD:
00426         return SWFDEC_KEY_DOT;
00427     case MMSKEY_GRAVE_ACCENT:
00428         return SWFDEC_KEY_GRAVE;
00429     case MMSKEY_APOSTROPHE:
00430         return SWFDEC_KEY_APOSTROPHE;
00431     default:
00432         return 0;
00433     }
00434 }
00435 
00436 bool MMSFlash::onHandleInput(MMSWindow *window, MMSInputEvent *input) {
00437     unsigned int    key;
00438 
00439     // check state
00440     if (!this->swfdec_player)
00441         return false;
00442     if (!input)
00443         return false;
00444 
00445     // lock me
00446     lock.lock();
00447 
00448     // calculate the pointer position within flash image
00449     int posx = input->posx;
00450     int posy = input->posy;
00451     if (input->type == MMSINPUTEVENTTYPE_BUTTONPRESS || input->type == MMSINPUTEVENTTYPE_BUTTONRELEASE || input->type == MMSINPUTEVENTTYPE_AXISMOTION) {
00452         MMSFBRectangle ig = window->getGeometry();
00453         if (this->width != ig.w)
00454             posx = ((posx * (this->width << 8)) / ig.w) >> 8;
00455         if (this->height != ig.h)
00456             posy = ((posy * (this->height << 8)) / ig.h) >> 8;
00457     }
00458 
00459     // send event to the player
00460     switch (input->type) {
00461     case MMSINPUTEVENTTYPE_KEYPRESS:
00462         if ((key = mapKey(input->key)))
00463             swfdec_player_key_press((SwfdecPlayer*)this->swfdec_player, key, 0);
00464         break;
00465     case MMSINPUTEVENTTYPE_KEYRELEASE:
00466         if ((key = mapKey(input->key)))
00467             swfdec_player_key_release((SwfdecPlayer*)this->swfdec_player, key, 0);
00468         break;
00469     case MMSINPUTEVENTTYPE_BUTTONPRESS:
00470         swfdec_player_mouse_press((SwfdecPlayer*)this->swfdec_player, posx, posy, 1);
00471         break;
00472     case MMSINPUTEVENTTYPE_BUTTONRELEASE:
00473         swfdec_player_mouse_release((SwfdecPlayer*)this->swfdec_player, posx, posy, 1);
00474         break;
00475     case MMSINPUTEVENTTYPE_AXISMOTION:
00476         swfdec_player_mouse_move((SwfdecPlayer*)this->swfdec_player, posx, posy);
00477         break;
00478     default:
00479         break;
00480     }
00481 
00482     // unlock me
00483     lock.unlock();
00484 
00485     return true;
00486 }
00487 
00488 void MMSFlash::startPlaying(string filename) {
00489     // check if i have a window
00490     if (!this->window)
00491         return;
00492 
00493     // first, stop the threads
00494     stopThreads();
00495 
00496     // check filename
00497     string prefix = filename.substr(0, 7);
00498     strToUpr(&prefix);
00499     if ((prefix != "FILE://")&&(prefix != "HTTP://"))
00500         if (filename.substr(0,1) != "/") {
00501             char path[1024];
00502             memset(path, 0, sizeof(path));
00503             this->filename = "file://" + (string)getcwd(path, 1024) + "/" + filename;
00504         }
00505         else
00506             this->filename = "file://" + filename;
00507     else
00508         this->filename = filename;
00509 
00510     // start the loader
00511     this->loaderthread->start();
00512 
00513     // start the player
00514     this->playerthread->start();
00515 }
00516 
00517 bool MMSFlash::isReady() {
00518     // waiting until loader thread is started
00519     while (!this->loaderthread->isStarted())
00520         msleep(50);
00521 
00522     // waiting for ready flag
00523     while ((!this->ready)&&(this->loaderthread->isRunning()))
00524         msleep(50);
00525 
00526     return this->ready;
00527 }
00528 
00529 bool MMSFlash::isPlaying(bool wait) {
00530     if (wait)
00531         while ((!this->playing)&&(this->playerthread->isRunning()))
00532             msleep(50);
00533     return this->playing;
00534 }
00535 
00536 
00537 #endif /* __HAVE_MMSFLASH__ */

Generated by doxygen