4 * Copyright (C) 2009 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "attachmentpoint.h"
26 #include "bcsignals.h"
27 #include "cplayback.h"
31 #include "edlsession.h"
32 #include "floatautos.h"
34 #include "keyframes.h"
35 #include "localsession.h"
36 #include "mainerror.h"
37 #include "mainprogress.h"
38 #include "menueffects.h"
40 #include "mwindowgui.h"
41 #include "playbackengine.h"
43 #include "pluginaclient.h"
44 #include "pluginaclientlad.h"
45 #include "pluginfclient.h"
46 #include "pluginclient.h"
47 #include "plugincommands.h"
48 #include "pluginserver.h"
49 #include "pluginvclient.h"
50 #include "preferences.h"
53 #include "mainsession.h"
55 #include "trackcanvas.h"
56 #include "transportque.h"
57 #include "vdevicex11.h"
59 #include "videodevice.h"
60 #include "virtualanode.h"
61 #include "virtualvnode.h"
69 #include <sys/types.h>
75 void PluginServer::init()
78 this->plugin_type = PLUGIN_TYPE_UNKNOWN;
79 plugin_obj = new PluginObj();
80 modules = new ArrayList<Module*>;
81 nodes = new ArrayList<VirtualNode*>;
84 PluginServer::PluginServer()
89 PluginServer::PluginServer(MWindow *mwindow, char *path, int type)
91 char fpath[BCTEXTLEN];
93 this->plugin_type = type;
94 this->mwindow = mwindow;
95 if( type == PLUGIN_TYPE_FFMPEG ) {
96 ff_name = cstrdup(path);
97 sprintf(fpath, "ff_%s", path);
103 PluginServer::PluginServer(PluginServer &that)
106 plugin_type = that.plugin_type;
107 plugin_obj = that.plugin_obj;
108 plugin_obj->add_user();
109 title = !that.title ? 0 : cstrdup(that.title);
110 path = !that.path ? 0 : cstrdup(that.path);
111 ff_name = !that.ff_name ? 0 : cstrdup(that.ff_name);
112 modules = new ArrayList<Module*>;
113 nodes = new ArrayList<VirtualNode*>;
115 attachment = that.attachment;
116 realtime = that.realtime;
117 multichannel = that.multichannel;
118 preferences = that.preferences;
119 synthesis = that.synthesis;
123 fileio = that.fileio;
124 uses_gui = that.uses_gui;
125 mwindow = that.mwindow;
126 keyframe = that.keyframe;
127 new_plugin = that.new_plugin;
129 lad_descriptor = that.lad_descriptor;
130 lad_descriptor_function = that.lad_descriptor_function;
131 lad_index = that.lad_index;
134 PluginServer::~PluginServer()
143 plugin_obj->remove_user();
146 // Done only once at creation
147 int PluginServer::reset_parameters()
159 audio = video = theme = 0;
162 realtime = multichannel = fileio = 0;
164 start_auto = end_auto = 0;
175 lad_descriptor_function = 0;
180 // Done every time the plugin is opened or closed
181 int PluginServer::cleanup_plugin()
183 in_buffer_size = out_buffer_size = 0;
184 total_in_buffers = total_out_buffers = 0;
189 written_samples = written_frames = 0;
196 void PluginServer::set_mwindow(MWindow *mwindow)
198 this->mwindow = mwindow;
201 void PluginServer::set_attachmentpoint(AttachmentPoint *attachmentpoint)
203 this->attachmentpoint = attachmentpoint;
206 void PluginServer::set_keyframe(KeyFrame *keyframe)
208 this->keyframe = keyframe;
211 void PluginServer::set_prompt(MenuEffectPrompt *prompt)
213 this->prompt = prompt;
216 void PluginServer::set_lad_index(int i)
221 int PluginServer::get_lad_index()
223 return this->lad_index;
226 int PluginServer::is_ladspa()
228 return plugin_type == PLUGIN_TYPE_LADSPA ? 1 : 0;
231 int PluginServer::is_ffmpeg()
233 return plugin_type == PLUGIN_TYPE_FFMPEG ? 1 : 0;
236 void PluginServer::set_path(const char *path)
238 delete [] this->path;
239 this->path = cstrdup(path);
242 char* PluginServer::get_path()
247 int PluginServer::get_synthesis()
253 void PluginServer::set_title(const char *string)
255 if(title) delete [] title;
256 title = cstrdup(string);
259 void PluginServer::generate_display_title(char *string)
261 char ltitle[BCTEXTLEN];
262 if(BC_Resources::locale_utf8)
263 strcpy(ltitle, _(title));
265 BC_Resources::encode(BC_Resources::encoding, 0,
266 _(title),strlen(title)+1, ltitle,BCTEXTLEN);
267 if(plugin && plugin->track)
268 sprintf(string, "%s: %s", plugin->track->title, ltitle);
270 strcpy(string, ltitle);
273 void *PluginObj::load(const char *plugin_dir, const char *path)
275 char dlpath[BCTEXTLEN], *dp = dlpath;
276 const char *cp = path;
278 const char *bp = plugin_dir;
279 while( *bp ) *dp++ = *bp++;
282 while( *cp ) *dp++ = *cp++;
284 return dlobj = load(dlpath);
287 int PluginServer::load_obj()
289 void *obj = plugin_obj->obj();
290 if( !obj ) obj =plugin_obj->load(preferences->plugin_dir, path);
294 const char *PluginServer::load_error()
296 return plugin_obj->load_error();
299 void *PluginServer::get_sym(const char *sym)
301 if( !plugin_obj->obj() ) return 0;
302 return plugin_obj->load_sym(sym);
305 // Open plugin for signal processing
306 int PluginServer::open_plugin(int master,
307 Preferences *preferences,
311 if(plugin_open) return 0;
313 this->preferences = preferences;
314 this->plugin = plugin;
316 if( plugin_type != PLUGIN_TYPE_FFMPEG && plugin_type != PLUGIN_TYPE_EXECUTABLE && !load_obj() ) {
317 // If the load failed it may still be an executable tool for a specific
318 // file format, in which case we just store the path.
320 char string[BCTEXTLEN];
321 strcpy(string, load_error());
322 if( !strstr(string, "executable") ) {
323 eprintf("PluginServer::open_plugin: load_obj %s = %s\n", path, string);
324 return PLUGINSERVER_NOT_RECOGNIZED;
326 plugin_type = PLUGIN_TYPE_EXECUTABLE;
328 if( plugin_type == PLUGIN_TYPE_UNKNOWN || plugin_type == PLUGIN_TYPE_BUILTIN ) {
330 (PluginClient* (*)(PluginServer*)) get_sym("new_plugin");
332 plugin_type = PLUGIN_TYPE_BUILTIN;
334 if( plugin_type == PLUGIN_TYPE_UNKNOWN || plugin_type == PLUGIN_TYPE_LADSPA ) {
335 lad_descriptor_function =
336 (LADSPA_Descriptor_Function) get_sym("ladspa_descriptor");
337 if( lad_descriptor_function ) {
338 if( lad_index < 0 ) return PLUGINSERVER_IS_LAD;
339 lad_descriptor = lad_descriptor_function(lad_index);
340 if( !lad_descriptor )
341 return PLUGINSERVER_NOT_RECOGNIZED;
342 plugin_type = PLUGIN_TYPE_LADSPA;
345 if( plugin_type == PLUGIN_TYPE_UNKNOWN ) {
346 fprintf(stderr, "PluginServer::open_plugin "
347 " %d: plugin undefined in %s\n", __LINE__, path);
348 return PLUGINSERVER_NOT_RECOGNIZED;
350 switch( plugin_type ) {
351 case PLUGIN_TYPE_EXECUTABLE:
352 return PLUGINSERVER_OK;
353 case PLUGIN_TYPE_BUILTIN:
354 client = new_plugin(this);
356 case PLUGIN_TYPE_LADSPA:
357 client = new PluginAClientLAD(this);
359 case PLUGIN_TYPE_FFMPEG:
360 client = new_ffmpeg_plugin();
367 return PLUGINSERVER_NOT_RECOGNIZED;
369 // Run initialization functions
370 realtime = client->is_realtime();
371 // Don't load defaults when probing the directory.
374 client->load_defaults_xml();
376 client->load_defaults();
378 audio = client->is_audio();
379 video = client->is_video();
380 theme = client->is_theme();
381 fileio = client->is_fileio();
382 uses_gui = client->uses_gui();
383 multichannel = client->is_multichannel();
384 synthesis = client->is_synthesis();
385 transition = client->is_transition();
386 set_title(client->plugin_title());
388 //printf("PluginServer::open_plugin 2\n");
390 return PLUGINSERVER_OK;
393 int PluginServer::close_plugin()
395 if(!plugin_open) return 0;
399 // Defaults are saved in the thread.
400 // if(client->defaults) client->save_defaults();
404 // shared object is persistent since plugin deletion would unlink its own object
410 void PluginServer::client_side_close()
412 // Last command executed in client thread
414 mwindow->hide_plugin(plugin, 1);
418 prompt->lock_window();
420 prompt->unlock_window();
424 void PluginServer::render_stop()
427 client->render_stop();
430 void PluginServer::write_table(FILE *fp, const char *path, int idx, int64_t mtime)
433 fprintf(fp, "%d \"%s\" \"%s\" " _LD " %d %d %d %d %d %d %d %d %d %d %d\n",
434 plugin_type, path, title, mtime, idx, audio, video, theme, realtime,
435 fileio, uses_gui, multichannel, synthesis, transition, lad_index);
438 int PluginServer::scan_table(char *text, int &type, char *path, char *title, int64_t &mtime)
440 int n = sscanf(text, "%d \"%[^\"]\" \"%[^\"]\" " _LD "", &type, path, title, &mtime);
441 return n < 4 ? 1 : 0;
444 int PluginServer::read_table(char *text)
446 char path[BCTEXTLEN], title[BCTEXTLEN];
448 int n = sscanf(text, "%d \"%[^\"]\" \"%[^\"]\" " _LD " %d %d %d %d %d %d %d %d %d %d %d",
449 &plugin_type, path, title, &mtime, &dir_idx, &audio, &video, &theme, &realtime,
450 &fileio, &uses_gui, &multichannel, &synthesis, &transition, &lad_index);
451 if( n != 15 ) return 1;
456 int PluginServer::init_realtime(int realtime_sched,
457 int total_in_buffers,
461 if(!plugin_open) return 0;
463 // set for realtime priority
465 // Call start_realtime
466 this->total_in_buffers = this->total_out_buffers = total_in_buffers;
467 client->plugin_init_realtime(realtime_sched,
475 // Replaced by pull method but still needed for transitions
476 void PluginServer::process_transition(VFrame *input,
478 int64_t current_position,
481 if(!plugin_open) return;
482 PluginVClient *vclient = (PluginVClient*)client;
484 vclient->source_position = current_position;
485 vclient->source_start = 0;
486 vclient->total_len = total_len;
488 vclient->input = new VFrame*[1];
489 vclient->output = new VFrame*[1];
491 vclient->input[0] = input;
492 vclient->output[0] = output;
494 vclient->process_realtime(input, output);
496 delete [] vclient->input;
497 delete [] vclient->output;
501 void PluginServer::process_transition(Samples *input,
503 int64_t current_position,
504 int64_t fragment_size,
507 if(!plugin_open) return;
508 PluginAClient *aclient = (PluginAClient*)client;
510 aclient->source_position = current_position;
511 aclient->total_len = total_len;
512 aclient->source_start = 0;
513 aclient->process_realtime(fragment_size,
519 void PluginServer::process_buffer(VFrame **frame,
520 int64_t current_position,
525 if(!plugin_open) return;
526 PluginVClient *vclient = (PluginVClient*)client;
528 vclient->source_position = current_position;
529 vclient->total_len = total_len;
530 vclient->frame_rate = frame_rate;
531 vclient->input = new VFrame*[total_in_buffers];
532 vclient->output = new VFrame*[total_in_buffers];
533 for(int i = 0; i < total_in_buffers; i++)
535 vclient->input[i] = frame[i];
536 vclient->output[i] = frame[i];
541 vclient->source_start = (int64_t)plugin->startproject *
543 vclient->project_frame_rate;
545 vclient->direction = direction;
549 //printf("plugin=%p source_start=%ld\n", plugin, vclient->source_start);
551 vclient->begin_process_buffer();
554 vclient->process_buffer(frame, current_position, frame_rate);
558 vclient->process_buffer(frame[0], current_position, frame_rate);
560 vclient->end_process_buffer();
562 for(int i = 0; i < total_in_buffers; i++)
563 frame[i]->push_prev_effect(title);
565 delete [] vclient->input;
566 delete [] vclient->output;
572 void PluginServer::process_buffer(Samples **buffer,
573 int64_t current_position,
574 int64_t fragment_size,
579 if(!plugin_open) return;
580 PluginAClient *aclient = (PluginAClient*)client;
582 aclient->source_position = current_position;
583 aclient->total_len = total_len;
584 aclient->sample_rate = sample_rate;
587 aclient->source_start = plugin->startproject *
589 aclient->project_sample_rate;
591 aclient->direction = direction;
592 aclient->begin_process_buffer();
595 aclient->process_buffer(fragment_size,
602 aclient->process_buffer(fragment_size,
607 aclient->end_process_buffer();
611 void PluginServer::send_render_gui(void *data)
613 //printf("PluginServer::send_render_gui 1 %p\n", attachmentpoint);
614 if(attachmentpoint) attachmentpoint->render_gui(data, this);
617 void PluginServer::send_render_gui(void *data, int size)
619 //printf("PluginServer::send_render_gui 1 %p\n", attachmentpoint);
620 if(attachmentpoint) attachmentpoint->render_gui(data, size, this);
623 void PluginServer::render_gui(void *data)
625 if(client) client->plugin_render_gui(data);
628 void PluginServer::render_gui(void *data, int size)
630 if(client) client->plugin_render_gui(data, size);
633 MainProgressBar* PluginServer::start_progress(char *string, int64_t length)
635 mwindow->gui->lock_window();
636 MainProgressBar *result = mwindow->mainprogress->start_progress(string, length);
637 mwindow->gui->unlock_window();
641 int64_t PluginServer::get_written_samples()
643 if(!plugin_open) return 0;
644 return written_samples;
647 int64_t PluginServer::get_written_frames()
649 if(!plugin_open) return 0;
650 return written_frames;
662 // ======================= Non-realtime plugin
664 int PluginServer::get_parameters(int64_t start, int64_t end, int channels)
666 if(!plugin_open) return 0;
668 client->start = start;
670 client->source_start = start;
671 client->total_len = end - start;
672 client->total_in_buffers = channels;
675 //printf(" source_start=%ld total_len=%ld\n", client->source_start, client->total_len);
677 return client->plugin_get_parameters();
680 int PluginServer::set_interactive()
682 if(!plugin_open) return 0;
683 client->set_interactive();
687 void PluginServer::append_module(Module *module)
689 modules->append(module);
692 void PluginServer::append_node(VirtualNode *node)
697 void PluginServer::reset_nodes()
702 int PluginServer::set_error()
708 int PluginServer::set_realtime_sched()
710 //struct sched_param params;
711 //params.sched_priority = 1;
712 //sched_setscheduler(0, SCHED_RR, ¶m);
717 int PluginServer::process_loop(VFrame **buffers, int64_t &write_length)
719 if(!plugin_open) return 1;
720 return client->plugin_process_loop(buffers, write_length);
723 int PluginServer::process_loop(Samples **buffers, int64_t &write_length)
725 if(!plugin_open) return 1;
726 return client->plugin_process_loop(buffers, write_length);
730 int PluginServer::start_loop(int64_t start,
735 if(!plugin_open) return 0;
736 client->plugin_start_loop(start, end, buffer_size, total_buffers);
740 int PluginServer::stop_loop()
742 if(!plugin_open) return 0;
743 return client->plugin_stop_loop();
746 int PluginServer::read_frame(VFrame *buffer,
748 int64_t start_position)
750 ((VModule*)modules->values[channel])->render(buffer,
753 mwindow->edl->session->frame_rate,
759 int PluginServer::read_samples(Samples *buffer,
762 int64_t start_position,
765 // len is now in buffer
766 if(!multichannel) channel = 0;
768 if(nodes->total > channel)
769 return ((VirtualANode*)nodes->values[channel])->read_data(buffer,
774 if(modules->total > channel)
775 return ((AModule*)modules->values[channel])->render(buffer,
783 printf("PluginServer::read_samples no object available for channel=%d\n",
791 int PluginServer::read_samples(Samples *buffer,
793 int64_t start_position,
796 // total_samples is now set in buffer
797 ((AModule*)modules->values[channel])->render(buffer,
801 mwindow->edl->session->sample_rate,
806 int PluginServer::read_frame(VFrame *buffer,
808 int64_t start_position,
812 // Data source depends on whether we're part of a virtual console or a
816 // If we're a VirtualNode, read_data in the virtual plugin node handles
817 // backward propogation and produces the data.
818 // If we're a Module, render in the module produces the data.
822 if(!multichannel) channel = 0;
824 // Push our name on the next effect stack
825 buffer->push_next_effect(title);
826 //printf("PluginServer::read_frame %p\n", buffer);
827 //buffer->dump_stacks();
829 if(nodes->total > channel)
831 //printf("PluginServer::read_frame %d\n", __LINE__);
832 result = ((VirtualVNode*)nodes->values[channel])->read_data(buffer,
838 if(modules->total > channel)
840 //printf("PluginServer::read_frame %d\n", __LINE__);
841 result = ((VModule*)modules->values[channel])->render(buffer,
852 printf("PluginServer::read_frame no object available for channel=%d\n",
856 // Pop our name from the next effect stack
857 buffer->pop_next_effect();
882 int PluginServer::get_gui_status()
885 return plugin->show ? GUI_ON : GUI_OFF;
890 void PluginServer::raise_window()
892 if(!plugin_open) return;
893 client->raise_window();
896 void PluginServer::show_gui()
898 if(!plugin_open) return;
899 if(plugin) client->total_len = plugin->length;
900 if(plugin) client->source_start = plugin->startproject;
903 client->source_position = Units::to_int64(
904 mwindow->edl->local_session->get_selectionstart(1) *
905 mwindow->edl->session->frame_rate);
910 client->source_position = Units::to_int64(
911 mwindow->edl->local_session->get_selectionstart(1) *
912 mwindow->edl->session->sample_rate);
915 client->update_display_title();
919 void PluginServer::hide_gui()
921 if(!plugin_open) return;
922 if(client->defaults) client->save_defaults();
926 void PluginServer::update_gui()
928 if(!plugin_open || !plugin) return;
930 client->total_len = plugin->length;
931 client->source_start = plugin->startproject;
935 client->source_position = Units::to_int64(
936 mwindow->edl->local_session->get_selectionstart(1) *
937 mwindow->edl->session->frame_rate);
942 client->source_position = Units::to_int64(
943 mwindow->edl->local_session->get_selectionstart(1) *
944 mwindow->edl->session->sample_rate);
947 client->plugin_update_gui();
950 void PluginServer::update_title()
952 if(!plugin_open) return;
954 client->update_display_title();
958 int PluginServer::set_string(char *string)
960 if(!plugin_open) return 0;
962 client->set_string_client(string);
966 int PluginServer::gui_open()
968 if(attachmentpoint) return attachmentpoint->gui_open();
972 void PluginServer::set_use_opengl(int value, VideoDevice *vdevice)
974 this->use_opengl = value;
975 this->vdevice = vdevice;
978 int PluginServer::get_use_opengl()
984 void PluginServer::run_opengl(PluginClient *plugin_client)
987 ((VDeviceX11*)vdevice->get_output_base())->run_plugin(plugin_client);
990 // ============================= queries
992 void PluginServer::get_defaults_path(char *path)
994 // Get plugin name from path
995 char *ptr1 = strrchr(get_path(), '/');
996 char *ptr2 = strrchr(get_path(), '.');
997 if(!ptr1) ptr1 = get_path();
998 if(!ptr2) ptr2 = get_path() + strlen(get_path());
999 char string2[BCTEXTLEN];
1000 char *ptr3 = string2;
1006 sprintf(path, "%s%s.xml", BCASTDIR, string2);
1009 void PluginServer::save_defaults()
1011 if(client) client->save_defaults();
1014 int PluginServer::get_samplerate()
1016 if(!plugin_open) return 0;
1019 return client->get_samplerate();
1023 return mwindow->edl->session->sample_rate;
1026 printf("PluginServer::get_samplerate audio and mwindow == NULL\n");
1032 double PluginServer::get_framerate()
1034 if(!plugin_open) return 0;
1037 return client->get_framerate();
1041 return mwindow->edl->session->frame_rate;
1044 printf("PluginServer::get_framerate video and mwindow == NULL\n");
1049 int PluginServer::get_project_samplerate()
1052 return mwindow->edl->session->sample_rate;
1055 return edl->session->sample_rate;
1058 printf("PluginServer::get_project_samplerate mwindow and edl are NULL.\n");
1063 double PluginServer::get_project_framerate()
1066 return mwindow->edl->session->frame_rate;
1069 return edl->session->frame_rate;
1072 printf("PluginServer::get_project_framerate mwindow and edl are NULL.\n");
1079 int PluginServer::detach_buffers()
1081 ring_buffers_out.remove_all();
1082 offset_out_render.remove_all();
1083 double_buffer_out_render.remove_all();
1084 realtime_out_size.remove_all();
1086 ring_buffers_in.remove_all();
1087 offset_in_render.remove_all();
1088 double_buffer_in_render.remove_all();
1089 realtime_in_size.remove_all();
1091 out_buffer_size = 0;
1093 total_out_buffers = 0;
1095 total_in_buffers = 0;
1099 int PluginServer::arm_buffer(int buffer_number,
1102 int double_buffer_in,
1103 int double_buffer_out)
1105 offset_in_render.values[buffer_number] = offset_in;
1106 offset_out_render.values[buffer_number] = offset_out;
1107 double_buffer_in_render.values[buffer_number] = double_buffer_in;
1108 double_buffer_out_render.values[buffer_number] = double_buffer_out;
1113 int PluginServer::set_automation(FloatAutos *autos, FloatAuto **start_auto, FloatAuto **end_auto, int reverse)
1115 this->autos = autos;
1116 this->start_auto = start_auto;
1117 this->end_auto = end_auto;
1118 this->reverse = reverse;
1124 void PluginServer::save_data(KeyFrame *keyframe)
1126 if(!plugin_open) return;
1127 client->save_data(keyframe);
1130 KeyFrame* PluginServer::get_prev_keyframe(int64_t position)
1132 KeyFrame *result = 0;
1134 result = plugin->get_prev_keyframe(position, client->direction);
1140 KeyFrame* PluginServer::get_next_keyframe(int64_t position)
1142 KeyFrame *result = 0;
1144 result = plugin->get_next_keyframe(position, client->direction);
1151 KeyFrame* PluginServer::get_keyframe()
1154 // Realtime plugin case
1155 return plugin->get_keyframe();
1157 // Rendered plugin case
1162 void PluginServer::apply_keyframe(KeyFrame *src)
1166 keyframe->copy_data(src);
1171 plugin->keyframes->update_parameter(src);
1179 void PluginServer::get_camera(float *x, float *y, float *z,
1180 int64_t position, int direction)
1182 plugin->track->automation->get_camera(x, y, z, position, direction);
1185 void PluginServer::get_projector(float *x, float *y, float *z,
1186 int64_t position, int direction)
1188 plugin->track->automation->get_projector(x, y, z, position, direction);
1192 int PluginServer::get_interpolation_type()
1194 return plugin->edl->session->interpolation_type;
1197 Theme* PluginServer::new_theme()
1201 return client->new_theme();
1207 Theme* PluginServer::get_theme()
1209 if(mwindow) return mwindow->theme;
1210 printf("PluginServer::get_theme mwindow not set\n");
1215 int PluginServer::get_theme_png_path(char *png_path, const char *theme_dir)
1217 char *bp = strrchr(path, '/');
1218 if( !bp ) bp = path; else ++bp;
1219 char *sp = strrchr(bp,'.');
1220 if( !sp || ( strcmp(sp, ".plugin") && strcmp(sp,".so") ) ) return 0;
1221 char *cp = png_path, *dp = bp;
1222 cp += sprintf(cp,"%s/%s/", mwindow->preferences->plugin_dir, theme_dir);
1223 while( dp < sp ) *cp++ = *dp++;
1226 if( stat(png_path, &st) ) return 0;
1227 if( !S_ISREG(st.st_mode) ) return 0;
1228 if( st.st_size == 0 ) return 0;
1232 int PluginServer::get_theme_png_path(char *png_path, Theme *theme)
1234 char *bp = strrchr(theme->path, '/');
1235 if( !bp ) bp = theme->path; else ++bp;
1236 char *sp = strrchr(bp,'.');
1237 if( !sp || ( strcmp(sp, ".plugin") && strcmp(sp,".so") ) ) return 0;
1238 char theme_dir[BCTEXTLEN], *cp = theme_dir;
1239 while( bp < sp ) *cp++ = *bp++;
1241 return get_theme_png_path(png_path, theme_dir);
1244 int PluginServer::get_plugin_png_path(char *png_path)
1246 int len = get_theme_png_path(png_path, mwindow->theme);
1248 len = get_theme_png_path(png_path, "picon");
1252 VFrame *PluginServer::get_plugin_images()
1254 char png_path[BCTEXTLEN];
1255 int len = get_plugin_png_path(png_path);
1256 if( !len ) return 0;
1257 int ret = 0, w = 0, h = 0;
1258 unsigned char *bfr = 0;
1259 int fd = ::open(png_path, O_RDONLY);
1260 if( fd < 0 ) ret = 1;
1262 bfr = (unsigned char *) ::mmap (NULL, len, PROT_READ, MAP_SHARED, fd, 0);
1263 if( bfr == MAP_FAILED ) ret = 1;
1267 double scale = BC_WindowBase::get_resources()->icon_scale;
1268 vframe = new VFramePng(bfr, len, scale, scale);
1269 if( (w=vframe->get_w()) <= 0 || (h=vframe->get_h()) <= 0 ||
1270 vframe->get_data() == 0 ) ret = 1;
1272 if( bfr && bfr != MAP_FAILED ) ::munmap(bfr, len);
1273 if( fd >= 0 ) ::close(fd);
1274 if( ret ) { delete vframe; vframe = 0; }
1278 VFrame *PluginServer::get_picon()
1281 picon = get_plugin_images();
1285 // Called when plugin interface is tweeked
1286 void PluginServer::sync_parameters()
1288 if(video) mwindow->restart_brender();
1289 mwindow->sync_parameters();
1290 mwindow->update_keyframe_guis();
1291 if(mwindow->edl->session->auto_conf->plugins)
1293 mwindow->gui->lock_window("PluginServer::sync_parameters");
1294 mwindow->gui->draw_overlays(1);
1295 mwindow->gui->unlock_window();
1301 void PluginServer::dump(FILE *fp)
1303 fprintf(fp," PluginServer %d %p %s %s %d\n",
1304 __LINE__, this, path, title, realtime);