00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
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
00048 bool MMSFlash::swfdec_initialized = false;
00049
00050
00051 MMSFlash::MMSFlash(MMSWindow *window) {
00052
00053 this->window = window;
00054 this->window->onHandleInput->connect(sigc::mem_fun(this,&MMSFlash::onHandleInput));
00055
00056
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
00087 lock.lock();
00088 this->ready = false;
00089 this->playing = false;
00090
00091
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
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
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
00120 this->swfdec_rate = swfdec_player_get_rate((SwfdecPlayer*)this->swfdec_player);
00121 DEBUGMSG("MMSFLASH", "frame rate = %d", this->swfdec_rate);
00122
00123
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
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
00172 this->ready = true;
00173
00174
00175 lock.unlock();
00176 DEBUGMSG("MMSFLASH", "loading finished");
00177 }
00178
00179 void MMSFlash::player(bool &stop) {
00180
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
00190 unsigned int sleep_time = (unsigned int)(1000 / this->swfdec_rate);
00191 while (!stop) {
00192 if (!this->window->isShown(true)) {
00193
00194 msleep(500);
00195 continue;
00196 }
00197
00198
00199 lock.lock();
00200
00201
00202 unsigned int start_ts = getMTimeStamp();
00203
00204
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
00209 DEBUGMSG("MMSFLASH", "rendering");
00210 swfdec_player_render((SwfdecPlayer*)this->swfdec_player, (cairo_t *)this->cairo);
00211 DEBUGMSG("MMSFLASH", "finished rendering");
00212
00213
00214 lock.unlock();
00215
00216
00217 this->window->getSurface()->stretchBlit(this->flash_temp_surface, NULL, NULL);
00218 this->window->flip();
00219
00220
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
00228 this->playing = false;
00229 }
00230
00231 void MMSFlash::stopThreads(void) {
00232
00233 this->loaderthread->invokeStop();
00234 this->playerthread->invokeStop();
00235 this->loaderthread->waitUntilStopped();
00236 this->playerthread->waitUntilStopped();
00237
00238
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
00440 if (!this->swfdec_player)
00441 return false;
00442 if (!input)
00443 return false;
00444
00445
00446 lock.lock();
00447
00448
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
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
00483 lock.unlock();
00484
00485 return true;
00486 }
00487
00488 void MMSFlash::startPlaying(string filename) {
00489
00490 if (!this->window)
00491 return;
00492
00493
00494 stopThreads();
00495
00496
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
00511 this->loaderthread->start();
00512
00513
00514 this->playerthread->start();
00515 }
00516
00517 bool MMSFlash::isReady() {
00518
00519 while (!this->loaderthread->isStarted())
00520 msleep(50);
00521
00522
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