bsd lang segv fix, enable bsd lv2, lv2 gui enable fix, proxy/ffmpeg toggle resize...
[goodguy/history.git] / cinelerra-5.1 / cinelerra / channeledit.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2011 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include "batch.h"
23 #include "bcprogressbox.h"
24 #include "bcsignals.h"
25 #include "channel.h"
26 #include "channeldb.h"
27 #include "channeledit.h"
28 #include "channelpicker.h"
29 #include "chantables.h"
30 #include "clip.h"
31 #include "condition.h"
32 #include "language.h"
33 #include "mainsession.h"
34 #include "mwindow.h"
35 #include "picture.h"
36 #include "theme.h"
37 #include "videodevice.h"
38 #include <ctype.h>
39 #include <string.h>
40 #include <unistd.h>
41
42 #define MSG_NO_PIC_CONTROLS _("Device has no picture controls.")
43 //#define MSG_NO_INP_SELECTION _("Device has no input selection.")
44
45 ChannelEditThread::ChannelEditThread(ChannelPicker *channel_picker,
46         ChannelDB *channeldb)
47  : Thread()
48 {
49         this->channel_picker = channel_picker;
50         this->channeldb = channeldb;
51         in_progress = 0;
52         this->window = 0;
53         new_channels = new ChannelDB;
54         completion = new Condition(1, "ChannelEditThread::completion");
55         scan_thread = 0;
56 }
57 ChannelEditThread::~ChannelEditThread()
58 {
59         close_threads();
60         delete scan_thread;
61         delete new_channels;
62         delete completion;
63 }
64
65 void ChannelEditThread::run()
66 {
67         if(in_progress)
68         {
69                 if(window)
70                 {
71                         window->lock_window("ChannelEditThread::run");
72                         window->raise_window(1);
73                         window->unlock_window();
74                 }
75                 return;
76         }
77         in_progress = 1;
78         completion->lock("ChannelEditThread::run");
79
80 // Copy master channel list to temporary.
81         new_channels->copy_from(channel_picker->channeldb);
82         Channel *channel = channel_picker->get_current_channel();
83         current_channel = channel_picker->channeldb->number_of(channel);
84 //printf("ChannelEditThread::run 1 %d\n", current_channel);
85
86 // Run the channel list window using the temporary list.
87         window = new ChannelEditWindow(this, channel_picker);
88         window->create_objects();
89         int result = window->run_window();
90         delete window;  window = 0;
91
92         if(!result) {
93 // Copy new channels to master list
94                 channel_picker->channeldb->clear();
95
96                 channel_picker->channeldb->copy_from(new_channels);
97                 channel_picker->update_channel_list();
98
99         }
100
101         channel_picker->handle_channel_edit(result);
102
103         completion->unlock();
104         in_progress = 0;
105
106 }
107
108 void ChannelEditThread::close_threads()
109 {
110         if(in_progress && window)
111         {
112                 window->set_done(1);
113                 completion->lock("ChannelEditThread::close_threads");
114                 completion->unlock();
115         }
116 }
117
118 char *ChannelEditThread::value_to_freqtable(int value)
119 {
120         switch(value)
121         {
122                 case NTSC_DVB: return _("NTSC_DVB");
123                 case CATV_DVB: return _("CATV_DVB");
124                 case NTSC_BCAST: return _("NTSC_BCAST");
125                 case NTSC_CABLE: return _("NTSC_CABLE");
126                 case NTSC_HRC: return _("NTSC_HRC");
127                 case NTSC_BCAST_JP: return _("NTSC_BCAST_JP");
128                 case NTSC_CABLE_JP: return _("NTSC_CABLE_JP");
129                 case PAL_AUSTRALIA: return _("PAL_AUSTRALIA");
130                 case PAL_EUROPE: return _("PAL_EUROPE");
131                 case PAL_E_EUROPE: return _("PAL_E_EUROPE");
132                 case PAL_ITALY: return _("PAL_ITALY");
133                 case PAL_IRELAND: return _("PAL_IRELAND");
134                 case PAL_NEWZEALAND: return _("PAL_NEWZEALAND");
135         }
136         return _("ERROR");
137 }
138
139 char* ChannelEditThread::value_to_norm(int value)
140 {
141         switch(value)
142         {
143                 case NTSC: return _("NTSC");
144                 case PAL: return _("PAL");
145                 case SECAM: return _("SECAM");
146         }
147         return _("ERROR");
148 }
149
150 char* ChannelEditThread::value_to_input(int value)
151 {
152         ArrayList<Channel*> *inputs = channel_picker->get_video_inputs();
153         return value >= inputs->total ? _("None") :
154                 inputs->values[value]->device_name;
155 }
156
157
158
159
160
161
162
163 ChannelEditWindow::ChannelEditWindow(ChannelEditThread *thread,
164         ChannelPicker *channel_picker)
165  : BC_Window(_(PROGRAM_NAME ": Channels"),
166         channel_picker->mwindow->session->channels_x,
167         channel_picker->mwindow->session->channels_y,
168         375, 400, 375, 400, 0, 0, 1)
169 {
170         this->thread = thread;
171         this->channel_picker = channel_picker;
172         this->edit_thread = 0;
173         this->picture_thread = 0;
174         this->scan_confirm_thread = 0;
175 }
176
177 ChannelEditWindow::~ChannelEditWindow()
178 {
179         if( thread->scan_thread )
180                 thread->scan_thread->stop();
181         channel_list.remove_all_objects();
182         delete edit_thread;
183         delete picture_thread;
184         delete scan_confirm_thread;
185 }
186
187 void ChannelEditWindow::create_objects()
188 {
189         int x = 10, y = 10;
190
191 // Create channel list
192         for(int i = 0; i < thread->new_channels->size(); i++)
193         {
194                 channel_list.append(new BC_ListBoxItem(thread->new_channels->get(i)->title));
195         }
196
197         add_subwindow(list_box = new ChannelEditList(this, x, y));
198         x += 200;
199         if(channel_picker->use_select())
200         {
201                 add_subwindow(new ChannelEditSelect(this, x, y));
202                 y += 30;
203         }
204         add_subwindow(new ChannelEditAdd(this, x, y));
205         y += 30;
206         add_subwindow(new ChannelEdit(this, x, y));
207         y += 30;
208         add_subwindow(new ChannelEditMoveUp(this, x, y));
209         y += 30;
210         add_subwindow(new ChannelEditMoveDown(this, x, y));
211         y += 30;
212         add_subwindow(new ChannelEditSort(this, x, y));
213         y += 30;
214
215         Channel *channel_usage = channel_picker->get_channel_usage();
216         if(channel_usage && channel_usage->has_scanning)
217         {
218                 add_subwindow(new ChannelEditScan(this, x, y));
219                 y += 30;
220         }
221         add_subwindow(new ChannelEditDel(this, x, y));
222         y += 30;
223         add_subwindow(new ChannelEditPicture(this, x, y));
224         y += 100;
225         x = 10;
226         add_subwindow(new BC_OKButton(this));
227         x += 150;
228         add_subwindow(new BC_CancelButton(this));
229
230
231         edit_thread = new ChannelEditEditThread(this, channel_picker);
232         picture_thread = new ChannelEditPictureThread(channel_picker);
233         show_window();
234 }
235
236 int ChannelEditWindow::close_event()
237 {
238         if( thread->scan_thread )
239                 thread->scan_thread->stop();
240         return BC_WindowBase::close_event();
241 }
242
243 int ChannelEditWindow::translation_event()
244 {
245         channel_picker->mwindow->session->channels_x = get_x();
246         channel_picker->mwindow->session->channels_y = get_y();
247         return 0;
248 }
249
250
251 int ChannelEditWindow::add_channel()
252 {
253         Channel *new_channel;
254         Channel *prev_channel = 0;
255
256 // Create new channel
257         new_channel = new Channel;
258
259 // Reuse parameters from previous channel
260         if(thread->new_channels->size())
261         {
262                 prev_channel = thread->new_channels->get(
263                                 thread->new_channels->size() - 1);
264                 new_channel->copy_settings(prev_channel);
265         }
266         else
267 // Use default channel parameters
268         if(channel_picker->get_master_channel())
269         {
270                 new_channel->copy_settings(channel_picker->get_master_channel());
271         }
272
273 // Copy device usage.  Need the same thing for playback.
274         if(channel_picker->get_master_channel())
275         {
276                 new_channel->copy_usage(channel_picker->get_master_channel());
277         }
278
279 // Add to channel table
280         channel_list.append(new BC_ListBoxItem(new_channel->title));
281         thread->new_channels->append(new_channel);
282         update_list();
283
284 // Start common routing
285         edit_thread->edit_channel(new_channel, 0);
286         return 0;
287 }
288
289 void ChannelEditWindow::update_list()
290 {
291 // Create channel list
292         channel_list.remove_all_objects();
293         for(int i = 0; i < thread->new_channels->size(); i++)
294         {
295                 channel_list.append(
296                         new BC_ListBoxItem(
297                                 thread->new_channels->get(i)->title));
298         }
299
300         list_box->update(&channel_list, 0, 0, 1, list_box->get_yposition());
301 }
302
303 void ChannelEditWindow::update_list(Channel *channel)
304 {
305         int i;
306         for(i = 0; i < thread->new_channels->size(); i++)
307                 if(thread->new_channels->get(i) == channel) break;
308
309         if(i < thread->new_channels->size())
310         {
311                 channel_list.values[i]->set_text(channel->title);
312         }
313
314         update_list();
315 }
316
317
318 void ChannelEditWindow::edit_channel()
319 {
320         if(list_box->get_selection_number(0, 0) > -1)
321         {
322                 thread->current_channel = list_box->get_selection_number(0, 0);
323                 edit_thread->edit_channel(
324                         thread->new_channels->get(
325                                 list_box->get_selection_number(0, 0)),
326                         1);
327         }
328 }
329
330 void ChannelEditWindow::edit_picture()
331 {
332         picture_thread->edit_picture();
333 }
334
335 void ChannelEditWindow::scan_confirm()
336 {
337         channel_picker->load_scan_defaults(&thread->scan_params);
338         if(!scan_confirm_thread) scan_confirm_thread = new ConfirmScanThread(this);
339         unlock_window();
340         scan_confirm_thread->start();
341         lock_window("ChannelEditWindow::scan_confirm");
342 }
343
344 void ChannelEditWindow::scan()
345 {
346         thread->new_channels->clear();
347         update_list();
348
349         if( !thread->scan_thread )
350                 thread->scan_thread = new ScanThread(thread);
351         thread->scan_thread->start();
352 }
353
354
355 void ChannelEditWindow::get_chan_num(Channel *channel, int &chan, int &stream)
356 {
357         const char *cp = channel->title;
358         int chn = 0, str = 0;
359         while( isdigit(*cp) ) chn = 10*chn + (*cp++ -'0');
360         if( chn != 0 && *cp != 0 ) {
361                 if( *cp++ == '.' )
362                         while( isdigit(*cp) ) str = 10*str + (*cp++ -'0');
363                 if( !str ) chn = 0;
364         }
365         chan = chn;  stream = str;
366 }
367
368 void ChannelEditWindow::sort()
369 {
370         int done = 0;
371         while(!done) {
372                 done = 1;
373                 for(int i = 0; i < thread->new_channels->size() - 1; i++) {
374                         Channel *channel1 = thread->new_channels->get(i);
375                         Channel *channel2 = thread->new_channels->get(i + 1);
376                         int ch1, st1;  get_chan_num(channel1, ch1, st1);
377                         int ch2, st2;  get_chan_num(channel2, ch2, st2);
378                         if( (ch1 > 0 && ch2 > 0) ?
379                              (ch1 > ch2 || (ch1 == ch2 && (st1 > st2 || (st1 == st2 &&
380                                 strcasecmp(channel2->title, channel1->title) < 0)))) :
381                              strcasecmp(channel2->title, channel1->title) < 0) {
382                                 thread->new_channels->set(i, channel2);
383                                 thread->new_channels->set(i + 1, channel1);
384                                 done = 0;
385                         }
386                 }
387         }
388         update_list();
389 }
390
391
392 void ChannelEditWindow::delete_channel(int number)
393 {
394         delete thread->new_channels->get(number);
395         channel_list.remove_number(number);
396         thread->new_channels->remove_number(number);
397         update_list();
398 }
399
400 void ChannelEditWindow::delete_channel(Channel *channel)
401 {
402         int i;
403         for(i = 0; i < thread->new_channels->size(); i++)
404         {
405                 if(thread->new_channels->get(i) == channel)
406                 {
407                         break;
408                 }
409         }
410         if(i < thread->new_channels->size()) delete_channel(i);
411 }
412
413 int ChannelEditWindow::move_channel_up()
414 {
415         if(list_box->get_selection_number(0, 0) > -1)
416         {
417                 int number2 = list_box->get_selection_number(0, 0);
418                 int number1 = number2 - 1;
419                 Channel *temp;
420                 BC_ListBoxItem *temp_text;
421
422                 if(number1 < 0) number1 = thread->new_channels->size() - 1;
423
424                 temp = thread->new_channels->get(number1);
425                 thread->new_channels->set(number1, thread->new_channels->get(number2));
426                 thread->new_channels->set(number2, temp);
427
428                 temp_text = channel_list.values[number1];
429                 channel_list.values[number1] = channel_list.values[number2];
430                 channel_list.values[number2] = temp_text;
431                 list_box->update(&channel_list,
432                         0,
433                         0,
434                         1,
435                         list_box->get_xposition(),
436                         list_box->get_yposition(),
437                         number1,
438                         1);
439         }
440         return 0;
441 }
442
443 int ChannelEditWindow::move_channel_down()
444 {
445         if(list_box->get_selection_number(0, 0) > -1)
446         {
447                 int number2 = list_box->get_selection_number(0, 0);
448                 int number1 = number2 + 1;
449                 Channel *temp;
450                 BC_ListBoxItem *temp_text;
451
452                 if(number1 > thread->new_channels->size() - 1) number1 = 0;
453
454                 temp = thread->new_channels->get(number1);
455                 thread->new_channels->set(number1, thread->new_channels->get(number2));
456                 thread->new_channels->set(number2, temp);
457                 temp_text = channel_list.values[number1];
458                 channel_list.values[number1] = channel_list.values[number2];
459                 channel_list.values[number2] = temp_text;
460                 list_box->update(&channel_list,
461                         0,
462                         0,
463                         1,
464                         list_box->get_xposition(),
465                         list_box->get_yposition(),
466                         number1,
467                         1);
468         }
469         return 0;
470 }
471
472 int ChannelEditWindow::change_channel_from_list(int channel_number)
473 {
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         }
479         return 0;
480 }
481
482 ChannelEditSelect::ChannelEditSelect(ChannelEditWindow *window, int x, int y)
483  : BC_GenericButton(x, y, _("Select"))
484 {
485         this->window = window;
486 }
487 ChannelEditSelect::~ChannelEditSelect()
488 {
489 }
490 int ChannelEditSelect::handle_event()
491 {
492         window->change_channel_from_list(
493                 window->list_box->get_selection_number(0, 0));
494         return 1;
495 }
496
497 ChannelEditAdd::ChannelEditAdd(ChannelEditWindow *window, int x, int y)
498  : BC_GenericButton(x, y, _("Add..."))
499 {
500         this->window = window;
501 }
502 ChannelEditAdd::~ChannelEditAdd()
503 {
504 }
505 int ChannelEditAdd::handle_event()
506 {
507         window->add_channel();
508         return 1;
509 }
510
511 ChannelEditList::ChannelEditList(ChannelEditWindow *window, int x, int y)
512  : BC_ListBox(x,
513                         y,
514                         185,
515                         window->get_h() - BC_OKButton::calculate_h() - y - 10,
516                         LISTBOX_TEXT,
517                         &(window->channel_list))
518 {
519         this->window = window;
520 }
521 ChannelEditList::~ChannelEditList()
522 {
523 }
524 int ChannelEditList::handle_event()
525 {
526         window->edit_channel();
527         return 1;
528 }
529
530 ChannelEditMoveUp::ChannelEditMoveUp(ChannelEditWindow *window, int x, int y)
531  : BC_GenericButton(x, y, _("Move up"))
532 {
533         this->window = window;
534 }
535 ChannelEditMoveUp::~ChannelEditMoveUp()
536 {
537 }
538 int ChannelEditMoveUp::handle_event()
539 {
540         lock_window("ChannelEditMoveUp::handle_event");
541         window->move_channel_up();
542         unlock_window();
543         return 1;
544 }
545
546 ChannelEditMoveDown::ChannelEditMoveDown(ChannelEditWindow *window, int x, int y)
547  : BC_GenericButton(x, y, _("Move down"))
548 {
549         this->window = window;
550 }
551 ChannelEditMoveDown::~ChannelEditMoveDown()
552 {
553 }
554 int ChannelEditMoveDown::handle_event()
555 {
556         lock_window("ChannelEditMoveDown::handle_event");
557         window->move_channel_down();
558         unlock_window();
559         return 1;
560 }
561
562 ChannelEditSort::ChannelEditSort(ChannelEditWindow *window, int x, int y)
563  : BC_GenericButton(x, y, _("Sort"))
564 {
565         this->window = window;
566 }
567 int ChannelEditSort::handle_event()
568 {
569         lock_window("ChannelEditSort::handle_event");
570         window->sort();
571         unlock_window();
572         return 1;
573 }
574
575 ChannelEditScan::ChannelEditScan(ChannelEditWindow *window, int x, int y)
576  : BC_GenericButton(x, y, _("Scan"))
577 {
578         this->window = window;
579 }
580 int ChannelEditScan::handle_event()
581 {
582         window->scan_confirm();
583         return 1;
584 }
585
586 ChannelEditDel::ChannelEditDel(ChannelEditWindow *window, int x, int y)
587  : BC_GenericButton(x, y, _("Delete"))
588 {
589         this->window = window;
590 }
591 ChannelEditDel::~ChannelEditDel()
592 {
593 }
594 int ChannelEditDel::handle_event()
595 {
596         if(window->list_box->get_selection_number(0, 0) > -1)
597                 window->delete_channel(window->list_box->get_selection_number(0, 0));
598         return 1;
599 }
600
601 ChannelEdit::ChannelEdit(ChannelEditWindow *window, int x, int y)
602  : BC_GenericButton(x, y, _("Edit..."))
603 {
604         this->window = window;
605 }
606 ChannelEdit::~ChannelEdit()
607 {
608 }
609 int ChannelEdit::handle_event()
610 {
611         window->edit_channel();
612         return 1;
613 }
614
615 ChannelEditPicture::ChannelEditPicture(ChannelEditWindow *window, int x, int y)
616  : BC_GenericButton(x, y, _("Picture..."))
617 {
618         this->window = window;
619 }
620 ChannelEditPicture::~ChannelEditPicture()
621 {
622 }
623 int ChannelEditPicture::handle_event()
624 {
625         window->edit_picture();
626         return 1;
627 }
628
629
630
631
632
633
634
635
636
637
638
639
640 // ========================= confirm overwrite by channel scannin
641
642
643 ConfirmScan::ConfirmScan(ChannelEditWindow *gui, int x, int y)
644  : BC_Window(_(PROGRAM_NAME ": Scan confirm"),
645         x,
646         y,
647         350,
648         BC_OKButton::calculate_h() + 130,
649         0,
650         0,
651         0,
652         0,
653         1)
654 {
655         this->gui = gui;
656 }
657
658 void ConfirmScan::create_objects()
659 {
660         int x = 10, y = 10;
661         int y2 = 0, x2 = 0;
662         BC_Title *title;
663         add_subwindow(title = new BC_Title(x, y, _("Set parameters for channel scanning.")));
664         y += title->get_h() + 10;
665         y2 = y;
666
667         add_subwindow(title = new BC_Title(x, y, _("Frequency table:")));
668         x2 = title->get_w();
669         y += BC_PopupMenu::calculate_h();
670         add_subwindow(title = new BC_Title(x, y, _("Norm:")));
671         x2 = MAX(x2, title->get_w());
672         y += BC_PopupMenu::calculate_h();
673         add_subwindow(title = new BC_Title(x, y, _("Input:")));
674         x2 = MAX(x2, title->get_w());
675         y += BC_PopupMenu::calculate_h();
676         x2 += x + 5;
677
678         y = y2;
679         x = x2;
680         ChannelEditEditFreqtable *table;
681         add_subwindow(table = new ChannelEditEditFreqtable(x,
682                 y,
683                 0,
684                 gui->thread));
685         table->add_items();
686         y += table->get_h() + 10;
687
688         ChannelEditEditNorm *norm;
689         add_subwindow(norm = new ChannelEditEditNorm(x,
690                 y,
691                 0,
692                 gui->thread));
693         norm->add_items();
694         y += norm->get_h() + 10;
695
696         ChannelEditEditInput *input;
697         add_subwindow(input = new ChannelEditEditInput(x,
698                 y,
699                 0,
700                 gui->thread));
701         input->add_items();
702
703
704         add_subwindow(new BC_OKButton(this));
705         add_subwindow(new BC_CancelButton(this));
706         show_window();
707 }
708
709
710
711
712
713
714
715 ConfirmScanThread::ConfirmScanThread(ChannelEditWindow *gui)
716  : BC_DialogThread()
717 {
718         this->gui = gui;
719 }
720
721 void ConfirmScanThread::handle_done_event(int result)
722 {
723         gui->channel_picker->save_scan_defaults(&gui->thread->scan_params);
724         if(!result)
725         {
726                 get_gui()->hide_window();
727                 gui->lock_window("ConfirmScanThread::handle_done_event");
728                 gui->scan();
729                 gui->unlock_window();
730         }
731 }
732
733 ConfirmScanThread::~ConfirmScanThread()
734 {
735         close_window();
736 }
737
738 BC_Window* ConfirmScanThread::new_gui()
739 {
740         int x = gui->get_abs_cursor_x(1);
741         int y = gui->get_abs_cursor_y(1);
742         ConfirmScan *result = new ConfirmScan(gui, x, y);
743         result->create_objects();
744         return result;
745 }
746
747
748
749
750
751
752 ScanThread::ScanThread(ChannelEditThread *edit)
753  : Thread(1, 0, 0)
754 {
755         this->edit = edit;
756         interrupt = 1;
757         progress = 0;
758 }
759
760 ScanThread::~ScanThread()
761 {
762         stop();
763 }
764
765 void ScanThread::stop()
766 {
767 // Cancel previous job
768         interrupt = 1;
769         Thread::join();
770         if( progress ) {
771                 progress->stop_progress();
772                 delete progress;  progress = 0;
773         }
774 }
775
776 void ScanThread::start()
777 {
778         stop();
779         interrupt = 0;
780
781         progress = new BC_ProgressBox(
782                 edit->channel_picker->parent_window->get_abs_cursor_x(1),
783                 edit->channel_picker->parent_window->get_abs_cursor_y(1),
784                 _("Scanning"),
785                 chanlists[edit->scan_params.freqtable].count);
786         progress->start();
787
788         Thread::start();
789 }
790
791 void ScanThread::run()
792 {
793         for(int i = 0; i < chanlists[edit->scan_params.freqtable].count &&
794                         !interrupt && !progress->is_cancelled(); i++) {
795                 edit->scan_params.entry = i;
796                 char string[BCTEXTLEN];
797                 sprintf(edit->scan_params.title, "%s",
798                         chanlists[edit->scan_params.freqtable].list[i].name);
799                 sprintf(string, _("Scanning %s"), edit->scan_params.title);
800                 progress->update_title(string, 1);
801                 progress->update(i, 1);
802                 edit->channel_picker->set_channel(&edit->scan_params);
803                 sleep(1); // has_signal should do whatever it takes
804                 if( interrupt ) break;
805                 int got_signal = edit->channel_picker->has_signal();
806                 if( interrupt ) break;
807                 if(!got_signal) continue;
808                 if(edit->channel_picker->get_channel_usage()->has_subchan) {
809                         ArrayList<Channel*> channels;
810                         edit->channel_picker->create_channeldb(&channels);
811                         if( channels.total ) {
812                                 edit->window->lock_window("ScanThread::run");
813                                 for( int i=0; i<channels.total; ++i ) {
814                                         Channel *new_channel = channels.values[i];
815                                         new_channel->copy_usage(&edit->scan_params);
816                                         edit->new_channels->append(new_channel);
817                                 }
818                                 edit->window->update_list();
819                                 edit->window->unlock_window();
820                                 continue;
821                         }
822                 }
823                 Channel *new_channel = new Channel;
824                 new_channel->copy_usage(&edit->scan_params);
825                 new_channel->copy_settings(&edit->scan_params);
826                 edit->window->lock_window("ScanThread::run");
827                 edit->new_channels->append(new_channel);
828                 edit->window->update_list();
829                 edit->window->unlock_window();
830         }
831         edit->window->set_done(interrupt || progress->is_cancelled() ? 1 : 0);
832 }
833
834
835
836
837
838
839
840 // ================================= Edit a single channel
841
842
843
844 ChannelEditEditThread::ChannelEditEditThread(ChannelEditWindow *window,
845         ChannelPicker *channel_picker)
846  : Thread()
847 {
848         this->window = window;
849         this->channel_picker = channel_picker;
850         in_progress = 0;
851         edit_window = 0;
852         editing = 0;
853         completion = new Condition(1, "ChannelEditEditThread::completion");
854 }
855
856 ChannelEditEditThread::~ChannelEditEditThread()
857 {
858         close_threads();
859         delete completion;
860 }
861
862 void ChannelEditEditThread::close_threads()
863 {
864         if(edit_window)
865         {
866                 edit_window->set_done(1);
867                 completion->lock("ChannelEditEditThread::close_threads");
868                 completion->unlock();
869         }
870 }
871
872 int ChannelEditEditThread::edit_channel(Channel *channel, int editing)
873 {
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;
882
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);
889
890         if(editing && new_channel.title[0])
891                 user_title = 1;
892         else
893                 user_title = 0;
894         set_synchronous(0);
895         Thread::start();
896         return 0;
897 }
898
899
900 void ChannelEditEditThread::set_device()
901 {
902         channel_picker->set_channel(&new_channel);
903 }
904
905 void ChannelEditEditThread::change_source(const char *source_name)
906 {
907         for(int 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         }
924 }
925
926 void ChannelEditEditThread::source_up()
927 {
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();
932 }
933
934 void ChannelEditEditThread::source_down()
935 {
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();
940 }
941
942 void ChannelEditEditThread::set_input(int value)
943 {
944         new_channel.input = value;
945         set_device();
946 }
947
948 void ChannelEditEditThread::set_norm(int value)
949 {
950         new_channel.norm = value;
951         set_device();
952 }
953
954 void ChannelEditEditThread::set_freqtable(int value)
955 {
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();
960 }
961
962 void ChannelEditEditThread::run()
963 {
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;
969
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;
991 }
992
993 ChannelEditEditWindow::ChannelEditEditWindow(ChannelEditEditThread *thread,
994         ChannelEditWindow *window,
995         ChannelPicker *channel_picker)
996  : BC_Window(_(PROGRAM_NAME ": Edit Channel"),
997         channel_picker->parent_window->get_abs_cursor_x(1),
998         channel_picker->parent_window->get_abs_cursor_y(1),
999         390,
1000         300,
1001         390,
1002         300,
1003         0,
1004         0,
1005         1)
1006 {
1007         this->channel_picker = channel_picker;
1008         this->window = window;
1009         this->thread = thread;
1010 }
1011 ChannelEditEditWindow::~ChannelEditEditWindow()
1012 {
1013 }
1014 void ChannelEditEditWindow::create_objects(Channel *channel)
1015 {
1016         this->new_channel = channel;
1017         Channel *channel_usage = channel_picker->get_channel_usage();
1018         title_text = 0;
1019
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, MSG_NO_INP_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 //      }
1036
1037         if(channel_usage && 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;
1044
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         }
1054
1055         if(channel_usage && 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         }
1061
1062         if(channel_usage && 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         }
1073
1074         if( (channel_usage && channel_usage->use_input) ||
1075                 !channel_usage)
1076         {
1077                 add_subwindow(new BC_Title(x, y, _("Input:")));
1078                 ChannelEditEditInput *input;
1079                 add_subwindow(input = new ChannelEditEditInput(x + 130,
1080                         y,
1081                         thread,
1082                         window->thread));
1083                 input->add_items();
1084                 y += 30;
1085         }
1086
1087         add_subwindow(new BC_OKButton(this));
1088         x += 200;
1089         add_subwindow(new BC_CancelButton(this));
1090         show_window();
1091 }
1092
1093 ChannelEditEditTitle::ChannelEditEditTitle(int x,
1094         int y,
1095         ChannelEditEditThread *thread)
1096  : BC_TextBox(x, y, 150, 1, thread->new_channel.title)
1097 {
1098         this->thread = thread;
1099 }
1100 ChannelEditEditTitle::~ChannelEditEditTitle()
1101 {
1102 }
1103 int ChannelEditEditTitle::handle_event()
1104 {
1105         if(strlen(get_text()) < 1024)
1106         {
1107                 strcpy(thread->new_channel.title, get_text());
1108         }
1109         thread->user_title = get_text()[0] ? 1 : 0;
1110         return 1;
1111 }
1112
1113
1114 ChannelEditEditSource::ChannelEditEditSource(int x, int y, ChannelEditEditThread *thread)
1115  : BC_TextBox(x, y, 150, 1, chanlists[thread->new_channel.freqtable].list[thread->new_channel.entry].name)
1116 {
1117         this->thread = thread;
1118 }
1119
1120 ChannelEditEditSource::~ChannelEditEditSource()
1121 {
1122 }
1123 int ChannelEditEditSource::handle_event()
1124 {
1125         thread->change_source(get_text());
1126         return 1;
1127 }
1128
1129
1130 ChannelEditEditSourceTumbler::ChannelEditEditSourceTumbler(int x, int y, ChannelEditEditThread *thread)
1131  : BC_Tumbler(x, y)
1132 {
1133         this->thread = thread;
1134 }
1135 ChannelEditEditSourceTumbler::~ChannelEditEditSourceTumbler()
1136 {
1137 }
1138 int ChannelEditEditSourceTumbler::handle_up_event()
1139 {
1140         thread->source_up();
1141         return 1;
1142 }
1143 int ChannelEditEditSourceTumbler::handle_down_event()
1144 {
1145         thread->source_down();
1146         return 1;
1147 }
1148
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))
1157 {
1158         this->thread = thread;
1159         this->edit = edit;
1160 }
1161 ChannelEditEditInput::~ChannelEditEditInput()
1162 {
1163 }
1164 void ChannelEditEditInput::add_items()
1165 {
1166         ArrayList<Channel*> *inputs;
1167         inputs = edit->channel_picker->get_video_inputs();
1168
1169         if(inputs)
1170         {
1171                 for(int i = 0; i < inputs->total; i++)
1172                 {
1173                         add_item(new ChannelEditEditInputItem(thread,
1174                                 edit,
1175                                 inputs->values[i]->device_name,
1176                                 i));
1177                 }
1178         }
1179 }
1180 int ChannelEditEditInput::handle_event()
1181 {
1182         return 0;
1183 }
1184
1185 ChannelEditEditInputItem::ChannelEditEditInputItem(ChannelEditEditThread *thread,
1186         ChannelEditThread *edit,
1187         char *text,
1188         int value)
1189  : BC_MenuItem(text)
1190 {
1191         this->thread = thread;
1192         this->edit = edit;
1193         this->value = value;
1194 }
1195 ChannelEditEditInputItem::~ChannelEditEditInputItem()
1196 {
1197 }
1198 int ChannelEditEditInputItem::handle_event()
1199 {
1200         get_popup_menu()->set_text(get_text());
1201         if(thread && !thread->user_title)
1202         {
1203                 strcpy(thread->new_channel.title, get_text());
1204                 if(thread->edit_window->title_text)
1205                 {
1206                         thread->edit_window->title_text->update(get_text());
1207                 }
1208         }
1209         if(thread)
1210                 thread->set_input(value);
1211         else
1212                 edit->scan_params.input = value;
1213         return 1;
1214 }
1215
1216 ChannelEditEditNorm::ChannelEditEditNorm(int x,
1217         int y,
1218         ChannelEditEditThread *thread,
1219         ChannelEditThread *edit)
1220  : BC_PopupMenu(x,
1221         y,
1222         100,
1223         edit->value_to_norm(thread ? thread->new_channel.norm : edit->scan_params.norm))
1224 {
1225         this->thread = thread;
1226         this->edit = edit;
1227 }
1228 ChannelEditEditNorm::~ChannelEditEditNorm()
1229 {
1230 }
1231 void ChannelEditEditNorm::add_items()
1232 {
1233         add_item(new ChannelEditEditNormItem(thread,
1234                 edit,
1235                 edit->value_to_norm(NTSC), NTSC));
1236         add_item(new ChannelEditEditNormItem(thread,
1237                 edit,
1238                 edit->value_to_norm(PAL), PAL));
1239         add_item(new ChannelEditEditNormItem(thread,
1240                 edit,
1241                 edit->value_to_norm(SECAM), SECAM));
1242 }
1243
1244
1245 ChannelEditEditNormItem::ChannelEditEditNormItem(ChannelEditEditThread *thread,
1246         ChannelEditThread *edit,
1247         char *text,
1248         int value)
1249  : BC_MenuItem(text)
1250 {
1251         this->value = value;
1252         this->edit = edit;
1253         this->thread = thread;
1254 }
1255 ChannelEditEditNormItem::~ChannelEditEditNormItem()
1256 {
1257 }
1258 int ChannelEditEditNormItem::handle_event()
1259 {
1260         get_popup_menu()->set_text(get_text());
1261         if(thread)
1262                 thread->set_norm(value);
1263         else
1264                 edit->scan_params.norm = value;
1265         return 1;
1266 }
1267
1268
1269 ChannelEditEditFreqtable::ChannelEditEditFreqtable(int x,
1270         int y,
1271         ChannelEditEditThread *thread,
1272         ChannelEditThread *edit)
1273  : BC_PopupMenu(x,
1274         y,
1275         150,
1276         edit->value_to_freqtable(thread ? thread->new_channel.freqtable : edit->scan_params.freqtable))
1277 {
1278         this->thread = thread;
1279         this->edit = edit;
1280 }
1281 ChannelEditEditFreqtable::~ChannelEditEditFreqtable()
1282 {
1283 }
1284 void ChannelEditEditFreqtable::add_items()
1285 {
1286         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(NTSC_DVB), NTSC_DVB));
1287         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(CATV_DVB), CATV_DVB));
1288         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(NTSC_BCAST), NTSC_BCAST));
1289         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(NTSC_CABLE), NTSC_CABLE));
1290         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(NTSC_HRC), NTSC_HRC));
1291         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(NTSC_BCAST_JP), NTSC_BCAST_JP));
1292         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(NTSC_CABLE_JP), NTSC_CABLE_JP));
1293         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(PAL_AUSTRALIA), PAL_AUSTRALIA));
1294         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(PAL_EUROPE), PAL_EUROPE));
1295         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(PAL_E_EUROPE), PAL_E_EUROPE));
1296         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(PAL_ITALY), PAL_ITALY));
1297         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(PAL_IRELAND), PAL_IRELAND));
1298         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(PAL_NEWZEALAND), PAL_NEWZEALAND));
1299 }
1300
1301 ChannelEditEditFreqItem::ChannelEditEditFreqItem(ChannelEditEditThread *thread,
1302         ChannelEditThread *edit,
1303         char *text, int value)
1304  : BC_MenuItem(text)
1305 {
1306         this->value = value;
1307         this->edit = edit;
1308         this->thread = thread;
1309 }
1310 ChannelEditEditFreqItem::~ChannelEditEditFreqItem()
1311 {
1312 }
1313 int ChannelEditEditFreqItem::handle_event()
1314 {
1315         get_popup_menu()->set_text(get_text());
1316         if(thread)
1317                 thread->set_freqtable(value);
1318         else
1319                 edit->scan_params.freqtable = value;
1320         return 1;
1321 }
1322
1323
1324
1325 ChannelEditEditFine::ChannelEditEditFine(int x,
1326         int y,
1327         ChannelEditEditThread *thread)
1328  : BC_ISlider(x,
1329                 y,
1330                 0,
1331                 240,
1332                 240,
1333                 -100,
1334                 100,
1335                 thread->new_channel.fine_tune)
1336 {
1337         this->thread = thread;
1338 }
1339 ChannelEditEditFine::~ChannelEditEditFine()
1340 {
1341 }
1342 int ChannelEditEditFine::handle_event()
1343 {
1344         return 1;
1345 }
1346 int ChannelEditEditFine::button_release_event()
1347 {
1348         if(BC_Slider::button_release_event())
1349         {
1350                 thread->new_channel.fine_tune = get_value();
1351                 thread->set_device();
1352                 return 1;
1353         }
1354         return 0;
1355 }
1356
1357
1358 // ========================== picture quality
1359
1360 ChannelEditPictureThread::ChannelEditPictureThread(
1361         ChannelPicker *channel_picker)
1362  : BC_DialogThread()
1363 {
1364         this->channel_picker = channel_picker;
1365 }
1366 ChannelEditPictureThread::~ChannelEditPictureThread()
1367 {
1368 }
1369
1370 void ChannelEditPictureThread::handle_done_event(int result)
1371 {
1372         if(channel_picker->get_picture_usage())
1373                 channel_picker->get_picture_usage()->save_defaults();
1374 }
1375
1376 BC_Window* ChannelEditPictureThread::new_gui()
1377 {
1378         ChannelEditPictureWindow *edit_window = new ChannelEditPictureWindow(this,
1379                 channel_picker);
1380         edit_window->create_objects();
1381         return edit_window;
1382 }
1383
1384 void ChannelEditPictureThread::edit_picture()
1385 {
1386         start();
1387 }
1388
1389
1390 ChannelEditPictureWindow::ChannelEditPictureWindow(ChannelEditPictureThread *thread,
1391         ChannelPicker *channel_picker)
1392  : BC_Window(_(PROGRAM_NAME ": Picture"),
1393         channel_picker->mwindow->session->picture_x,
1394         channel_picker->mwindow->session->picture_y,
1395         calculate_w(channel_picker),
1396         calculate_h(channel_picker),
1397         calculate_w(channel_picker),
1398         calculate_h(channel_picker))
1399 {
1400         this->thread = thread;
1401         this->channel_picker = channel_picker;
1402 }
1403 ChannelEditPictureWindow::~ChannelEditPictureWindow()
1404 {
1405 }
1406
1407 int ChannelEditPictureWindow::calculate_h(ChannelPicker *channel_picker)
1408 {
1409         PictureConfig *picture_usage = channel_picker->get_picture_usage();
1410         int pad = BC_Pot::calculate_h();
1411         int text_h = channel_picker->parent_window->get_text_height(MEDIUMFONT);
1412         int result = 20 + text_h + 5 + BC_OKButton::calculate_h();
1413
1414 // Only used for Video4Linux 1
1415         if( !picture_usage || (
1416              !picture_usage->use_brightness &&
1417              !picture_usage->use_contrast &&
1418              !picture_usage->use_color &&
1419              !picture_usage->use_hue &&
1420              !picture_usage->use_whiteness &&
1421              !channel_picker->get_controls() ) ) {
1422                 result += BC_Title::calculate_h(channel_picker->parent_window,
1423                         MSG_NO_PIC_CONTROLS);
1424         }
1425         else
1426         {
1427                 if(picture_usage->use_brightness)
1428                         result += pad;
1429                 if(picture_usage->use_contrast)
1430                         result += pad;
1431                 if(picture_usage->use_color)
1432                         result += pad;
1433                 if(picture_usage->use_hue)
1434                         result += pad;
1435                 if(picture_usage->use_whiteness)
1436                         result += pad;
1437         }
1438
1439         result += channel_picker->get_controls() * pad;
1440         return result;
1441 }
1442
1443 int ChannelEditPictureWindow::calculate_w(ChannelPicker *channel_picker)
1444 {
1445         PictureConfig *picture_usage = channel_picker->get_picture_usage();
1446         int widget_border = ((Theme*)channel_picker->get_theme())->widget_border;
1447         int pad = BC_Pot::calculate_w() + 4 * widget_border;
1448         int result = 0;
1449
1450 // Only used for Video4Linux 1
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                 result = BC_Title::calculate_w(channel_picker->parent_window,
1460                         MSG_NO_PIC_CONTROLS) + 20;
1461         }
1462
1463 // Only used for Video4Linux 1
1464         if(picture_usage)
1465         {
1466                 if(picture_usage->use_brightness)
1467                 {
1468                         int new_w = BC_Title::calculate_w(channel_picker->parent_window, _("Brightness:")) + pad;
1469                         result = MAX(result, new_w);
1470                 }
1471                 if(picture_usage->use_contrast)
1472                 {
1473                         int new_w = BC_Title::calculate_w(channel_picker->parent_window, _("Contrast:")) + pad;
1474                         result = MAX(result, new_w);
1475                 }
1476                 if(picture_usage->use_color)
1477                 {
1478                         int new_w = BC_Title::calculate_w(channel_picker->parent_window, _("Color:")) + pad;
1479                         result = MAX(result, new_w);
1480                 }
1481                 if(picture_usage->use_hue)
1482                 {
1483                         int new_w = BC_Title::calculate_w(channel_picker->parent_window, _("Hue:")) + pad;
1484                         result = MAX(result, new_w);
1485                 }
1486                 if(picture_usage->use_whiteness)
1487                 {
1488                         int new_w = BC_Title::calculate_w(channel_picker->parent_window, _("Whiteness:")) + pad;
1489                         result = MAX(result, new_w);
1490                 }
1491         }
1492
1493         for(int i = 0; i < channel_picker->get_controls(); i++)
1494         {
1495                 int new_w = BC_Title::calculate_w(channel_picker->parent_window,
1496                                 channel_picker->get_control(i)->name) +
1497                         pad;
1498                 result = MAX(result, new_w);
1499         }
1500
1501         return result;
1502 }
1503
1504
1505 void ChannelEditPictureWindow::create_objects()
1506 {
1507         int x = 10, y = 10;
1508         int widget_border = ((Theme*)channel_picker->get_theme())->widget_border;
1509         int x1 = get_w() - BC_Pot::calculate_w() * 2 - widget_border * 2;
1510         int x2 = get_w() - BC_Pot::calculate_w() - widget_border;
1511         int pad = BC_Pot::calculate_h();
1512
1513 #define SWAP_X x1 ^= x2; x2 ^= x1; x1 ^= x2;
1514
1515         PictureConfig *picture_usage = channel_picker->get_picture_usage();
1516
1517 // Only used for Video4Linux 1
1518         if(!picture_usage ||
1519                 (!picture_usage->use_brightness &&
1520                 !picture_usage->use_contrast &&
1521                 !picture_usage->use_color &&
1522                 !picture_usage->use_hue &&
1523                 !picture_usage->use_whiteness &&
1524                 !channel_picker->get_controls()))
1525         {
1526                 add_subwindow(new BC_Title(x, y, MSG_NO_PIC_CONTROLS));
1527                 y += 50;
1528         }
1529
1530 // Only used for Video4Linux 1
1531         if(picture_usage && picture_usage->use_brightness)
1532         {
1533                 add_subwindow(new BC_Title(x, y + 10, _("Brightness:")));
1534                 add_subwindow(new ChannelEditBright(x1, y, channel_picker, channel_picker->get_brightness()));
1535                 y += pad;
1536                 SWAP_X
1537
1538         }
1539
1540         if(picture_usage && picture_usage->use_contrast)
1541         {
1542                 add_subwindow(new BC_Title(x, y + 10, _("Contrast:")));
1543                 add_subwindow(new ChannelEditContrast(x1, y, channel_picker, channel_picker->get_contrast()));
1544                 y += pad;
1545                 SWAP_X
1546         }
1547
1548         if(picture_usage && picture_usage->use_color)
1549         {
1550                 add_subwindow(new BC_Title(x, y + 10, _("Color:")));
1551                 add_subwindow(new ChannelEditColor(x1, y, channel_picker, channel_picker->get_color()));
1552                 y += pad;
1553                 SWAP_X
1554         }
1555
1556         if(picture_usage && picture_usage->use_hue)
1557         {
1558                 add_subwindow(new BC_Title(x, y + 10, _("Hue:")));
1559                 add_subwindow(new ChannelEditHue(x1, y, channel_picker, channel_picker->get_hue()));
1560                 y += pad;
1561                 SWAP_X
1562         }
1563
1564         if(picture_usage && picture_usage->use_whiteness)
1565         {
1566                 add_subwindow(new BC_Title(x, y + 10, _("Whiteness:")));
1567                 add_subwindow(new ChannelEditWhiteness(x1, y, channel_picker, channel_picker->get_whiteness()));
1568                 y += pad;
1569                 SWAP_X
1570         }
1571
1572         for(int i = 0; i < channel_picker->get_controls(); i++)
1573         {
1574                 BC_Title *title;
1575                 add_subwindow(title = new BC_Title(x,
1576                         y + 10,
1577                         _(channel_picker->get_control(i)->name)));
1578
1579                 int x3 = x1;
1580                 if(x3 < title->get_x() + title->get_w() + widget_border)
1581                         x3 = title->get_x() + title->get_w() + widget_border;
1582
1583                 add_subwindow(new ChannelEditCommon(x3,
1584                         y,
1585                         channel_picker,
1586                         channel_picker->get_control(i)));
1587                 y += pad;
1588                 SWAP_X
1589         }
1590
1591
1592         y += pad;
1593         add_subwindow(new BC_OKButton(this));
1594         show_window();
1595 }
1596
1597 int ChannelEditPictureWindow::translation_event()
1598 {
1599         channel_picker->mwindow->session->picture_x = get_x();
1600         channel_picker->mwindow->session->picture_y = get_y();
1601         return 0;
1602 }
1603
1604
1605
1606 ChannelEditBright::ChannelEditBright(int x, int y, ChannelPicker *channel_picker, int value)
1607  : BC_IPot(x,
1608                 y,
1609                 value,
1610                 -100,
1611                 100)
1612 {
1613         this->channel_picker = channel_picker;
1614 }
1615 ChannelEditBright::~ChannelEditBright() {}
1616 int ChannelEditBright::handle_event()
1617 {
1618         return 1;
1619 }
1620 int ChannelEditBright::button_release_event()
1621 {
1622         if(BC_Pot::button_release_event())
1623         {
1624                 channel_picker->set_brightness(get_value());
1625                 return 1;
1626         }
1627         return 0;
1628 }
1629
1630 ChannelEditContrast::ChannelEditContrast(int x, int y, ChannelPicker *channel_picker, int value)
1631  : BC_IPot(x,
1632                 y,
1633                 value,
1634                 -100,
1635                 100)
1636 {
1637         this->channel_picker = channel_picker;
1638 }
1639 ChannelEditContrast::~ChannelEditContrast() {}
1640 int ChannelEditContrast::handle_event()
1641 {
1642         return 1;
1643 }
1644 int ChannelEditContrast::button_release_event()
1645 {
1646         if(BC_Pot::button_release_event())
1647         {
1648                 channel_picker->set_contrast(get_value());
1649                 return 1;
1650         }
1651         return 0;
1652 }
1653
1654
1655 ChannelEditColor::ChannelEditColor(int x, int y, ChannelPicker *channel_picker, int value)
1656  : BC_IPot(x,
1657                 y,
1658                 value,
1659                 -100,
1660                 100)
1661 {
1662         this->channel_picker = channel_picker;
1663 }
1664 ChannelEditColor::~ChannelEditColor() {}
1665 int ChannelEditColor::handle_event()
1666 {
1667         return 1;
1668 }
1669 int ChannelEditColor::button_release_event()
1670 {
1671         if(BC_Pot::button_release_event())
1672         {
1673                 channel_picker->set_color(get_value());
1674                 return 1;
1675         }
1676         return 0;
1677 }
1678
1679 ChannelEditHue::ChannelEditHue(int x, int y, ChannelPicker *channel_picker, int value)
1680  : BC_IPot(x,
1681                 y,
1682                 value,
1683                 -100,
1684                 100)
1685 {
1686         this->channel_picker = channel_picker;
1687 }
1688 ChannelEditHue::~ChannelEditHue() {}
1689 int ChannelEditHue::handle_event()
1690 {
1691         return 1;
1692 }
1693 int ChannelEditHue::button_release_event()
1694 {
1695         if(BC_Pot::button_release_event())
1696         {
1697                 channel_picker->set_hue(get_value());
1698                 return 1;
1699         }
1700         return 0;
1701 }
1702
1703 ChannelEditWhiteness::ChannelEditWhiteness(int x, int y, ChannelPicker *channel_picker, int value)
1704  : BC_IPot(x,
1705                 y,
1706                 value,
1707                 -100,
1708                 100)
1709 {
1710         this->channel_picker = channel_picker;
1711 }
1712 ChannelEditWhiteness::~ChannelEditWhiteness()
1713 {
1714 }
1715 int ChannelEditWhiteness::handle_event()
1716 {
1717         return 1;
1718 }
1719 int ChannelEditWhiteness::button_release_event()
1720 {
1721         if(BC_Pot::button_release_event())
1722         {
1723                 channel_picker->set_whiteness(get_value());
1724                 return 1;
1725         }
1726         return 0;
1727 }
1728
1729
1730
1731 ChannelEditCommon::ChannelEditCommon(int x,
1732         int y,
1733         ChannelPicker *channel_picker,
1734         PictureItem *item)
1735  : BC_IPot(x,
1736                 y,
1737                 item->value,
1738                 item->min,
1739                 item->max)
1740 {
1741         this->channel_picker = channel_picker;
1742         this->device_id = item->device_id;
1743 }
1744
1745 ChannelEditCommon::~ChannelEditCommon()
1746 {
1747 }
1748
1749 int ChannelEditCommon::handle_event()
1750 {
1751         return 1;
1752 }
1753
1754 int ChannelEditCommon::button_release_event()
1755 {
1756         if(BC_Pot::button_release_event())
1757         {
1758                 channel_picker->set_picture(device_id, get_value());
1759                 return 1;
1760         }
1761         return 0;
1762 }
1763
1764 int ChannelEditCommon::keypress_event()
1765 {
1766         if(BC_Pot::keypress_event())
1767         {
1768                 channel_picker->set_picture(device_id, get_value());
1769                 return 1;
1770         }
1771         return 0;
1772 }
1773
1774
1775
1776
1777