r863: Merge 2.1:
[cinelerra_cv/ct.git] / cinelerra / channeledit.C
blobd4fa6da5170a4ad4e48b2473133e45bcba495ba5
1 #include "batch.h"
2 #include "bcprogressbox.h"
3 #include "bcsignals.h"
4 #include "channel.h"
5 #include "channeldb.h"
6 #include "channeledit.h"
7 #include "channelpicker.h"
8 #include "chantables.h"
9 #include "clip.h"
10 #include "condition.h"
11 #include "language.h"
12 #include "picture.h"
13 #include "theme.h"
14 #include "videodevice.h"
15 #include <ctype.h>
16 #include <string.h>
17 #include <unistd.h>
20 ChannelEditThread::ChannelEditThread(ChannelPicker *channel_picker,
21         ChannelDB *channeldb)
22  : Thread()
24         this->channel_picker = channel_picker;
25         this->channeldb = channeldb;
26         in_progress = 0;
27         this->window = 0;
28         new_channels = new ChannelDB;
29         completion = new Condition(1, "ChannelEditThread::completion");
30         scan_thread = 0;
32 ChannelEditThread::~ChannelEditThread()
34         channel_picker->get_subwindow()->unlock_window();
35         delete scan_thread;
36         channel_picker->get_subwindow()->lock_window("ChannelEditThread::~ChannelEditThread");
37         delete new_channels;
38         delete completion;
41 void ChannelEditThread::run()
43         int i;
45         if(in_progress) 
46         {
47                 if(window)
48                 {
49                         window->lock_window("ChannelEditThread::run");
50                         window->raise_window(1);
51                         window->unlock_window();
52                 }
53                 return;
54         }
55         in_progress = 1;
56         completion->lock("ChannelEditThread::run");
58 // Copy master channel list to temporary.
59         new_channels->copy_from(channel_picker->channeldb);
60         current_channel = channel_picker->get_current_channel_number();
61 //printf("ChannelEditThread::run 1 %d\n", current_channel);
63 // Run the channel list window using the temporary list.
64         ChannelEditWindow window(this, channel_picker);
65         window.create_objects();
66         this->window = &window;
67         int result = window.run_window();
68         this->window = 0;
70         if(!result)
71         {
72 // Copy new channels to master list
73                 channel_picker->channeldb->clear();
74                 
75                 channel_picker->channeldb->copy_from(new_channels);
76                 channel_picker->update_channel_list();
78         }
80         channel_picker->handle_channel_edit(result);
82         window.edit_thread->close_threads();
83         window.picture_thread->close_threads();
85         completion->unlock();
86         in_progress = 0;
90 int ChannelEditThread::close_threads()
92         if(in_progress && window)
93         {
94                 window->edit_thread->close_threads();
95                 window->picture_thread->close_threads();
96                 window->set_done(1);
97                 completion->lock("ChannelEditThread::close_threads");
98                 completion->unlock();
99         }
102 char *ChannelEditThread::value_to_freqtable(int value)
104         switch(value)
105         {
106                 case NTSC_BCAST:
107                         return _("NTSC_BCAST");
108                         break;
109                 case NTSC_CABLE:
110                         return _("NTSC_CABLE");
111                         break;
112                 case NTSC_HRC:
113                         return _("NTSC_HRC");
114                         break;
115                 case NTSC_BCAST_JP:
116                         return _("NTSC_BCAST_JP");
117                         break;
118                 case NTSC_CABLE_JP:
119                         return _("NTSC_CABLE_JP");
120                         break;
121                 case PAL_AUSTRALIA:
122                         return _("PAL_AUSTRALIA");
123                         break;
124                 case PAL_EUROPE:
125                         return _("PAL_EUROPE");
126                         break;
127                 case PAL_E_EUROPE:
128                         return _("PAL_E_EUROPE");
129                         break;
130                 case PAL_ITALY:
131                         return _("PAL_ITALY");
132                         break;
133                 case PAL_IRELAND:
134                         return _("PAL_IRELAND");
135                         break;
136                 case PAL_NEWZEALAND:
137                         return _("PAL_NEWZEALAND");
138                         break;
139         }
142 char* ChannelEditThread::value_to_norm(int value)
144         switch(value)
145         {
146                 case NTSC:
147                         return _("NTSC");
148                         break;
149                 case PAL:
150                         return _("PAL");
151                         break;
152                 case SECAM:
153                         return _("SECAM");
154                         break;
155         }
158 char* ChannelEditThread::value_to_input(int value)
160         if(channel_picker->get_video_inputs()->total > value)
161                 return channel_picker->get_video_inputs()->values[value]->device_name;
162         else
163                 return _("None");
172 ChannelEditWindow::ChannelEditWindow(ChannelEditThread *thread, 
173         ChannelPicker *channel_picker)
174  : BC_Window(PROGRAM_NAME ": Channels", 
175         channel_picker->parent_window->get_abs_cursor_x(1) - 330, 
176         channel_picker->parent_window->get_abs_cursor_y(1), 
177         350, 
178         400, 
179         350, 
180         400,
181         0,
182         0,
183         1)
185         this->thread = thread;
186         this->channel_picker = channel_picker;
187         scan_confirm_thread = 0;
189 ChannelEditWindow::~ChannelEditWindow()
191         int i;
192         for(i = 0; i < channel_list.total; i++)
193         {
194                 delete channel_list.values[i];
195         }
196         channel_list.remove_all();
197         delete edit_thread;
198         delete picture_thread;
199         delete scan_confirm_thread;
202 int ChannelEditWindow::create_objects()
204         int x = 10, y = 10, i;
205         char string[1024];
207 // Create channel list
208         for(i = 0; i < thread->new_channels->size(); i++)
209         {
210                 channel_list.append(new BC_ListBoxItem(thread->new_channels->get(i)->title));
211         }
213         add_subwindow(list_box = new ChannelEditList(this, x, y));
214         x += 200;
215         if(channel_picker->use_select())
216         {
217                 add_subwindow(new ChannelEditSelect(this, x, y));
218                 y += 30;
219         }
220         add_subwindow(new ChannelEditAdd(this, x, y));
221         y += 30;
222         add_subwindow(new ChannelEdit(this, x, y));
223         y += 30;
224         add_subwindow(new ChannelEditMoveUp(this, x, y));
225         y += 30;
226         add_subwindow(new ChannelEditMoveDown(this, x, y));
227         y += 30;
228         add_subwindow(new ChannelEditSort(this, x, y));
229         y += 30;
231         Channel *channel_usage = channel_picker->get_channel_usage();
232         if(channel_usage && channel_usage->has_scanning)
233         {
234                 add_subwindow(new ChannelEditScan(this, x, y));
235                 y += 30;
236         }
237         add_subwindow(new ChannelEditDel(this, x, y));
238         y += 30;
239         add_subwindow(new ChannelEditPicture(this, x, y));
240         y += 100;
241         x = 10;
242         add_subwindow(new BC_OKButton(this));
243         x += 150;
244         add_subwindow(new BC_CancelButton(this));
247         edit_thread = new ChannelEditEditThread(this, 
248                 channel_picker);
249         picture_thread = new ChannelEditPictureThread(channel_picker, this);
250         show_window();
251         return 0;
254 int ChannelEditWindow::close_event()
256         set_done(0);
259 int ChannelEditWindow::add_channel()
261         Channel *new_channel;
262         Channel *prev_channel = 0;
264 // Create new channel
265         new_channel = new Channel;
267 // Reuse parameters from previous channel
268         if(thread->new_channels->size()) 
269         {
270                 prev_channel = thread->new_channels->get(
271                                 thread->new_channels->size() - 1);
272                 new_channel->copy_settings(prev_channel);
273         }
274         else
275 // Use default channel parameters
276         if(channel_picker->get_master_channel())
277         {
278                 new_channel->copy_settings(channel_picker->get_master_channel());
279         }
281 // Copy device usage.  Need the same thing for playback.
282         if(channel_picker->get_master_channel())
283         {
284                 new_channel->copy_usage(channel_picker->get_master_channel());
285         }
287 // Add to channel table
288         channel_list.append(new BC_ListBoxItem(new_channel->title));
289         thread->new_channels->append(new_channel);
290         update_list();
292 // Start common routing
293         edit_thread->edit_channel(new_channel, 0);
294         return 0;
297 int ChannelEditWindow::update_list()
299 // Create channel list
300         channel_list.remove_all_objects();
301         for(int i = 0; i < thread->new_channels->size(); i++)
302         {
303                 channel_list.append(
304                         new BC_ListBoxItem(
305                                 thread->new_channels->get(i)->title));
306         }
308         list_box->update(&channel_list, 0, 0, 1, list_box->get_yposition());
311 int ChannelEditWindow::update_list(Channel *channel)
313         int i;
314         for(i = 0; i < thread->new_channels->size(); i++)
315                 if(thread->new_channels->get(i) == channel) break;
317         if(i < thread->new_channels->size())
318         {
319                 channel_list.values[i]->set_text(channel->title);
320         }
322         update_list();
326 int ChannelEditWindow::edit_channel()
328         if(list_box->get_selection_number(0, 0) > -1)
329         {
330                 thread->current_channel = list_box->get_selection_number(0, 0);
331                 edit_thread->edit_channel(
332                         thread->new_channels->get(
333                                 list_box->get_selection_number(0, 0)), 
334                         1);
335         }
338 int ChannelEditWindow::edit_picture()
340         picture_thread->edit_picture();
343 void ChannelEditWindow::scan_confirm()
345         channel_picker->load_scan_defaults(&thread->scan_params);
346         if(!scan_confirm_thread) scan_confirm_thread = new ConfirmScanThread(this);
347         unlock_window();
348         scan_confirm_thread->start();
349         lock_window("ChannelEditWindow::scan_confirm");
352 void ChannelEditWindow::scan()
354         thread->new_channels->clear();
355         update_list();
357         if(!thread->scan_thread) thread->scan_thread = new ScanThread(thread);
358         thread->scan_thread->start();
362 void ChannelEditWindow::sort()
364         int done = 0;
365         while(!done)
366         {
367                 done = 1;
368                 for(int i = 0; i < thread->new_channels->size() - 1; i++)
369                 {
370                         Channel *channel1 = thread->new_channels->get(i);
371                         Channel *channel2 = thread->new_channels->get(i + 1);
372                         int is_num = 1;
373                         for(int j = 0; j < strlen(channel1->title); j++)
374                                 if(!isdigit(channel1->title[j])) is_num = 0;
375                         for(int j = 0; j < strlen(channel2->title); j++)
376                                 if(!isdigit(channel2->title[j])) is_num = 0;
377                         if(is_num && atoi(channel1->title) > atoi(channel2->title) ||
378                                 !is_num && strcasecmp(channel2->title, channel1->title) < 0)
379                         {
380                                 thread->new_channels->set(i, channel2);
381                                 thread->new_channels->set(i + 1, channel1);
382                                 done = 0;
383                         }
384                 }
385         }
386         update_list();
390 int ChannelEditWindow::delete_channel(int number)
392         delete thread->new_channels->get(number);
393         channel_list.remove_number(number);
394         thread->new_channels->remove_number(number);
395         update_list();
398 int ChannelEditWindow::delete_channel(Channel *channel)
400         int i;
401         for(i = 0; i < thread->new_channels->size(); i++)
402         {
403                 if(thread->new_channels->get(i) == channel)
404                 {
405                         break;
406                 }
407         }
408         if(i < thread->new_channels->size()) delete_channel(i);
409         return 0;
412 int ChannelEditWindow::move_channel_up()
414         if(list_box->get_selection_number(0, 0) > -1)
415         {
416                 int number2 = list_box->get_selection_number(0, 0);
417                 int number1 = number2 - 1;
418                 Channel *temp;
419                 BC_ListBoxItem *temp_text;
421                 if(number1 < 0) number1 = thread->new_channels->size() - 1;
423                 temp = thread->new_channels->get(number1);
424                 thread->new_channels->set(number1, thread->new_channels->get(number2));
425                 thread->new_channels->set(number2, temp);
427                 temp_text = channel_list.values[number1];
428                 channel_list.values[number1] = channel_list.values[number2];
429                 channel_list.values[number2] = temp_text;
430                 list_box->update(&channel_list, 
431                         0, 
432                         0, 
433                         1, 
434                         list_box->get_xposition(), 
435                         list_box->get_yposition(), 
436                         number1,
437                         1);
438         }
439         return 0;
442 int ChannelEditWindow::move_channel_down()
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 > thread->new_channels->size() - 1) number1 = 0;
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);
456                 temp_text = channel_list.values[number1];
457                 channel_list.values[number1] = channel_list.values[number2];
458                 channel_list.values[number2] = temp_text;
459                 list_box->update(&channel_list, 
460                         0, 
461                         0, 
462                         1, 
463                         list_box->get_xposition(), 
464                         list_box->get_yposition(), 
465                         number1,
466                         1);
467         }
468         return 0;
471 int ChannelEditWindow::change_channel_from_list(int channel_number)
473         Channel *channel;
474         if(channel_number > -1 && channel_number < thread->new_channels->size())
475         {
476                 thread->current_channel = channel_number;
477                 channel_picker->set_channel(thread->new_channels->get(channel_number));
478         }
481 ChannelEditSelect::ChannelEditSelect(ChannelEditWindow *window, int x, int y)
482  : BC_GenericButton(x, y, _("Select"))
485 ChannelEditSelect::~ChannelEditSelect()
488 int ChannelEditSelect::handle_event()
490         window->change_channel_from_list(
491                 window->list_box->get_selection_number(0, 0));
494 ChannelEditAdd::ChannelEditAdd(ChannelEditWindow *window, int x, int y)
495  : BC_GenericButton(x, y, _("Add..."))
497         this->window = window;
499 ChannelEditAdd::~ChannelEditAdd()
502 int ChannelEditAdd::handle_event()
504         window->add_channel();
507 ChannelEditList::ChannelEditList(ChannelEditWindow *window, int x, int y)
508  : BC_ListBox(x, 
509                         y, 
510                         185, 
511                         window->get_h() - BC_OKButton::calculate_h() - y - 10, 
512                         LISTBOX_TEXT, 
513                         &(window->channel_list))
515         this->window = window;
517 ChannelEditList::~ChannelEditList()
520 int ChannelEditList::handle_event()
522         window->edit_channel();
525 ChannelEditMoveUp::ChannelEditMoveUp(ChannelEditWindow *window, int x, int y)
526  : BC_GenericButton(x, y, _("Move up"))
528         this->window = window;
530 ChannelEditMoveUp::~ChannelEditMoveUp()
533 int ChannelEditMoveUp::handle_event()
535         lock_window("ChannelEditMoveUp::handle_event");
536         window->move_channel_up();
537         unlock_window();
540 ChannelEditMoveDown::ChannelEditMoveDown(ChannelEditWindow *window, int x, int y)
541  : BC_GenericButton(x, y, _("Move down"))
543         this->window = window;
545 ChannelEditMoveDown::~ChannelEditMoveDown()
548 int ChannelEditMoveDown::handle_event()
550         lock_window("ChannelEditMoveDown::handle_event");
551         window->move_channel_down();
552         unlock_window();
555 ChannelEditSort::ChannelEditSort(ChannelEditWindow *window, int x, int y)
556  : BC_GenericButton(x, y, _("Sort"))
558         this->window = window;
560 int ChannelEditSort::handle_event()
562         lock_window("ChannelEditSort::handle_event");
563         window->sort();
564         unlock_window();
567 ChannelEditScan::ChannelEditScan(ChannelEditWindow *window, int x, int y)
568  : BC_GenericButton(x, y, _("Scan"))
570         this->window = window;
572 int ChannelEditScan::handle_event()
574         window->scan_confirm();
577 ChannelEditDel::ChannelEditDel(ChannelEditWindow *window, int x, int y)
578  : BC_GenericButton(x, y, _("Delete"))
580         this->window = window;
582 ChannelEditDel::~ChannelEditDel()
585 int ChannelEditDel::handle_event()
587         if(window->list_box->get_selection_number(0, 0) > -1) window->delete_channel(window->list_box->get_selection_number(0, 0));
590 ChannelEdit::ChannelEdit(ChannelEditWindow *window, int x, int y)
591  : BC_GenericButton(x, y, _("Edit..."))
593         this->window = window;
595 ChannelEdit::~ChannelEdit()
598 int ChannelEdit::handle_event()
600         window->edit_channel();
603 ChannelEditPicture::ChannelEditPicture(ChannelEditWindow *window, int x, int y)
604  : BC_GenericButton(x, y, _("Picture..."))
606         this->window = window;
608 ChannelEditPicture::~ChannelEditPicture()
611 int ChannelEditPicture::handle_event()
613         window->edit_picture();
627 // ========================= confirm overwrite by channel scannin
630 ConfirmScan::ConfirmScan(ChannelEditWindow *gui, int x, int y)
631  : BC_Window(PROGRAM_NAME ": Scan confirm",
632         x,
633         y,
634         350,
635         BC_OKButton::calculate_h() + 130,
636         0,
637         0,
638         0,
639         0,
640         1)
642         this->gui = gui;
645 void ConfirmScan::create_objects()
647         int x = 10, y = 10;
648         int y2 = 0, x2 = 0;
649         BC_Title *title;
650         add_subwindow(title = new BC_Title(x, y, _("Set parameters for channel scanning.")));
651         y += title->get_h() + 10;
652         y2 = y;
654         add_subwindow(title = new BC_Title(x, y, _("Frequency table:")));
655         x2 = title->get_w();
656         y += BC_PopupMenu::calculate_h();
657         add_subwindow(title = new BC_Title(x, y, _("Norm:")));
658         x2 = MAX(x2, title->get_w());
659         y += BC_PopupMenu::calculate_h();
660         add_subwindow(title = new BC_Title(x, y, _("Input:")));
661         x2 = MAX(x2, title->get_w());
662         y += BC_PopupMenu::calculate_h();
663         x2 += x + 5;
665         y = y2;
666         x = x2;
667         ChannelEditEditFreqtable *table;
668         add_subwindow(table = new ChannelEditEditFreqtable(x, 
669                 y, 
670                 0, 
671                 gui->thread));
672         table->add_items();
673         y += table->get_h() + 10;
675         ChannelEditEditNorm *norm;
676         add_subwindow(norm = new ChannelEditEditNorm(x, 
677                 y, 
678                 0,
679                 gui->thread));
680         norm->add_items();
681         y += norm->get_h() + 10;
683         ChannelEditEditInput *input;
684         add_subwindow(input = new ChannelEditEditInput(x, 
685                 y, 
686                 0, 
687                 gui->thread));
688         input->add_items();
691         add_subwindow(new BC_OKButton(this));
692         add_subwindow(new BC_CancelButton(this));
693         show_window();
702 ConfirmScanThread::ConfirmScanThread(ChannelEditWindow *gui)
703  : BC_DialogThread()
705         this->gui = gui;
708 void ConfirmScanThread::handle_done_event(int result)
710         gui->channel_picker->save_scan_defaults(&gui->thread->scan_params);
711         if(!result)
712         {
713                 get_gui()->hide_window();
714                 gui->lock_window("ConfirmScanThread::handle_done_event");
715                 gui->scan();
716                 gui->unlock_window();
717         }
720 BC_Window* ConfirmScanThread::new_gui()
722         int x = gui->get_abs_cursor_x(1);
723         int y = gui->get_abs_cursor_y(1);
724         ConfirmScan *result = new ConfirmScan(gui, x, y);
725         result->create_objects();
726         return result;
734 ScanThread::ScanThread(ChannelEditThread *edit)
735  : Thread(1, 0, 0)
737         this->edit = edit;
738         interrupt = 0;
739         progress = 0;
742 ScanThread::~ScanThread()
744         interrupt = 1;
745         Thread::join();
747         delete progress;
751 void ScanThread::start()
753 // Cancel previous job
754         interrupt = 1;
755         Thread::join();
756         delete progress;
757         interrupt = 0;
760         progress = new BC_ProgressBox(
761                 edit->channel_picker->parent_window->get_abs_cursor_x(1),
762                 edit->channel_picker->parent_window->get_abs_cursor_y(1),
763                 "Scanning", 
764                 chanlists[edit->scan_params.freqtable].count);
765         Thread::start();
768 void ScanThread::run()
770         for(int i = 0; 
771                 i < chanlists[edit->scan_params.freqtable].count &&
772                         !interrupt && 
773                         !progress->is_cancelled();
774                 i++)
775         {
776                 edit->scan_params.entry = i;
777                 char string[BCTEXTLEN];
778                 sprintf(edit->scan_params.title, 
779                         "%s", 
780                         chanlists[edit->scan_params.freqtable].list[i].name);
781                 sprintf(string, 
782                         "Scanning %s", 
783                         edit->scan_params.title);
784                 progress->update_title(string, 1);
785                 progress->update(i, 1);
786                 edit->channel_picker->set_channel(&edit->scan_params);
789                 sleep(2);
791             int got_signal = edit->channel_picker->has_signal();
792                 if(got_signal)
793                 {
794                         Channel *new_channel = new Channel;
795                         new_channel->copy_usage(&edit->scan_params);
796                         new_channel->copy_settings(&edit->scan_params);
797                         edit->window->lock_window("ScanThread::run");
798                         edit->new_channels->append(new_channel);
799                         edit->window->update_list();
800                         edit->window->unlock_window();
801                 }
802         }
803         delete progress;
804         progress = 0;
813 // ================================= Edit a single channel
817 ChannelEditEditThread::ChannelEditEditThread(ChannelEditWindow *window, 
818         ChannelPicker *channel_picker)
819  : Thread()
821         this->window = window;
822         this->channel_picker = channel_picker;
823         in_progress = 0;
824         edit_window = 0;
825         editing = 0;
826         completion = new Condition(1, "ChannelEditEditThread::completion");
829 ChannelEditEditThread::~ChannelEditEditThread()
831         delete completion;
834 int ChannelEditEditThread::close_threads()
836         if(edit_window)
837         {
838                 edit_window->set_done(1);
839                 completion->lock("ChannelEditEditThread::close_threads");
840                 completion->unlock();
841         }
844 int ChannelEditEditThread::edit_channel(Channel *channel, int editing)
846         if(in_progress) 
847         {
848                 edit_window->lock_window("ChannelEditEditThread::edit_channel");
849                 edit_window->raise_window(1);
850                 edit_window->unlock_window();
851                 return 1;
852         }
853         in_progress = 1;
855 // Copy the channel to edit into a temporary
856         completion->lock("ChannelEditEditThread::edit_channel");
857         this->editing = editing;
858         this->output_channel = channel;
859         new_channel.copy_settings(output_channel);
860         new_channel.copy_usage(output_channel);
862         if(editing && new_channel.title[0])
863                 user_title = 1;
864         else
865                 user_title = 0;
866         set_synchronous(0);
867         Thread::start();
871 void ChannelEditEditThread::set_device()
873         channel_picker->set_channel(&new_channel);
876 int ChannelEditEditThread::change_source(char *source_name)
878         int i, result;
879         for(i = 0; i < chanlists[new_channel.freqtable].count; i++)
880         {
881                 if(!strcasecmp(chanlists[new_channel.freqtable].list[i].name, source_name))
882                 {
883                         new_channel.entry = i;
884                         i = chanlists[new_channel.freqtable].count;
885                         set_device();
886                 }
887         }
888         if(!user_title)
889         {
890                 strcpy(new_channel.title, source_name);
891                 if(edit_window->title_text)
892                 {
893                         edit_window->title_text->update(source_name);
894                 }
895         }
898 int ChannelEditEditThread::source_up()
900         new_channel.entry++;
901         if(new_channel.entry > chanlists[new_channel.freqtable].count - 1) new_channel.entry = 0;
902         source_text->update(chanlists[new_channel.freqtable].list[new_channel.entry].name);
903         set_device();
906 int ChannelEditEditThread::source_down()
908         new_channel.entry--;
909         if(new_channel.entry < 0) new_channel.entry = chanlists[new_channel.freqtable].count - 1;
910         source_text->update(chanlists[new_channel.freqtable].list[new_channel.entry].name);
911         set_device();
914 int ChannelEditEditThread::set_input(int value)
916         new_channel.input = value;
917         set_device();
920 int ChannelEditEditThread::set_norm(int value)
922         new_channel.norm = value;
923         set_device();
926 int ChannelEditEditThread::set_freqtable(int value)
928         new_channel.freqtable = value;
929         if(new_channel.entry > chanlists[new_channel.freqtable].count - 1) new_channel.entry = 0;
930         source_text->update(chanlists[new_channel.freqtable].list[new_channel.entry].name);
931         set_device();
934 void ChannelEditEditThread::run()
936 SET_TRACE
937         ChannelEditEditWindow edit_window(this, window, channel_picker);
938 SET_TRACE
939         edit_window.create_objects(&new_channel);
940 SET_TRACE
941         this->edit_window = &edit_window;
942 SET_TRACE
943         int result = edit_window.run_window();
944         this->edit_window = 0;
946 // Done editing channel.  Keep channel.
947         if(!result)
948         {
949                 output_channel->copy_settings(&new_channel);
950                 window->lock_window();
951                 window->update_list(output_channel);
952                 window->unlock_window();
953         }
954         else
955         {
956 // Discard channel.
957                 if(!editing)
958                 {
959                         window->lock_window();
960                         window->delete_channel(output_channel);
961                         window->unlock_window();
962                 }
963         }
964         editing = 0;
965         completion->unlock();
966         in_progress = 0;
969 ChannelEditEditWindow::ChannelEditEditWindow(ChannelEditEditThread *thread, 
970         ChannelEditWindow *window,
971         ChannelPicker *channel_picker)
972  : BC_Window(PROGRAM_NAME ": Edit Channel", 
973         channel_picker->parent_window->get_abs_cursor_x(1), 
974         channel_picker->parent_window->get_abs_cursor_y(1), 
975         390, 
976         300, 
977         390, 
978         300,
979         0,
980         0,
981         1)
983         this->channel_picker = channel_picker;
984         this->window = window;
985         this->thread = thread;
987 ChannelEditEditWindow::~ChannelEditEditWindow()
990 int ChannelEditEditWindow::create_objects(Channel *channel)
992         this->new_channel = channel;
993         Channel *channel_usage = channel_picker->get_channel_usage();
994         title_text = 0;
996 SET_TRACE
997         int x = 10, y = 10;
998 //      if(!channel_usage ||
999 //              (!channel_usage->use_frequency && 
1000 //              !channel_usage->use_fine && 
1001 //              !channel_usage->use_norm && 
1002 //              !channel_usage->use_input))
1003 //      {
1004 //              add_subwindow(new BC_Title(x, y, "Device has no input selection."));
1005 //              y += 30;
1006 //      }
1007 //      else
1008 //      {
1009                 add_subwindow(new BC_Title(x, y, _("Title:")));
1010                 add_subwindow(title_text = new ChannelEditEditTitle(x, y + 20, thread));
1011                 y += 50;
1012 //      }
1014         if(channel_usage && channel_usage->use_frequency)
1015         {
1016 SET_TRACE
1017                 add_subwindow(new BC_Title(x, y, _("Channel:")));
1018                 y += 20;
1019                 add_subwindow(thread->source_text = new ChannelEditEditSource(x, y, thread));
1020                 add_subwindow(new ChannelEditEditSourceTumbler(x + 160, y, thread));
1021                 y += 40;
1023                 add_subwindow(new BC_Title(x, y, _("Frequency table:")));
1024                 ChannelEditEditFreqtable *table;
1025                 add_subwindow(table = new ChannelEditEditFreqtable(x + 130, 
1026                         y, 
1027                         thread, 
1028                         window->thread));
1029                 table->add_items();
1030                 y += 30;
1031         }
1033 SET_TRACE
1034         if(channel_usage && channel_usage->use_fine)
1035         {
1036                 add_subwindow(new BC_Title(x, y, _("Fine:")));
1037                 add_subwindow(new ChannelEditEditFine(x + 130, y, thread));
1038                 y += 30;
1039         }
1041 SET_TRACE
1042         if(channel_usage && channel_usage->use_norm)
1043         {
1044                 add_subwindow(new BC_Title(x, y, _("Norm:")));
1045                 ChannelEditEditNorm *norm;
1046                 add_subwindow(norm = new ChannelEditEditNorm(x + 130, 
1047                         y, 
1048                         thread,
1049                         window->thread));
1050                 norm->add_items();
1051                 y += 30;
1052         }
1053 SET_TRACE
1055         if(channel_usage && channel_usage->use_input ||
1056                 !channel_usage)
1057         {
1058                 add_subwindow(new BC_Title(x, y, _("Input:")));
1059                 ChannelEditEditInput *input;
1060                 add_subwindow(input = new ChannelEditEditInput(x + 130, 
1061                         y, 
1062                         thread, 
1063                         window->thread));
1064                 input->add_items();
1065                 y += 30;
1066         }
1068 SET_TRACE
1069         add_subwindow(new BC_OKButton(this));
1070         x += 200;
1071         add_subwindow(new BC_CancelButton(this));
1072         show_window();
1073 SET_TRACE
1074         return 0;
1077 ChannelEditEditTitle::ChannelEditEditTitle(int x, 
1078         int y, 
1079         ChannelEditEditThread *thread)
1080  : BC_TextBox(x, y, 150, 1, thread->new_channel.title)
1082         this->thread = thread;
1084 ChannelEditEditTitle::~ChannelEditEditTitle()
1087 int ChannelEditEditTitle::handle_event()
1089         if(strlen(get_text()) < 1024)
1090         {
1091                 strcpy(thread->new_channel.title, get_text());
1092         }
1093         if(get_text()[0]) 
1094                 thread->user_title = 1;
1095         else
1096                 thread->user_title = 0;
1097         return 1;
1101 ChannelEditEditSource::ChannelEditEditSource(int x, int y, ChannelEditEditThread *thread)
1102  : BC_TextBox(x, y, 150, 1, chanlists[thread->new_channel.freqtable].list[thread->new_channel.entry].name)
1104         this->thread = thread;
1107 ChannelEditEditSource::~ChannelEditEditSource()
1110 int ChannelEditEditSource::handle_event()
1112         thread->change_source(get_text());
1116 ChannelEditEditSourceTumbler::ChannelEditEditSourceTumbler(int x, int y, ChannelEditEditThread *thread)
1117  : BC_Tumbler(x, y)
1119         this->thread = thread;
1121 ChannelEditEditSourceTumbler::~ChannelEditEditSourceTumbler()
1124 int ChannelEditEditSourceTumbler::handle_up_event()
1126         thread->source_up();
1128 int ChannelEditEditSourceTumbler::handle_down_event()
1130         thread->source_down();
1133 ChannelEditEditInput::ChannelEditEditInput(int x, 
1134         int y, 
1135         ChannelEditEditThread *thread, 
1136         ChannelEditThread *edit)
1137  : BC_PopupMenu(x, 
1138         y, 
1139         150, 
1140         edit->value_to_input(thread ? thread->new_channel.input : edit->scan_params.input))
1142         this->thread = thread;
1143         this->edit = edit;
1145 ChannelEditEditInput::~ChannelEditEditInput()
1148 int ChannelEditEditInput::add_items()
1150         ArrayList<Channel*> *inputs;
1151         inputs = edit->channel_picker->get_video_inputs();
1153         if(inputs)
1154                 for(int i = 0; i < inputs->total; i++)
1155                 {
1156                         add_item(new ChannelEditEditInputItem(thread, 
1157                                 edit,
1158                                 inputs->values[i]->device_name, 
1159                                 i));
1160                 }
1162 int ChannelEditEditInput::handle_event()
1164         return 0;
1167 ChannelEditEditInputItem::ChannelEditEditInputItem(ChannelEditEditThread *thread, 
1168         ChannelEditThread *edit,
1169         char *text, 
1170         int value)
1171  : BC_MenuItem(text)
1173         this->thread = thread;
1174         this->edit = edit;
1175         this->value = value;
1177 ChannelEditEditInputItem::~ChannelEditEditInputItem()
1180 int ChannelEditEditInputItem::handle_event()
1182         get_popup_menu()->set_text(get_text());
1183         if(thread && !thread->user_title)
1184         {
1185                 strcpy(thread->new_channel.title, get_text());
1186                 if(thread->edit_window->title_text)
1187                 {
1188                         thread->edit_window->title_text->update(get_text());
1189                 }
1190         }
1191         if(thread) 
1192                 thread->set_input(value);
1193         else
1194                 edit->scan_params.input = value;
1197 ChannelEditEditNorm::ChannelEditEditNorm(int x, 
1198         int y, 
1199         ChannelEditEditThread *thread,
1200         ChannelEditThread *edit)
1201  : BC_PopupMenu(x, 
1202         y, 
1203         100, 
1204         edit->value_to_norm(thread ? thread->new_channel.norm : edit->scan_params.norm))
1206         this->thread = thread;
1207         this->edit = edit;
1209 ChannelEditEditNorm::~ChannelEditEditNorm()
1212 int ChannelEditEditNorm::add_items()
1214         add_item(new ChannelEditEditNormItem(thread, 
1215                 edit, 
1216                 edit->value_to_norm(NTSC), NTSC));
1217         add_item(new ChannelEditEditNormItem(thread, 
1218                 edit, 
1219                 edit->value_to_norm(PAL), PAL));
1220         add_item(new ChannelEditEditNormItem(thread, 
1221                 edit, 
1222                 edit->value_to_norm(SECAM), SECAM));
1223         return 0;
1227 ChannelEditEditNormItem::ChannelEditEditNormItem(ChannelEditEditThread *thread, 
1228         ChannelEditThread *edit,
1229         char *text, 
1230         int value)
1231  : BC_MenuItem(text)
1233         this->value = value;
1234         this->edit = edit;
1235         this->thread = thread;
1237 ChannelEditEditNormItem::~ChannelEditEditNormItem()
1240 int ChannelEditEditNormItem::handle_event()
1242         get_popup_menu()->set_text(get_text());
1243         if(thread)
1244                 thread->set_norm(value);
1245         else
1246                 edit->scan_params.norm = value;
1250 ChannelEditEditFreqtable::ChannelEditEditFreqtable(int x, 
1251         int y, 
1252         ChannelEditEditThread *thread,
1253         ChannelEditThread *edit)
1254  : BC_PopupMenu(x, 
1255         y, 
1256         150, 
1257         edit->value_to_freqtable(thread ? thread->new_channel.freqtable : edit->scan_params.freqtable))
1259         this->thread = thread;
1260         this->edit = edit;
1262 ChannelEditEditFreqtable::~ChannelEditEditFreqtable()
1265 int ChannelEditEditFreqtable::add_items()
1267         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(NTSC_BCAST), NTSC_BCAST));
1268         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(NTSC_CABLE), NTSC_CABLE));
1269         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(NTSC_HRC), NTSC_HRC));
1270         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(NTSC_BCAST_JP), NTSC_BCAST_JP));
1271         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(NTSC_CABLE_JP), NTSC_CABLE_JP));
1272         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(PAL_AUSTRALIA), PAL_AUSTRALIA));
1273         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(PAL_EUROPE), PAL_EUROPE));
1274         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(PAL_E_EUROPE), PAL_E_EUROPE));
1275         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(PAL_ITALY), PAL_ITALY));
1276         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(PAL_IRELAND), PAL_IRELAND));
1277         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(PAL_NEWZEALAND), PAL_NEWZEALAND));
1278         return 0;
1281 ChannelEditEditFreqItem::ChannelEditEditFreqItem(ChannelEditEditThread *thread, 
1282         ChannelEditThread *edit,
1283         char *text, int value)
1284  : BC_MenuItem(text)
1286         this->value = value;
1287         this->edit = edit;
1288         this->thread = thread;
1290 ChannelEditEditFreqItem::~ChannelEditEditFreqItem()
1293 int ChannelEditEditFreqItem::handle_event()
1295         get_popup_menu()->set_text(get_text());
1296         if(thread)
1297                 thread->set_freqtable(value);
1298         else
1299                 edit->scan_params.freqtable = value;
1304 ChannelEditEditFine::ChannelEditEditFine(int x, 
1305         int y, 
1306         ChannelEditEditThread *thread)
1307  : BC_ISlider(x, 
1308                 y, 
1309                 0, 
1310                 240, 
1311                 240, 
1312                 -100, 
1313                 100, 
1314                 thread->new_channel.fine_tune)
1316         this->thread = thread;
1318 ChannelEditEditFine::~ChannelEditEditFine()
1321 int ChannelEditEditFine::handle_event()
1323         return 1;
1325 int ChannelEditEditFine::button_release_event()
1327         if(BC_Slider::button_release_event())
1328         {
1329                 thread->new_channel.fine_tune = get_value();
1330                 thread->set_device();
1331                 return 1;
1332         }
1333         return 0;
1337 // ========================== picture quality
1339 ChannelEditPictureThread::ChannelEditPictureThread(ChannelPicker *channel_picker, ChannelEditWindow *window)
1340  : Thread()
1342         this->channel_picker = channel_picker;
1343         this->window = window;
1344         in_progress = 0;
1345         edit_window = 0;
1346         completion = new Condition(1, "ChannelEditPictureThread::completion");
1348 ChannelEditPictureThread::~ChannelEditPictureThread()
1350         delete completion;
1353 int ChannelEditPictureThread::edit_picture()
1355         if(in_progress) 
1356         {
1357                 edit_window->lock_window("ChannelEditPictureThread::edit_picture");
1358                 edit_window->raise_window(1);
1359                 edit_window->unlock_window();
1360                 return 1;
1361         }
1362         in_progress = 1;
1363         completion->lock("ChannelEditPictureThread::edit_picture");
1364         set_synchronous(0);
1365         Thread::start();
1368 void ChannelEditPictureThread::run()
1370 SET_TRACE
1371         ChannelEditPictureWindow edit_window(this, 
1372                 channel_picker);
1373 SET_TRACE
1374         edit_window.create_objects();
1375 SET_TRACE
1376         this->edit_window = &edit_window;
1377 SET_TRACE
1378         int result = edit_window.run_window();
1379 SET_TRACE
1380         this->edit_window = 0;
1381 SET_TRACE
1382         completion->unlock();
1383 SET_TRACE
1384         in_progress = 0;
1387 int ChannelEditPictureThread::close_threads()
1389         if(edit_window)
1390         {
1391                 edit_window->set_done(1);
1392                 completion->lock("ChannelEditPictureThread::close_threads");
1393                 completion->unlock();
1394         }
1398 ChannelEditPictureWindow::ChannelEditPictureWindow(ChannelEditPictureThread *thread, 
1399         ChannelPicker *channel_picker)
1400  : BC_Window(PROGRAM_NAME ": Picture", 
1401         channel_picker->parent_window->get_abs_cursor_x(1) - 200, 
1402         channel_picker->parent_window->get_abs_cursor_y(1) - 220, 
1403         250, 
1404         calculate_h(channel_picker), 
1405         250, 
1406         calculate_h(channel_picker))
1408         this->thread = thread;
1409         this->channel_picker = channel_picker;
1411 ChannelEditPictureWindow::~ChannelEditPictureWindow()
1415 int ChannelEditPictureWindow::calculate_h(ChannelPicker *channel_picker)
1417         PictureConfig *picture_usage = channel_picker->get_picture_usage();
1418         int pad = BC_Pot::calculate_h();
1419         int result = 20 + 
1420                 channel_picker->parent_window->get_text_height(MEDIUMFONT) + 5 + 
1421                 BC_OKButton::calculate_h();
1423         if(picture_usage)
1424         {
1425                 if(picture_usage->use_brightness)
1426                         result += pad;
1427                 if(picture_usage->use_contrast)
1428                         result += pad;
1429                 if(picture_usage->use_color)
1430                         result += pad;
1431                 if(picture_usage->use_hue)
1432                         result += pad;
1433                 if(picture_usage->use_whiteness)
1434                         result += pad;
1435         }
1436         result += channel_picker->get_controls() * pad;
1437         return result;
1440 int ChannelEditPictureWindow::create_objects()
1442         int x = 10, y = 10;
1443         int x1 = 110, x2 = 145;
1444         int pad = BC_Pot::calculate_h();
1445 #define SWAP_X x1 ^= x2; x2 ^= x1; x1 ^= x2;
1447 SET_TRACE
1448         PictureConfig *picture_usage = channel_picker->get_picture_usage();
1449 SET_TRACE
1451         if(!picture_usage ||
1452                 (!picture_usage->use_brightness &&
1453                 !picture_usage->use_contrast &&
1454                 !picture_usage->use_color &&
1455                 !picture_usage->use_hue &&
1456                 !picture_usage->use_whiteness &&
1457                 !channel_picker->get_controls()))
1458         {
1459                 add_subwindow(new BC_Title(x, y, "Device has no picture controls."));
1460                 y += 50;
1461         }
1463 SET_TRACE
1464         if(picture_usage && picture_usage->use_brightness)
1465         {
1466                 add_subwindow(new BC_Title(x, y + 10, _("Brightness:")));
1467                 add_subwindow(new ChannelEditBright(x1, y, channel_picker, channel_picker->get_brightness()));
1468                 y += pad;
1469                 SWAP_X
1470                 
1471         }
1473 SET_TRACE
1474         if(picture_usage && picture_usage->use_contrast)
1475         {
1476                 add_subwindow(new BC_Title(x, y + 10, _("Contrast:")));
1477                 add_subwindow(new ChannelEditContrast(x1, y, channel_picker, channel_picker->get_contrast()));
1478                 y += pad;
1479                 SWAP_X
1480         }
1482 SET_TRACE
1483         if(picture_usage && picture_usage->use_color)
1484         {
1485                 add_subwindow(new BC_Title(x, y + 10, _("Color:")));
1486                 add_subwindow(new ChannelEditColor(x1, y, channel_picker, channel_picker->get_color()));
1487                 y += pad;
1488                 SWAP_X
1489         }
1491 SET_TRACE
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 SET_TRACE
1501         if(picture_usage && picture_usage->use_whiteness)
1502         {
1503                 add_subwindow(new BC_Title(x, y + 10, _("Whiteness:")));
1504                 add_subwindow(new ChannelEditWhiteness(x1, y, channel_picker, channel_picker->get_whiteness()));
1505                 y += pad;
1506                 SWAP_X
1507         }
1509 SET_TRACE
1510         for(int i = 0; i < channel_picker->get_controls(); i++)
1511         {
1512                 add_subwindow(new BC_Title(x, 
1513                         y + 10, 
1514                         _(channel_picker->get_control(i)->name)));
1515                 add_subwindow(new ChannelEditCommon(x1, 
1516                         y, 
1517                         channel_picker,
1518                         channel_picker->get_control(i)));
1519                 y += pad;
1520                 SWAP_X
1521         }
1523 SET_TRACE
1525         y += pad;
1526         add_subwindow(new BC_OKButton(this));
1527         return 0;
1532 ChannelEditBright::ChannelEditBright(int x, int y, ChannelPicker *channel_picker, int value)
1533  : BC_IPot(x, 
1534                 y, 
1535                 value, 
1536                 -100, 
1537                 100)
1539         this->channel_picker = channel_picker;
1541 ChannelEditBright::~ChannelEditBright() {}
1542 int ChannelEditBright::handle_event()
1544         return 1;
1546 int ChannelEditBright::button_release_event()
1548         if(BC_Pot::button_release_event())
1549         {
1550                 channel_picker->set_brightness(get_value());
1551                 return 1;
1552         }
1553         return 0;
1556 ChannelEditContrast::ChannelEditContrast(int x, int y, ChannelPicker *channel_picker, int value)
1557  : BC_IPot(x, 
1558                 y, 
1559                 value, 
1560                 -100, 
1561                 100)
1563         this->channel_picker = channel_picker;
1565 ChannelEditContrast::~ChannelEditContrast() {}
1566 int ChannelEditContrast::handle_event()
1568         return 1;
1570 int ChannelEditContrast::button_release_event()
1572         if(BC_Pot::button_release_event())
1573         {
1574                 channel_picker->set_contrast(get_value());
1575                 return 1;
1576         }
1577         return 0;
1581 ChannelEditColor::ChannelEditColor(int x, int y, ChannelPicker *channel_picker, int value)
1582  : BC_IPot(x, 
1583                 y, 
1584                 value, 
1585                 -100, 
1586                 100)
1588         this->channel_picker = channel_picker;
1590 ChannelEditColor::~ChannelEditColor() {}
1591 int ChannelEditColor::handle_event()
1593         return 1;
1595 int ChannelEditColor::button_release_event()
1597         if(BC_Pot::button_release_event())
1598         {
1599                 channel_picker->set_color(get_value());
1600                 return 1;
1601         }
1602         return 0;
1605 ChannelEditHue::ChannelEditHue(int x, int y, ChannelPicker *channel_picker, int value)
1606  : BC_IPot(x, 
1607                 y, 
1608                 value, 
1609                 -100, 
1610                 100)
1612         this->channel_picker = channel_picker;
1614 ChannelEditHue::~ChannelEditHue() {}
1615 int ChannelEditHue::handle_event()
1617         return 1;
1619 int ChannelEditHue::button_release_event()
1621         if(BC_Pot::button_release_event())
1622         {
1623                 channel_picker->set_hue(get_value());
1624                 return 1;
1625         }
1626         return 0;
1629 ChannelEditWhiteness::ChannelEditWhiteness(int x, int y, ChannelPicker *channel_picker, int value)
1630  : BC_IPot(x, 
1631                 y, 
1632                 value, 
1633                 -100, 
1634                 100)
1636         this->channel_picker = channel_picker;
1638 ChannelEditWhiteness::~ChannelEditWhiteness() 
1641 int ChannelEditWhiteness::handle_event()
1643         return 1;
1645 int ChannelEditWhiteness::button_release_event()
1647         if(BC_Pot::button_release_event())
1648         {
1649                 channel_picker->set_whiteness(get_value());
1650                 return 1;
1651         }
1652         return 0;
1657 ChannelEditCommon::ChannelEditCommon(int x, 
1658         int y, 
1659         ChannelPicker *channel_picker,
1660         PictureItem *item)
1661  : BC_IPot(x, 
1662                 y, 
1663                 item->value, 
1664                 item->min, 
1665                 item->max)
1667         this->channel_picker = channel_picker;
1668         this->device_id = item->device_id;
1671 ChannelEditCommon::~ChannelEditCommon() 
1675 int ChannelEditCommon::handle_event()
1677         return 1;
1680 int ChannelEditCommon::button_release_event()
1682         if(BC_Pot::button_release_event())
1683         {
1684                 channel_picker->set_picture(device_id, get_value());
1685                 return 1;
1686         }
1687         return 0;