r793: Small API addon, so plugins can 'see' camera and projector automation
[cinelerra_cv/mob.git] / cinelerra / channeledit.C
blob6b2b273f4d29a907be159da04fe1c2db83114006
1 #include "batch.h"
2 #include "channel.h"
3 #include "channeldb.h"
4 #include "channeledit.h"
5 #include "channelpicker.h"
6 #include "chantables.h"
7 #include "clip.h"
8 #include "condition.h"
9 #include "language.h"
10 #include "mainprogress.h"
11 #include "mwindow.h"
12 #include "mwindowgui.h"
13 #include "picture.h"
14 #include "record.h"
15 #include "recordgui.h"
16 #include "theme.h"
17 #include "videodevice.h"
18 #include <ctype.h>
19 #include <string.h>
20 #include <unistd.h>
23 ChannelEditThread::ChannelEditThread(MWindow *mwindow, 
24         ChannelPicker *channel_picker,
25         ChannelDB *channeldb,
26         Record *record)
27  : Thread()
29         this->channel_picker = channel_picker;
30         this->mwindow = mwindow;
31         this->channeldb = channeldb;
32         this->record = record;
33         in_progress = 0;
34         this->window = 0;
35         new_channels = new ChannelDB;
36         completion = new Condition(1, "ChannelEditThread::completion");
37         scan_thread = 0;
39 ChannelEditThread::~ChannelEditThread()
41         printf("ST: %i\n", scan_thread);
42         if(channel_picker->get_subwindow())
43                 channel_picker->get_subwindow()->unlock_window();
44         delete scan_thread;
45         if(channel_picker->get_subwindow())
46                 channel_picker->get_subwindow()->lock_window("ChannelEditThread::~ChannelEditThread");
47         delete new_channels;
48         delete completion;
51 void ChannelEditThread::run()
53         int i;
55         if(in_progress) 
56         {
57                 if(window)
58                 {
59                         window->lock_window("ChannelEditThread::run");
60                         window->raise_window(1);
61                         window->unlock_window();
62                 }
63                 return;
64         }
65         in_progress = 1;
66         completion->lock("ChannelEditThread::run");
68 // Copy master channel list to temporary.
69         new_channels->copy_from(channel_picker->channeldb);
70         current_channel = channel_picker->get_current_channel_number();
71 //printf("ChannelEditThread::run 1 %d\n", current_channel);
73 // Run the channel list window using the temporary list.
74         ChannelEditWindow window(mwindow, this, channel_picker);
75         window.create_objects();
76         this->window = &window;
77         int result = window.run_window();
78         this->window = 0;
80         if(!result)
81         {
82 // Copy new channels to master list
83                 channel_picker->channeldb->clear();
84                 
85                 channel_picker->channeldb->copy_from(new_channels);
86                 channel_picker->update_channel_list();
88                 if(record)
89                 {
90                         record->record_gui->lock_window("ChannelEditThread::run");
91                         record->record_gui->update_batch_sources();
93                         record->set_channel(current_channel);
94                         record->record_gui->unlock_window();
95                         record->save_defaults();
96                         record->channeldb->save(record->get_channeldb_prefix());
97                 }
98                 mwindow->save_defaults();
99         }
100         else
101         {
102 // Rejected.
103                 if(record)
104                 {
105                         record->set_channel(record->get_editing_batch()->channel);
106                 }
107         }
109         window.edit_thread->close_threads();
110         window.picture_thread->close_threads();
112         completion->unlock();
113         in_progress = 0;
117 int ChannelEditThread::close_threads()
119         if(in_progress && window)
120         {
121                 window->edit_thread->close_threads();
122                 window->picture_thread->close_threads();
123                 window->set_done(1);
124                 completion->lock("ChannelEditThread::close_threads");
125                 completion->unlock();
126         }
129 char *ChannelEditThread::value_to_freqtable(int value)
131         switch(value)
132         {
133                 case NTSC_BCAST:
134                         return _("NTSC_BCAST");
135                         break;
136                 case NTSC_CABLE:
137                         return _("NTSC_CABLE");
138                         break;
139                 case NTSC_HRC:
140                         return _("NTSC_HRC");
141                         break;
142                 case NTSC_BCAST_JP:
143                         return _("NTSC_BCAST_JP");
144                         break;
145                 case NTSC_CABLE_JP:
146                         return _("NTSC_CABLE_JP");
147                         break;
148                 case PAL_AUSTRALIA:
149                         return _("PAL_AUSTRALIA");
150                         break;
151                 case PAL_EUROPE:
152                         return _("PAL_EUROPE");
153                         break;
154                 case PAL_E_EUROPE:
155                         return _("PAL_E_EUROPE");
156                         break;
157                 case PAL_ITALY:
158                         return _("PAL_ITALY");
159                         break;
160                 case PAL_IRELAND:
161                         return _("PAL_IRELAND");
162                         break;
163                 case PAL_NEWZEALAND:
164                         return _("PAL_NEWZEALAND");
165                         break;
166         }
169 char* ChannelEditThread::value_to_norm(int value)
171         switch(value)
172         {
173                 case NTSC:
174                         return _("NTSC");
175                         break;
176                 case PAL:
177                         return _("PAL");
178                         break;
179                 case SECAM:
180                         return _("SECAM");
181                         break;
182         }
185 char* ChannelEditThread::value_to_input(int value)
187         if(channel_picker->get_video_inputs()->total > value)
188                 return channel_picker->get_video_inputs()->values[value]->device_name;
189         else
190                 return _("None");
199 ChannelEditWindow::ChannelEditWindow(MWindow *mwindow, 
200         ChannelEditThread *thread, 
201         ChannelPicker *channel_picker)
202  : BC_Window(PROGRAM_NAME ": Channels", 
203         mwindow->gui->get_abs_cursor_x(1) - 330, 
204         mwindow->gui->get_abs_cursor_y(1), 
205         350, 
206         400, 
207         350, 
208         400,
209         0,
210         0,
211         1)
213         this->thread = thread;
214         this->channel_picker = channel_picker;
215         this->mwindow = mwindow;
216         scan_confirm_thread = 0;
218 ChannelEditWindow::~ChannelEditWindow()
220         int i;
221         for(i = 0; i < channel_list.total; i++)
222         {
223                 delete channel_list.values[i];
224         }
225         channel_list.remove_all();
226         delete edit_thread;
227         delete picture_thread;
228         delete scan_confirm_thread;
231 int ChannelEditWindow::create_objects()
233         int x = 10, y = 10, i;
234         char string[1024];
236 // Create channel list
237         for(i = 0; i < thread->new_channels->size(); i++)
238         {
239                 channel_list.append(new BC_ListBoxItem(thread->new_channels->get(i)->title));
240         }
242         add_subwindow(list_box = new ChannelEditList(mwindow, this, x, y));
243         x += 200;
244         if(thread->record)
245         {
246                 add_subwindow(new ChannelEditSelect(mwindow, this, x, y));
247                 y += 30;
248         }
249         add_subwindow(new ChannelEditAdd(mwindow, this, x, y));
250         y += 30;
251         add_subwindow(new ChannelEdit(mwindow, this, x, y));
252         y += 30;
253         add_subwindow(new ChannelEditMoveUp(mwindow, this, x, y));
254         y += 30;
255         add_subwindow(new ChannelEditMoveDown(mwindow, this, x, y));
256         y += 30;
257         add_subwindow(new ChannelEditSort(mwindow, this, x, y));
258         y += 30;
260         Channel *channel_usage = channel_picker->get_channel_usage();
261         if(channel_usage && channel_usage->has_scanning)
262         {
263                 add_subwindow(new ChannelEditScan(mwindow, this, x, y));
264                 y += 30;
265         }
266         add_subwindow(new ChannelEditDel(mwindow, this, x, y));
267         y += 30;
268         add_subwindow(new ChannelEditPicture(mwindow, this, x, y));
269         y += 100;
270         x = 10;
271         add_subwindow(new BC_OKButton(this));
272         x += 150;
273         add_subwindow(new BC_CancelButton(this));
276         edit_thread = new ChannelEditEditThread(this, 
277                 channel_picker, 
278                 thread->record);
279         picture_thread = new ChannelEditPictureThread(channel_picker, this);
280         show_window();
281         return 0;
284 int ChannelEditWindow::close_event()
286         set_done(0);
289 int ChannelEditWindow::add_channel()
291         Channel *new_channel;
292         Channel *prev_channel = 0;
294 // Create new channel
295         new_channel = new Channel;
297 // Reuse parameters from previous channel
298         if(thread->new_channels->size()) 
299         {
300                 prev_channel = thread->new_channels->get(
301                                 thread->new_channels->size() - 1);
302                 new_channel->copy_settings(prev_channel);
303         }
304         else
305 // Use default channel parameters
306         if(thread->record)
307         {
308                 new_channel->copy_settings(thread->record->master_channel);
309         }
311 // Copy device usage.  Need the same thing for playback.
312         if(thread->record)
313         {
314                 new_channel->copy_usage(thread->record->master_channel);
315         }
317 // Add to channel table
318         channel_list.append(new BC_ListBoxItem(new_channel->title));
319         thread->new_channels->append(new_channel);
320         update_list();
322 // Start common routing
323         edit_thread->edit_channel(new_channel, 0);
324         return 0;
327 int ChannelEditWindow::update_list()
329 // Create channel list
330         channel_list.remove_all_objects();
331         for(int i = 0; i < thread->new_channels->size(); i++)
332         {
333                 channel_list.append(
334                         new BC_ListBoxItem(
335                                 thread->new_channels->get(i)->title));
336         }
338         list_box->update(&channel_list, 0, 0, 1, list_box->get_yposition());
341 int ChannelEditWindow::update_list(Channel *channel)
343         int i;
344         for(i = 0; i < thread->new_channels->size(); i++)
345                 if(thread->new_channels->get(i) == channel) break;
347         if(i < thread->new_channels->size())
348         {
349                 channel_list.values[i]->set_text(channel->title);
350         }
352         update_list();
356 int ChannelEditWindow::edit_channel()
358         if(list_box->get_selection_number(0, 0) > -1)
359         {
360                 thread->current_channel = list_box->get_selection_number(0, 0);
361                 edit_thread->edit_channel(
362                         thread->new_channels->get(
363                                 list_box->get_selection_number(0, 0)), 
364                         1);
365         }
368 int ChannelEditWindow::edit_picture()
370         picture_thread->edit_picture();
373 void ChannelEditWindow::scan_confirm()
375         thread->scan_params.load_defaults(mwindow->defaults);
376         if(!scan_confirm_thread) scan_confirm_thread = new ConfirmScanThread(this);
377         unlock_window();
378         scan_confirm_thread->start();
379         lock_window("ChannelEditWindow::scan_confirm");
382 void ChannelEditWindow::scan()
384         thread->new_channels->clear();
385         update_list();
387         if(!thread->scan_thread) thread->scan_thread = new ScanThread(thread);
388         thread->scan_thread->start();
392 void ChannelEditWindow::sort()
394         int done = 0;
395         while(!done)
396         {
397                 done = 1;
398                 for(int i = 0; i < thread->new_channels->size() - 1; i++)
399                 {
400                         Channel *channel1 = thread->new_channels->get(i);
401                         Channel *channel2 = thread->new_channels->get(i + 1);
402                         int is_num = 1;
403                         for(int j = 0; j < strlen(channel1->title); j++)
404                                 if(!isdigit(channel1->title[j])) is_num = 0;
405                         for(int j = 0; j < strlen(channel2->title); j++)
406                                 if(!isdigit(channel2->title[j])) is_num = 0;
407                         if(is_num && atoi(channel1->title) > atoi(channel2->title) ||
408                                 !is_num && strcasecmp(channel2->title, channel1->title) < 0)
409                         {
410                                 thread->new_channels->set(i, channel2);
411                                 thread->new_channels->set(i + 1, channel1);
412                                 done = 0;
413                         }
414                 }
415         }
416         update_list();
420 int ChannelEditWindow::delete_channel(int number)
422         delete thread->new_channels->get(number);
423         channel_list.remove_number(number);
424         thread->new_channels->remove_number(number);
425         update_list();
428 int ChannelEditWindow::delete_channel(Channel *channel)
430         int i;
431         for(i = 0; i < thread->new_channels->size(); i++)
432         {
433                 if(thread->new_channels->get(i) == channel)
434                 {
435                         break;
436                 }
437         }
438         if(i < thread->new_channels->size()) delete_channel(i);
439         return 0;
442 int ChannelEditWindow::move_channel_up()
444         if(list_box->get_selection_number(0, 0) > -1)
445         {
446                 int number2 = list_box->get_selection_number(0, 0);
447                 int number1 = number2 - 1;
448                 Channel *temp;
449                 BC_ListBoxItem *temp_text;
451                 if(number1 < 0) number1 = thread->new_channels->size() - 1;
453                 temp = thread->new_channels->get(number1);
454                 thread->new_channels->set(number1, thread->new_channels->get(number2));
455                 thread->new_channels->set(number2, temp);
457                 temp_text = channel_list.values[number1];
458                 channel_list.values[number1] = channel_list.values[number2];
459                 channel_list.values[number2] = temp_text;
460                 list_box->update(&channel_list, 
461                         0, 
462                         0, 
463                         1, 
464                         list_box->get_xposition(), 
465                         list_box->get_yposition(), 
466                         number1,
467                         1);
468         }
469         return 0;
472 int ChannelEditWindow::move_channel_down()
474         if(list_box->get_selection_number(0, 0) > -1)
475         {
476                 int number2 = list_box->get_selection_number(0, 0);
477                 int number1 = number2 + 1;
478                 Channel *temp;
479                 BC_ListBoxItem *temp_text;
481                 if(number1 > thread->new_channels->size() - 1) number1 = 0;
483                 temp = thread->new_channels->get(number1);
484                 thread->new_channels->set(number1, thread->new_channels->get(number2));
485                 thread->new_channels->set(number2, temp);
486                 temp_text = channel_list.values[number1];
487                 channel_list.values[number1] = channel_list.values[number2];
488                 channel_list.values[number2] = temp_text;
489                 list_box->update(&channel_list, 
490                         0, 
491                         0, 
492                         1, 
493                         list_box->get_xposition(), 
494                         list_box->get_yposition(), 
495                         number1,
496                         1);
497         }
498         return 0;
501 int ChannelEditWindow::change_channel_from_list(int channel_number)
503         Channel *channel;
504         if(channel_number > -1 && channel_number < thread->new_channels->size())
505         {
506                 thread->current_channel = channel_number;
507                 channel_picker->set_channel(thread->new_channels->get(channel_number));
508         }
511 ChannelEditSelect::ChannelEditSelect(MWindow *mwindow, ChannelEditWindow *window, int x, int y)
512  : BC_GenericButton(x, y, _("Select"))
514         this->window = window;
516 ChannelEditSelect::~ChannelEditSelect()
519 int ChannelEditSelect::handle_event()
521         window->change_channel_from_list(
522                 window->list_box->get_selection_number(0, 0));
525 ChannelEditAdd::ChannelEditAdd(MWindow *mwindow, ChannelEditWindow *window, int x, int y)
526  : BC_GenericButton(x, y, _("Add..."))
528         this->window = window;
530 ChannelEditAdd::~ChannelEditAdd()
533 int ChannelEditAdd::handle_event()
535         window->add_channel();
538 ChannelEditList::ChannelEditList(MWindow *mwindow, ChannelEditWindow *window, int x, int y)
539  : BC_ListBox(x, 
540                         y, 
541                         185, 
542                         window->get_h() - BC_OKButton::calculate_h() - y - 10, 
543                         LISTBOX_TEXT, 
544                         &(window->channel_list))
546         this->window = window;
548 ChannelEditList::~ChannelEditList()
551 int ChannelEditList::handle_event()
553         window->edit_channel();
556 ChannelEditMoveUp::ChannelEditMoveUp(MWindow *mwindow, ChannelEditWindow *window, int x, int y)
557  : BC_GenericButton(x, y, _("Move up"))
559         this->window = window;
561 ChannelEditMoveUp::~ChannelEditMoveUp()
564 int ChannelEditMoveUp::handle_event()
566         lock_window("ChannelEditMoveUp::handle_event");
567         window->move_channel_up();
568         unlock_window();
571 ChannelEditMoveDown::ChannelEditMoveDown(MWindow *mwindow, ChannelEditWindow *window, int x, int y)
572  : BC_GenericButton(x, y, _("Move down"))
574         this->window = window;
576 ChannelEditMoveDown::~ChannelEditMoveDown()
579 int ChannelEditMoveDown::handle_event()
581         lock_window("ChannelEditMoveDown::handle_event");
582         window->move_channel_down();
583         unlock_window();
586 ChannelEditSort::ChannelEditSort(MWindow *mwindow, ChannelEditWindow *window, int x, int y)
587  : BC_GenericButton(x, y, _("Sort"))
589         this->window = window;
591 int ChannelEditSort::handle_event()
593         lock_window("ChannelEditSort::handle_event");
594         window->sort();
595         unlock_window();
598 ChannelEditScan::ChannelEditScan(MWindow *mwindow, ChannelEditWindow *window, int x, int y)
599  : BC_GenericButton(x, y, _("Scan"))
601         this->window = window;
603 int ChannelEditScan::handle_event()
605         window->scan_confirm();
608 ChannelEditDel::ChannelEditDel(MWindow *mwindow, ChannelEditWindow *window, int x, int y)
609  : BC_GenericButton(x, y, _("Delete"))
611         this->window = window;
613 ChannelEditDel::~ChannelEditDel()
616 int ChannelEditDel::handle_event()
618         if(window->list_box->get_selection_number(0, 0) > -1) window->delete_channel(window->list_box->get_selection_number(0, 0));
621 ChannelEdit::ChannelEdit(MWindow *mwindow, ChannelEditWindow *window, int x, int y)
622  : BC_GenericButton(x, y, _("Edit..."))
624         this->window = window;
626 ChannelEdit::~ChannelEdit()
629 int ChannelEdit::handle_event()
631         window->edit_channel();
634 ChannelEditPicture::ChannelEditPicture(MWindow *mwindow, ChannelEditWindow *window, int x, int y)
635  : BC_GenericButton(x, y, _("Picture..."))
637         this->window = window;
639 ChannelEditPicture::~ChannelEditPicture()
642 int ChannelEditPicture::handle_event()
644         window->edit_picture();
658 // ========================= confirm overwrite by channel scannin
661 ConfirmScan::ConfirmScan(ChannelEditWindow *gui, int x, int y)
662  : BC_Window(PROGRAM_NAME ": Scan confirm",
663         x,
664         y,
665         350,
666         BC_OKButton::calculate_h() + 130,
667         0,
668         0,
669         0,
670         0,
671         1)
673         this->gui = gui;
676 void ConfirmScan::create_objects()
678         int x = 10, y = 10;
679         int y2 = 0, x2 = 0;
680         BC_Title *title;
681         add_subwindow(title = new BC_Title(x, y, _("Set parameters for channel scanning.")));
682         y += title->get_h() + 10;
683         y2 = y;
685         add_subwindow(title = new BC_Title(x, y, _("Frequency table:")));
686         x2 = title->get_w();
687         y += BC_PopupMenu::calculate_h();
688         add_subwindow(title = new BC_Title(x, y, _("Norm:")));
689         x2 = MAX(x2, title->get_w());
690         y += BC_PopupMenu::calculate_h();
691         add_subwindow(title = new BC_Title(x, y, _("Input:")));
692         x2 = MAX(x2, title->get_w());
693         y += BC_PopupMenu::calculate_h();
694         x2 += x + 5;
696         y = y2;
697         x = x2;
698         ChannelEditEditFreqtable *table;
699         add_subwindow(table = new ChannelEditEditFreqtable(x, 
700                 y, 
701                 0, 
702                 gui->thread));
703         table->add_items();
704         y += table->get_h() + 10;
706         ChannelEditEditNorm *norm;
707         add_subwindow(norm = new ChannelEditEditNorm(x, 
708                 y, 
709                 0,
710                 gui->thread));
711         norm->add_items();
712         y += norm->get_h() + 10;
714         ChannelEditEditInput *input;
715         add_subwindow(input = new ChannelEditEditInput(x, 
716                 y, 
717                 0, 
718                 gui->thread));
719         input->add_items();
722         add_subwindow(new BC_OKButton(this));
723         add_subwindow(new BC_CancelButton(this));
724         show_window();
733 ConfirmScanThread::ConfirmScanThread(ChannelEditWindow *gui)
734  : BC_DialogThread()
736         this->gui = gui;
739 void ConfirmScanThread::handle_done_event(int result)
741         gui->thread->scan_params.save_defaults(gui->thread->mwindow->defaults);
742         if(!result)
743         {
744                 get_gui()->hide_window();
745                 gui->lock_window("ConfirmScanThread::handle_done_event");
746                 gui->scan();
747                 gui->unlock_window();
748         }
751 BC_Window* ConfirmScanThread::new_gui()
753         int x = gui->get_abs_cursor_x(1);
754         int y = gui->get_abs_cursor_y(1);
755         ConfirmScan *result = new ConfirmScan(gui, x, y);
756         result->create_objects();
757         return result;
765 ScanThread::ScanThread(ChannelEditThread *edit)
766  : Thread(1, 0, 0)
768         this->edit = edit;
769         interrupt = 0;
770         progress = 0;
773 ScanThread::~ScanThread()
775         interrupt = 1;
776         Thread::join();
778         delete progress;
782 void ScanThread::start()
784 // Cancel previous job
785         interrupt = 1;
786         Thread::join();
787         delete progress;
788         interrupt = 0;
791         progress = edit->mwindow->mainprogress->start_progress("Scanning", 
792                 chanlists[edit->scan_params.freqtable].count, 
793                 1);
794         Thread::start();
797 void ScanThread::run()
799         for(int i = 0; 
800                 i < chanlists[edit->scan_params.freqtable].count &&
801                         !interrupt && 
802                         !progress->is_cancelled();
803                 i++)
804         {
805                 edit->scan_params.entry = i;
806                 char string[BCTEXTLEN];
807                 sprintf(edit->scan_params.title, 
808                         "%s", 
809                         chanlists[edit->scan_params.freqtable].list[i].name);
810                 sprintf(string, 
811                         "Scanning %s", 
812                         edit->scan_params.title);
813                 progress->update_title(string);
814                 progress->update(i);
815                 edit->channel_picker->set_channel(&edit->scan_params);
818                 sleep(2);
820             int got_signal = edit->channel_picker->has_signal();
821                 if(got_signal)
822                 {
823                         Channel *new_channel = new Channel;
824                         new_channel->copy_usage(&edit->scan_params);
825                         new_channel->copy_settings(&edit->scan_params);
826                         edit->window->lock_window("ScanThread::run");
827                         edit->new_channels->append(new_channel);
828                         edit->window->update_list();
829                         edit->window->unlock_window();
830                 }
831         }
832         delete progress;
833         progress = 0;
842 // ================================= Edit a single channel
846 ChannelEditEditThread::ChannelEditEditThread(ChannelEditWindow *window, 
847         ChannelPicker *channel_picker,
848         Record *record)
849  : Thread()
851         this->window = window;
852         this->channel_picker = channel_picker;
853         this->record = record;
854         in_progress = 0;
855         edit_window = 0;
856         editing = 0;
857         completion = new Condition(1, "ChannelEditEditThread::completion");
860 ChannelEditEditThread::~ChannelEditEditThread()
862         delete completion;
865 int ChannelEditEditThread::close_threads()
867         if(edit_window)
868         {
869                 edit_window->set_done(1);
870                 completion->lock("ChannelEditEditThread::close_threads");
871                 completion->unlock();
872         }
875 int ChannelEditEditThread::edit_channel(Channel *channel, int editing)
877         if(in_progress) 
878         {
879                 edit_window->lock_window("ChannelEditEditThread::edit_channel");
880                 edit_window->raise_window(1);
881                 edit_window->unlock_window();
882                 return 1;
883         }
884         in_progress = 1;
886 // Copy the channel to edit into a temporary
887         completion->lock("ChannelEditEditThread::edit_channel");
888         this->editing = editing;
889         this->output_channel = channel;
890         new_channel.copy_settings(output_channel);
891         new_channel.copy_usage(output_channel);
893         if(editing && new_channel.title[0])
894                 user_title = 1;
895         else
896                 user_title = 0;
897         set_synchronous(0);
898         Thread::start();
902 void ChannelEditEditThread::set_device()
904         channel_picker->set_channel(&new_channel);
907 int ChannelEditEditThread::change_source(char *source_name)
909         int i, result;
910         for(i = 0; i < chanlists[new_channel.freqtable].count; i++)
911         {
912                 if(!strcasecmp(chanlists[new_channel.freqtable].list[i].name, source_name))
913                 {
914                         new_channel.entry = i;
915                         i = chanlists[new_channel.freqtable].count;
916                         set_device();
917                 }
918         }
919         if(!user_title)
920         {
921                 strcpy(new_channel.title, source_name);
922                 if(edit_window->title_text)
923                 {
924                         edit_window->title_text->update(source_name);
925                 }
926         }
929 int ChannelEditEditThread::source_up()
931         new_channel.entry++;
932         if(new_channel.entry > chanlists[new_channel.freqtable].count - 1) new_channel.entry = 0;
933         source_text->update(chanlists[new_channel.freqtable].list[new_channel.entry].name);
934         set_device();
937 int ChannelEditEditThread::source_down()
939         new_channel.entry--;
940         if(new_channel.entry < 0) new_channel.entry = chanlists[new_channel.freqtable].count - 1;
941         source_text->update(chanlists[new_channel.freqtable].list[new_channel.entry].name);
942         set_device();
945 int ChannelEditEditThread::set_input(int value)
947         new_channel.input = value;
948         set_device();
951 int ChannelEditEditThread::set_norm(int value)
953         new_channel.norm = value;
954         set_device();
957 int ChannelEditEditThread::set_freqtable(int value)
959         new_channel.freqtable = value;
960         if(new_channel.entry > chanlists[new_channel.freqtable].count - 1) new_channel.entry = 0;
961         source_text->update(chanlists[new_channel.freqtable].list[new_channel.entry].name);
962         set_device();
965 void ChannelEditEditThread::run()
967         ChannelEditEditWindow edit_window(this, window, channel_picker);
968         edit_window.create_objects(&new_channel);
969         this->edit_window = &edit_window;
970         int result = edit_window.run_window();
971         this->edit_window = 0;
973 // Done editing channel.  Keep channel.
974         if(!result)
975         {
976                 output_channel->copy_settings(&new_channel);
977                 window->lock_window();
978                 window->update_list(output_channel);
979                 window->unlock_window();
980         }
981         else
982         {
983 // Discard channel.
984                 if(!editing)
985                 {
986                         window->lock_window();
987                         window->delete_channel(output_channel);
988                         window->unlock_window();
989                 }
990         }
991         editing = 0;
992         completion->unlock();
993         in_progress = 0;
996 ChannelEditEditWindow::ChannelEditEditWindow(ChannelEditEditThread *thread, 
997         ChannelEditWindow *window,
998         ChannelPicker *channel_picker)
999  : BC_Window(PROGRAM_NAME ": Edit Channel", 
1000         channel_picker->mwindow->gui->get_abs_cursor_x(1), 
1001         channel_picker->mwindow->gui->get_abs_cursor_y(1), 
1002         390, 
1003         300, 
1004         390, 
1005         300,
1006         0,
1007         0,
1008         1)
1010         this->channel_picker = channel_picker;
1011         this->window = window;
1012         this->thread = thread;
1014 ChannelEditEditWindow::~ChannelEditEditWindow()
1017 int ChannelEditEditWindow::create_objects(Channel *channel)
1019         this->new_channel = channel;
1020         Channel *channel_usage = channel_picker->get_channel_usage();
1021         title_text = 0;
1023         int x = 10, y = 10;
1024         if(!channel_usage ||
1025                 (!channel_usage->use_frequency && 
1026                 !channel_usage->use_fine && 
1027                 !channel_usage->use_norm && 
1028                 !channel_usage->use_input))
1029         {
1030                 add_subwindow(new BC_Title(x, y, "Device has no input selection."));
1031                 y += 30;
1032         }
1033         else
1034         {
1035                 add_subwindow(new BC_Title(x, y, _("Title:")));
1036                 add_subwindow(title_text = new ChannelEditEditTitle(x, y + 20, thread));
1037                 y += 50;
1038         }
1040         if(channel_usage && channel_usage->use_frequency)
1041         {
1042                 add_subwindow(new BC_Title(x, y, _("Channel:")));
1043                 y += 20;
1044                 add_subwindow(thread->source_text = new ChannelEditEditSource(x, y, thread));
1045                 add_subwindow(new ChannelEditEditSourceTumbler(x + 160, y, thread));
1046                 y += 40;
1048                 add_subwindow(new BC_Title(x, y, _("Frequency table:")));
1049                 ChannelEditEditFreqtable *table;
1050                 add_subwindow(table = new ChannelEditEditFreqtable(x + 130, 
1051                         y, 
1052                         thread, 
1053                         window->thread));
1054                 table->add_items();
1055                 y += 30;
1056         }
1058         if(channel_usage && channel_usage->use_fine)
1059         {
1060                 add_subwindow(new BC_Title(x, y, _("Fine:")));
1061                 add_subwindow(new ChannelEditEditFine(x + 130, y, thread));
1062                 y += 30;
1063         }
1065         if(channel_usage && channel_usage->use_norm)
1066         {
1067                 add_subwindow(new BC_Title(x, y, _("Norm:")));
1068                 ChannelEditEditNorm *norm;
1069                 add_subwindow(norm = new ChannelEditEditNorm(x + 130, 
1070                         y, 
1071                         thread,
1072                         window->thread));
1073                 norm->add_items();
1074                 y += 30;
1075         }
1077         if(channel_usage && channel_usage->use_input)
1078         {
1079                 add_subwindow(new BC_Title(x, y, _("Input:")));
1080                 ChannelEditEditInput *input;
1081                 add_subwindow(input = new ChannelEditEditInput(x + 130, 
1082                         y, 
1083                         thread, 
1084                         window->thread));
1085                 input->add_items();
1086                 y += 30;
1087         }
1089         add_subwindow(new BC_OKButton(this));
1090         x += 200;
1091         add_subwindow(new BC_CancelButton(this));
1092         show_window();
1093         return 0;
1096 ChannelEditEditTitle::ChannelEditEditTitle(int x, 
1097         int y, 
1098         ChannelEditEditThread *thread)
1099  : BC_TextBox(x, y, 150, 1, thread->new_channel.title)
1101         this->thread = thread;
1103 ChannelEditEditTitle::~ChannelEditEditTitle()
1106 int ChannelEditEditTitle::handle_event()
1108         if(strlen(get_text()) < 1024)
1109         {
1110                 strcpy(thread->new_channel.title, get_text());
1111         }
1112         if(get_text()[0]) 
1113                 thread->user_title = 1;
1114         else
1115                 thread->user_title = 0;
1116         return 1;
1120 ChannelEditEditSource::ChannelEditEditSource(int x, int y, ChannelEditEditThread *thread)
1121  : BC_TextBox(x, y, 150, 1, chanlists[thread->new_channel.freqtable].list[thread->new_channel.entry].name)
1123         this->thread = thread;
1126 ChannelEditEditSource::~ChannelEditEditSource()
1129 int ChannelEditEditSource::handle_event()
1131         thread->change_source(get_text());
1135 ChannelEditEditSourceTumbler::ChannelEditEditSourceTumbler(int x, int y, ChannelEditEditThread *thread)
1136  : BC_Tumbler(x, y)
1138         this->thread = thread;
1140 ChannelEditEditSourceTumbler::~ChannelEditEditSourceTumbler()
1143 int ChannelEditEditSourceTumbler::handle_up_event()
1145         thread->source_up();
1147 int ChannelEditEditSourceTumbler::handle_down_event()
1149         thread->source_down();
1152 ChannelEditEditInput::ChannelEditEditInput(int x, 
1153         int y, 
1154         ChannelEditEditThread *thread, 
1155         ChannelEditThread *edit)
1156  : BC_PopupMenu(x, 
1157         y, 
1158         150, 
1159         edit->value_to_input(thread ? thread->new_channel.input : edit->scan_params.input))
1161         this->thread = thread;
1162         this->edit = edit;
1164 ChannelEditEditInput::~ChannelEditEditInput()
1167 int ChannelEditEditInput::add_items()
1169         ArrayList<Channel*> *inputs;
1170         inputs = edit->channel_picker->get_video_inputs();
1172         if(inputs)
1173                 for(int i = 0; i < inputs->total; i++)
1174                 {
1175                         add_item(new ChannelEditEditInputItem(thread, 
1176                                 edit,
1177                                 inputs->values[i]->device_name, 
1178                                 i));
1179                 }
1181 int ChannelEditEditInput::handle_event()
1183         return 0;
1186 ChannelEditEditInputItem::ChannelEditEditInputItem(ChannelEditEditThread *thread, 
1187         ChannelEditThread *edit,
1188         char *text, 
1189         int value)
1190  : BC_MenuItem(text)
1192         this->thread = thread;
1193         this->edit = edit;
1194         this->value = value;
1196 ChannelEditEditInputItem::~ChannelEditEditInputItem()
1199 int ChannelEditEditInputItem::handle_event()
1201         get_popup_menu()->set_text(get_text());
1202         if(thread && !thread->user_title)
1203         {
1204                 strcpy(thread->new_channel.title, get_text());
1205                 if(thread->edit_window->title_text)
1206                 {
1207                         thread->edit_window->title_text->update(get_text());
1208                 }
1209         }
1210         if(thread) 
1211                 thread->set_input(value);
1212         else
1213                 edit->scan_params.input = value;
1216 ChannelEditEditNorm::ChannelEditEditNorm(int x, 
1217         int y, 
1218         ChannelEditEditThread *thread,
1219         ChannelEditThread *edit)
1220  : BC_PopupMenu(x, 
1221         y, 
1222         100, 
1223         edit->value_to_norm(thread ? thread->new_channel.norm : edit->scan_params.norm))
1225         this->thread = thread;
1226         this->edit = edit;
1228 ChannelEditEditNorm::~ChannelEditEditNorm()
1231 int ChannelEditEditNorm::add_items()
1233         add_item(new ChannelEditEditNormItem(thread, 
1234                 edit, 
1235                 edit->value_to_norm(NTSC), NTSC));
1236         add_item(new ChannelEditEditNormItem(thread, 
1237                 edit, 
1238                 edit->value_to_norm(PAL), PAL));
1239         add_item(new ChannelEditEditNormItem(thread, 
1240                 edit, 
1241                 edit->value_to_norm(SECAM), SECAM));
1242         return 0;
1246 ChannelEditEditNormItem::ChannelEditEditNormItem(ChannelEditEditThread *thread, 
1247         ChannelEditThread *edit,
1248         char *text, 
1249         int value)
1250  : BC_MenuItem(text)
1252         this->value = value;
1253         this->edit = edit;
1254         this->thread = thread;
1256 ChannelEditEditNormItem::~ChannelEditEditNormItem()
1259 int ChannelEditEditNormItem::handle_event()
1261         get_popup_menu()->set_text(get_text());
1262         if(thread)
1263                 thread->set_norm(value);
1264         else
1265                 edit->scan_params.norm = value;
1269 ChannelEditEditFreqtable::ChannelEditEditFreqtable(int x, 
1270         int y, 
1271         ChannelEditEditThread *thread,
1272         ChannelEditThread *edit)
1273  : BC_PopupMenu(x, 
1274         y, 
1275         150, 
1276         edit->value_to_freqtable(thread ? thread->new_channel.freqtable : edit->scan_params.freqtable))
1278         this->thread = thread;
1279         this->edit = edit;
1281 ChannelEditEditFreqtable::~ChannelEditEditFreqtable()
1284 int ChannelEditEditFreqtable::add_items()
1286         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(NTSC_BCAST), NTSC_BCAST));
1287         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(NTSC_CABLE), NTSC_CABLE));
1288         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(NTSC_HRC), NTSC_HRC));
1289         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(NTSC_BCAST_JP), NTSC_BCAST_JP));
1290         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(NTSC_CABLE_JP), NTSC_CABLE_JP));
1291         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(PAL_AUSTRALIA), PAL_AUSTRALIA));
1292         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(PAL_EUROPE), PAL_EUROPE));
1293         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(PAL_E_EUROPE), PAL_E_EUROPE));
1294         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(PAL_ITALY), PAL_ITALY));
1295         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(PAL_IRELAND), PAL_IRELAND));
1296         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(PAL_NEWZEALAND), PAL_NEWZEALAND));
1297         return 0;
1300 ChannelEditEditFreqItem::ChannelEditEditFreqItem(ChannelEditEditThread *thread, 
1301         ChannelEditThread *edit,
1302         char *text, int value)
1303  : BC_MenuItem(text)
1305         this->value = value;
1306         this->edit = edit;
1307         this->thread = thread;
1309 ChannelEditEditFreqItem::~ChannelEditEditFreqItem()
1312 int ChannelEditEditFreqItem::handle_event()
1314         get_popup_menu()->set_text(get_text());
1315         if(thread)
1316                 thread->set_freqtable(value);
1317         else
1318                 edit->scan_params.freqtable = value;
1323 ChannelEditEditFine::ChannelEditEditFine(int x, 
1324         int y, 
1325         ChannelEditEditThread *thread)
1326  : BC_ISlider(x, 
1327                 y, 
1328                 0, 
1329                 240, 
1330                 240, 
1331                 -100, 
1332                 100, 
1333                 thread->new_channel.fine_tune)
1335         this->thread = thread;
1337 ChannelEditEditFine::~ChannelEditEditFine()
1340 int ChannelEditEditFine::handle_event()
1342         thread->new_channel.fine_tune = get_value();
1343         thread->set_device();
1347 // ========================== picture quality
1349 ChannelEditPictureThread::ChannelEditPictureThread(ChannelPicker *channel_picker, ChannelEditWindow *window)
1350  : Thread()
1352         this->channel_picker = channel_picker;
1353         this->window = window;
1354         in_progress = 0;
1355         edit_window = 0;
1356         completion = new Condition(1, "ChannelEditPictureThread::completion");
1358 ChannelEditPictureThread::~ChannelEditPictureThread()
1360         delete completion;
1363 int ChannelEditPictureThread::edit_picture()
1365         if(in_progress) 
1366         {
1367                 edit_window->lock_window("ChannelEditPictureThread::edit_picture");
1368                 edit_window->raise_window(1);
1369                 edit_window->unlock_window();
1370                 return 1;
1371         }
1372         in_progress = 1;
1373         completion->lock("ChannelEditPictureThread::edit_picture");
1374         set_synchronous(0);
1375         Thread::start();
1378 void ChannelEditPictureThread::run()
1380         ChannelEditPictureWindow edit_window(this, 
1381                 channel_picker);
1382         edit_window.create_objects();
1383         this->edit_window = &edit_window;
1384         int result = edit_window.run_window();
1385         this->edit_window = 0;
1386         completion->unlock();
1387         in_progress = 0;
1390 int ChannelEditPictureThread::close_threads()
1392         if(edit_window)
1393         {
1394                 edit_window->set_done(1);
1395                 completion->lock("ChannelEditPictureThread::close_threads");
1396                 completion->unlock();
1397         }
1401 ChannelEditPictureWindow::ChannelEditPictureWindow(ChannelEditPictureThread *thread, 
1402         ChannelPicker *channel_picker)
1403  : BC_Window(PROGRAM_NAME ": Picture", 
1404         channel_picker->mwindow->gui->get_abs_cursor_x(1) - 200, 
1405         channel_picker->mwindow->gui->get_abs_cursor_y(1) - 220, 
1406         200, 
1407         calculate_h(channel_picker), 
1408         200, 
1409         calculate_h(channel_picker))
1411         this->thread = thread;
1412         this->channel_picker = channel_picker;
1414 ChannelEditPictureWindow::~ChannelEditPictureWindow()
1418 int ChannelEditPictureWindow::calculate_h(ChannelPicker *channel_picker)
1420         PictureConfig *picture_usage = channel_picker->get_picture_usage();
1421         int pad = BC_Pot::calculate_h();
1422         int result = 0;
1424         if(picture_usage)
1425         {
1426                 if(picture_usage->use_brightness)
1427                         result += pad;
1428                 if(picture_usage->use_contrast)
1429                         result += pad;
1430                 if(picture_usage->use_color)
1431                         result += pad;
1432                 if(picture_usage->use_hue)
1433                         result += pad;
1434                 if(picture_usage->use_whiteness)
1435                         result += pad;
1436         }
1437         result += channel_picker->get_controls() * pad;
1439         if (result == 0)
1440                 result += 20;   // space for "Device has no controls"
1442         result += 20 + BC_OKButton::calculate_h();
1443         return result;
1446 int ChannelEditPictureWindow::create_objects()
1448         int x = 10, y = 10;
1449         int x1 = 110, x2 = 145;
1450         int pad = BC_Pot::calculate_h();
1451 #define SWAP_X x1 ^= x2; x2 ^= x1; x1 ^= x2;
1453         PictureConfig *picture_usage = channel_picker->get_picture_usage();
1455         if(!picture_usage ||
1456                 (!picture_usage->use_brightness &&
1457                 !picture_usage->use_contrast &&
1458                 !picture_usage->use_color &&
1459                 !picture_usage->use_hue &&
1460                 !picture_usage->use_whiteness &&
1461                 !channel_picker->get_controls()))
1462         {
1463                 add_subwindow(new BC_Title(x, y, "Device has no picture controls."));
1464                 y += 50;
1465         }
1467         if(picture_usage && picture_usage->use_brightness)
1468         {
1469                 add_subwindow(new BC_Title(x, y + 10, _("Brightness:")));
1470                 add_subwindow(new ChannelEditBright(x1, y, channel_picker, channel_picker->get_brightness()));
1471                 y += pad;
1472                 SWAP_X
1473                 
1474         }
1476         if(picture_usage && picture_usage->use_contrast)
1477         {
1478                 add_subwindow(new BC_Title(x, y + 10, _("Contrast:")));
1479                 add_subwindow(new ChannelEditContrast(x1, y, channel_picker, channel_picker->get_contrast()));
1480                 y += pad;
1481                 SWAP_X
1482         }
1484         if(picture_usage && picture_usage->use_color)
1485         {
1486                 add_subwindow(new BC_Title(x, y + 10, _("Color:")));
1487                 add_subwindow(new ChannelEditColor(x1, y, channel_picker, channel_picker->get_color()));
1488                 y += pad;
1489                 SWAP_X
1490         }
1492         if(picture_usage && picture_usage->use_hue)
1493         {
1494                 add_subwindow(new BC_Title(x, y + 10, _("Hue:")));
1495                 add_subwindow(new ChannelEditHue(x1, y, channel_picker, channel_picker->get_hue()));
1496                 y += pad;
1497                 SWAP_X
1498         }
1500         if(picture_usage && picture_usage->use_whiteness)
1501         {
1502                 add_subwindow(new BC_Title(x, y + 10, _("Whiteness:")));
1503                 add_subwindow(new ChannelEditWhiteness(x1, y, channel_picker, channel_picker->get_whiteness()));
1504                 y += pad;
1505                 SWAP_X
1506         }
1508         for(int i = 0; i < channel_picker->get_controls(); i++)
1509         {
1510                 add_subwindow(new BC_Title(x, 
1511                         y + 10, 
1512                         _(channel_picker->get_control(i)->name)));
1513                 add_subwindow(new ChannelEditCommon(x1, 
1514                         y, 
1515                         channel_picker,
1516                         channel_picker->get_control(i)));
1517                 y += pad;
1518                 SWAP_X
1519         }
1522         y += pad;
1523         add_subwindow(new BC_OKButton(this));
1524         return 0;
1529 ChannelEditBright::ChannelEditBright(int x, int y, ChannelPicker *channel_picker, int value)
1530  : BC_IPot(x, 
1531                 y, 
1532                 value, 
1533                 -100, 
1534                 100)
1536         this->channel_picker = channel_picker;
1538 ChannelEditBright::~ChannelEditBright() {}
1539 int ChannelEditBright::handle_event()
1541         return 1;
1543 int ChannelEditBright::button_release_event()
1545         if(BC_Pot::button_release_event())
1546         {
1547                 channel_picker->set_brightness(get_value());
1548                 return 1;
1549         }
1550         return 0;
1553 ChannelEditContrast::ChannelEditContrast(int x, int y, ChannelPicker *channel_picker, int value)
1554  : BC_IPot(x, 
1555                 y, 
1556                 value, 
1557                 -100, 
1558                 100)
1560         this->channel_picker = channel_picker;
1562 ChannelEditContrast::~ChannelEditContrast() {}
1563 int ChannelEditContrast::handle_event()
1565         return 1;
1567 int ChannelEditContrast::button_release_event()
1569         if(BC_Pot::button_release_event())
1570         {
1571                 channel_picker->set_contrast(get_value());
1572                 return 1;
1573         }
1574         return 0;
1578 ChannelEditColor::ChannelEditColor(int x, int y, ChannelPicker *channel_picker, int value)
1579  : BC_IPot(x, 
1580                 y, 
1581                 value, 
1582                 -100, 
1583                 100)
1585         this->channel_picker = channel_picker;
1587 ChannelEditColor::~ChannelEditColor() {}
1588 int ChannelEditColor::handle_event()
1590         return 1;
1592 int ChannelEditColor::button_release_event()
1594         if(BC_Pot::button_release_event())
1595         {
1596                 channel_picker->set_color(get_value());
1597                 return 1;
1598         }
1599         return 0;
1602 ChannelEditHue::ChannelEditHue(int x, int y, ChannelPicker *channel_picker, int value)
1603  : BC_IPot(x, 
1604                 y, 
1605                 value, 
1606                 -100, 
1607                 100)
1609         this->channel_picker = channel_picker;
1611 ChannelEditHue::~ChannelEditHue() {}
1612 int ChannelEditHue::handle_event()
1614         return 1;
1616 int ChannelEditHue::button_release_event()
1618         if(BC_Pot::button_release_event())
1619         {
1620                 channel_picker->set_hue(get_value());
1621                 return 1;
1622         }
1623         return 0;
1626 ChannelEditWhiteness::ChannelEditWhiteness(int x, int y, ChannelPicker *channel_picker, int value)
1627  : BC_IPot(x, 
1628                 y, 
1629                 value, 
1630                 -100, 
1631                 100)
1633         this->channel_picker = channel_picker;
1635 ChannelEditWhiteness::~ChannelEditWhiteness() 
1638 int ChannelEditWhiteness::handle_event()
1640         return 1;
1642 int ChannelEditWhiteness::button_release_event()
1644         if(BC_Pot::button_release_event())
1645         {
1646                 channel_picker->set_whiteness(get_value());
1647                 return 1;
1648         }
1649         return 0;
1654 ChannelEditCommon::ChannelEditCommon(int x, 
1655         int y, 
1656         ChannelPicker *channel_picker,
1657         PictureItem *item)
1658  : BC_IPot(x, 
1659                 y, 
1660                 item->value, 
1661                 item->min, 
1662                 item->max)
1664         this->channel_picker = channel_picker;
1665         this->device_id = item->device_id;
1668 ChannelEditCommon::~ChannelEditCommon() 
1672 int ChannelEditCommon::handle_event()
1674         return 1;
1677 int ChannelEditCommon::button_release_event()
1679         if(BC_Pot::button_release_event())
1680         {
1681                 channel_picker->set_picture(device_id, get_value());
1682                 return 1;
1683         }
1684         return 0;