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