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