add haupauge-1657 dual usb capture support, add deinterlace to recordmonitor, asset...
[goodguy/cinelerra.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         xS(375), yS(400), xS(375), yS(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 xs10 = xS(10), ys10 = yS(10), ys30 = yS(30);
190         lock_window("ChannelEditWindow::create_objects");
191         int x = xs10, y = ys10;
192
193 // Create channel list
194         for(int i = 0; i < thread->new_channels->size(); i++)
195         {
196                 channel_list.append(new BC_ListBoxItem(thread->new_channels->get(i)->title));
197         }
198
199         add_subwindow(list_box = new ChannelEditList(this, x, y));
200         x += xS(200);
201         if(channel_picker->use_select())
202         {
203                 add_subwindow(new ChannelEditSelect(this, x, y));
204                 y += ys30;
205         }
206         add_subwindow(new ChannelEditAdd(this, x, y));
207         y += ys30;
208         add_subwindow(new ChannelEdit(this, x, y));
209         y += ys30;
210         add_subwindow(new ChannelEditMoveUp(this, x, y));
211         y += ys30;
212         add_subwindow(new ChannelEditMoveDown(this, x, y));
213         y += ys30;
214         add_subwindow(new ChannelEditSort(this, x, y));
215         y += ys30;
216
217         Channel *channel_usage = channel_picker->get_channel_usage();
218         if(channel_usage && channel_usage->has_scanning)
219         {
220                 add_subwindow(new ChannelEditScan(this, x, y));
221                 y += ys30;
222         }
223         add_subwindow(new ChannelEditDel(this, x, y));
224         y += ys30;
225         add_subwindow(new ChannelEditPicture(this, x, y));
226         y += yS(100);
227         x = xs10;
228         add_subwindow(new BC_OKButton(this));
229         x += xS(150);
230         add_subwindow(new BC_CancelButton(this));
231
232
233         edit_thread = new ChannelEditEditThread(this, channel_picker);
234         picture_thread = new ChannelEditPictureThread(channel_picker);
235         show_window();
236         unlock_window();
237 }
238
239 int ChannelEditWindow::close_event()
240 {
241         if( thread->scan_thread )
242                 thread->scan_thread->stop();
243         return BC_WindowBase::close_event();
244 }
245
246 int ChannelEditWindow::translation_event()
247 {
248         channel_picker->mwindow->session->channels_x = get_x();
249         channel_picker->mwindow->session->channels_y = get_y();
250         return 0;
251 }
252
253
254 int ChannelEditWindow::add_channel()
255 {
256         Channel *new_channel;
257         Channel *prev_channel = 0;
258
259 // Create new channel
260         new_channel = new Channel;
261
262 // Reuse parameters from previous channel
263         if(thread->new_channels->size())
264         {
265                 prev_channel = thread->new_channels->get(
266                                 thread->new_channels->size() - 1);
267                 new_channel->copy_settings(prev_channel);
268         }
269         else
270 // Use default channel parameters
271         if(channel_picker->get_master_channel())
272         {
273                 new_channel->copy_settings(channel_picker->get_master_channel());
274         }
275
276 // Copy device usage.  Need the same thing for playback.
277         if(channel_picker->get_master_channel())
278         {
279                 new_channel->copy_usage(channel_picker->get_master_channel());
280         }
281
282 // Add to channel table
283         channel_list.append(new BC_ListBoxItem(new_channel->title));
284         thread->new_channels->append(new_channel);
285         update_list();
286
287 // Start common routing
288         edit_thread->edit_channel(new_channel, 0);
289         return 0;
290 }
291
292 void ChannelEditWindow::update_list()
293 {
294 // Create channel list
295         channel_list.remove_all_objects();
296         for(int i = 0; i < thread->new_channels->size(); i++)
297         {
298                 channel_list.append(
299                         new BC_ListBoxItem(
300                                 thread->new_channels->get(i)->title));
301         }
302
303         list_box->update(&channel_list, 0, 0, 1, list_box->get_yposition());
304 }
305
306 void ChannelEditWindow::update_list(Channel *channel)
307 {
308         int i;
309         for(i = 0; i < thread->new_channels->size(); i++)
310                 if(thread->new_channels->get(i) == channel) break;
311
312         if(i < thread->new_channels->size())
313         {
314                 channel_list.values[i]->set_text(channel->title);
315         }
316
317         update_list();
318 }
319
320
321 void ChannelEditWindow::edit_channel()
322 {
323         if(list_box->get_selection_number(0, 0) > -1)
324         {
325                 thread->current_channel = list_box->get_selection_number(0, 0);
326                 edit_thread->edit_channel(
327                         thread->new_channels->get(
328                                 list_box->get_selection_number(0, 0)),
329                         1);
330         }
331 }
332
333 void ChannelEditWindow::edit_picture()
334 {
335         picture_thread->edit_picture();
336 }
337
338 void ChannelEditWindow::scan_confirm()
339 {
340         channel_picker->load_scan_defaults(&thread->scan_params);
341         if(!scan_confirm_thread) scan_confirm_thread = new ConfirmScanThread(this);
342         unlock_window();
343         scan_confirm_thread->start();
344         lock_window("ChannelEditWindow::scan_confirm");
345 }
346
347 void ChannelEditWindow::scan()
348 {
349         thread->new_channels->clear();
350         update_list();
351
352         if( !thread->scan_thread )
353                 thread->scan_thread = new ScanThread(thread);
354         thread->scan_thread->start();
355 }
356
357
358 void ChannelEditWindow::get_chan_num(Channel *channel, int &chan, int &stream)
359 {
360         const char *cp = channel->title;
361         int chn = 0, str = 0;
362         while( isdigit(*cp) ) chn = 10*chn + (*cp++ -'0');
363         if( chn != 0 && *cp != 0 ) {
364                 if( *cp++ == '.' )
365                         while( isdigit(*cp) ) str = 10*str + (*cp++ -'0');
366                 if( !str ) chn = 0;
367         }
368         chan = chn;  stream = str;
369 }
370
371 void ChannelEditWindow::sort()
372 {
373         int done = 0;
374         while(!done) {
375                 done = 1;
376                 for(int i = 0; i < thread->new_channels->size() - 1; i++) {
377                         Channel *channel1 = thread->new_channels->get(i);
378                         Channel *channel2 = thread->new_channels->get(i + 1);
379                         int ch1, st1;  get_chan_num(channel1, ch1, st1);
380                         int ch2, st2;  get_chan_num(channel2, ch2, st2);
381                         if( (ch1 > 0 && ch2 > 0) ?
382                              (ch1 > ch2 || (ch1 == ch2 && (st1 > st2 || (st1 == st2 &&
383                                 strcasecmp(channel2->title, channel1->title) < 0)))) :
384                              strcasecmp(channel2->title, channel1->title) < 0) {
385                                 thread->new_channels->set(i, channel2);
386                                 thread->new_channels->set(i + 1, channel1);
387                                 done = 0;
388                         }
389                 }
390         }
391         update_list();
392 }
393
394
395 void ChannelEditWindow::delete_channel(int number)
396 {
397         delete thread->new_channels->get(number);
398         channel_list.remove_number(number);
399         thread->new_channels->remove_number(number);
400         update_list();
401 }
402
403 void ChannelEditWindow::delete_channel(Channel *channel)
404 {
405         int i;
406         for(i = 0; i < thread->new_channels->size(); i++)
407         {
408                 if(thread->new_channels->get(i) == channel)
409                 {
410                         break;
411                 }
412         }
413         if(i < thread->new_channels->size()) delete_channel(i);
414 }
415
416 int ChannelEditWindow::move_channel_up()
417 {
418         if(list_box->get_selection_number(0, 0) > -1)
419         {
420                 int number2 = list_box->get_selection_number(0, 0);
421                 int number1 = number2 - 1;
422                 Channel *temp;
423                 BC_ListBoxItem *temp_text;
424
425                 if(number1 < 0) number1 = thread->new_channels->size() - 1;
426
427                 temp = thread->new_channels->get(number1);
428                 thread->new_channels->set(number1, thread->new_channels->get(number2));
429                 thread->new_channels->set(number2, temp);
430
431                 temp_text = channel_list.values[number1];
432                 channel_list.values[number1] = channel_list.values[number2];
433                 channel_list.values[number2] = temp_text;
434                 list_box->update(&channel_list, 0, 0, 1,
435                         list_box->get_xposition(), list_box->get_yposition(),
436                         number1, 1);
437         }
438         return 0;
439 }
440
441 int ChannelEditWindow::move_channel_down()
442 {
443         if(list_box->get_selection_number(0, 0) > -1)
444         {
445                 int number2 = list_box->get_selection_number(0, 0);
446                 int number1 = number2 + 1;
447                 Channel *temp;
448                 BC_ListBoxItem *temp_text;
449
450                 if(number1 > thread->new_channels->size() - 1) number1 = 0;
451
452                 temp = thread->new_channels->get(number1);
453                 thread->new_channels->set(number1, thread->new_channels->get(number2));
454                 thread->new_channels->set(number2, temp);
455                 temp_text = channel_list.values[number1];
456                 channel_list.values[number1] = channel_list.values[number2];
457                 channel_list.values[number2] = temp_text;
458                 list_box->update(&channel_list, 0, 0, 1,
459                         list_box->get_xposition(), list_box->get_yposition(),
460                         number1, 1);
461         }
462         return 0;
463 }
464
465 int ChannelEditWindow::change_channel_from_list(int channel_number)
466 {
467         if(channel_number > -1 && channel_number < thread->new_channels->size())
468         {
469                 thread->current_channel = channel_number;
470                 channel_picker->set_channel(thread->new_channels->get(channel_number));
471         }
472         return 0;
473 }
474
475 ChannelEditSelect::ChannelEditSelect(ChannelEditWindow *window, int x, int y)
476  : BC_GenericButton(x, y, _("Select"))
477 {
478         this->window = window;
479 }
480 ChannelEditSelect::~ChannelEditSelect()
481 {
482 }
483 int ChannelEditSelect::handle_event()
484 {
485         window->change_channel_from_list(
486                 window->list_box->get_selection_number(0, 0));
487         return 1;
488 }
489
490 ChannelEditAdd::ChannelEditAdd(ChannelEditWindow *window, int x, int y)
491  : BC_GenericButton(x, y, _("Add..."))
492 {
493         this->window = window;
494 }
495 ChannelEditAdd::~ChannelEditAdd()
496 {
497 }
498 int ChannelEditAdd::handle_event()
499 {
500         window->add_channel();
501         return 1;
502 }
503
504 ChannelEditList::ChannelEditList(ChannelEditWindow *window, int x, int y)
505  : BC_ListBox(x, y,
506         xS(185), window->get_h() - BC_OKButton::calculate_h() - y - yS(10),
507         LISTBOX_TEXT, &(window->channel_list))
508 {
509         this->window = window;
510 }
511 ChannelEditList::~ChannelEditList()
512 {
513 }
514 int ChannelEditList::handle_event()
515 {
516         window->edit_channel();
517         return 1;
518 }
519
520 ChannelEditMoveUp::ChannelEditMoveUp(ChannelEditWindow *window, int x, int y)
521  : BC_GenericButton(x, y, _("Move up"))
522 {
523         this->window = window;
524 }
525 ChannelEditMoveUp::~ChannelEditMoveUp()
526 {
527 }
528 int ChannelEditMoveUp::handle_event()
529 {
530         lock_window("ChannelEditMoveUp::handle_event");
531         window->move_channel_up();
532         unlock_window();
533         return 1;
534 }
535
536 ChannelEditMoveDown::ChannelEditMoveDown(ChannelEditWindow *window, int x, int y)
537  : BC_GenericButton(x, y, _("Move down"))
538 {
539         this->window = window;
540 }
541 ChannelEditMoveDown::~ChannelEditMoveDown()
542 {
543 }
544 int ChannelEditMoveDown::handle_event()
545 {
546         lock_window("ChannelEditMoveDown::handle_event");
547         window->move_channel_down();
548         unlock_window();
549         return 1;
550 }
551
552 ChannelEditSort::ChannelEditSort(ChannelEditWindow *window, int x, int y)
553  : BC_GenericButton(x, y, _("Sort"))
554 {
555         this->window = window;
556 }
557 int ChannelEditSort::handle_event()
558 {
559         lock_window("ChannelEditSort::handle_event");
560         window->sort();
561         unlock_window();
562         return 1;
563 }
564
565 ChannelEditScan::ChannelEditScan(ChannelEditWindow *window, int x, int y)
566  : BC_GenericButton(x, y, _("Scan"))
567 {
568         this->window = window;
569 }
570 int ChannelEditScan::handle_event()
571 {
572         window->scan_confirm();
573         return 1;
574 }
575
576 ChannelEditDel::ChannelEditDel(ChannelEditWindow *window, int x, int y)
577  : BC_GenericButton(x, y, _("Delete"))
578 {
579         this->window = window;
580 }
581 ChannelEditDel::~ChannelEditDel()
582 {
583 }
584 int ChannelEditDel::handle_event()
585 {
586         if(window->list_box->get_selection_number(0, 0) > -1)
587                 window->delete_channel(window->list_box->get_selection_number(0, 0));
588         return 1;
589 }
590
591 ChannelEdit::ChannelEdit(ChannelEditWindow *window, int x, int y)
592  : BC_GenericButton(x, y, _("Edit..."))
593 {
594         this->window = window;
595 }
596 ChannelEdit::~ChannelEdit()
597 {
598 }
599 int ChannelEdit::handle_event()
600 {
601         window->edit_channel();
602         return 1;
603 }
604
605 ChannelEditPicture::ChannelEditPicture(ChannelEditWindow *window, int x, int y)
606  : BC_GenericButton(x, y, _("Picture..."))
607 {
608         this->window = window;
609 }
610 ChannelEditPicture::~ChannelEditPicture()
611 {
612 }
613 int ChannelEditPicture::handle_event()
614 {
615         window->edit_picture();
616         return 1;
617 }
618
619
620 // ========================= confirm overwrite by channel scanning
621
622 ConfirmScan::ConfirmScan(ChannelEditWindow *gui, int x, int y)
623  : BC_Window(_(PROGRAM_NAME ": Scan confirm"),
624         x, y, xS(350), BC_OKButton::calculate_h() + yS(130),
625         0, 0, 0, 0, 1)
626 {
627         this->gui = gui;
628 }
629
630 void ConfirmScan::create_objects()
631 {
632         int xs5 = xS(5), xs10 = xS(10);
633         int ys10 = yS(10);
634         lock_window("ConfirmScan::create_objects");
635         int x = xs10, y = ys10;
636         int y2 = 0, x2 = 0;
637         BC_Title *title;
638         add_subwindow(title = new BC_Title(x, y, _("Set parameters for channel scanning.")));
639         y += title->get_h() + ys10;
640         y2 = y;
641
642         add_subwindow(title = new BC_Title(x, y, _("Frequency table:")));
643         x2 = title->get_w();
644         y += BC_PopupMenu::calculate_h();
645         add_subwindow(title = new BC_Title(x, y, _("Norm:")));
646         x2 = MAX(x2, title->get_w());
647         y += BC_PopupMenu::calculate_h();
648         add_subwindow(title = new BC_Title(x, y, _("Input:")));
649         x2 = MAX(x2, title->get_w());
650         y += BC_PopupMenu::calculate_h();
651         x2 += x + xs5;
652
653         y = y2;
654         x = x2;
655         ChannelEditEditFreqtable *table;
656         add_subwindow(table = new ChannelEditEditFreqtable(x, y, 0, gui->thread));
657         table->add_items();
658         y += table->get_h() + ys10;
659
660         ChannelEditEditNorm *norm;
661         add_subwindow(norm = new ChannelEditEditNorm(x, y, 0, gui->thread));
662         norm->add_items();
663         y += norm->get_h() + ys10;
664
665         ChannelEditEditInput *input;
666         add_subwindow(input = new ChannelEditEditInput(x, y, 0, gui->thread));
667         input->add_items();
668
669
670         add_subwindow(new BC_OKButton(this));
671         add_subwindow(new BC_CancelButton(this));
672         show_window();
673         unlock_window();
674 }
675
676 ConfirmScanThread::ConfirmScanThread(ChannelEditWindow *gui)
677  : BC_DialogThread()
678 {
679         this->gui = gui;
680 }
681
682 void ConfirmScanThread::handle_done_event(int result)
683 {
684         gui->channel_picker->save_scan_defaults(&gui->thread->scan_params);
685         if(!result)
686         {
687                 gui->lock_window("ConfirmScanThread::handle_done_event");
688                 gui->scan();
689                 gui->unlock_window();
690         }
691 }
692
693 ConfirmScanThread::~ConfirmScanThread()
694 {
695         close_window();
696 }
697
698 BC_Window* ConfirmScanThread::new_gui()
699 {
700         int x = gui->get_abs_cursor_x(1);
701         int y = gui->get_abs_cursor_y(1);
702         ConfirmScan *result = new ConfirmScan(gui, x, y);
703         result->create_objects();
704         return result;
705 }
706
707
708
709
710
711
712 ScanThread::ScanThread(ChannelEditThread *edit)
713  : Thread(1, 0, 0)
714 {
715         this->edit = edit;
716         interrupt = 1;
717         progress = 0;
718 }
719
720 ScanThread::~ScanThread()
721 {
722         stop();
723 }
724
725 void ScanThread::stop()
726 {
727 // Cancel previous job
728         interrupt = 1;
729         Thread::join();
730         if( progress ) {
731                 progress->stop_progress();
732                 delete progress;  progress = 0;
733         }
734 }
735
736 void ScanThread::start()
737 {
738         stop();
739         interrupt = 0;
740
741         progress = new BC_ProgressBox(
742                 edit->channel_picker->parent_window->get_abs_cursor_x(1),
743                 edit->channel_picker->parent_window->get_abs_cursor_y(1),
744                 _("Scanning"),
745                 chanlists[edit->scan_params.freqtable].count);
746         progress->start();
747
748         Thread::start();
749 }
750
751 void ScanThread::run()
752 {
753         for(int i = 0; i < chanlists[edit->scan_params.freqtable].count &&
754                         !interrupt && !progress->is_cancelled(); i++) {
755                 edit->scan_params.entry = i;
756                 char string[BCTEXTLEN];
757                 sprintf(edit->scan_params.title, "%s",
758                         chanlists[edit->scan_params.freqtable].list[i].name);
759                 sprintf(string, _("Scanning %s"), edit->scan_params.title);
760                 progress->update_title(string, 1);
761                 progress->update(i, 1);
762                 edit->channel_picker->set_channel(&edit->scan_params);
763                 sleep(1); // has_signal should do whatever it takes
764                 if( interrupt ) break;
765                 int got_signal = edit->channel_picker->has_signal();
766                 if( interrupt ) break;
767                 if(!got_signal) continue;
768                 if(edit->channel_picker->get_channel_usage()->has_subchan) {
769                         ArrayList<Channel*> channels;
770                         edit->channel_picker->create_channeldb(&channels);
771                         if( channels.total ) {
772                                 edit->window->lock_window("ScanThread::run");
773                                 for( int i=0; i<channels.total; ++i ) {
774                                         Channel *new_channel = channels.values[i];
775                                         new_channel->copy_usage(&edit->scan_params);
776                                         edit->new_channels->append(new_channel);
777                                 }
778                                 edit->window->update_list();
779                                 edit->window->unlock_window();
780                                 continue;
781                         }
782                 }
783                 Channel *new_channel = new Channel;
784                 new_channel->copy_usage(&edit->scan_params);
785                 new_channel->copy_settings(&edit->scan_params);
786                 edit->window->lock_window("ScanThread::run");
787                 edit->new_channels->append(new_channel);
788                 edit->window->update_list();
789                 edit->window->unlock_window();
790         }
791         edit->window->set_done(interrupt || progress->is_cancelled() ? 1 : 0);
792 }
793
794
795
796
797
798
799
800 // ================================= Edit a single channel
801
802
803
804 ChannelEditEditThread::ChannelEditEditThread(ChannelEditWindow *window,
805         ChannelPicker *channel_picker)
806  : Thread()
807 {
808         this->window = window;
809         this->channel_picker = channel_picker;
810         in_progress = 0;
811         edit_window = 0;
812         editing = 0;
813         completion = new Condition(1, "ChannelEditEditThread::completion");
814 }
815
816 ChannelEditEditThread::~ChannelEditEditThread()
817 {
818         close_threads();
819         delete completion;
820 }
821
822 void ChannelEditEditThread::close_threads()
823 {
824         if(edit_window)
825         {
826                 edit_window->set_done(1);
827                 completion->lock("ChannelEditEditThread::close_threads");
828                 completion->unlock();
829         }
830 }
831
832 int ChannelEditEditThread::edit_channel(Channel *channel, int editing)
833 {
834         if(in_progress)
835         {
836                 edit_window->lock_window("ChannelEditEditThread::edit_channel");
837                 edit_window->raise_window(1);
838                 edit_window->unlock_window();
839                 return 1;
840         }
841         in_progress = 1;
842
843 // Copy the channel to edit into a temporary
844         completion->lock("ChannelEditEditThread::edit_channel");
845         this->editing = editing;
846         this->output_channel = channel;
847         new_channel.copy_settings(output_channel);
848         new_channel.copy_usage(output_channel);
849
850         if(editing && new_channel.title[0])
851                 user_title = 1;
852         else
853                 user_title = 0;
854         set_synchronous(0);
855         Thread::start();
856         return 0;
857 }
858
859
860 void ChannelEditEditThread::set_device()
861 {
862         channel_picker->set_channel(&new_channel);
863 }
864
865 void ChannelEditEditThread::change_source(const char *source_name)
866 {
867         for(int i = 0; i < chanlists[new_channel.freqtable].count; i++)
868         {
869                 if(!strcasecmp(chanlists[new_channel.freqtable].list[i].name, source_name))
870                 {
871                         new_channel.entry = i;
872                         i = chanlists[new_channel.freqtable].count;
873                         set_device();
874                 }
875         }
876         if(!user_title)
877         {
878                 strcpy(new_channel.title, source_name);
879                 if(edit_window->title_text)
880                 {
881                         edit_window->title_text->update(source_name);
882                 }
883         }
884 }
885
886 void ChannelEditEditThread::source_up()
887 {
888         new_channel.entry++;
889         if(new_channel.entry > chanlists[new_channel.freqtable].count - 1) new_channel.entry = 0;
890         source_text->update(chanlists[new_channel.freqtable].list[new_channel.entry].name);
891         set_device();
892 }
893
894 void ChannelEditEditThread::source_down()
895 {
896         new_channel.entry--;
897         if(new_channel.entry < 0) new_channel.entry = chanlists[new_channel.freqtable].count - 1;
898         source_text->update(chanlists[new_channel.freqtable].list[new_channel.entry].name);
899         set_device();
900 }
901
902 void ChannelEditEditThread::set_input(int value)
903 {
904         new_channel.input = value;
905         set_device();
906 }
907
908 void ChannelEditEditThread::set_norm(int value)
909 {
910         new_channel.norm = value;
911         set_device();
912 }
913
914 void ChannelEditEditThread::set_freqtable(int value)
915 {
916         new_channel.freqtable = value;
917         if(new_channel.entry > chanlists[new_channel.freqtable].count - 1) new_channel.entry = 0;
918         source_text->update(chanlists[new_channel.freqtable].list[new_channel.entry].name);
919         set_device();
920 }
921
922 void ChannelEditEditThread::run()
923 {
924         ChannelEditEditWindow edit_window(this, window, channel_picker);
925         edit_window.create_objects(&new_channel);
926         this->edit_window = &edit_window;
927         int result = edit_window.run_window();
928         this->edit_window = 0;
929
930 // Done editing channel.  Keep channel.
931         if(!result)
932         {
933                 output_channel->copy_settings(&new_channel);
934                 window->lock_window();
935                 window->update_list(output_channel);
936                 window->unlock_window();
937         }
938         else
939         {
940 // Discard channel.
941                 if(!editing)
942                 {
943                         window->lock_window();
944                         window->delete_channel(output_channel);
945                         window->unlock_window();
946                 }
947         }
948         editing = 0;
949         completion->unlock();
950         in_progress = 0;
951 }
952
953 ChannelEditEditWindow::ChannelEditEditWindow(ChannelEditEditThread *thread,
954         ChannelEditWindow *window,
955         ChannelPicker *channel_picker)
956  : BC_Window(_(PROGRAM_NAME ": Edit Channel"),
957         channel_picker->parent_window->get_abs_cursor_x(1),
958         channel_picker->parent_window->get_abs_cursor_y(1),
959         xS(390), yS(300), xS(390), yS(300), 0, 0, 1)
960 {
961         this->channel_picker = channel_picker;
962         this->window = window;
963         this->thread = thread;
964 }
965 ChannelEditEditWindow::~ChannelEditEditWindow()
966 {
967 }
968
969 void ChannelEditEditWindow::create_objects(Channel *channel)
970 {
971         int xs10 = xS(10), xs130 = xS(130);
972         int ys10 = yS(10), ys20 = yS(20), ys30 = yS(30);
973         lock_window("ChannelEditEditWindow::create_objects");
974         this->new_channel = channel;
975         Channel *channel_usage = channel_picker->get_channel_usage();
976         title_text = 0;
977
978         int x = xs10, y = ys10;
979 //      if(!channel_usage ||
980 //              (!channel_usage->use_frequency &&
981 //              !channel_usage->use_fine &&
982 //              !channel_usage->use_norm &&
983 //              !channel_usage->use_input))
984 //      {
985 //              add_subwindow(new BC_Title(x, y, MSG_NO_INP_SELECTION));
986 //              y += ys30;
987 //      }
988 //      else
989 //      {
990                 add_subwindow(new BC_Title(x, y, _("Title:")));
991                 add_subwindow(title_text = new ChannelEditEditTitle(x, y + ys20, thread));
992                 y += yS(50);
993 //      }
994
995         if(channel_usage && channel_usage->use_frequency)
996         {
997                 add_subwindow(new BC_Title(x, y, _("Channel:")));
998                 y += ys20;
999                 add_subwindow(thread->source_text = new ChannelEditEditSource(x, y, thread));
1000                 add_subwindow(new ChannelEditEditSourceTumbler(x + xS(160), y, thread));
1001                 y += yS(40);
1002
1003                 add_subwindow(new BC_Title(x, y, _("Frequency table:")));
1004                 ChannelEditEditFreqtable *table;
1005                 add_subwindow(table = new ChannelEditEditFreqtable(x + xs130,
1006                         y, thread, window->thread));
1007                 table->add_items();
1008                 y += ys30;
1009         }
1010
1011         if(channel_usage && channel_usage->use_fine)
1012         {
1013                 add_subwindow(new BC_Title(x, y, _("Fine:")));
1014                 add_subwindow(new ChannelEditEditFine(x + xs130, y, thread));
1015                 y += ys30;
1016         }
1017
1018         if(channel_usage && channel_usage->use_norm)
1019         {
1020                 add_subwindow(new BC_Title(x, y, _("Norm:")));
1021                 ChannelEditEditNorm *norm;
1022                 add_subwindow(norm = new ChannelEditEditNorm(x + xs130,
1023                         y, thread, window->thread));
1024                 norm->add_items();
1025                 y += ys30;
1026         }
1027
1028         if( (channel_usage && channel_usage->use_input) ||
1029                 !channel_usage)
1030         {
1031                 add_subwindow(new BC_Title(x, y, _("Input:")));
1032                 ChannelEditEditInput *input;
1033                 add_subwindow(input = new ChannelEditEditInput(x + xs130,
1034                         y, thread, window->thread));
1035                 input->add_items();
1036                 y += ys30;
1037         }
1038
1039         add_subwindow(new BC_OKButton(this));
1040         x += xS(200);
1041         add_subwindow(new BC_CancelButton(this));
1042         show_window();
1043         unlock_window();
1044 }
1045
1046 ChannelEditEditTitle::ChannelEditEditTitle(int x,
1047         int y,
1048         ChannelEditEditThread *thread)
1049  : BC_TextBox(x, y, xS(150), 1, thread->new_channel.title)
1050 {
1051         this->thread = thread;
1052 }
1053 ChannelEditEditTitle::~ChannelEditEditTitle()
1054 {
1055 }
1056 int ChannelEditEditTitle::handle_event()
1057 {
1058         if(strlen(get_text()) < 1024)
1059         {
1060                 strcpy(thread->new_channel.title, get_text());
1061         }
1062         thread->user_title = get_text()[0] ? 1 : 0;
1063         return 1;
1064 }
1065
1066
1067 ChannelEditEditSource::ChannelEditEditSource(int x, int y, ChannelEditEditThread *thread)
1068  : BC_TextBox(x, y, xS(150), 1, chanlists[thread->new_channel.freqtable].list[thread->new_channel.entry].name)
1069 {
1070         this->thread = thread;
1071 }
1072
1073 ChannelEditEditSource::~ChannelEditEditSource()
1074 {
1075 }
1076 int ChannelEditEditSource::handle_event()
1077 {
1078         thread->change_source(get_text());
1079         return 1;
1080 }
1081
1082
1083 ChannelEditEditSourceTumbler::ChannelEditEditSourceTumbler(int x, int y, ChannelEditEditThread *thread)
1084  : BC_Tumbler(x, y)
1085 {
1086         this->thread = thread;
1087 }
1088 ChannelEditEditSourceTumbler::~ChannelEditEditSourceTumbler()
1089 {
1090 }
1091 int ChannelEditEditSourceTumbler::handle_up_event()
1092 {
1093         thread->source_up();
1094         return 1;
1095 }
1096 int ChannelEditEditSourceTumbler::handle_down_event()
1097 {
1098         thread->source_down();
1099         return 1;
1100 }
1101
1102 ChannelEditEditInput::ChannelEditEditInput(int x,
1103         int y,
1104         ChannelEditEditThread *thread,
1105         ChannelEditThread *edit)
1106  : BC_PopupMenu(x, y, xS(150),
1107         edit->value_to_input(thread ? thread->new_channel.input : edit->scan_params.input))
1108 {
1109         this->thread = thread;
1110         this->edit = edit;
1111 }
1112 ChannelEditEditInput::~ChannelEditEditInput()
1113 {
1114 }
1115 void ChannelEditEditInput::add_items()
1116 {
1117         ArrayList<Channel*> *inputs;
1118         inputs = edit->channel_picker->get_video_inputs();
1119
1120         if(inputs)
1121         {
1122                 for(int i = 0; i < inputs->total; i++)
1123                 {
1124                         add_item(new ChannelEditEditInputItem(thread,
1125                                 edit,
1126                                 inputs->values[i]->device_name,
1127                                 i));
1128                 }
1129         }
1130 }
1131 int ChannelEditEditInput::handle_event()
1132 {
1133         return 0;
1134 }
1135
1136 ChannelEditEditInputItem::ChannelEditEditInputItem(ChannelEditEditThread *thread,
1137         ChannelEditThread *edit,
1138         char *text,
1139         int value)
1140  : BC_MenuItem(text)
1141 {
1142         this->thread = thread;
1143         this->edit = edit;
1144         this->value = value;
1145 }
1146 ChannelEditEditInputItem::~ChannelEditEditInputItem()
1147 {
1148 }
1149 int ChannelEditEditInputItem::handle_event()
1150 {
1151         get_popup_menu()->set_text(get_text());
1152         if(thread && !thread->user_title)
1153         {
1154                 strcpy(thread->new_channel.title, get_text());
1155                 if(thread->edit_window->title_text)
1156                 {
1157                         thread->edit_window->title_text->update(get_text());
1158                 }
1159         }
1160         if(thread)
1161                 thread->set_input(value);
1162         else
1163                 edit->scan_params.input = value;
1164         return 1;
1165 }
1166
1167 ChannelEditEditNorm::ChannelEditEditNorm(int x,
1168         int y,
1169         ChannelEditEditThread *thread,
1170         ChannelEditThread *edit)
1171  : BC_PopupMenu(x, y, xS(100),
1172         edit->value_to_norm(thread ? thread->new_channel.norm : edit->scan_params.norm))
1173 {
1174         this->thread = thread;
1175         this->edit = edit;
1176 }
1177 ChannelEditEditNorm::~ChannelEditEditNorm()
1178 {
1179 }
1180 void ChannelEditEditNorm::add_items()
1181 {
1182         add_item(new ChannelEditEditNormItem(thread,
1183                 edit,
1184                 edit->value_to_norm(NTSC), NTSC));
1185         add_item(new ChannelEditEditNormItem(thread,
1186                 edit,
1187                 edit->value_to_norm(PAL), PAL));
1188         add_item(new ChannelEditEditNormItem(thread,
1189                 edit,
1190                 edit->value_to_norm(SECAM), SECAM));
1191 }
1192
1193
1194 ChannelEditEditNormItem::ChannelEditEditNormItem(ChannelEditEditThread *thread,
1195         ChannelEditThread *edit,
1196         char *text,
1197         int value)
1198  : BC_MenuItem(text)
1199 {
1200         this->value = value;
1201         this->edit = edit;
1202         this->thread = thread;
1203 }
1204 ChannelEditEditNormItem::~ChannelEditEditNormItem()
1205 {
1206 }
1207 int ChannelEditEditNormItem::handle_event()
1208 {
1209         get_popup_menu()->set_text(get_text());
1210         if(thread)
1211                 thread->set_norm(value);
1212         else
1213                 edit->scan_params.norm = value;
1214         return 1;
1215 }
1216
1217
1218 ChannelEditEditFreqtable::ChannelEditEditFreqtable(int x,
1219         int y,
1220         ChannelEditEditThread *thread,
1221         ChannelEditThread *edit)
1222  : BC_PopupMenu(x, y, xS(150),
1223         edit->value_to_freqtable(thread ? thread->new_channel.freqtable : edit->scan_params.freqtable))
1224 {
1225         this->thread = thread;
1226         this->edit = edit;
1227 }
1228 ChannelEditEditFreqtable::~ChannelEditEditFreqtable()
1229 {
1230 }
1231 void ChannelEditEditFreqtable::add_items()
1232 {
1233         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(NTSC_DVB), NTSC_DVB));
1234         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(CATV_DVB), CATV_DVB));
1235         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(NTSC_BCAST), NTSC_BCAST));
1236         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(NTSC_CABLE), NTSC_CABLE));
1237         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(NTSC_HRC), NTSC_HRC));
1238         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(NTSC_BCAST_JP), NTSC_BCAST_JP));
1239         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(NTSC_CABLE_JP), NTSC_CABLE_JP));
1240         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(PAL_AUSTRALIA), PAL_AUSTRALIA));
1241         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(PAL_EUROPE), PAL_EUROPE));
1242         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(PAL_E_EUROPE), PAL_E_EUROPE));
1243         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(PAL_ITALY), PAL_ITALY));
1244         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(PAL_IRELAND), PAL_IRELAND));
1245         add_item(new ChannelEditEditFreqItem(thread, edit, edit->value_to_freqtable(PAL_NEWZEALAND), PAL_NEWZEALAND));
1246 }
1247
1248 ChannelEditEditFreqItem::ChannelEditEditFreqItem(ChannelEditEditThread *thread,
1249         ChannelEditThread *edit,
1250         char *text, int value)
1251  : BC_MenuItem(text)
1252 {
1253         this->value = value;
1254         this->edit = edit;
1255         this->thread = thread;
1256 }
1257 ChannelEditEditFreqItem::~ChannelEditEditFreqItem()
1258 {
1259 }
1260 int ChannelEditEditFreqItem::handle_event()
1261 {
1262         get_popup_menu()->set_text(get_text());
1263         if(thread)
1264                 thread->set_freqtable(value);
1265         else
1266                 edit->scan_params.freqtable = value;
1267         return 1;
1268 }
1269
1270
1271
1272 ChannelEditEditFine::ChannelEditEditFine(int x,
1273         int y,
1274         ChannelEditEditThread *thread)
1275  : BC_ISlider(x, y, 0, xS(240), xS(240), -100, 100,
1276                 thread->new_channel.fine_tune)
1277 {
1278         this->thread = thread;
1279 }
1280 ChannelEditEditFine::~ChannelEditEditFine()
1281 {
1282 }
1283 int ChannelEditEditFine::handle_event()
1284 {
1285         return 1;
1286 }
1287 int ChannelEditEditFine::button_release_event()
1288 {
1289         if(BC_Slider::button_release_event())
1290         {
1291                 thread->new_channel.fine_tune = get_value();
1292                 thread->set_device();
1293                 return 1;
1294         }
1295         return 0;
1296 }
1297
1298
1299 // ========================== picture quality
1300
1301 ChannelEditPictureThread::ChannelEditPictureThread(
1302         ChannelPicker *channel_picker)
1303  : BC_DialogThread()
1304 {
1305         this->channel_picker = channel_picker;
1306 }
1307 ChannelEditPictureThread::~ChannelEditPictureThread()
1308 {
1309 }
1310
1311 void ChannelEditPictureThread::handle_done_event(int result)
1312 {
1313         if(channel_picker->get_picture_usage())
1314                 channel_picker->get_picture_usage()->save_defaults();
1315 }
1316
1317 BC_Window* ChannelEditPictureThread::new_gui()
1318 {
1319         ChannelEditPictureWindow *edit_window = new ChannelEditPictureWindow(this,
1320                 channel_picker);
1321         edit_window->create_objects();
1322         return edit_window;
1323 }
1324
1325 void ChannelEditPictureThread::edit_picture()
1326 {
1327         start();
1328 }
1329
1330
1331 ChannelEditPictureWindow::ChannelEditPictureWindow(ChannelEditPictureThread *thread,
1332         ChannelPicker *channel_picker)
1333  : BC_Window(_(PROGRAM_NAME ": Picture"),
1334         channel_picker->mwindow->session->picture_x,
1335         channel_picker->mwindow->session->picture_y,
1336         calculate_w(channel_picker), calculate_h(channel_picker),
1337         calculate_w(channel_picker), calculate_h(channel_picker))
1338 {
1339         this->thread = thread;
1340         this->channel_picker = channel_picker;
1341 }
1342 ChannelEditPictureWindow::~ChannelEditPictureWindow()
1343 {
1344 }
1345
1346 int ChannelEditPictureWindow::calculate_h(ChannelPicker *channel_picker)
1347 {
1348         PictureConfig *picture_usage = channel_picker->get_picture_usage();
1349         int pad = BC_Pot::calculate_h();
1350         int text_h = channel_picker->parent_window->get_text_height(MEDIUMFONT);
1351         int result = yS(20+5) + text_h + BC_OKButton::calculate_h();
1352
1353 // Only used for Video4Linux 1
1354         if( !picture_usage || (
1355              !picture_usage->use_brightness &&
1356              !picture_usage->use_contrast &&
1357              !picture_usage->use_color &&
1358              !picture_usage->use_hue &&
1359              !picture_usage->use_whiteness &&
1360              !channel_picker->get_controls() ) ) {
1361                 result += BC_Title::calculate_h(channel_picker->parent_window,
1362                         MSG_NO_PIC_CONTROLS);
1363         }
1364         else
1365         {
1366                 if(picture_usage->use_brightness)
1367                         result += pad;
1368                 if(picture_usage->use_contrast)
1369                         result += pad;
1370                 if(picture_usage->use_color)
1371                         result += pad;
1372                 if(picture_usage->use_hue)
1373                         result += pad;
1374                 if(picture_usage->use_whiteness)
1375                         result += pad;
1376         }
1377
1378         result += channel_picker->get_controls() * pad;
1379         return result;
1380 }
1381
1382 int ChannelEditPictureWindow::calculate_w(ChannelPicker *channel_picker)
1383 {
1384         PictureConfig *picture_usage = channel_picker->get_picture_usage();
1385         int widget_border = ((Theme*)channel_picker->get_theme())->widget_border;
1386         int pad = BC_Pot::calculate_w() + 4 * widget_border;
1387         int result = 0;
1388
1389 // Only used for Video4Linux 1
1390         if(!picture_usage ||
1391                 (!picture_usage->use_brightness &&
1392                 !picture_usage->use_contrast &&
1393                 !picture_usage->use_color &&
1394                 !picture_usage->use_hue &&
1395                 !picture_usage->use_whiteness &&
1396                 !channel_picker->get_controls()))
1397         {
1398                 result = BC_Title::calculate_w(channel_picker->parent_window,
1399                         MSG_NO_PIC_CONTROLS) + xS(20);
1400         }
1401
1402 // Only used for Video4Linux 1
1403         if(picture_usage)
1404         {
1405                 if(picture_usage->use_brightness)
1406                 {
1407                         int new_w = BC_Title::calculate_w(channel_picker->parent_window, _("Brightness:")) + pad;
1408                         result = MAX(result, new_w);
1409                 }
1410                 if(picture_usage->use_contrast)
1411                 {
1412                         int new_w = BC_Title::calculate_w(channel_picker->parent_window, _("Contrast:")) + pad;
1413                         result = MAX(result, new_w);
1414                 }
1415                 if(picture_usage->use_color)
1416                 {
1417                         int new_w = BC_Title::calculate_w(channel_picker->parent_window, _("Color:")) + pad;
1418                         result = MAX(result, new_w);
1419                 }
1420                 if(picture_usage->use_hue)
1421                 {
1422                         int new_w = BC_Title::calculate_w(channel_picker->parent_window, _("Hue:")) + pad;
1423                         result = MAX(result, new_w);
1424                 }
1425                 if(picture_usage->use_whiteness)
1426                 {
1427                         int new_w = BC_Title::calculate_w(channel_picker->parent_window, _("Whiteness:")) + pad;
1428                         result = MAX(result, new_w);
1429                 }
1430         }
1431
1432         for(int i = 0; i < channel_picker->get_controls(); i++)
1433         {
1434                 int new_w = BC_Title::calculate_w(channel_picker->parent_window,
1435                                 channel_picker->get_control(i)->name) +
1436                         pad;
1437                 result = MAX(result, new_w);
1438         }
1439
1440         return result;
1441 }
1442
1443
1444 void ChannelEditPictureWindow::create_objects()
1445 {
1446         int xs10 = xS(10), ys10 = yS(10);
1447         lock_window("ChannelEditPictureWindow::create_objects");
1448         int x = xs10, y = ys10;
1449         int widget_border = ((Theme*)channel_picker->get_theme())->widget_border;
1450         int x1 = get_w() - BC_Pot::calculate_w() * 2 - widget_border * 2;
1451         int x2 = get_w() - BC_Pot::calculate_w() - widget_border;
1452         int pad = BC_Pot::calculate_h();
1453
1454 #define SWAP_X x1 ^= x2; x2 ^= x1; x1 ^= x2;
1455
1456         PictureConfig *picture_usage = channel_picker->get_picture_usage();
1457
1458 // Only used for Video4Linux 1
1459         if(!picture_usage ||
1460                 (!picture_usage->use_brightness &&
1461                 !picture_usage->use_contrast &&
1462                 !picture_usage->use_color &&
1463                 !picture_usage->use_hue &&
1464                 !picture_usage->use_whiteness &&
1465                 !channel_picker->get_controls()))
1466         {
1467                 add_subwindow(new BC_Title(x, y, MSG_NO_PIC_CONTROLS));
1468                 y += yS(50);
1469         }
1470
1471 // Only used for Video4Linux 1
1472         if(picture_usage && picture_usage->use_brightness)
1473         {
1474                 add_subwindow(new BC_Title(x, y + ys10, _("Brightness:")));
1475                 add_subwindow(new ChannelEditBright(x1, y, channel_picker, channel_picker->get_brightness()));
1476                 y += pad;
1477                 SWAP_X
1478
1479         }
1480
1481         if(picture_usage && picture_usage->use_contrast)
1482         {
1483                 add_subwindow(new BC_Title(x, y + ys10, _("Contrast:")));
1484                 add_subwindow(new ChannelEditContrast(x1, y, channel_picker, channel_picker->get_contrast()));
1485                 y += pad;
1486                 SWAP_X
1487         }
1488
1489         if(picture_usage && picture_usage->use_color)
1490         {
1491                 add_subwindow(new BC_Title(x, y + ys10, _("Color:")));
1492                 add_subwindow(new ChannelEditColor(x1, y, channel_picker, channel_picker->get_color()));
1493                 y += pad;
1494                 SWAP_X
1495         }
1496
1497         if(picture_usage && picture_usage->use_hue)
1498         {
1499                 add_subwindow(new BC_Title(x, y + ys10, _("Hue:")));
1500                 add_subwindow(new ChannelEditHue(x1, y, channel_picker, channel_picker->get_hue()));
1501                 y += pad;
1502                 SWAP_X
1503         }
1504
1505         if(picture_usage && picture_usage->use_whiteness)
1506         {
1507                 add_subwindow(new BC_Title(x, y + ys10, _("Whiteness:")));
1508                 add_subwindow(new ChannelEditWhiteness(x1, y, channel_picker, channel_picker->get_whiteness()));
1509                 y += pad;
1510                 SWAP_X
1511         }
1512
1513         for(int i = 0; i < channel_picker->get_controls(); i++)
1514         {
1515                 BC_Title *title;
1516                 add_subwindow(title = new BC_Title(x, y + ys10,
1517                         _(channel_picker->get_control(i)->name)));
1518
1519                 int x3 = x1;
1520                 if(x3 < title->get_x() + title->get_w() + widget_border)
1521                         x3 = title->get_x() + title->get_w() + widget_border;
1522
1523                 add_subwindow(new ChannelEditCommon(x3,
1524                         y,
1525                         channel_picker,
1526                         channel_picker->get_control(i)));
1527                 y += pad;
1528                 SWAP_X
1529         }
1530
1531
1532         y += pad;
1533         add_subwindow(new BC_OKButton(this));
1534         show_window();
1535         unlock_window();
1536 }
1537
1538 int ChannelEditPictureWindow::translation_event()
1539 {
1540         channel_picker->mwindow->session->picture_x = get_x();
1541         channel_picker->mwindow->session->picture_y = get_y();
1542         return 0;
1543 }
1544
1545
1546
1547 ChannelEditBright::ChannelEditBright(int x, int y, ChannelPicker *channel_picker, int value)
1548  : BC_IPot(x, y, value, -100, 100)
1549 {
1550         this->channel_picker = channel_picker;
1551 }
1552 ChannelEditBright::~ChannelEditBright() {}
1553 int ChannelEditBright::handle_event()
1554 {
1555         return 1;
1556 }
1557 int ChannelEditBright::button_release_event()
1558 {
1559         if(BC_Pot::button_release_event())
1560         {
1561                 channel_picker->set_brightness(get_value());
1562                 return 1;
1563         }
1564         return 0;
1565 }
1566
1567 ChannelEditContrast::ChannelEditContrast(int x, int y, ChannelPicker *channel_picker, int value)
1568  : BC_IPot(x, y, value, -100, 100)
1569 {
1570         this->channel_picker = channel_picker;
1571 }
1572 ChannelEditContrast::~ChannelEditContrast() {}
1573 int ChannelEditContrast::handle_event()
1574 {
1575         return 1;
1576 }
1577 int ChannelEditContrast::button_release_event()
1578 {
1579         if(BC_Pot::button_release_event())
1580         {
1581                 channel_picker->set_contrast(get_value());
1582                 return 1;
1583         }
1584         return 0;
1585 }
1586
1587
1588 ChannelEditColor::ChannelEditColor(int x, int y, ChannelPicker *channel_picker, int value)
1589  : BC_IPot(x, y, value, -100, 100)
1590 {
1591         this->channel_picker = channel_picker;
1592 }
1593 ChannelEditColor::~ChannelEditColor() {}
1594 int ChannelEditColor::handle_event()
1595 {
1596         return 1;
1597 }
1598 int ChannelEditColor::button_release_event()
1599 {
1600         if(BC_Pot::button_release_event())
1601         {
1602                 channel_picker->set_color(get_value());
1603                 return 1;
1604         }
1605         return 0;
1606 }
1607
1608 ChannelEditHue::ChannelEditHue(int x, int y, ChannelPicker *channel_picker, int value)
1609  : BC_IPot(x, y, value, -100, 100)
1610 {
1611         this->channel_picker = channel_picker;
1612 }
1613 ChannelEditHue::~ChannelEditHue() {}
1614 int ChannelEditHue::handle_event()
1615 {
1616         return 1;
1617 }
1618 int ChannelEditHue::button_release_event()
1619 {
1620         if(BC_Pot::button_release_event())
1621         {
1622                 channel_picker->set_hue(get_value());
1623                 return 1;
1624         }
1625         return 0;
1626 }
1627
1628 ChannelEditWhiteness::ChannelEditWhiteness(int x, int y, ChannelPicker *channel_picker, int value)
1629  : BC_IPot(x, y, value, -100, 100)
1630 {
1631         this->channel_picker = channel_picker;
1632 }
1633 ChannelEditWhiteness::~ChannelEditWhiteness()
1634 {
1635 }
1636 int ChannelEditWhiteness::handle_event()
1637 {
1638         return 1;
1639 }
1640 int ChannelEditWhiteness::button_release_event()
1641 {
1642         if(BC_Pot::button_release_event())
1643         {
1644                 channel_picker->set_whiteness(get_value());
1645                 return 1;
1646         }
1647         return 0;
1648 }
1649
1650
1651
1652 ChannelEditCommon::ChannelEditCommon(int x, int y,
1653                 ChannelPicker *channel_picker, PictureItem *item)
1654  : BC_IPot(x, y, item->value, item->min, item->max)
1655 {
1656         this->channel_picker = channel_picker;
1657         this->device_id = item->device_id;
1658 }
1659
1660 ChannelEditCommon::~ChannelEditCommon()
1661 {
1662 }
1663
1664 int ChannelEditCommon::handle_event()
1665 {
1666         return 1;
1667 }
1668
1669 int ChannelEditCommon::button_release_event()
1670 {
1671         if(BC_Pot::button_release_event())
1672         {
1673                 channel_picker->set_picture(device_id, get_value());
1674                 return 1;
1675         }
1676         return 0;
1677 }
1678
1679 int ChannelEditCommon::keypress_event()
1680 {
1681         if(BC_Pot::keypress_event())
1682         {
1683                 channel_picker->set_picture(device_id, get_value());
1684                 return 1;
1685         }
1686         return 0;
1687 }
1688
1689
1690
1691
1692