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