00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <string.h>
00023
00024
00025
00026 #include <layer.h>
00027 #include <blitter.h>
00028 #include <filter.h>
00029 #include <iterator.h>
00030 #include <closure.h>
00031
00032 #include <context.h>
00033 #include <jutils.h>
00034 #include <config.h>
00035
00036 #include <jsparser_data.h>
00037
00038
00039
00040 Layer::Layer()
00041 :Entry(), JSyncThread() {
00042 func("%s this=%p",__PRETTY_FUNCTION__, this);
00043 active = false;
00044 hidden = false;
00045 fade = false;
00046 use_audio = false;
00047 need_crop = true;
00048 audio = NULL;
00049 opened = false;
00050 bgcolor = 0;
00051 set_name("???");
00052 filename[0] = 0;
00053 buffer = NULL;
00054 screen = NULL;
00055 is_native_sdl_surface = false;
00056 jsclass = &layer_class;
00057
00058 zoom_x = 1.0;
00059 zoom_y = 1.0;
00060 rotate = 0.0;
00061 zooming = false;
00062 rotating = false;
00063
00064 antialias = false;
00065
00066 blitter = NULL;
00067 current_blit = NULL;
00068
00069 null_feeds = 0;
00070 max_null_feeds = 10;
00071
00072 parameters = NULL;
00073
00074 priv_data = NULL;
00075
00076 fps.set(25);
00077
00078 }
00079
00080 Layer::~Layer() {
00081 func("%s this=%p",__PRETTY_FUNCTION__, this);
00082
00083 active = false;
00084 FilterInstance *f = (FilterInstance*)filters.begin();
00085 while(f) {
00086 f->rem();
00087 delete f;
00088 f = (FilterInstance*)filters.begin();
00089 }
00090
00091
00092 if(parameters) {
00093 Parameter *par;
00094 par = parameters->begin();
00095 while(par) {
00096 par->rem();
00097 delete par;
00098 par = parameters->begin();
00099 }
00100 }
00101
00102 if(blitter) delete blitter;
00103 }
00104
00105 void *Layer::get_data() {
00106 return priv_data;
00107 }
00108
00109 void Layer::set_data(void *data) {
00110 priv_data = data;
00111 }
00112 bool Layer::init(int wdt, int hgt, int bpp) {
00113
00114 geo.init(wdt, hgt, bpp);
00115
00116 func("initialized %s layer %ix%i",
00117 get_name(), geo.w, geo.h);
00118
00119 if (!geo.bytesize) {
00120
00121
00122
00123 act("initialized %s layer with dynamic size", get_name());
00124
00125 }
00126
00127
00128 fps.set(25);
00129
00130
00131 return _init();
00132
00133 }
00134
00135 void Layer::thread_setup() {
00136 func("ok, layer %s in rolling loop",get_name());
00137
00138
00139
00140 func(" layer %s entering loop",get_name());
00141 }
00142
00143 void Layer::thread_loop() {
00144
00145 void *tmp_buf;
00146
00147
00148
00149
00150
00151 tmp_buf = feed();
00152
00153
00154 if(tmp_buf) {
00155
00156 tmp_buf = do_filters(tmp_buf);
00157 }
00158
00159
00160
00161
00162
00163 buffer = tmp_buf;
00164
00165 fps.calc();
00166 fps.delay();
00167 }
00168
00169 void Layer::thread_teardown() {
00170 func("%s this=%p thread end: %p %s",__PRETTY_FUNCTION__, this, pthread_self(), name);
00171 }
00172
00173 char *Layer::get_blit() {
00174
00175 if(!current_blit) {
00176 error("no blit currently selected for layer %s",name);
00177 return((char*)"unknown");
00178 }
00179 return current_blit->name;
00180 }
00181
00182 bool Layer::set_blit(const char *bname) {
00183 Blit *b;
00184 int idx;
00185
00186 if (screen && blitter) {
00187 b = (Blit*)blitter->blitlist.search(bname, &idx);
00188
00189 if(!b) {
00190 error("blit %s not found in screen %s",bname, screen->name);
00191 return(false);
00192 }
00193
00194 func("blit for layer %s set to %s",name, b->name);
00195
00196 current_blit = b;
00197 need_crop = true;
00198 blitter->crop(this, screen);
00199 blitter->blitlist.sel(0);
00200 b->sel(true);
00201 act("blit %s set for layer %s", current_blit->name, name);
00202 } else {
00203 warning("can't set blit for layer %s: not added on any screen yet", name);
00204 return(false);
00205 }
00206
00207 return(true);
00208 }
00209
00210 void Layer::blit() {
00211 if(!buffer) {
00212
00213
00214 func("feed returns NULL on layer %s",get_name());
00215 null_feeds++;
00216 if(null_feeds > max_null_feeds) {
00217 warning("layer %s has no video, deactivating", get_name());
00218 active = false;
00219 return;
00220 }
00221
00222 } else {
00223
00224 null_feeds = 0;
00225
00226 lock();
00227 screen->blit(this);
00228 unlock();
00229 }
00230 }
00231
00232 bool Layer::cafudda() {
00233 if(!opened) return false;
00234
00235 if(!fade)
00236 if(!active || hidden)
00237 return false;
00238
00239 do_iterators();
00240
00241
00242
00243
00244 return(true);
00245 }
00246
00247 void *Layer::do_filters(void *tmp_buf) {
00248 if( filters.len() ) {
00249 FilterInstance *filt;
00250 filters.lock();
00251 filt = (FilterInstance *)filters.begin();
00252 while(filt) {
00253 if(filt->active) {
00255 tmp_buf = (void*) filt->process(25.0, (uint32_t*)tmp_buf);
00256 }
00257 filt = (FilterInstance *)filt->next;
00258 }
00259 filters.unlock();
00260 }
00261 return tmp_buf;
00262 }
00263
00264 int Layer::do_iterators() {
00265
00266
00267 if(iterators.len()) {
00268 iterators.lock();
00269 iter = (Iterator*)iterators.begin();
00270 while(iter) {
00271 res = iter->cafudda();
00272 itertmp = iter;
00273 iter = (Iterator*) ((Entry*)iter)->next;
00274 if(res<0) {
00275 iterators.unlock();
00276 delete itertmp;
00277 iterators.lock();
00278 if(!iter)
00279 if(fade) {
00280 fade = false;
00281 active = false;
00282 }
00283 }
00284 }
00285 iterators.unlock();
00286 }
00287 return(1);
00288 }
00289
00290 bool Layer::set_parameter(int idx) {
00291
00292 Parameter *param;
00293 param = (Parameter*)parameters->pick(idx);
00294 if( ! param) {
00295 error("parameter %s not found in layer %s", param->name, name );
00296 return false;
00297 } else
00298 func("parameter %s found in layer %s at position %u",
00299 param->name, name, idx);
00300
00301 if(!param->layer_set_f) {
00302 error("no layer callback function registered in this parameter");
00303 return false;
00304 }
00305
00306 (*param->layer_set_f)(this, param, idx);
00307
00308 return true;
00309 }
00310
00311
00312 void Layer::set_filename(const char *f) {
00313 const char *p = f + strlen(f);
00314 while(*p!='/' && (p >= f))
00315 p--;
00316 strncpy(filename,p+1,256);
00317 }
00318
00319
00320 void Layer::_set_position(int x, int y) {
00321 geo.x = x;
00322 geo.y = y;
00323 need_crop = true;
00324 }
00325
00326 void Layer::set_position(int x, int y) {
00327 Closure *job = NewClosure(this, &Layer::_set_position, x, y);
00328 deferred_calls->add_job(job);
00329 }
00330
00331
00332 void Layer::_set_zoom(double x, double y) {
00333 if ((x == 1) && (y == 1)) {
00334 zooming = false;
00335 zoom_x = zoom_y = 1.0;
00336 act("%s layer %s zoom deactivated", name, filename);
00337 } else {
00338 zoom_x = x;
00339 zoom_y = y;
00340 zooming = true;
00341 func("%s layer %s zoom set to x%.2f y%.2f",
00342 name, filename, zoom_x, zoom_y);
00343 }
00344 need_crop = true;
00345 }
00346
00347 void Layer::set_zoom(double x, double y) {
00348 Closure *job = NewClosure(this, &Layer::_set_zoom, x, y);
00349 deferred_calls->add_job(job);
00350 }
00351
00352
00353 void Layer::_set_rotate(double angle) {
00354 if(!angle) {
00355 rotating = false;
00356 rotate = 0;
00357 act("%s layer %s rotation deactivated", name, filename);
00358 } else {
00359 rotate = angle;
00360 rotating = true;
00361 func("%s layer %s rotation set to %.2f", name, filename, rotate);
00362 }
00363 need_crop = true;
00364 }
00365
00366 void Layer::set_rotate(double angle) {
00367 Closure *job = NewClosure(this, &Layer::_set_rotate, angle);
00368 deferred_calls->add_job(job);
00369 }
00370
00371
00372 void Layer::_fit(bool maintain_aspect_ratio) {
00373 double width_zoom, height_zoom;
00374 int new_x = 0;
00375 int new_y = 0;
00376 if (this->screen == NULL) {
00377 error("Cannot fit layer without a screen, add layer to a screen first");
00378 return;
00379 }
00380 width_zoom = (double)screen->geo.w / geo.w;
00381 height_zoom = (double)screen->geo.h / geo.h;
00382 if (maintain_aspect_ratio){
00383
00384
00385 if(width_zoom > height_zoom) {
00386 width_zoom = height_zoom;
00387 } else {
00388 height_zoom = width_zoom;
00389 }
00390 }
00391 _set_zoom(width_zoom, height_zoom);
00392
00393 new_x = ((double)(width_zoom * geo.w - geo.w) / 2.0);
00394 new_y = ((double)(height_zoom * geo.h - geo.h) / 2.0);
00395
00396 new_x += ((double)(screen->geo.w - width_zoom * geo.w) / 2.0);
00397 new_y += ((double)(screen->geo.h - height_zoom * geo.h) / 2.0);
00398 _set_position(new_x, new_y);
00399 }
00400
00401 void Layer::fit(bool maintain_aspect_ratio) {
00402 Closure *job = NewClosure(this, &Layer::_fit, maintain_aspect_ratio);
00403 deferred_calls->add_job(job);
00404 }
00405
00406 #ifdef WITH_JAVASCRIPT
00407 void *Layer::js_constructor(Context *env, JSContext *cx, JSObject *obj,
00408 int argc, void *aargv, char *err_msg) {
00409
00410 char *filename;
00411 void *ret = NULL;
00412 int check_thread;
00413 uint16_t width = geo.w;
00414 uint16_t height = geo.h;
00415
00416 jsval *argv = (jsval*)aargv;
00417 check_thread = JS_GetContextThread(cx);
00418 if (!check_thread)
00419 JS_SetContextThread(cx);
00420 JS_BeginRequest(cx);
00421 if(argc==0) {
00422 if(!init()) {
00423 sprintf(err_msg, "Layer constructor failed initialization");
00424 return NULL; }
00425
00426 } else if(argc==1) {
00427 filename = js_get_string(argv[0]);
00428 if(!init()) {
00429 sprintf(err_msg, "Layer constructor failed initialization");
00430 return NULL; }
00431
00432 if(!open(filename)) {
00433 snprintf(err_msg, MAX_ERR_MSG, "Layer constructor failed open(%s): %s",
00434 filename, strerror(errno));
00435 return NULL; }
00436
00437 } else if(argc==2) {
00438 JS_ValueToUint16(cx, argv[0], &width);
00439 JS_ValueToUint16(cx, argv[1], &height);
00440 if(!init(width, height, 32)) {
00441 snprintf(err_msg, MAX_ERR_MSG,
00442 "Layer constructor failed initialization w[%u] h[%u]", width, height);
00443 return NULL;
00444 }
00445
00446 } else if(argc==3) {
00447 JS_ValueToUint16(cx, argv[0], &width);
00448 JS_ValueToUint16(cx, argv[1], &height);
00449 filename = js_get_string(argv[2]);
00450 if(!init(width, height,32)) {
00451 snprintf(err_msg, MAX_ERR_MSG,
00452 "Layer constructor failed initializaztion w[%u] h[%u]", width, height);
00453 return NULL;
00454 }
00455 if(!open(filename)) {
00456 snprintf(err_msg, MAX_ERR_MSG,
00457 "Layer constructor failed initialization (%s): %s", filename, strerror(errno));
00458 return NULL;
00459 }
00460
00461 } else {
00462 sprintf(err_msg,
00463 "Wrong numbers of arguments\n use (\"filename\") or (width, height, \"filename\") or ()");
00464 return NULL;
00465 }
00466 if(JS_SetPrivate(cx,obj,(void*)this)) {
00467 jsobj = obj;
00468 ret = (void*)OBJECT_TO_JSVAL(obj);
00469 } else {
00470 sprintf(err_msg, "%s", "JS_SetPrivate failed");
00471 }
00472 JS_EndRequest(cx);
00473 if (!check_thread)
00474 JS_ClearContextThread(cx);
00475 return ret;
00476
00477 }
00478 #endif