r663: This commit was generated by cvs2svn to compensate for changes in r662,
[cinelerra_cv.git] / cinelerra / channeledit.C
blob8b9697b6538f311acb64d7f12b7520fc3c1f4593
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         channel_picker->get_subwindow()->unlock_window();
42         delete scan_thread;
43         channel_picker->get_subwindow()->lock_window("ChannelEditThread::~ChannelEditThread");
44         delete new_channels;
45         delete completion;
48 void ChannelEditThread::run()
50         int i;
52         if(in_progress) 
53         {
54                 if(window)
55                 {
56                         window->lock_window("ChannelEditThread::run");
57                         window->raise_window(1);
58                         window->unlock_window();
59                 }
60                 return;
61         }
62         in_progress = 1;
63         completion->lock("ChannelEditThread::run");
65 // Copy master channel list to temporary.
66         new_channels->copy_from(channel_picker->channeldb);
67         current_channel = channel_picker->get_current_channel_number();
68 //printf("ChannelEditThread::run 1 %d\n", current_channel);
70 // Run the channel list window using the temporary list.
71         ChannelEditWindow window(mwindow, this, channel_picker);
72         window.create_objects();
73         this->window = &window;
74         int result = window.run_window();
75         this->window = 0;
77         if(!result)
78         {
79 // Copy new channels to master list
80                 channel_picker->channeldb->clear();
81                 
82                 channel_picker->channeldb->copy_from(new_channels);
83                 channel_picker->update_channel_list();
85                 if(record)
86                 {
87                         record->record_gui->lock_window("ChannelEditThread::run");
88                         record->record_gui->update_batch_sources();
90                         record->set_channel(current_channel);
91                         record->record_gui->unlock_window();
92                         record->save_defaults();
93                         record->channeldb->save(record->get_channeldb_prefix());
94                 }
95                 mwindow->save_defaults();
96         }
97         else
98         {
99 // Rejected.
100                 if(record)
101                 {
102                         record->set_channel(record->get_editing_batch()->channel);
103                 }
104         }
106         window.edit_thread->close_threads();
107         window.picture_thread->close_threads();
109         completion->unlock();
110         in_progress = 0;
114 int ChannelEditThread::close_threads()
116         if(in_progress && window)
117         {
118                 window->edit_thread->close_threads();
119                 window->picture_thread->close_threads();
120                 window->set_done(1);
121                 completion->lock("ChannelEditThread::close_threads");
122                 completion->unlock();
123         }
126 char *ChannelEditThread::value_to_freqtable(int value)
128         switch(value)
129         {
130                 case NTSC_BCAST:
131                         return _("NTSC_BCAST");
132                         break;
133                 case NTSC_CABLE:
134                         return _("NTSC_CABLE");
135                         break;
136                 case NTSC_HRC:
137                         return _("NTSC_HRC");
138                         break;
139                 case NTSC_BCAST_JP:
140                         return _("NTSC_BCAST_JP");
141                         break;
142                 case NTSC_CABLE_JP:
143                         return _("NTSC_CABLE_JP");
144                         break;
145                 case PAL_AUSTRALIA:
146                         return _("PAL_AUSTRALIA");
147                         break;
148                 case PAL_EUROPE:
149                         return _("PAL_EUROPE");
150                         break;
151                 case PAL_E_EUROPE:
152                         return _("PAL_E_EUROPE");
153                         break;
154                 case PAL_ITALY:
155                         return _("PAL_ITALY");
156                         break;
157                 case PAL_IRELAND:
158                         return _("PAL_IRELAND");
159                         break;
160                 case PAL_NEWZEALAND:
161                         return _("PAL_NEWZEALAND");
162                         break;
163         }
166 char* ChannelEditThread::value_to_norm(int value)
168         switch(value)
169         {
170                 case NTSC:
171                         return _("NTSC");
172                         break;
173                 case PAL:
174                         return _("PAL");
175                         break;
176                 case SECAM:
177                         return _("SECAM");
178                         break;
179         }
182 char* ChannelEditThread::value_to_input(int value)
184         if(channel_picker->get_video_inputs()->total > value)
185                 return channel_picker->get_video_inputs()->values[value]->device_name;
186         else
187                 return _("None");
196 ChannelEditWindow::ChannelEditWindow(MWindow *mwindow, 
197         ChannelEditThread *thread, 
198         ChannelPicker *channel_picker)
199  : BC_Window(PROGRAM_NAME ": Channels", 
200         mwindow->gui->get_abs_cursor_x(1) - 330, 
201         mwindow->gui->get_abs_cursor_y(1), 
202         350, 
203         400, 
204         350, 
205         400,
206         0,
207         0,
208         1)
210         this->thread = thread;
211         this->channel_picker = channel_picker;
212         this->mwindow = mwindow;
213         scan_confirm_thread = 0;
215 ChannelEditWindow::~ChannelEditWindow()
217         int i;
218         for(i = 0; i < channel_list.total; i++)
219         {
220                 delete channel_list.values[i];
221         }
222         channel_list.remove_all();
223         delete edit_thread;
224         delete picture_thread;
225         delete scan_confirm_thread;
228 int ChannelEditWindow::create_objects()
230         int x = 10, y = 10, i;
231         char string[1024];
233 // Create channel list
234         for(i = 0; i < thread->new_channels->size(); i++)
235         {
236                 channel_list.append(new BC_ListBoxItem(thread->new_channels->get(i)->title));
237         }
239         add_subwindow(list_box = new ChannelEditList(mwindow, this, x, y));
240         x += 200;
241         if(thread->record)
242         {
243                 add_subwindow(new ChannelEditSelect(mwindow, this, x, y));
244                 y += 30;
245         }
246         add_subwindow(new ChannelEditAdd(mwindow, this, x, y));
247         y += 30;
248         add_subwindow(new ChannelEdit(mwindow, this, x, y));
249         y += 30;
250         add_subwindow(new ChannelEditMoveUp(mwindow, this, x, y));
251         y += 30;
252         add_subwindow(new ChannelEditMoveDown(mwindow, this, x, y));
253         y += 30;
254         add_subwindow(new ChannelEditSort(mwindow, this, x, y));
255         y += 30;
257         Channel *channel_usage = channel_picker->get_channel_usage();
258         if(channel_usage->has_scanning)
259         {
260                 add_subwindow(new ChannelEditScan(mwindow, this, x, y));
261                 y += 30;
262         }
263         add_subwindow(new ChannelEditDel(mwindow, this, x, y));
264         y += 30;
265         add_subwindow(new ChannelEditPicture(mwindow, this, x, y));
266         y += 100;
267         x = 10;
268         add_subwindow(new BC_OKButton(this));
269         x += 150;
270         add_subwindow(new BC_CancelButton(this));
273         edit_thread = new ChannelEditEditThread(this, 
274                 channel_picker, 
275                 thread->record);
276         picture_thread = new ChannelEditPictureThread(channel_picker, this);
277         show_window();
278         return 0;
281 int ChannelEditWindow::close_event()
283         set_done(0);
286 int ChannelEditWindow::add_channel()
288         Channel *new_channel;
289         Channel *prev_channel = 0;
291 // Create new channel
292         new_channel = new Channel;
294 // Reuse parameters from previous channel
295         if(thread->new_channels->size()) 
296         {
297                 prev_channel = thread->new_channels->get(
298                                 thread->new_channels->size() - 1);
299                 new_channel->copy_settings(prev_channel);
300         }
301         else
302 // Use default channel parameters
303         if(thread->record)
304         {
305                 new_channel->copy_settings(thread->record->master_channel);
306         }
308 // Copy device usage.  Need the same thing for playback.
309         if(thread->record)
310         {
311                 new_channel->copy_usage(thread->record->master_channel);
312         }
314 // Add to channel table
315         channel_list.append(new BC_ListBoxItem(new_channel->title));
316         thread->new_channels->append(new_channel);
317         update_list();
319 // Start common routing
320         edit_thread->edit_channel(new_channel, 0);
321         return 0;
324 int ChannelEditWindow::update_list()
326 // Create channel list
327         channel_list.remove_all_objects();
328         for(int i = 0; i < thread->new_channels->size(); i++)
329         {
330                 channel_list.append(
331                         new BC_ListBoxItem(
332                                 thread->new_channels->get(i)->title));
333         }
335         list_box->update(&channel_list, 0, 0, 1, list_box->get_yposition());
338 int ChannelEditWindow::update_list(Channel *channel)
340         int i;
341         for(i = 0; i < thread->new_channels->size(); i++)
342                 if(thread->new_channels->get(i) == channel) break;
344         if(i < thread->new_channels->size())
345         {
346                 channel_list.values[i]->set_text(channel->title);
347         }
349         update_list();
353 int ChannelEditWindow::edit_channel()
355         if(list_box->get_selection_number(0, 0) > -1)
356         {
357                 thread->current_channel = list_box->get_selection_number(0, 0);
358                 edit_thread->edit_channel(
359                         thread->new_channels->get(
360                                 list_box->get_selection_number(0, 0)), 
361                         1);
362         }
365 int ChannelEditWindow::edit_picture()
367         picture_thread->edit_picture();
370 void ChannelEditWindow::scan_confirm()
372         thread->scan_params.load_defaults(mwindow->defaults);
373         if(!scan_confirm_thread) scan_confirm_thread = new ConfirmScanThread(this);
374         unlock_window();
375         scan_confirm_thread->start();
376         lock_window("ChannelEditWindow::scan_confirm");
379 void ChannelEditWindow::scan()
381         thread->new_channels->clear();
382         update_list();
384         if(!thread->scan_thread) thread->scan_thread = new ScanThread(thread);
385         thread->scan_thread->start();
389 void ChannelEditWindow::sort()
391         int done = 0;
392         while(!done)
393         {
394                 done = 1;
395                 for(int i = 0; i < thread->new_channels->size() - 1; i++)
396                 {
397                         Channel *channel1 = thread->new_channels->get(i);
398                         Channel *channel2 = thread->new_channels->get(i + 1);
399                         int is_num = 1;
400                         for(int j = 0; j < strlen(channel1->title); j++)
401                                 if(!isdigit(channel1->title[j])) is_num = 0;
402                         for(int j = 0; j < strlen(channel2->title); j++)
403                                 if(!isdigit(channel2->title[j])) is_num = 0;
404                         if(is_num && atoi(channel1->title) > atoi(channel2->title) ||
405                                 !is_num && strcasecmp(channel2->title, channel1->title) < 0)
406                         {
407                                 thread->new_channels->set(i, channel2);
408                                 thread->new_channels->set(i + 1, channel1);
409                                 done = 0;
410                         }
411                 }
412         }
413         update_list();
417 int ChannelEditWindow::delete_channel(int number)
419         delete thread->new_channels->get(number);
420         channel_list.remove_number(number);
421         thread->new_channels->remove_number(number);
422         update_list();
425 int ChannelEditWindow::delete_channel(Channel *channel)
427         int i;
428         for(i = 0; i < thread->new_channels->size(); i++)
429         {
430                 if(thread->new_channels->get(i) == channel)
431                 {
432                         break;
433                 }
434         }
435         if(i < thread->new_channels->size()) delete_channel(i);
436         return 0;
439 int ChannelEditWindow::move_channel_up()
441         if(list_box->get_selection_number(0, 0) > -1)
442         {
443                 int number2 = list_box->get_selection_number(0, 0);
444                 int number1 = number2 - 1;
445                 Channel *temp;
446                 BC_ListBoxItem *temp_text;
448                 if(number1 < 0) number1 = thread->new_channels->size() - 1;
450                 temp = thread->new_channels->get(number1);
451                 thread->new_channels->set(number1, thread->new_channels->get(number2));
452                 thread->new_channels->set(number2, temp);
454                 temp_text = channel_list.values[number1];
455                 channel_list.values[number1] = channel_list.values[number2];
456                 channel_list.values[number2] = temp_text;
457                 list_box->update(&channel_list, 
458                         0, 
459                         0, 
460                         1, 
461                         list_box->get_xposition(), 
462                         list_box->get_yposition(), 
463                         number1,
464                         1);
465         }
466         return 0;
469 int ChannelEditWindow::move_channel_down()
471         if(list_box->get_selection_number(0, 0) > -1)
472         {
473                 int number2 = list_box->get_selection_number(0, 0);
474                 int number1 = number2 + 1;
475                 Channel *temp;
476                 BC_ListBoxItem *temp_text;
478                 if(number1 > thread->new_channels->size() - 1) number1 = 0;
480                 temp = thread->new_channels->get(number1);
481                 thread->new_channels->set(number1, thread->new_channels->get(number2));
482                 thread->new_channels->set(number2, temp);
483                 temp_text = channel_list.values[number1];
484                 channel_list.values[number1] = channel_list.values[number2];
485                 channel_list.values[number2] = temp_text;
486                 list_box->update(&channel_list, 
487                         0, 
488                         0, 
489                         1, 
490                         list_box->get_xposition(), 
491                         list_box->get_yposition(), 
492                         number1,
493                         1);
494         }
495         return 0;
498 int ChannelEditWindow::change_channel_from_list(int channel_number)
500         Channel *channel;
501         if(channel_number > -1 && channel_number < thread->new_channels->size())
502         {
503                 thread->current_channel = channel_number;
504                 channel_picker->set_channel(thread->new_channels->get(channel_number));
505         }
508 ChannelEditSelect::ChannelEditSelect(MWindow *mwindow, ChannelEditWindow *window, int x, int y)
509  : BC_GenericButton(x, y, _("Select"))
511         this->window = window;
513 ChannelEditSelect::~ChannelEditSelect()
516 int ChannelEditSelect::handle_event()
518         window->change_channel_from_list(
519                 window->list_box->get_selection_number(0, 0));
522 ChannelEditAdd::ChannelEditAdd(MWindow *mwindow, ChannelEditWindow *window, int x, int y)
523  : BC_GenericButton(x, y, _("Add..."))
525         this->window = window;
527 ChannelEditAdd::~ChannelEditAdd()
530 int ChannelEditAdd::handle_event()
532         window->add_channel();
535 ChannelEditList::ChannelEditList(MWindow *mwindow, ChannelEditWindow *window, int x, int y)
536  : BC_ListBox(x, 
537                         y, 
538                         185, 
539                         window->get_h() - BC_OKButton::calculate_h() - y - 10, 
540                         LISTBOX_TEXT, 
541                         &(window->channel_list))
543         this->window = window;
545 ChannelEditList::~ChannelEditList()
548 int ChannelEditList::handle_event()
550         window->edit_channel();
553 ChannelEditMoveUp::ChannelEditMoveUp(MWindow *mwindow, ChannelEditWindow *window, int x, int y)
554  : BC_GenericButton(x, y, _("Move up"))
556         this->window = window;
558 ChannelEditMoveUp::~ChannelEditMoveUp()
561 int ChannelEditMoveUp::handle_event()
563         lock_window("ChannelEditMoveUp::handle_event");
564         window->move_channel_up();
565         unlock_window();
568 ChannelEditMoveDown::ChannelEditMoveDown(MWindow *mwindow, ChannelEditWindow *window, int x, int y)
569  : BC_GenericButton(x, y, _("Move down"))
571         this->window = window;
573 ChannelEditMoveDown::~ChannelEditMoveDown()
576 int ChannelEditMoveDown::handle_event()
578         lock_window("ChannelEditMoveDown::handle_event");
579         window->move_channel_down();
580         unlock_window();
583 ChannelEditSort::ChannelEditSort(MWindow *mwindow, ChannelEditWindow *window, int x, int y)
584  : BC_GenericButton(x, y, _("Sort"))
586         this->window = window;
588 int ChannelEditSort::handle_event()
590         lock_window("ChannelEditSort::handle_event");
591         window->sort();
592         unlock_window();
595 ChannelEditScan::ChannelEditScan(MWindow *mwindow, ChannelEditWindow *window, int x, int y)
596  : BC_GenericButton(x, y, _("Scan"))
598         this->window = window;
600 int ChannelEditScan::handle_event()
602         window->scan_confirm();
605 ChannelEditDel::ChannelEditDel(MWindow *mwindow, ChannelEditWindow *window, int x, int y)
606  : BC_GenericButton(x, y, _("Delete"))
608         this->window = window;
610 ChannelEditDel::~ChannelEditDel()
613 int ChannelEditDel::handle_event()
615         if(window->list_box->get_selection_number(0, 0) > -1) window->delete_channel(window->list_box->get_selection_number(0, 0));
618 ChannelEdit::ChannelEdit(MWindow *mwindow, ChannelEditWindow *window, int x, int y)
619  : BC_GenericButton(x, y, _("Edit..."))
621         this->window = window;
623 ChannelEdit::~ChannelEdit()
626 int ChannelEdit::handle_event()
628         window->edit_channel();
631 ChannelEditPicture::ChannelEditPicture(MWindow *mwindow, ChannelEditWindow *window, int x, int y)
632  : BC_GenericButton(x, y, _("Picture..."))
634         this->window = window;
636 ChannelEditPicture::~ChannelEditPicture()
639 int ChannelEditPicture::handle_event()
641         window->edit_picture();
655 // ========================= confirm overwrite by channel scannin
658 ConfirmScan::ConfirmScan(ChannelEditWindow *gui, int x, int y)
659  : BC_Window(PROGRAM_NAME ": Scan confirm",
660         x,
661         y,
662         350,
663         BC_OKButton::calculate_h() + 130,
664         0,
665         0,
666         0,
667         0,
668         1)
670         this->gui = gui;
673 void ConfirmScan::create_objects()
675         int x = 10, y = 10;
676         int y2 = 0, x2 = 0;
677         BC_Title *title;
678         add_subwindow(title = new BC_Title(x, y, _("Set parameters for channel scanning.")));
679         y += title->get_h() + 10;
680         y2 = y;
682         add_subwindow(title = new BC_Title(x, y, _("Frequency table:")));
683         x2 = title->get_w();
684         y += BC_PopupMenu::calculate_h();
685         add_subwindow(title = new BC_Title(x, y, _("Norm:")));
686         x2 = MAX(x2, title->get_w());
687         y += BC_PopupMenu::calculate_h();
688         add_subwindow(title = new BC_Title(x, y, _("Input:")));
689         x2 = MAX(x2, title->get_w());
690         y += BC_PopupMenu::calculate_h();
691         x2 += x + 5;
693         y = y2;
694         x = x2;
695         ChannelEditEditFreqtable *table;
696         add_subwindow(table = new ChannelEditEditFreqtable(x, 
697                 y, 
698                 0, 
699                 gui->thread));
700         table->add_items();
701         y += table->get_h() + 10;
703         ChannelEditEditNorm *norm;
704         add_subwindow(norm = new ChannelEditEditNorm(x, 
705                 y, 
706                 0,
707                 gui->thread));
708         norm->add_items();
709         y += norm->get_h() + 10;
711         ChannelEditEditInput *input;
712         add_subwindow(input = new ChannelEditEditInput(x, 
713                 y, 
714                 0, 
715                 gui->thread));
716         input->add_items();
719         add_subwindow(new BC_OKButton(this));
720         add_subwindow(new BC_CancelButton(this));
721         show_window();
730 ConfirmScanThread::ConfirmScanThread(ChannelEditWindow *gui)
731  : BC_DialogThread()
733         this->gui = gui;
736 void ConfirmScanThread::handle_done_event(int result)
738         gui->thread->scan_params.save_defaults(gui->thread->mwindow->defaults);
739         if(!result)
740         {
741                 get_gui()->hide_window();
742                 gui->lock_window("ConfirmScanThread::handle_done_event");
743                 gui->scan();
744                 gui->unlock_window();
745         }
748 BC_Window* ConfirmScanThread::new_gui()
750         int x = gui->get_abs_cursor_x(1);
751         int y = gui->get_abs_cursor_y(1);
752         ConfirmScan *result = new ConfirmScan(gui, x, y);
753         result->create_objects();
754         return result;
762 ScanThread::ScanThread(ChannelEditThread *edit)
763  : Thread(1, 0, 0)
765         this->edit = edit;
766         interrupt = 0;
767         progress = 0;
770 ScanThread::~ScanThread()
772         interrupt = 1;
773         Thread::join();
775         delete progress;
779 void ScanThread::start()
781 // Cancel previous job
782         interrupt = 1;
783         Thread::join();
784         delete progress;
785         interrupt = 0;
788         progress = edit->mwindow->mainprogress->start_progress("Scanning", 
789                 chanlists[edit->scan_params.freqtable].count, 
790                 1);
791         Thread::start();
794 void ScanThread::run()
796         for(int i = 0; 
797                 i < chanlists[edit->scan_params.freqtable].count &&
798                         !interrupt && 
799                         !progress->is_cancelled();
800                 i++)
801         {
802                 edit->scan_params.entry = i;
803                 char string[BCTEXTLEN];
804                 sprintf(edit->scan_params.title, 
805                         "%s", 
806                         chanlists[edit->scan_params.freqtable].list[i].name);
807                 sprintf(string, 
808                         "Scanning %s", 
809                         edit->scan_params.title);
810                 progress->update_title(string);
811                 progress->update(i);
812                 edit->channel_picker->set_channel(&edit->scan_params);
815                 sleep(2);
817             int got_signal = edit->channel_picker->has_signal();
818                 if(got_signal)
819                 {
820                         Channel *new_channel = new Channel;
821                         new_channel->copy_usage(&edit->scan_params);
822                         new_channel->copy_settings(&edit->scan_params);
823                         edit->window->lock_window("ScanThread::run");
824                         edit->new_channels->append(new_channel);
825                         edit->window->update_list();
826                         edit->window->unlock_window();
827                 }
828         }
829         delete progress;
830         progress = 0;
839 // ================================= Edit a single channel
843 ChannelEditEditThread::ChannelEditEditThread(ChannelEditWindow *window, 
844         ChannelPicker *channel_picker,
845         Record *record)
846  : Thread()
848         this->window = window;
849         this->channel_picker = channel_picker;
850         this->record = record;
851         in_progress = 0;
852         edit_window = 0;
853         editing = 0;
854         completion = new Condition(1, "ChannelEditEditThread::completion");
857 ChannelEditEditThread::~ChannelEditEditThread()
859         delete completion;
862 int ChannelEditEditThread::close_threads()
864         if(edit_window)
865         {
866                 edit_window->set_done(1);
867                 completion->lock("ChannelEditEditThread::close_threads");
868                 completion->unlock();
869         }
872 int ChannelEditEditThread::edit_channel(Channel *channel, int editing)
874         if(in_progress) 
875         {
876                 edit_window->lock_window("ChannelEditEditThread::edit_channel");
877                 edit_window->raise_window(1);
878                 edit_window->unlock_window();
879                 return 1;
880         }
881         in_progress = 1;
883 // Copy the channel to edit into a temporary
884         completion->lock("ChannelEditEditThread::edit_channel");
885         this->editing = editing;
886         this->output_channel = channel;
887         new_channel.copy_settings(output_channel);
888         new_channel.copy_usage(output_channel);
890         if(editing && new_channel.title[0])
891                 user_title = 1;
892         else
893                 user_title = 0;
894         set_synchronous(0);
895         Thread::start();
899 void ChannelEditEditThread::set_device()
901         channel_picker->set_channel(&new_channel);
904 int ChannelEditEditThread::change_source(char *source_name)
906         int i, result;
907         for(i = 0; i < chanlists[new_channel.freqtable].count; i++)
908         {
909                 if(!strcasecmp(chanlists[new_channel.freqtable].list[i].name, source_name))
910                 {
911                         new_channel.entry = i;
912                         i = chanlists[new_channel.freqtable].count;
913                         set_device();
914                 }
915         }
916         if(!user_title)
917         {
918                 strcpy(new_channel.title, source_name);
919                 if(edit_window->title_text)
920                 {
921                         edit_window->title_text->update(source_name);
922                 }
923         }
926 int ChannelEditEditThread::source_up()
928         new_channel.entry++;
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 int ChannelEditEditThread::source_down()
936         new_channel.entry--;
937         if(new_channel.entry < 0) new_channel.entry = chanlists[new_channel.freqtable].count - 1;
938         source_text->update(chanlists[new_channel.freqtable].list[new_channel.entry].name);
939         set_device();
942 int ChannelEditEditThread::set_input(int value)
944         new_channel.input = value;
945         set_device();
948 int ChannelEditEditThread::set_norm(int value)
950         new_channel.norm = value;
951         set_device();
954 int ChannelEditEditThread::set_freqtable(int value)
956         new_channel.freqtable = value;
957         if(new_channel.entry > chanlists[new_channel.freqtable].count - 1) new_channel.entry = 0;
958         source_text->update(chanlists[new_channel.freqtable].list[new_channel.entry].name);
959         set_device();
962 void ChannelEditEditThread::run()
964         ChannelEditEditWindow edit_window(this, window, channel_picker);
965         edit_window.create_objects(&new_channel);
966         this->edit_window = &edit_window;
967         int result = edit_window.run_window();
968         this->edit_window = 0;
970 // Done editing channel.  Keep channel.
971         if(!result)
972         {
973                 output_channel->copy_settings(&new_channel);
974                 window->lock_window();
975                 window->update_list(output_channel);
976                 window->unlock_window();
977         }
978         else
979         {
980 // Discard channel.
981                 if(!editing)
982                 {
983                         window->lock_window();
984                         window->delete_channel(output_channel);
985                         window->unlock_window();
986                 }
987         }
988         editing = 0;
989         completion->unlock();
990         in_progress = 0;
993 ChannelEditEditWindow::ChannelEditEditWindow(ChannelEditEditThread *thread, 
994         ChannelEditWindow *window,
995         ChannelPicker *channel_picker)
996  : BC_Window(PROGRAM_NAME ": Edit Channel", 
997         channel_picker->mwindow->gui->get_abs_cursor_x(1), 
998         channel_picker->mwindow->gui->get_abs_cursor_y(1), 
999         390, 
1000         300, 
1001         390, 
1002         300,
1003         0,
1004         0,
1005         1)
1007         this->channel_picker = channel_picker;
1008         this->window = window;
1009         this->thread = thread;
1011 ChannelEditEditWindow::~ChannelEditEditWindow()
1014 int ChannelEditEditWindow::create_objects(Channel *channel)
1016         this->new_channel = channel;
1017         Channel *channel_usage = channel_picker->get_channel_usage();
1018         title_text = 0;
1020         int x = 10, y = 10;
1021         if(!channel_usage ||
1022                 (!channel_usage->use_frequency && 
1023                 !channel_usage->use_fine && 
1024                 !channel_usage->use_norm && 
1025                 !channel_usage->use_input))
1026         {
1027                 add_subwindow(new BC_Title(x, y, "Device has no input selection."));
1028                 y += 30;
1029         }
1030         else
1031         {
1032                 add_subwindow(new BC_Title(x, y, _("Title:")));
1033                 add_subwindow(title_text = new ChannelEditEditTitle(x, y + 20, thread));
1034                 y += 50;
1035         }
1037         if(channel_usage->use_frequency)
1038         {
1039                 add_subwindow(new BC_Title(x, y, _("Channel:")));
1040                 y += 20;
1041                 add_subwindow(thread->source_text = new ChannelEditEditSource(x, y, thread));
1042                 add_subwindow(new ChannelEditEditSourceTumbler(x + 160, y, thread));
1043                 y += 40;
1045                 add_subwindow(new BC_Title(x, y, _("Frequency table:")));
1046                 ChannelEditEditFreqtable *table;
1047                 add_subwindow(table = new ChannelEditEditFreqtable(x + 130, 
1048                         y, 
1049                         thread, 
1050                         window->thread));
1051                 table->add_items();
1052                 y += 30;
1053         }
1055         if(channel_usage->use_fine)
1056         {
1057                 add_subwindow(new BC_Title(x, y, _("Fine:")));
1058                 add_subwindow(new ChannelEditEditFine(x + 130, y, thread));
1059                 y += 30;
1060         }
1062         if(channel_usage->use_norm)
1063         {
1064                 add_subwindow(new BC_Title(x, y, _("Norm:")));
1065                 ChannelEditEditNorm *norm;
1066                 add_subwindow(norm = new ChannelEditEditNorm(x + 130, 
1067                         y, 
1068                         thread,
1069                         window->thread));
1070                 norm->add_items();
1071                 y += 30;
1072         }
1074         if(channel_usage->use_input)
1075         {
1076                 add_subwindow(new BC_Title(x, y, _("Input:")));
1077                 ChannelEditEditInput *input;
1078                 add_subwindow(input = new ChannelEditEditInput(x + 130, 
1079                         y, 
1080                         thread, 
1081                         window->thread));
1082                 input->add_items();
1083                 y += 30;
1084         }
1086         add_subwindow(new BC_OKButton(this));
1087         x += 200;
1088         add_subwindow(new BC_CancelButton(this));
1089         show_window();
1090         return 0;
1093 ChannelEditEditTitle::ChannelEditEditTitle(int x, 
1094         int y, 
1095         ChannelEditEditThread *thread)
1096  : BC_TextBox(x, y, 150, 1, thread->new_channel.title)
1098         this->thread = thread;
1100 ChannelEditEditTitle::~ChannelEditEditTitle()
1103 int ChannelEditEditTitle::handle_event()
1105         if(strlen(get_text()) < 1024)
1106         {
1107                 strcpy(thread->new_channel.title, get_text());
1108         }
1109         if(get_text()[0]) 
1110                 thread->user_title = 1;
1111         else
1112                 thread->user_title = 0;
1113         return 1;
1117 ChannelEditEditSource::ChannelEditEditSource(int x, int y, ChannelEditEditThread *thread)
1118  : BC_TextBox(x, y, 150, 1, chanlists[thread->new_channel.freqtable].list[thread->new_channel.entry].name)
1120         this->thread = thread;
1123 ChannelEditEditSource::~ChannelEditEditSource()
1126 int ChannelEditEditSource::handle_event()
1128         thread->change_source(get_text());
1132 ChannelEditEditSourceTumbler::ChannelEditEditSourceTumbler(int x, int y, ChannelEditEditThread *thread)
1133  : BC_Tumbler(x, y)
1135         this->thread = thread;
1137 ChannelEditEditSourceTumbler::~ChannelEditEditSourceTumbler()
1140 int ChannelEditEditSourceTumbler::handle_up_event()
1142         thread->source_up();
1144 int ChannelEditEditSourceTumbler::handle_down_event()
1146         thread->source_down();
1149 ChannelEditEditInput::ChannelEditEditInput(int x, 
1150         int y, 
1151         ChannelEditEditThread *thread, 
1152         ChannelEditThread *edit)
1153  : BC_PopupMenu(x, 
1154         y, 
1155         150, 
1156         edit->value_to_input(thread ? thread->new_channel.input : edit->scan_params.input))
1158         this->thread = thread;
1159         this->edit = edit;
1161 ChannelEditEditInput::~ChannelEditEditInput()
1164 int ChannelEditEditInput::add_items()
1166         ArrayList<Channel*> *inputs;
1167         inputs = edit->channel_picker->get_video_inputs();
1169         if(inputs)
1170                 for(int i = 0; i < inputs->total; i++)
1171                 {
1172                         add_item(new ChannelEditEditInputItem(thread, 
1173                                 edit,
1174                                 inputs->values[i]->device_name, 
1175                                 i));
1176                 }
1178 int ChannelEditEditInput::handle_event()
1180         return 0;
1183 ChannelEditEditInputItem::ChannelEditEditInputItem(ChannelEditEditThread *thread, 
1184         ChannelEditThread *edit,
1185         char *text, 
1186         int value)
1187  : BC_MenuItem(text)
1189         this->thread = thread;
1190         this->edit = edit;
1191         this->value = value;
1193 ChannelEditEditInputItem::~ChannelEditEditInputItem()
1196 int ChannelEditEditInputItem::handle_event()
1198         get_popup_menu()->set_text(get_text());
1199         if(thread && !thread->user_title)
1200         {
1201                 strcpy(thread->new_channel.title, get_text());
1202                 if(thread->edit_window->title_text)
1203                 {
1204                         thread->edit_window->title_text->update(get_text());
1205                 }
1206         }
1207         if(thread) 
1208                 thread->set_input(value);
1209         else
1210                 edit->scan_params.input = value;
1213 ChannelEditEditNorm::ChannelEditEditNorm(int x, 
1214         int y, 
1215         ChannelEditEditThread *thread,
1216         ChannelEditThread *edit)
1217  : BC_PopupMenu(x, 
1218         y, 
1219         100, 
1220         edit->value_to_norm(thread ? thread->new_channel.norm : edit->scan_params.norm))
1222         this->thread = thread;
1223         this->edit = edit;
1225 ChannelEditEditNorm::~ChannelEditEditNorm()
1228 int ChannelEditEditNorm::add_items()
1230         add_item(new ChannelEditEditNormItem(thread, 
1231                 edit, 
1232                 edit->value_to_norm(NTSC), NTSC));
1233         add_item(new ChannelEditEditNormItem(thread, 
1234                 edit, 
1235                 edit->value_to_norm(PAL), PAL));
1236         add_item(new ChannelEditEditNormItem(thread, 
1237                 edit, 
1238                 edit->value_to_norm(SECAM), SECAM));
1239         return 0;
1243 ChannelEditEditNormItem::ChannelEditEditNormItem(ChannelEditEditThread *thread, 
1244         ChannelEditThread *edit,
1245         char *text, 
1246         int value)
1247  : BC_MenuItem(text)
1249         this->value = value;
1250         this->edit = edit;
1251         this->thread = thread;
1253 ChannelEditEditNormItem::~ChannelEditEditNormItem()
1256 int ChannelEditEditNormItem::handle_event()
1258         get_popup_menu()->set_text(get_text());
1259         if(thread)
1260                 thread->set_norm(value);
1261         else
1262                 edit->scan_params.norm = value;
1266 ChannelEditEditFreqtable::ChannelEditEditFreqtable(int x, 
1267         int y, 
1268         ChannelEditEditThread *thread,
1269         ChannelEditThread *edit)
1270  : BC_PopupMenu(x, 
1271         y, 
1272         150, 
1273         edit->value_to_freqtable(thread ? thread->new_channel.freqtable : edit->scan_params.freqtable))
1275         this->thread = thread;
1276         this->edit = edit;
1278 ChannelEditEditFreqtable::~ChannelEditEditFreqtable()
1281 int ChannelEditEditFreqtable::add_items()
1283         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(NTSC_BCAST), NTSC_BCAST));
1284         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(NTSC_CABLE), NTSC_CABLE));
1285         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(NTSC_HRC), NTSC_HRC));
1286         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(NTSC_BCAST_JP), NTSC_BCAST_JP));
1287         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(NTSC_CABLE_JP), NTSC_CABLE_JP));
1288         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(PAL_AUSTRALIA), PAL_AUSTRALIA));
1289         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(PAL_EUROPE), PAL_EUROPE));
1290         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(PAL_E_EUROPE), PAL_E_EUROPE));
1291         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(PAL_ITALY), PAL_ITALY));
1292         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(PAL_IRELAND), PAL_IRELAND));
1293         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(PAL_NEWZEALAND), PAL_NEWZEALAND));
1294         return 0;
1297 ChannelEditEditFreqItem::ChannelEditEditFreqItem(ChannelEditEditThread *thread, 
1298         ChannelEditThread *edit,
1299         char *text, int value)
1300  : BC_MenuItem(text)
1302         this->value = value;
1303         this->edit = edit;
1304         this->thread = thread;
1306 ChannelEditEditFreqItem::~ChannelEditEditFreqItem()
1309 int ChannelEditEditFreqItem::handle_event()
1311         get_popup_menu()->set_text(get_text());
1312         if(thread)
1313                 thread->set_freqtable(value);
1314         else
1315                 edit->scan_params.freqtable = value;
1320 ChannelEditEditFine::ChannelEditEditFine(int x, 
1321         int y, 
1322         ChannelEditEditThread *thread)
1323  : BC_ISlider(x, 
1324                 y, 
1325                 0, 
1326                 240, 
1327                 240, 
1328                 -100, 
1329                 100, 
1330                 thread->new_channel.fine_tune)
1332         this->thread = thread;
1334 ChannelEditEditFine::~ChannelEditEditFine()
1337 int ChannelEditEditFine::handle_event()
1339         thread->new_channel.fine_tune = get_value();
1340         thread->set_device();
1344 // ========================== picture quality
1346 ChannelEditPictureThread::ChannelEditPictureThread(ChannelPicker *channel_picker, ChannelEditWindow *window)
1347  : Thread()
1349         this->channel_picker = channel_picker;
1350         this->window = window;
1351         in_progress = 0;
1352         edit_window = 0;
1353         completion = new Condition(1, "ChannelEditPictureThread::completion");
1355 ChannelEditPictureThread::~ChannelEditPictureThread()
1357         delete completion;
1360 int ChannelEditPictureThread::edit_picture()
1362         if(in_progress) 
1363         {
1364                 edit_window->lock_window("ChannelEditPictureThread::edit_picture");
1365                 edit_window->raise_window(1);
1366                 edit_window->unlock_window();
1367                 return 1;
1368         }
1369         in_progress = 1;
1370         completion->lock("ChannelEditPictureThread::edit_picture");
1371         set_synchronous(0);
1372         Thread::start();
1375 void ChannelEditPictureThread::run()
1377         ChannelEditPictureWindow edit_window(this, 
1378                 channel_picker);
1379         edit_window.create_objects();
1380         this->edit_window = &edit_window;
1381         int result = edit_window.run_window();
1382         this->edit_window = 0;
1383         completion->unlock();
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->mwindow->gui->get_abs_cursor_x(1) - 200, 
1402         channel_picker->mwindow->gui->get_abs_cursor_y(1) - 220, 
1403         200, 
1404         calculate_h(channel_picker), 
1405         200, 
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 + BC_OKButton::calculate_h();
1421         if(picture_usage->use_brightness)
1422                 result += pad;
1423         if(picture_usage->use_contrast)
1424                 result += pad;
1425         if(picture_usage->use_color)
1426                 result += pad;
1427         if(picture_usage->use_hue)
1428                 result += pad;
1429         if(picture_usage->use_whiteness)
1430                 result += pad;
1431         result += channel_picker->get_controls() * pad;
1432         return result;
1435 int ChannelEditPictureWindow::create_objects()
1437         int x = 10, y = 10;
1438         int x1 = 110, x2 = 145;
1439         int pad = BC_Pot::calculate_h();
1440 #define SWAP_X x1 ^= x2; x2 ^= x1; x1 ^= x2;
1442         PictureConfig *picture_usage = channel_picker->get_picture_usage();
1444         if(!picture_usage ||
1445                 (!picture_usage->use_brightness &&
1446                 !picture_usage->use_contrast &&
1447                 !picture_usage->use_color &&
1448                 !picture_usage->use_hue &&
1449                 !picture_usage->use_whiteness &&
1450                 !channel_picker->get_controls()))
1451         {
1452                 add_subwindow(new BC_Title(x, y, "Device has no picture controls."));
1453                 y += 50;
1454         }
1456         if(picture_usage->use_brightness)
1457         {
1458                 add_subwindow(new BC_Title(x, y + 10, _("Brightness:")));
1459                 add_subwindow(new ChannelEditBright(x1, y, channel_picker, channel_picker->get_brightness()));
1460                 y += pad;
1461                 SWAP_X
1462                 
1463         }
1465         if(picture_usage->use_contrast)
1466         {
1467                 add_subwindow(new BC_Title(x, y + 10, _("Contrast:")));
1468                 add_subwindow(new ChannelEditContrast(x1, y, channel_picker, channel_picker->get_contrast()));
1469                 y += pad;
1470                 SWAP_X
1471         }
1473         if(picture_usage->use_color)
1474         {
1475                 add_subwindow(new BC_Title(x, y + 10, _("Color:")));
1476                 add_subwindow(new ChannelEditColor(x1, y, channel_picker, channel_picker->get_color()));
1477                 y += pad;
1478                 SWAP_X
1479         }
1481         if(picture_usage->use_hue)
1482         {
1483                 add_subwindow(new BC_Title(x, y + 10, _("Hue:")));
1484                 add_subwindow(new ChannelEditHue(x1, y, channel_picker, channel_picker->get_hue()));
1485                 y += pad;
1486                 SWAP_X
1487         }
1489         if(picture_usage->use_whiteness)
1490         {
1491                 add_subwindow(new BC_Title(x, y + 10, _("Whiteness:")));
1492                 add_subwindow(new ChannelEditWhiteness(x1, y, channel_picker, channel_picker->get_whiteness()));
1493                 y += pad;
1494                 SWAP_X
1495         }
1497         for(int i = 0; i < channel_picker->get_controls(); i++)
1498         {
1499                 add_subwindow(new BC_Title(x, 
1500                         y + 10, 
1501                         _(channel_picker->get_control(i)->name)));
1502                 add_subwindow(new ChannelEditCommon(x1, 
1503                         y, 
1504                         channel_picker,
1505                         channel_picker->get_control(i)));
1506                 y += pad;
1507                 SWAP_X
1508         }
1511         y += pad;
1512         add_subwindow(new BC_OKButton(this));
1513         return 0;
1518 ChannelEditBright::ChannelEditBright(int x, int y, ChannelPicker *channel_picker, int value)
1519  : BC_IPot(x, 
1520                 y, 
1521                 value, 
1522                 -100, 
1523                 100)
1525         this->channel_picker = channel_picker;
1527 ChannelEditBright::~ChannelEditBright() {}
1528 int ChannelEditBright::handle_event()
1530         return 1;
1532 int ChannelEditBright::button_release_event()
1534         if(BC_Pot::button_release_event())
1535         {
1536                 channel_picker->set_brightness(get_value());
1537                 return 1;
1538         }
1539         return 0;
1542 ChannelEditContrast::ChannelEditContrast(int x, int y, ChannelPicker *channel_picker, int value)
1543  : BC_IPot(x, 
1544                 y, 
1545                 value, 
1546                 -100, 
1547                 100)
1549         this->channel_picker = channel_picker;
1551 ChannelEditContrast::~ChannelEditContrast() {}
1552 int ChannelEditContrast::handle_event()
1554         return 1;
1556 int ChannelEditContrast::button_release_event()
1558         if(BC_Pot::button_release_event())
1559         {
1560                 channel_picker->set_contrast(get_value());
1561                 return 1;
1562         }
1563         return 0;
1567 ChannelEditColor::ChannelEditColor(int x, int y, ChannelPicker *channel_picker, int value)
1568  : BC_IPot(x, 
1569                 y, 
1570                 value, 
1571                 -100, 
1572                 100)
1574         this->channel_picker = channel_picker;
1576 ChannelEditColor::~ChannelEditColor() {}
1577 int ChannelEditColor::handle_event()
1579         return 1;
1581 int ChannelEditColor::button_release_event()
1583         if(BC_Pot::button_release_event())
1584         {
1585                 channel_picker->set_color(get_value());
1586                 return 1;
1587         }
1588         return 0;
1591 ChannelEditHue::ChannelEditHue(int x, int y, ChannelPicker *channel_picker, int value)
1592  : BC_IPot(x, 
1593                 y, 
1594                 value, 
1595                 -100, 
1596                 100)
1598         this->channel_picker = channel_picker;
1600 ChannelEditHue::~ChannelEditHue() {}
1601 int ChannelEditHue::handle_event()
1603         return 1;
1605 int ChannelEditHue::button_release_event()
1607         if(BC_Pot::button_release_event())
1608         {
1609                 channel_picker->set_hue(get_value());
1610                 return 1;
1611         }
1612         return 0;
1615 ChannelEditWhiteness::ChannelEditWhiteness(int x, int y, ChannelPicker *channel_picker, int value)
1616  : BC_IPot(x, 
1617                 y, 
1618                 value, 
1619                 -100, 
1620                 100)
1622         this->channel_picker = channel_picker;
1624 ChannelEditWhiteness::~ChannelEditWhiteness() 
1627 int ChannelEditWhiteness::handle_event()
1629         return 1;
1631 int ChannelEditWhiteness::button_release_event()
1633         if(BC_Pot::button_release_event())
1634         {
1635                 channel_picker->set_whiteness(get_value());
1636                 return 1;
1637         }
1638         return 0;
1643 ChannelEditCommon::ChannelEditCommon(int x, 
1644         int y, 
1645         ChannelPicker *channel_picker,
1646         PictureItem *item)
1647  : BC_IPot(x, 
1648                 y, 
1649                 item->value, 
1650                 item->min, 
1651                 item->max)
1653         this->channel_picker = channel_picker;
1654         this->device_id = item->device_id;
1657 ChannelEditCommon::~ChannelEditCommon() 
1661 int ChannelEditCommon::handle_event()
1663         return 1;
1666 int ChannelEditCommon::button_release_event()
1668         if(BC_Pot::button_release_event())
1669         {
1670                 channel_picker->set_picture(device_id, get_value());
1671                 return 1;
1672         }
1673         return 0;