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