add proxy index builds, perperual session, backup.prev, disarmed track indication...
[goodguy/history.git] / cinelerra-5.1 / cinelerra / preferences.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
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.
10  *
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.
15  *
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
19  *
20  */
21
22 #include "asset.h"
23 #include "audioconfig.h"
24 #include "audiodevice.inc"
25 #include "bcmeter.inc"
26 #include "bcsignals.h"
27 #include "cache.inc"
28 #include "clip.h"
29 #include "bchash.h"
30 #include "file.h"
31 #include "filesystem.h"
32 #include "guicast.h"
33 #include "indexfile.h"
34 #include "maxchannels.h"
35 #include "mutex.h"
36 #include "preferences.h"
37 #include "probeprefs.h"
38 #include "shbtnprefs.h"
39 #include "theme.h"
40 #include "videoconfig.h"
41 #include "videodevice.inc"
42
43 #include <ctype.h>
44 #include <string.h>
45 #include <unistd.h>
46 #include <sys/types.h>
47 #include <sys/stat.h>
48
49
50 Preferences::Preferences()
51 {
52 // Set defaults
53         FileSystem fs;
54         preferences_lock = new Mutex("Preferences::preferences_lock");
55
56 // initial plugin path from build -DPLUGIN_DIR="..."
57         sprintf(plugin_dir, "%s/", File::get_plugin_path());
58         sprintf(index_directory, "%s/", File::get_config_path());
59         if( strlen(index_directory) )
60                 fs.complete_path(index_directory);
61         cache_size = 0x10000000;
62         index_size = 0x400000;
63         index_count = 500;
64         use_thumbnails = 1;
65         keyframe_reticle = HAIRLINE_DRAGGING;
66         perpetual_session = 0;
67         trap_sigsegv = 1;
68         trap_sigintr = 1;
69         theme[0] = 0;
70         plugin_icons[0] = 0;
71         strcpy(snapshot_path, "/tmp");
72         use_renderfarm = 0;
73         force_uniprocessor = 0;
74         renderfarm_port = DEAMON_PORT;
75         render_preroll = 0.5;
76         brender_preroll = 0;
77         renderfarm_mountpoint[0] = 0;
78         renderfarm_vfs = 0;
79         renderfarm_job_count = 20;
80         renderfarm_watchdog_timeout = 60;
81         project_smp = processors = calculate_processors(0);
82         real_processors = calculate_processors(1);
83         ffmpeg_marker_indexes = 1;
84         warn_indexes = 1;
85         warn_version = 1;
86         bd_warn_root = 1;
87         popupmenu_btnup = 1;
88         grab_input_focus = 1;
89         textbox_focus_policy = 0;
90         forward_render_displacement = 0;
91         dvd_yuv420p_interlace = 0;
92         highlight_inverse = 0xffffff;
93         yuv_color_space = BC_COLORS_BT601;
94         yuv_color_range = BC_COLORS_JPEG;
95
96 // Default brender asset
97         brender_asset = new Asset;
98         brender_asset->audio_data = 0;
99         brender_asset->video_data = 1;
100         sprintf(brender_asset->path, "/tmp/brender");
101         brender_asset->format = FILE_JPEG_LIST;
102         brender_asset->jpeg_quality = 80;
103
104         use_brender = 0;
105         brender_fragment = 1;
106         local_rate = 0.0;
107
108         use_tipwindow = 1;
109         scan_commercials = 0;
110
111         android_remote = 0;
112         android_port = 23432;
113         strcpy(android_pin, "cinelerra");
114
115         memset(channel_positions, 0, sizeof(channel_positions));
116         int channels = 0;
117         while( channels < MAXCHANNELS ) {
118                 int *positions = channel_positions[channels++];
119                 for( int i=0; i<channels; ++i )
120                         positions[i] = default_audio_channel_position(i, channels);
121         }
122 }
123
124 Preferences::~Preferences()
125 {
126         brender_asset->Garbage::remove_user();
127         shbtn_prefs.remove_all_objects();
128         file_probes.remove_all_objects();
129         renderfarm_nodes.remove_all_objects();
130         delete preferences_lock;
131 }
132
133 void Preferences::copy_rates_from(Preferences *preferences)
134 {
135         preferences_lock->lock("Preferences::copy_rates_from");
136 // Need to match node titles in case the order changed and in case
137 // one of the nodes in the source is the master node.
138         local_rate = preferences->local_rate;
139
140         for( int j=0; j<preferences->renderfarm_nodes.total; ++j ) {
141                 double new_rate = preferences->renderfarm_rate.values[j];
142 // Put in the master node
143                 if( preferences->renderfarm_nodes.values[j][0] == '/' ) {
144                         if( !EQUIV(new_rate, 0.0) )
145                                 local_rate = new_rate;
146                 }
147                 else
148 // Search for local node and copy it to that node
149                 if( !EQUIV(new_rate, 0.0) ) {
150                         for( int i=0; i<renderfarm_nodes.total; ++i ) {
151                                 if( !strcmp(preferences->renderfarm_nodes.values[j], renderfarm_nodes.values[i]) &&
152                                         preferences->renderfarm_ports.values[j] == renderfarm_ports.values[i] ) {
153                                         renderfarm_rate.values[i] = new_rate;
154                                         break;
155                                 }
156                         }
157                 }
158         }
159
160 //printf("Preferences::copy_rates_from 1 %f %f\n", local_rate, preferences->local_rate);
161         preferences_lock->unlock();
162 }
163
164 void Preferences::copy_from(Preferences *that)
165 {
166 // ================================= Performance ================================
167         strcpy(index_directory, that->index_directory);
168         index_size = that->index_size;
169         index_count = that->index_count;
170         use_thumbnails = that->use_thumbnails;
171         keyframe_reticle = that->keyframe_reticle;
172         perpetual_session = that->perpetual_session;
173         strcpy(theme, that->theme);
174         strcpy(plugin_icons, that->plugin_icons);
175         strcpy(snapshot_path, that->snapshot_path);
176
177         use_tipwindow = that->use_tipwindow;
178         scan_commercials = that->scan_commercials;
179         android_remote = that->android_remote;
180         android_port = that->android_port;
181         strcpy(android_pin, that->android_pin);
182         this->shbtn_prefs.remove_all_objects();
183         for( int i=0; i<that->shbtn_prefs.size(); ++i )
184                 this->shbtn_prefs.append(new ShBtnPref(*that->shbtn_prefs[i]));
185         this->file_probes.remove_all_objects();
186         for( int i=0; i<that->file_probes.size(); ++i )
187                 this->file_probes.append(new ProbePref(*that->file_probes[i]));
188         cache_size = that->cache_size;
189         project_smp = that->project_smp;
190         force_uniprocessor = that->force_uniprocessor;
191         trap_sigsegv = that->trap_sigsegv;
192         trap_sigintr = that->trap_sigintr;
193         processors = that->processors;
194         real_processors = that->real_processors;
195         ffmpeg_marker_indexes = that->ffmpeg_marker_indexes;
196         warn_indexes = that->warn_indexes;
197         warn_version = that->warn_version;
198         bd_warn_root = that->bd_warn_root;
199         popupmenu_btnup = that->popupmenu_btnup;
200         grab_input_focus = that->grab_input_focus;
201         textbox_focus_policy = that->textbox_focus_policy;
202         forward_render_displacement = that->forward_render_displacement;
203         dvd_yuv420p_interlace = that->dvd_yuv420p_interlace;
204         highlight_inverse = that->highlight_inverse;
205         yuv_color_space = that->yuv_color_space;
206         yuv_color_range = that->yuv_color_range;
207         renderfarm_nodes.remove_all_objects();
208         renderfarm_ports.remove_all();
209         renderfarm_enabled.remove_all();
210         renderfarm_rate.remove_all();
211         local_rate = that->local_rate;
212         for( int i=0; i<that->renderfarm_nodes.size(); ++i ) {
213                 add_node(that->renderfarm_nodes.get(i),
214                         that->renderfarm_ports.get(i),
215                         that->renderfarm_enabled.get(i),
216                         that->renderfarm_rate.get(i));
217         }
218         use_renderfarm = that->use_renderfarm;
219         renderfarm_port = that->renderfarm_port;
220         render_preroll = that->render_preroll;
221         brender_preroll = that->brender_preroll;
222         renderfarm_job_count = that->renderfarm_job_count;
223         renderfarm_watchdog_timeout = that->renderfarm_watchdog_timeout;
224         renderfarm_vfs = that->renderfarm_vfs;
225         strcpy(renderfarm_mountpoint, that->renderfarm_mountpoint);
226         renderfarm_consolidate = that->renderfarm_consolidate;
227         use_brender = that->use_brender;
228         brender_fragment = that->brender_fragment;
229         brender_asset->copy_from(that->brender_asset, 0);
230
231 // Check boundaries
232
233         FileSystem fs;
234         if( strlen(index_directory) ) {
235                 fs.complete_path(index_directory);
236                 fs.add_end_slash(index_directory);
237         }
238
239 //      if( strlen(global_plugin_dir) )
240 //      {
241 //              fs.complete_path(global_plugin_dir);
242 //              fs.add_end_slash(global_plugin_dir);
243 //      }
244 //
245
246 // Redo with the proper value of force_uniprocessor
247         processors = calculate_processors(0);
248         boundaries();
249 }
250
251 void Preferences::boundaries()
252 {
253         renderfarm_job_count = MAX(renderfarm_job_count, 1);
254         CLAMP(cache_size, MIN_CACHE_SIZE, MAX_CACHE_SIZE);
255 }
256
257 Preferences& Preferences::operator=(Preferences &that)
258 {
259 printf("Preferences::operator=\n");
260         copy_from(&that);
261         return *this;
262 }
263
264 void Preferences::print_channels(char *string, int *channel_positions, int channels)
265 {
266         char *cp = string, *ep = cp+BCTEXTLEN-1;
267         for( int i=0; i<channels; ++i ) {
268                 if( i ) cp += snprintf(cp, ep-cp, ", ");
269                 cp += snprintf(cp, ep-cp, "%d", channel_positions[i]);
270         }
271         *cp = 0;
272 }
273
274 void Preferences::scan_channels(char *string, int *channel_positions, int channels)
275 {
276         char *cp = string;
277         int current_channel = 0;
278         for(;;) {
279                 while( isspace(*cp) ) ++cp;
280                 if( !cp ) break;
281                 channel_positions[current_channel++] = strtol(cp, &cp, 0);
282                 if( current_channel >= channels ) break;
283                 while( isspace(*cp) ) ++cp;
284                 if( *cp == ',' ) ++cp;
285         }
286         while( current_channel < channels ) {
287                 int pos = default_audio_channel_position(current_channel, channels);
288                 channel_positions[current_channel++] = pos;
289         }
290 }
291
292 int Preferences::load_defaults(BC_Hash *defaults)
293 {
294         char string[BCTEXTLEN];
295
296         use_tipwindow = defaults->get("USE_TIPWINDOW", use_tipwindow);
297         scan_commercials = defaults->get("SCAN_COMMERCIALS", scan_commercials);
298         android_remote = defaults->get("ANDROID_REMOTE", android_remote);
299         android_port = defaults->get("ANDROID_PORT", android_port);
300         defaults->get("ANDROID_PIN", android_pin);
301         defaults->get("INDEX_DIRECTORY", index_directory);
302         index_size = defaults->get("INDEX_SIZE", index_size);
303         index_count = defaults->get("INDEX_COUNT", index_count);
304         keyframe_reticle = defaults->get("KEYFRAME_RETICLE", keyframe_reticle);
305         perpetual_session = defaults->get("PERPETUAL_SESSION", perpetual_session);
306         trap_sigsegv = defaults->get("TRAP_SIGSEGV", trap_sigsegv);
307         trap_sigintr = defaults->get("TRAP_SIGINTR", trap_sigintr);
308
309         strcpy(theme, _(DEFAULT_THEME));
310         strcpy(plugin_icons, DEFAULT_PICON);
311         defaults->get("THEME", theme);
312         defaults->get("PLUGIN_ICONS", plugin_icons);
313         strcpy(snapshot_path, "/tmp");
314         defaults->get("SNAPSHOT_PATH", snapshot_path);
315
316         for( int i=0; i<MAXCHANNELS; ++i ) {
317                 char string2[BCTEXTLEN];
318                 sprintf(string, "CHANNEL_POSITIONS%d", i);
319                 print_channels(string2, &channel_positions[i][0], i+1);
320                 defaults->get(string, string2);
321                 scan_channels(string2, &channel_positions[i][0], i+1);
322         }
323         brender_asset->load_defaults(defaults, "BRENDER_", 1, 1, 1, 0, 0);
324
325         project_smp = defaults->get("PROJECT_SMP", project_smp);
326         force_uniprocessor = defaults->get("FORCE_UNIPROCESSOR", force_uniprocessor);
327         ffmpeg_marker_indexes = defaults->get("FFMPEG_MARKER_INDEXES", ffmpeg_marker_indexes);
328         warn_indexes = defaults->get("WARN_INDEXES", warn_indexes);
329         warn_version = defaults->get("WARN_VERSION", warn_version);
330         bd_warn_root = defaults->get("BD_WARN_ROOT", bd_warn_root);
331         popupmenu_btnup = defaults->get("POPUPMENU_BTNUP", popupmenu_btnup);
332         grab_input_focus = defaults->get("GRAB_FOCUS", grab_input_focus);
333         textbox_focus_policy = defaults->get("TEXTBOX_FOCUS_POLICY", textbox_focus_policy);
334         forward_render_displacement = defaults->get("FORWARD_RENDER_DISPLACEMENT", forward_render_displacement);
335         dvd_yuv420p_interlace = defaults->get("DVD_YUV420P_INTERLACE", dvd_yuv420p_interlace);
336         highlight_inverse = defaults->get("HIGHLIGHT_INVERSE", highlight_inverse);
337         yuv_color_space = defaults->get("YUV_COLOR_SPACE", yuv_color_space);
338         yuv_color_range = defaults->get("YUV_COLOR_RANGE", yuv_color_range);
339         use_brender = defaults->get("USE_BRENDER", use_brender);
340         brender_fragment = defaults->get("BRENDER_FRAGMENT", brender_fragment);
341         cache_size = defaults->get("CACHE_SIZE", cache_size);
342         local_rate = defaults->get("LOCAL_RATE", local_rate);
343         use_renderfarm = defaults->get("USE_RENDERFARM", use_renderfarm);
344         renderfarm_port = defaults->get("RENDERFARM_PORT", renderfarm_port);
345         render_preroll = defaults->get("RENDERFARM_PREROLL", render_preroll);
346         brender_preroll = defaults->get("BRENDER_PREROLL", brender_preroll);
347         renderfarm_job_count = defaults->get("RENDERFARM_JOBS_COUNT", renderfarm_job_count);
348         renderfarm_watchdog_timeout = defaults->get("RENDERFARM_WATCHDOG_TIMEOUT", renderfarm_watchdog_timeout);
349         renderfarm_consolidate = defaults->get("RENDERFARM_CONSOLIDATE", renderfarm_consolidate);
350 //      renderfarm_vfs = defaults->get("RENDERFARM_VFS", renderfarm_vfs);
351         defaults->get("RENDERFARM_MOUNTPOINT", renderfarm_mountpoint);
352         int renderfarm_total = defaults->get("RENDERFARM_TOTAL", 0);
353
354         for( int i = 0; i < renderfarm_total; i++ ) {
355                 sprintf(string, "RENDERFARM_NODE%d", i);
356                 char result[BCTEXTLEN];
357                 int result_port = 0;
358                 int result_enabled = 0;
359                 float result_rate = 0.0;
360
361                 result[0] = 0;
362                 defaults->get(string, result);
363
364                 sprintf(string, "RENDERFARM_PORT%d", i);
365                 result_port = defaults->get(string, renderfarm_port);
366
367                 sprintf(string, "RENDERFARM_ENABLED%d", i);
368                 result_enabled = defaults->get(string, result_enabled);
369
370                 sprintf(string, "RENDERFARM_RATE%d", i);
371                 result_rate = defaults->get(string, result_rate);
372
373                 if( result[0] != 0 ) {
374                         add_node(result, result_port, result_enabled, result_rate);
375                 }
376         }
377
378         shbtn_prefs.remove_all_objects();
379         int shbtns_total = defaults->get("SHBTNS_TOTAL", -1);
380         if( shbtns_total < 0 ) {
381                 shbtn_prefs.append(new ShBtnPref(_("Features5"), "$CIN_BROWSER file://$CIN_DAT/doc/Features5.pdf", 0));
382                 shbtn_prefs.append(new ShBtnPref(_("Online Help"), "$CIN_BROWSER https://cinelerra-cv.org/docs.php", 0));
383                 shbtn_prefs.append(new ShBtnPref(_("Original Manual"), "$CIN_BROWSER file://$CIN_DAT/doc/cinelerra.html", 0));
384                 shbtn_prefs.append(new ShBtnPref(_("Setting Shell Commands"), "$CIN_BROWSER file://$CIN_DAT/doc/ShellCmds.html", 0));
385                 shbtn_prefs.append(new ShBtnPref(_("Shortcuts"), "$CIN_BROWSER file://$CIN_DAT/doc/shortcuts.html", 0));
386                 shbtn_prefs.append(new ShBtnPref(_("RenderMux"), "$CIN_DAT/doc/RenderMux.sh",0));
387                 shbtns_total = 0;
388         }
389         for( int i=0; i<shbtns_total; ++i ) {
390                 char name[BCTEXTLEN], commands[BCTEXTLEN];
391                 sprintf(string, "SHBTN%d_NAME", i);
392                 defaults->get(string, name);
393                 sprintf(string, "SHBTN%d_COMMANDS", i);
394                 defaults->get(string, commands);
395                 sprintf(string, "SHBTN%d_WARN", i);
396                 int warn = defaults->get(string, 0);
397                 shbtn_prefs.append(new ShBtnPref(name, commands, warn));
398         }
399
400         file_probes.remove_all_objects();
401         int file_probe_total = defaults->get("FILE_PROBE_TOTAL", 0);
402         for( int i=0; i<file_probe_total; ++i ) {
403                 char name[BCTEXTLEN];
404                 sprintf(string, "FILE_PROBE%d_NAME", i);
405                 defaults->get(string, name);
406                 sprintf(string, "FILE_PROBE%d_ARMED", i);
407                 int armed = defaults->get(string, 1);
408                 file_probes.append(new ProbePref(name, armed));
409         }
410         // append any missing probes
411         for( int i=0; i<File::nb_probes; ++i ) {
412                 const char *nm = File::default_probes[i];
413                 int k = file_probes.size();
414                 while( --k>=0 && strcmp(nm, file_probes[k]->name) );
415                 if( k >= 0 ) continue;
416                 int armed = 1;
417                 if( !strcmp(nm, "FFMPEG_Late") ||
418                     !strcmp(nm, "CR2") ) armed = 0;
419                 file_probes.append(new ProbePref(nm, armed));
420         }
421
422 // Redo with the proper value of force_uniprocessor
423         processors = calculate_processors(0);
424         boundaries();
425         return 0;
426 }
427
428 int Preferences::save_defaults(BC_Hash *defaults)
429 {
430         char string[BCTEXTLEN];
431
432
433         defaults->update("USE_TIPWINDOW", use_tipwindow);
434         defaults->update("SCAN_COMMERCIALS", scan_commercials);
435         defaults->update("ANDROID_REMOTE", android_remote);
436         defaults->update("ANDROID_PIN", android_pin);
437         defaults->update("ANDROID_PORT", android_port);
438
439         defaults->update("CACHE_SIZE", cache_size);
440         defaults->update("INDEX_DIRECTORY", index_directory);
441         defaults->update("INDEX_SIZE", index_size);
442         defaults->update("INDEX_COUNT", index_count);
443         defaults->update("USE_THUMBNAILS", use_thumbnails);
444         defaults->update("KEYFRAME_RETICLE", keyframe_reticle);
445         defaults->update("PERPETUAL_SESSION", perpetual_session);
446         defaults->update("TRAP_SIGSEGV", trap_sigsegv);
447         defaults->update("TRAP_SIGINTR", trap_sigintr);
448         defaults->update("THEME", theme);
449         defaults->update("PLUGIN_ICONS", plugin_icons);
450         defaults->update("SNAPSHOT_PATH", snapshot_path);
451
452         for( int i = 0; i < MAXCHANNELS; i++ ) {
453                 char string2[BCTEXTLEN];
454                 sprintf(string, "CHANNEL_POSITIONS%d", i);
455                 print_channels(string2, &channel_positions[i][0], i + 1);
456                 defaults->update(string, string2);
457         }
458
459         defaults->update("PROJECT_SMP", project_smp);
460         defaults->update("FORCE_UNIPROCESSOR", force_uniprocessor);
461         defaults->update("FFMPEG_MARKER_INDEXES", ffmpeg_marker_indexes);
462         defaults->update("WARN_INDEXES", warn_indexes);
463         defaults->update("WARN_VERSION", warn_version);
464         defaults->update("BD_WARN_ROOT", bd_warn_root);
465         defaults->update("POPUPMENU_BTNUP", popupmenu_btnup);
466         defaults->update("GRAB_FOCUS", grab_input_focus);
467         defaults->update("TEXTBOX_FOCUS_POLICY", textbox_focus_policy);
468         defaults->update("FORWARD_RENDER_DISPLACEMENT", forward_render_displacement);
469         defaults->update("DVD_YUV420P_INTERLACE", dvd_yuv420p_interlace);
470         defaults->update("HIGHLIGHT_INVERSE", highlight_inverse);
471         defaults->update("YUV_COLOR_SPACE", yuv_color_space);
472         defaults->update("YUV_COLOR_RANGE", yuv_color_range);
473         brender_asset->save_defaults(defaults, "BRENDER_", 1, 1, 1, 0, 0);
474         defaults->update("USE_BRENDER", use_brender);
475         defaults->update("BRENDER_FRAGMENT", brender_fragment);
476         defaults->update("USE_RENDERFARM", use_renderfarm);
477         defaults->update("LOCAL_RATE", local_rate);
478         defaults->update("RENDERFARM_PORT", renderfarm_port);
479         defaults->update("RENDERFARM_PREROLL", render_preroll);
480         defaults->update("BRENDER_PREROLL", brender_preroll);
481 //      defaults->update("RENDERFARM_VFS", renderfarm_vfs);
482         defaults->update("RENDERFARM_MOUNTPOINT", renderfarm_mountpoint);
483         defaults->update("RENDERFARM_JOBS_COUNT", renderfarm_job_count);
484         defaults->update("RENDERFARM_WATCHDOG_TIMEOUT", renderfarm_watchdog_timeout);
485         defaults->update("RENDERFARM_CONSOLIDATE", renderfarm_consolidate);
486         defaults->update("RENDERFARM_TOTAL", (int64_t)renderfarm_nodes.total);
487         for( int i = 0; i < renderfarm_nodes.total; i++ ) {
488                 sprintf(string, "RENDERFARM_NODE%d", i);
489                 defaults->update(string, renderfarm_nodes.values[i]);
490                 sprintf(string, "RENDERFARM_PORT%d", i);
491                 defaults->update(string, renderfarm_ports.values[i]);
492                 sprintf(string, "RENDERFARM_ENABLED%d", i);
493                 defaults->update(string, renderfarm_enabled.values[i]);
494                 sprintf(string, "RENDERFARM_RATE%d", i);
495                 defaults->update(string, renderfarm_rate.values[i]);
496         }
497         defaults->update("SHBTNS_TOTAL", shbtn_prefs.size());
498         for( int i=0; i<shbtn_prefs.size(); ++i ) {
499                 ShBtnPref *pref = shbtn_prefs[i];
500                 sprintf(string, "SHBTN%d_NAME", i);
501                 defaults->update(string, pref->name);
502                 sprintf(string, "SHBTN%d_COMMANDS", i);
503                 defaults->update(string, pref->commands);
504                 sprintf(string, "SHBTN%d_WARN", i);
505                 defaults->update(string, pref->warn);
506         }
507         defaults->update("FILE_PROBE_TOTAL", file_probes.size());
508         for( int i=0; i<file_probes.size(); ++i ) {
509                 ProbePref *pref = file_probes[i];
510                 sprintf(string, "FILE_PROBE%d_NAME", i);
511                 defaults->update(string, pref->name);
512                 sprintf(string, "FILE_PROBE%d_ARMED", i);
513                 defaults->update(string, pref->armed);
514         }
515         return 0;
516 }
517
518
519 void Preferences::add_node(const char *text, int port, int enabled, float rate)
520 {
521         if( text[0] == 0 ) return;
522
523         preferences_lock->lock("Preferences::add_node");
524         char *new_item = new char[strlen(text) + 1];
525         strcpy(new_item, text);
526         renderfarm_nodes.append(new_item);
527         renderfarm_nodes.set_array_delete();
528         renderfarm_ports.append(port);
529         renderfarm_enabled.append(enabled);
530         renderfarm_rate.append(rate);
531         preferences_lock->unlock();
532 }
533
534 void Preferences::delete_node(int number)
535 {
536         preferences_lock->lock("Preferences::delete_node");
537         if( number < renderfarm_nodes.total && number >= 0 ) {
538                 delete [] renderfarm_nodes.values[number];
539                 renderfarm_nodes.remove_number(number);
540                 renderfarm_ports.remove_number(number);
541                 renderfarm_enabled.remove_number(number);
542                 renderfarm_rate.remove_number(number);
543         }
544         preferences_lock->unlock();
545 }
546
547 void Preferences::delete_nodes()
548 {
549         preferences_lock->lock("Preferences::delete_nodes");
550         for( int i = 0; i < renderfarm_nodes.total; i++ )
551                 delete [] renderfarm_nodes.values[i];
552         renderfarm_nodes.remove_all();
553         renderfarm_ports.remove_all();
554         renderfarm_enabled.remove_all();
555         renderfarm_rate.remove_all();
556         preferences_lock->unlock();
557 }
558
559 void Preferences::reset_rates()
560 {
561         for( int i = 0; i < renderfarm_nodes.total; i++ ) {
562                 renderfarm_rate.values[i] = 0.0;
563         }
564         local_rate = 0.0;
565 }
566
567 float Preferences::get_rate(int node)
568 {
569         if( node < 0 ) {
570                 return local_rate;
571         }
572         else {
573                 int total = 0;
574                 for( int i = 0; i < renderfarm_nodes.size(); i++ ) {
575                         if( renderfarm_enabled.get(i) ) total++;
576                         if( total == node + 1 ) {
577                                 return renderfarm_rate.get(i);
578                         }
579                 }
580         }
581
582         return 0;
583 }
584
585 void Preferences::set_rate(float rate, int node)
586 {
587 //printf("Preferences::set_rate %f %d\n", rate, node);
588         if( node < 0 ) {
589                 local_rate = rate;
590         }
591         else {
592                 int total = 0;
593                 for( int i = 0; i < renderfarm_nodes.size(); i++ ) {
594                         if( renderfarm_enabled.get(i) ) total++;
595                         if( total == node + 1 ) {
596                                 renderfarm_rate.set(i, rate);
597                                 return;
598                         }
599                 }
600         }
601 }
602
603 float Preferences::get_avg_rate(int use_master_node)
604 {
605         preferences_lock->lock("Preferences::get_avg_rate");
606         float total = 0.0;
607         if( renderfarm_rate.total ) {
608                 int enabled = 0;
609                 if( use_master_node ) {
610                         if( EQUIV(local_rate, 0.0) ) {
611                                 preferences_lock->unlock();
612                                 return 0.0;
613                         }
614                         else {
615                                 enabled++;
616                                 total += local_rate;
617                         }
618                 }
619
620                 for( int i = 0; i < renderfarm_rate.total; i++ ) {
621                         if( renderfarm_enabled.values[i] ) {
622                                 enabled++;
623                                 total += renderfarm_rate.values[i];
624                                 if( EQUIV(renderfarm_rate.values[i], 0.0) ) {
625                                         preferences_lock->unlock();
626                                         return 0.0;
627                                 }
628                         }
629                 }
630
631                 if( enabled )
632                         total /= enabled;
633                 else
634                         total = 0.0;
635         }
636         preferences_lock->unlock();
637
638         return total;
639 }
640
641 void Preferences::sort_nodes()
642 {
643         int done = 0;
644
645         while(!done)
646         {
647                 done = 1;
648                 for( int i = 0; i < renderfarm_nodes.total - 1; i++ ) {
649                         if( strcmp(renderfarm_nodes.values[i], renderfarm_nodes.values[i + 1]) > 0 ) {
650                                 char *temp = renderfarm_nodes.values[i];
651                                 int temp_port = renderfarm_ports.values[i];
652
653                                 renderfarm_nodes.values[i] = renderfarm_nodes.values[i + 1];
654                                 renderfarm_nodes.values[i + 1] = temp;
655
656                                 renderfarm_ports.values[i] = renderfarm_ports.values[i + 1];
657                                 renderfarm_ports.values[i + 1] = temp_port;
658
659                                 renderfarm_enabled.values[i] = renderfarm_enabled.values[i + 1];
660                                 renderfarm_enabled.values[i + 1] = temp_port;
661
662                                 renderfarm_rate.values[i] = renderfarm_rate.values[i + 1];
663                                 renderfarm_rate.values[i + 1] = temp_port;
664                                 done = 0;
665                         }
666                 }
667         }
668 }
669
670 void Preferences::edit_node(int number,
671         const char *new_text,
672         int new_port,
673         int new_enabled)
674 {
675         char *new_item = new char[strlen(new_text) + 1];
676         strcpy(new_item, new_text);
677
678         delete [] renderfarm_nodes.values[number];
679         renderfarm_nodes.values[number] = new_item;
680         renderfarm_ports.values[number] = new_port;
681         renderfarm_enabled.values[number] = new_enabled;
682 }
683
684 int Preferences::get_enabled_nodes()
685 {
686         int result = 0;
687         for( int i = 0; i < renderfarm_enabled.total; i++ )
688                 if( renderfarm_enabled.values[i] ) result++;
689         return result;
690 }
691
692 const char* Preferences::get_node_hostname(int number)
693 {
694         int total = 0;
695         for( int i = 0; i < renderfarm_nodes.total; i++ ) {
696                 if( renderfarm_enabled.values[i] ) {
697                         if( total == number )
698                                 return renderfarm_nodes.values[i];
699                         else
700                                 total++;
701                 }
702         }
703         return "";
704 }
705
706 int Preferences::get_node_port(int number)
707 {
708         int total = 0;
709         for( int i = 0; i < renderfarm_ports.total; i++ ) {
710                 if( renderfarm_enabled.values[i] ) {
711                         if( total == number )
712                                 return renderfarm_ports.values[i];
713                         else
714                                 total++;
715                 }
716         }
717         return -1;
718 }
719
720 int Preferences::get_asset_file_path(Asset *asset, char *path)
721 {
722         strcpy(path, asset->path);
723         int result = !access(path, R_OK) ? 0 : -1;
724         if( !result && ( asset->format == FILE_MPEG || asset->format == FILE_AC3 ||
725                 asset->format == FILE_VMPEG || asset->format == FILE_AMPEG ) ) {
726                 char source_filename[BCTEXTLEN], index_filename[BCTEXTLEN];
727                 IndexFile::get_index_filename(source_filename,
728                         index_directory, index_filename, asset->path, ".toc");
729                 strcpy(path, index_filename);
730                 if( access(path, R_OK) )
731                         result = 1;
732         }
733 // result = 0, asset->path/toc exist, -1 no asset, 1 no toc
734         return result;
735 }
736
737
738 int Preferences::calculate_processors(int interactive)
739 {
740         if( force_uniprocessor && !interactive ) return 1;
741         return BC_WindowBase::get_resources()->machine_cpus;
742 }
743
744 int Preferences::get_file_probe_armed(const char *nm)
745 {
746         int k = file_probes.size();
747         while( --k>=0 && strcmp(nm, file_probes[k]->name) );
748         if( k < 0 ) return -1;
749         return file_probes[k]->armed;
750 }
751
752 void Preferences::set_file_probe_armed(const char *nm, int v)
753 {
754         int k = file_probes.size();
755         while( --k>=0 && strcmp(nm, file_probes[k]->name) );
756         if( k < 0 ) return;
757         file_probes[k]->armed = v;
758 }
759