3 * Copyright (C) 2016-2020 William Morrow
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published
7 * by the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public
16 * License along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
26 #include "channelinfo.h"
28 #include "channeldb.h"
29 #include "condition.h"
31 #include "devicedvbinput.h"
33 #include "edlsession.h"
35 #include "mainerror.h"
37 #include "mainsession.h"
39 #include "mwindowgui.h"
41 #include "bcmenuitem.h"
43 #include "recordconfig.h"
45 #include "videodevice.h"
46 #include "videoconfig.h"
47 #include "videodevice.h"
48 #include "libzmpeg3.h"
52 static inline int min(int a,int b) { return a<b ? a : b; }
54 static inline int max(int a,int b) { return a>b ? a : b; }
57 ChanSearch::ChanSearch(ChannelInfo *iwindow)
60 this->iwindow = iwindow;
61 window_lock = new Mutex("ChanSearch::window_lock");
65 ChanSearch::~ChanSearch()
72 void ChanSearch::start()
74 window_lock->lock("ChanSearch::start1");
75 if( Thread::running() ) {
76 gui->lock_window("ChanSearch::start2");
82 gui = new ChanSearchGUI(this);
85 window_lock->unlock();
88 void ChanSearch::stop()
90 if( Thread::running() ) {
91 window_lock->lock("ChanSearch::stop");
92 if( gui ) gui->set_done(1);
93 window_lock->unlock();
99 void ChanSearch::run()
101 gui->lock_window("ChanSearch::run");
102 gui->create_objects();
103 gui->unlock_window();
105 window_lock->lock("ChanSearch::stop");
107 window_lock->unlock();
111 ChanSearchTitleText::ChanSearchTitleText(ChanSearchGUI *gui, int x, int y)
112 : BC_CheckBox(x, y, &gui->title_text_enable, _("titles"))
117 ChanSearchTitleText::~ChanSearchTitleText()
121 int ChanSearchTitleText::handle_event()
123 gui->title_text_enable = get_value();
124 if( !gui->title_text_enable ) gui->info_text->update(1);
129 ChanSearchInfoText::ChanSearchInfoText(ChanSearchGUI *gui, int x, int y)
130 : BC_CheckBox(x, y, &gui->info_text_enable, _("info"))
135 ChanSearchInfoText::~ChanSearchInfoText()
139 int ChanSearchInfoText::handle_event()
141 gui->info_text_enable = get_value();
142 if( !gui->info_text_enable ) gui->title_text->update(1);
147 ChanSearchMatchCase::ChanSearchMatchCase(ChanSearchGUI *gui, int x, int y)
148 : BC_CheckBox(x, y, &gui->match_case_enable, _("match case"))
153 ChanSearchMatchCase::~ChanSearchMatchCase()
157 int ChanSearchMatchCase::handle_event()
159 gui->match_case_enable = get_value();
164 ChanSearchText::ChanSearchText(ChanSearchGUI *gui, int x, int y, int w)
165 : BC_TextBox(x, y, w, 1, "")
170 ChanSearchText::~ChanSearchText()
175 int ChanSearchText::handle_event()
180 int ChanSearchText::keypress_event()
182 switch(get_keypress())
189 return BC_TextBox::keypress_event();
193 ChanSearchStart::ChanSearchStart(ChanSearchGUI *gui, int x, int y)
194 : BC_GenericButton(x, y, _("Search"))
199 ChanSearchStart::~ChanSearchStart()
203 int ChanSearchStart::handle_event()
210 ChanSearchCancel::ChanSearchCancel(ChanSearchGUI *gui, int x, int y)
211 : BC_CancelButton(x, y)
216 ChanSearchCancel::~ChanSearchCancel()
220 int ChanSearchCancel::handle_event()
227 ChanSearchList::ChanSearchList(ChanSearchGUI *gui, int x, int y, int w, int h)
228 : BC_ListBox(x, y, w, h, LISTBOX_TEXT, &gui->search_items[0],
229 &gui->search_column_titles[0], &gui->search_column_widths[0],
230 lengthof(gui->search_items))
233 set_sort_column(gui->sort_column);
234 set_sort_order(gui->sort_order);
235 set_allow_drag_column(1);
238 ChanSearchList::~ChanSearchList()
242 int ChanSearchList::handle_event()
244 if( get_double_click() ) {
245 ChannelPanel *panel = gui->panel;
246 panel->lock_window("ChanSearchList::handle_event");
247 ChannelEvent *item = gui->highlighted_event;
249 item->text_color(-1);
252 int i = get_highlighted_item();
253 item = gui->search_results.get(i);
254 int x = item->x0-panel->x0 - panel->frame_w/2 + item->get_w()/2;
256 int w = panel->x1 - panel->x0;
258 panel->time_line_scroll->update_value(x);
259 panel->set_x_scroll(x);
260 item->text_color(YELLOW);
262 gui->highlighted_event = item;
263 panel->unlock_window();
268 int ChanSearchList::sort_order_event()
270 gui->sort_events(get_sort_column(), get_sort_order());
274 int ChanSearchList::move_column_event()
276 gui->move_column(get_from_column(), get_to_column());
280 void ChanSearchGUI::create_objects()
282 int xs10 = xS(10), xs20 = xS(20);
283 int ys5 = yS(5), ys10 = yS(10);
284 lock_window("ChanSearchGUI::create_objects");
285 int pady = BC_TextBox::calculate_h(this, MEDIUMFONT, 0, 1) + ys5;
286 int padx = BC_Title::calculate_w(this, (char*)"X", MEDIUMFONT);
287 int x = padx/2, y = pady/4;
288 BC_Title *title = new BC_Title(text_x, text_y, _("Text:"), MEDIUMFONT, YELLOW);
289 add_subwindow(title); x += title->get_w();
290 text_x = x; text_y = y;
291 search_text = new ChanSearchText(this, x, y, get_w()-x-xs10);
292 add_subwindow(search_text);
293 x = padx; y += pady + ys5;
294 title_text = new ChanSearchTitleText(this, x, y);
295 add_subwindow(title_text); x += title_text->get_w() + padx;
296 info_text = new ChanSearchInfoText(this, x, y);
297 add_subwindow(info_text); x += title_text->get_w() + padx;
298 match_case = new ChanSearchMatchCase(this, x, y);
299 add_subwindow(match_case); x += match_case->get_w() + padx;
300 results_x = x + xs20; results_y = y + ys5;
301 results = new BC_Title(results_x, results_y, " ", MEDIUMFONT, YELLOW);
302 add_subwindow(results);
303 x = padx; y += pady + ys5;
305 search_y = get_h() - BC_GenericButton::calculate_h() - ys10;
306 search_start = new ChanSearchStart(this, search_x, search_y);
307 add_subwindow(search_start);
308 cancel_w = ChanSearchCancel::calculate_w();
309 cancel_h = ChanSearchCancel::calculate_h();
310 cancel_x = get_w() - cancel_w - xs10;
311 cancel_y = get_h() - cancel_h - ys10;
312 cancel = new ChanSearchCancel(this, cancel_x, cancel_y);
313 add_subwindow(cancel);
314 list_x = x; list_y = y;
315 int list_w = get_w()-xs10 - list_x;
316 int list_h = min(search_y, cancel_y)-ys10 - list_y;
317 search_list = new ChanSearchList(this, list_x, list_y, list_w, list_h);
318 add_subwindow(search_list);
319 search_list->show_window();
320 int clktip_x = list_x;
321 int clktip_y = list_y + list_h + ys5;
322 click_tip = new BC_Title(clktip_x, clktip_y, _("dbl clk row to find title"));
323 add_subwindow(click_tip);
325 set_icon(iwindow->mwindow->theme->get_image("record_icon"));
326 search_text->activate();
330 #define CSW_W xS(500)
331 #define CSW_H yS(300)
333 ChanSearchGUI::ChanSearchGUI(ChanSearch *cswindow)
334 : BC_Window(_(PROGRAM_NAME ": ChanSearch"),
335 cswindow->iwindow->gui->get_abs_cursor_x(1) - CSW_W/2,
336 cswindow->iwindow->gui->get_abs_cursor_y(1) - CSW_H/2,
337 CSW_W, CSW_H, xS(400), yS(300))
339 this->cswindow = cswindow;
340 this->iwindow = cswindow->iwindow;
341 this->panel = cswindow->iwindow->gui->panel;
352 search_x = search_y = text_x = text_y = 0;
353 cancel_x = cancel_y = cancel_w = cancel_h = 0;
354 list_x = list_y = list_w = list_h = 0;
355 results_x = results_y = 0;
356 sort_column = sort_order = 0;
358 title_text_enable = 1;
359 info_text_enable = 0;
360 match_case_enable = 0;
361 highlighted_event = 0;
363 search_columns[0] = 0;
364 search_columns[1] = 1;
365 search_columns[2] = 2;
366 search_column_titles[0] = _("Source");
367 search_column_titles[1] = C_("Title");
368 search_column_titles[2] = _("Start time");
369 search_column_widths[0] = xS(120);
370 search_column_widths[2] = xS(120);
371 search_column_widths[1] = get_w()-search_column_widths[0]-search_column_widths[2]-xS(32);
372 // *** CONTEXT_HELP ***
373 context_help_set_keyword("Capture at some Future Time via Batch");
376 ChanSearchGUI::~ChanSearchGUI()
379 ChannelEvent *item = highlighted_event;
381 panel->lock_window("ChanSearchGUI::~ChanSearchGUI");
382 item->text_color(-1);
384 panel->unlock_window();
386 for( int i=0; i<lengthof(search_items); ++i )
387 search_items[i].remove_all_objects();
390 int ChanSearchGUI::resize_event(int w, int h)
392 int xs5 = xS(5), xs10 = xS(10);
394 search_text->reposition_window(text_x, text_y, w-text_x-10);
395 int cancel_x = w - BC_CancelButton::calculate_w() - xs10;
396 int cancel_y = h - BC_CancelButton::calculate_h() - ys10;
397 cancel->reposition_window(cancel_x, cancel_y);
399 search_y = h - BC_GenericButton::calculate_h() - ys10;
400 search_start->reposition_window(search_x, search_y);
401 int list_w = w-xs10 - list_x;
402 int list_h = min(search_y, cancel_y)-ys10 - list_y;
403 search_column_widths[1] = w-search_column_widths[0]-search_column_widths[2]-xS(32);
404 search_list->reposition_window(list_x, list_y, list_w, list_h);
405 int clktip_x = list_x;
406 int clktip_y = list_y + list_h + xs5;
407 click_tip->reposition_window(clktip_x, clktip_y);
412 int ChanSearchGUI::close_event()
418 int ChanSearchGUI::search(const char *sp)
420 char const *tp = search_text->get_text();
422 for( const char *cp=sp; *cp!=0; ++cp ) {
423 if( match_case_enable ? !strncmp(tp, cp, n) :
424 !strncasecmp(tp, cp, n) ) return 1;
429 void ChanSearchGUI::search()
431 search_results.remove_all();
433 int n = panel->channel_event_items.size();
434 for( int i=0; i<n; ++i ) {
435 ChannelEvent *item = panel->channel_event_items.get(i);
436 if( (title_text_enable && search(item->get_text())) ||
437 (info_text_enable && search(item->get_tooltip()) ) )
438 search_results.append(item);
444 void ChanSearchGUI::update()
447 for( int i=0; i<lengthof(search_items); ++i )
448 search_items[i].remove_all_objects();
450 char text[BCTEXTLEN];
451 int n = search_results.size();
452 for( int i=0; i<n; ++i ) {
453 ChannelEvent *item = search_results.get(i);
454 for( int k=0; k<lengthof(search_columns); ++k ) {
456 switch( search_columns[k] ) {
457 case 0: cp = item->channel->title; break;
458 case 1: cp = item->get_text(); break;
460 struct tm stm; localtime_r(&item->start_time,&stm);
461 double seconds = stm.tm_hour*3600 + stm.tm_min*60 + stm.tm_sec;
462 Units::totext(text, seconds, TIME_HMS3);
465 if( cp ) search_items[k].append(new BC_ListBoxItem(cp, LTYELLOW));
469 search_list->update(search_items, &search_column_titles[0],
470 &search_column_widths[0], lengthof(search_items));
471 sprintf(text, _("%d found"), n);
472 results->update(text);
476 #define CmprFn(nm,key) int ChanSearchGUI:: \
477 cmpr_##nm(const void *a, const void *b) { \
478 ChannelEvent *&ap = *(ChannelEvent **)a; \
479 ChannelEvent *&bp = *(ChannelEvent **)b; \
480 int n = key; if( !n ) n = ap->no-bp->no; \
484 CmprFn(Text_dn, strcasecmp(ap->get_text(), bp->get_text()))
485 CmprFn(text_dn, strcmp(ap->get_text(), bp->get_text()))
486 CmprFn(Text_up, strcasecmp(bp->get_text(), ap->get_text()))
487 CmprFn(text_up, strcmp(bp->get_text(), ap->get_text()))
488 CmprFn(time_dn, ap->start_time - bp->start_time)
489 CmprFn(time_up, bp->start_time - ap->start_time)
490 CmprFn(Title_dn, strcasecmp(ap->channel->title, bp->channel->title))
491 CmprFn(title_dn, strcmp(ap->channel->title, bp->channel->title))
492 CmprFn(Title_up, strcasecmp(bp->channel->title, ap->channel->title))
493 CmprFn(title_up, strcmp(bp->channel->title, ap->channel->title))
496 void ChanSearchGUI::sort_events(int column, int order)
498 sort_column = column; sort_order = order;
499 int n = search_results.size();
501 ChannelEvent **events = &search_results.values[0];
502 for( int i=0; i<n; ++i ) events[i]->no = i;
504 int(*cmpr)(const void *, const void *) = 0;
505 switch( search_columns[sort_column] ) {
506 case 0: cmpr = match_case_enable ?
507 (sort_order ? cmpr_Title_up : cmpr_Title_dn) :
508 (sort_order ? cmpr_title_up : cmpr_title_dn) ;
510 case 1: cmpr = match_case_enable ?
511 (sort_order ? cmpr_Text_up : cmpr_Text_dn) :
512 (sort_order ? cmpr_text_up : cmpr_text_dn) ;
514 case 2: cmpr = sort_order ? cmpr_time_up : cmpr_time_dn;
519 ChannelEvent **events = &search_results.values[0];
520 qsort(events, n, sizeof(*events), cmpr);
525 void ChanSearchGUI::move_column(int src, int dst)
527 if( src == dst ) return;
528 int src_column = search_columns[src];
529 const char *src_column_title = search_column_titles[src];
530 int src_column_width = search_column_widths[src];
532 for( int i=src; i<dst; ++i ) {
533 search_columns[i] = search_columns[i+1];
534 search_column_titles[i] = search_column_titles[i+1];
535 search_column_widths[i] = search_column_widths[i+1];
539 for( int i=src; i>dst; --i ) {
540 search_columns[i] = search_columns[i-1];
541 search_column_titles[i] = search_column_titles[i-1];
542 search_column_widths[i] = search_column_widths[i-1];
545 search_columns[dst] = src_column;
546 search_column_titles[dst] = src_column_title;
547 search_column_widths[dst] = src_column_width;
552 ChannelProgress::ChannelProgress(ChannelInfoGUI *gui,
553 int x, int y, int w, int h, int len)
555 BC_SubWindow(x, y, w, h)
564 eta_timer = new Timer;
567 ChannelProgress::~ChannelProgress()
573 void ChannelProgress::create_objects()
575 int w = BC_Title::calculate_w(gui, (char*)"XXXXX", MEDIUMFONT);
576 eta = new BC_Title(0, 0, "+0:00", MEDIUMFONT, -1, 0, w);
578 int x = eta->get_w();
579 bar = new BC_ProgressBar(x, 0, get_w()-x, length);
584 void ChannelProgress::start()
591 void ChannelProgress::stop()
593 if( Thread::running() ) {
600 void ChannelProgress::run()
604 if( update() ) break;
611 int ChannelProgress::update()
613 double elapsed = (double)eta_timer->get_scaled_difference(1000) / 1000.;
614 double estimate = value < 1 ? 0 : (length/value-1)*elapsed;
615 char text[BCTEXTLEN], *cp = &text[0];
616 Units::totext(cp, estimate, TIME_MS1);
617 gui->lock_window("ChannelProgress::update");
620 gui->unlock_window();
621 return value < length ? 0 : 1;
626 TimeLineItem::TimeLineItem(ChannelPanel *panel, int x, int y, char *text)
627 : BC_Title(x-panel->x_scroll, 0, text, MEDIUMFONT,
628 x==panel->x_now ? GREEN : YELLOW)
634 TimeLineItem::~TimeLineItem()
639 TimeLine::TimeLine(ChannelPanel *panel)
640 : BC_SubWindow(panel->frame_x, 0, panel->frame_w, panel->path_h)
645 TimeLine::~TimeLine()
649 int TimeLine::resize_event(int w, int h)
656 ChannelDataItem::ChannelDataItem(ChannelPanel *panel, int x, int y, int w,
657 int color, const char *text)
658 : BC_Title(x, y-panel->y_scroll, text, MEDIUMFONT, color)
663 set_force_tooltip(1);
666 ChannelDataItem::~ChannelDataItem()
671 int ChannelDataItem::repeat_event(int64_t duration)
673 if( tip_info && cursor_above() &&
674 duration == get_resources()->tooltip_delay ) {
681 void ChannelDataItem::set_tooltip(const char *tip)
683 BC_Title::set_tooltip(tip_info = tip ? cstrdup(tip) : 0);
687 ChannelData::ChannelData(ChannelPanel *panel, int x, int y, int w, int h)
688 : BC_SubWindow(x, y, w, h, LTBLACK)
693 ChannelData::~ChannelData()
697 int ChannelData::resize_event(int w, int h)
704 ChannelScroll::ChannelScroll(ChannelPanel *panel, int x, int y, int h)
705 : BC_ScrollBar(x, y, SCROLL_VERT, h, 0, 0, 0)
710 ChannelScroll::~ChannelScroll()
714 int ChannelScroll::handle_event()
716 panel->set_y_scroll(get_value());
721 TimeLineScroll::TimeLineScroll(ChannelPanel *panel, int x, int y, int w)
722 : BC_ScrollBar(x, y, SCROLL_HORIZ, w, 0, 0, 0)
727 TimeLineScroll::~TimeLineScroll()
731 int TimeLineScroll::handle_event()
733 panel->set_x_scroll(get_value());
738 ChannelEventLine::ChannelEventLine(ChannelPanel *panel,
739 int x, int y, int w, int h, int color)
740 : BC_SubWindow(0, y, w, h, color)
746 ChannelEventLine::~ChannelEventLine()
750 void ChannelEventLine::resize(int w, int h)
756 ChannelEvent::ChannelEvent(ChannelEventLine *channel_line, Channel *channel,
757 time_t start_time, time_t end_time, int x, int y, int w, const char *text)
758 : BC_GenericButton( x-channel_line->panel->x_scroll,
759 y-channel_line->panel->y_scroll, w, text)
761 this->channel_line = channel_line;
762 this->channel = channel;
763 this->start_time = start_time;
764 this->end_time = end_time;
765 x0 = x; y0 = y; no = 0;
767 set_force_tooltip(1);
770 ChannelEvent::~ChannelEvent()
775 int ChannelEvent::handle_event()
777 ChannelInfoGUI *gui = channel_line->panel->gui;
778 Batch *batch = gui->batch_bay->get_editing_batch();
779 char *path = batch->asset->path;
780 int len = sizeof(batch->asset->path)-1;
781 const char *text = get_text();
782 const char *dir = gui->channel_dir->get_directory();
784 while( i<len && *dir ) path[i++] = *dir++;
785 if( i > 0 && dir[i-1] != '/' ) path[i++] = '/';
786 while( i<len && *text ) {
788 if( !isalnum(ch) ) ch = '_';
791 if( i < len ) path[i++] = '.';
792 if( i < len ) path[i++] = 't';
793 if( i < len ) path[i++] = 's';
795 int early = (int)gui->early_time->get_time();
796 int late = (int)gui->late_time->get_time();
797 time_t st = start_time + early;
798 struct tm stm; localtime_r(&st,&stm);
799 batch->record_mode = RECORD_TIMED;
801 batch->start_day = stm.tm_wday;
802 batch->start_time = stm.tm_hour*3600 + stm.tm_min*60 + stm.tm_sec;
803 batch->duration = end_time - start_time - early + late;
804 batch->channel = channel;
805 gui->batch_bay->update_batches();
806 gui->update_channel_tools();
810 void ChannelEvent::set_tooltip(const char *tip)
812 BC_GenericButton::set_tooltip(tip_info = tip ? cstrdup(tip) : 0);
816 ChannelFrame::ChannelFrame(ChannelPanel *panel)
817 : BC_SubWindow(panel->frame_x, panel->frame_y,
818 panel->frame_w, panel->frame_h, BLACK)
823 ChannelFrame::~ChannelFrame()
828 void ChannelPanel::create_objects()
830 iwd = BC_ScrollBar::get_span(SCROLL_VERT);
831 iht = BC_ScrollBar::get_span(SCROLL_HORIZ);
833 frame_x = path_w; frame_y = path_h;
834 frame_w = iwindow_w-frame_x - iwd;
835 frame_h = iwindow_h-frame_y - iht;
837 time_line = new TimeLine(this);
838 add_subwindow(time_line);
839 time_line_scroll = new TimeLineScroll(this, frame_x, iwindow_h-iht, frame_w);
840 add_subwindow(time_line_scroll);
841 channel_data = new ChannelData(this, 0, frame_y, path_w, frame_h);
842 add_subwindow(channel_data);
843 channel_frame = new ChannelFrame(this);
844 add_subwindow(channel_frame);
845 channel_scroll = new ChannelScroll(this, iwindow_w-iwd, frame_y, frame_h);
846 add_subwindow(channel_scroll);
849 ChannelPanel::ChannelPanel(ChannelInfoGUI *gui,
850 int x, int y, int w, int h)
851 : BC_SubWindow(x, y, w, h)
854 gettimeofday(&tv, &tz);
855 st_org = ((tv.tv_sec+1800-1) / 1800) * 1800 - 1800;
856 x_now = (tv.tv_sec-st_org)/1800 * hhr_w;
857 path_w = gui->path_w; path_h = gui->path_h;
858 x0 = y0 = x1 = y1 = t0 = t1 = 0;
859 x_scroll = y_scroll = 0;
860 x_moved = y_moved = 0;
861 iwindow_w = w; iwindow_h = h;
862 hhr_w = BC_GenericButton::calculate_w(gui, (char*)"XXXXXXXX") + 5;
865 ChannelPanel::~ChannelPanel()
869 ChannelEventLine *ChannelPanel::NewChannelLine(int y, int h, int color)
871 ChannelEventLine *channel_line =
872 new ChannelEventLine(this, 0, y, frame_w, h, color);
873 channel_frame->add_subwindow(channel_line);
874 channel_line_items.append(channel_line);
878 void ChannelPanel::resize(int w, int h)
880 frame_w = (iwindow_w=w) - frame_x - iwd;
881 frame_h = (iwindow_h=h) - frame_y - iht;
882 time_line->resize_window(frame_w, path_h);
883 time_line_scroll->reposition_window(frame_x, frame_y+frame_h, frame_w);
884 time_line_scroll->update_length(x1-x0, x_scroll-x0, frame_w,0);
885 time_line_scroll->update_value(-x0);
886 channel_data->resize_window(path_w, frame_h);
887 channel_frame->resize_window(frame_w, frame_h);
888 int nitems = channel_line_items.size();
889 for( int i=0; i<nitems; ++i )
890 channel_line_items.values[i]->resize_window(frame_w, path_h);
891 channel_scroll->reposition_window(frame_x+frame_w, frame_y, frame_h);
892 channel_scroll->update_length(y1-y0, y_scroll-y0, frame_h,0);
896 int ChannelPanel::button_press_event()
898 if(get_buttonpress() == 3 && cursor_inside()) {
899 gui->lock_window("ChannelPanel::button_press_event");
900 gui->channel_search->start();
901 gui->unlock_window();
907 void ChannelPanel::bounding_box(int ix0, int iy0, int ix1, int iy1)
909 int x_changed = 0, y_changed = 0;
910 if( ix0 < x0 ) { x0 = ix0; x_changed = 1; }
911 if( iy0 < y0 ) { y0 = iy0; y_changed = 1; }
912 if( ix1 > x1 ) { x1 = ix1; x_changed = 1; }
913 if( iy1 > y1 ) { y1 = iy1; y_changed = 1; }
915 time_line_update(x0, x1);
916 time_line_scroll->update_length(x1-x0, x_scroll-x0, frame_w, 0);
917 if( !x_moved ) time_line_scroll->update_value(-x0);
920 channel_scroll->update_length(y1-y0, y_scroll-y0, frame_h, 0);
921 if( x_changed || y_changed ) flush();
924 void ChannelPanel::set_x_scroll(int v)
931 void ChannelPanel::set_y_scroll(int v)
938 void ChannelPanel::reposition()
941 n = time_line_items.size();
942 for( i=0; i<n; ++i ) {
943 TimeLineItem *item = time_line_items[i];
944 if( item->get_x() == item->x0-x_scroll &&
945 item->get_y() == item->y0-y_scroll) continue;
946 item->reposition_window(item->x0-x_scroll, item->y0);
948 n = channel_data_items.size();
949 for( i=0; i<n; ++i ) {
950 ChannelDataItem *item = channel_data_items[i];
951 if( item->get_x() == item->x0-x_scroll &&
952 item->get_y() == item->y0-y_scroll) continue;
953 item->reposition_window(item->x0, item->y0-y_scroll);
955 n = channel_line_items.size();
956 for( i=0; i<n; ++i ) {
957 ChannelEventLine *item = channel_line_items[i];
958 if( item->get_x() == item->x0-x_scroll &&
959 item->get_y() == item->y0-y_scroll) continue;
960 item->reposition_window(item->x0, item->y0-y_scroll);
962 n = channel_event_items.size();
963 for( i=0; i<n; ++i ) {
964 ChannelEvent *item = channel_event_items[i];
965 if( item->get_x() == item->x0-x_scroll &&
966 item->get_y() == item->y0-y_scroll) continue;
967 item->reposition_window(item->x0-x_scroll, item->y0);
971 void ChannelPanel::get_xtime(int x, char *cp)
973 time_t xt = st_org + (x/hhr_w) * 1800;
974 if( !strcmp(tzname[0],"UTC") ) xt -= tz.tz_minuteswest*60;
975 struct tm xtm; localtime_r(&xt,&xtm);
976 cp += sprintf(cp,"%02d:%02d",xtm.tm_hour, xtm.tm_min);
977 if( !xtm.tm_hour && !xtm.tm_min ) {
978 sprintf(cp,"(%3.3s) ",&_("sunmontuewedthufrisat")[xtm.tm_wday*3]);
982 void ChannelPanel::time_line_update(int ix0, int ix1)
984 int x; char text[BCTEXTLEN];
985 for( x=t0; x>=ix0; x-=hhr_w ) {
986 get_xtime(x, text); t0 = x;
987 TimeLineItem *time_line_item = new TimeLineItem(this, t0, 0, text);
988 time_line->add_subwindow(time_line_item);
989 time_line_items.insert(time_line_item,0);
991 for( x=t1; x<ix1; x+=hhr_w ) {
992 get_xtime(x, text); t1 = x;
993 TimeLineItem *time_line_item = new TimeLineItem(this, t1, 0, text);
994 time_line->add_subwindow(time_line_item);
995 time_line_items.append(time_line_item);
1000 ChannelInfoCron(ChannelInfoGUI *gui, int x, int y, int *value)
1001 : BC_CheckBox(x, y, value, gui->cron_caption)
1004 set_tooltip(_("activate batch record when ok pressed"));
1012 int ChannelInfoCron::
1015 gui->iwindow->cron_enable = get_value();
1020 ChannelInfoPowerOff::ChannelInfoPowerOff(ChannelInfoGUI *gui, int x, int y, int *value)
1021 : BC_CheckBox(x, y , value, gui->power_caption)
1024 set_tooltip(_("poweroff system when batch record done"));
1027 ChannelInfoPowerOff::~ChannelInfoPowerOff()
1031 int ChannelInfoPowerOff::handle_event()
1033 gui->iwindow->poweroff_enable = get_value();
1038 ChannelInfoFind::ChannelInfoFind(ChannelInfoGUI *gui, int x, int y)
1039 : BC_GenericButton(x, y, _("Find"))
1042 set_tooltip(_("search event titles/info"));
1045 ChannelInfoFind::~ChannelInfoFind()
1049 int ChannelInfoFind::handle_event()
1051 gui->lock_window("ChannelInfoFind::handle_event");
1052 gui->channel_search->start();
1053 gui->unlock_window();
1057 void ChannelThread::start()
1059 if( !Thread::running() ) {
1065 void ChannelThread::stop()
1067 if( Thread::running() ) {
1074 ChannelThread::ChannelThread(ChannelInfoGUI *gui)
1078 this->iwindow = gui->iwindow;
1079 this->panel = gui->panel;
1085 ChannelThread::~ChannelThread()
1090 int ChannelThread::load_ident(int n, int y, char *ident)
1092 ChannelDataItem *data_item = new ChannelDataItem(panel, 0, y,
1093 panel->path_w, !n ? YELLOW : LTYELLOW, ident);
1094 panel->channel_data->add_subwindow(data_item);
1095 panel->channel_data_items.append(data_item);
1097 char info[BCTEXTLEN];
1098 int i = mpeg3_dvb_get_chan_info(fd, n, -1, 0, info, sizeof(info)-1);
1099 while( --i >= 0 && (info[i]=='\n' || info[i]==' ') ) info[i] = 0;
1100 if( info[0] ) data_item->set_tooltip(info);
1105 int ChannelThread::load_info(Channel *channel, ChannelEventLine *channel_line)
1107 int n = channel->element;
1110 while( ord < 0x80 ) {
1111 char info[65536], *cp = &info[0];
1112 int len = mpeg3_dvb_get_chan_info(fd,n,ord,i++,cp,sizeof(info)-1);
1113 if( len < 0 ) { i = 0; ++ord; continue; }
1114 char *bp = cp; cp += len;
1115 struct tm stm; memset(&stm,0,sizeof(stm));
1116 struct tm etm; memset(&etm,0,sizeof(etm));
1117 int k, l = sscanf(bp,"%d:%d:%d-%d:%d:%d %n",
1118 &stm.tm_hour, &stm.tm_min, &stm.tm_sec,
1119 &etm.tm_hour, &etm.tm_min, &etm.tm_sec,
1122 printf(_("bad scan time: %s\n"),info);
1125 char *title = (bp += k);
1126 while( bp<cp && *bp!='\n' ) ++bp;
1127 char *dp = bp; *bp++ = 0;
1129 printf(_("bad title: %s\n"),info);
1132 char stm_wday[4]; memset(&stm_wday,0,sizeof(stm_wday));
1133 l = sscanf(bp, "(%3s) %d/%d/%d", &stm_wday[0],
1134 &stm.tm_year, &stm.tm_mon, &stm.tm_mday);
1136 printf(_("bad scan date: %s\n"),info);
1139 while( bp<cp && *bp!='\n' ) ++bp;
1141 etm.tm_year = (stm.tm_year -= 1900);
1142 etm.tm_mon = --stm.tm_mon;
1143 etm.tm_mday = stm.tm_mday;
1144 stm.tm_isdst = etm.tm_isdst = -1;
1145 time_t st = mktime(&stm);
1146 time_t et = mktime(&etm);
1147 if( et < st ) et += 24*3600;
1149 printf(_("end before start: %s\n"),info);
1152 if( panel->st_org - et > 24*3600*2) {
1153 printf(_("end time early: %s\n"),info);
1156 if( st - panel->st_org > 24*3600*12 ) {
1157 printf(_("start time late: %s\n"),info);
1160 time_t st_min = (st - panel->st_org)/60;
1161 time_t et_min = (et - panel->st_org)/60;
1162 int dt = et_min - st_min;
1164 printf(_("zero duration: %s\n"),info);
1168 int w = (dt * panel->hhr_w) / 30;
1169 int x = (st_min * panel->hhr_w) / 30;
1170 int y = channel_line->y0;
1171 panel->bounding_box(x, y, x+w, y+panel->path_h);
1172 ChannelEvent *channel_event =
1173 new ChannelEvent(channel_line, channel,
1174 st, et, x, 0, w, title);
1175 channel_line->add_subwindow(channel_event);
1176 panel->channel_event_items.append(channel_event);
1178 *dp = '\n'; *bp++ = '\n';
1179 for( char *lp=bp; bp<cp; ++bp ) {
1180 if( *bp == '\n' || ((bp-lp)>=60 && *bp==' ') )
1184 for( bp=&info[0]; --cp>=bp && (*cp=='\n' || *cp==' '); *cp=0 );
1185 if( info[0] ) channel_event->set_tooltip(info);
1190 void ChannelThread::run()
1193 Channel *channel = 0;
1195 int nchannels = total_channels();
1198 for(int ch=0; !done && ch<nchannels; gui->update_progress(++ch) ) {
1199 Channel *chan = get_channel(ch);
1200 if( !chan ) continue;
1202 iwindow->vdevice_lock->lock("ChannelThread::run");
1203 DeviceDVBInput *dvb_input = iwindow->dvb_input;
1204 if( !channel || chan->entry != channel->entry ) {
1206 while( dvb_input->set_channel(chan) && --retry >= 0 );
1211 y += panel->separator(y);
1212 gui->unlock_window();
1218 else if( chan->element == channel->element )
1222 if( !done && chan && channel && (fd=dvb_input->get_src()) ) {
1224 load_ident(chan->element, y, chan->title);
1225 ChannelEventLine *channel_line = panel->NewChannelLine(y);
1226 load_info(chan, channel_line);
1227 channel_line->show_window();
1228 gui->unlock_window();
1229 dvb_input->put_src();
1232 iwindow->vdevice_lock->unlock();
1236 gui->lock_window("ChannelProgress::run");
1237 gui->channel_status->hide_window();
1238 gui->unlock_window();
1241 iwindow->close_vdevice();
1245 ChannelInfoOK::ChannelInfoOK(ChannelInfoGUI *gui, int x, int y)
1249 set_tooltip(_("end channel info, start record"));
1252 ChannelInfoOK::~ChannelInfoOK()
1256 int ChannelInfoOK::button_press_event()
1258 if(get_buttonpress() == 1 && is_event_win() && cursor_inside()) {
1265 int ChannelInfoOK::keypress_event()
1267 return context_help_check_and_show();
1271 ChannelInfoCancel::ChannelInfoCancel(ChannelInfoGUI *gui, int x, int y)
1272 : BC_CancelButton(x, y)
1277 ChannelInfoCancel::~ChannelInfoCancel()
1281 int ChannelInfoCancel::button_press_event()
1283 if(get_buttonpress() == 1 && is_event_win() && cursor_inside()) {
1291 ChannelInfoGUIBatches::ChannelInfoGUIBatches(ChannelInfoGUI *gui,
1292 int x, int y, int w, int h)
1293 : RecordBatchesGUI(gui->iwindow->record_batches, x, y, w, h)
1298 ChannelInfoGUIBatches::~ChannelInfoGUIBatches()
1302 int ChannelInfoGUIBatches::selection_changed()
1304 return RecordBatchesGUI::selection_changed();
1307 int ChannelInfoGUIBatches::handle_event()
1309 if( get_double_click() )
1310 gui->update_channel_tools();
1315 void ChannelInfoGUI::create_objects()
1318 int ys5 = yS(5), ys10 = yS(10);
1319 lock_window("ChannelInfoGUI::create_objects");
1320 panel = new ChannelPanel(this,0,0,panel_w,panel_h);
1321 add_subwindow(panel);
1322 panel->create_objects();
1323 int items = iwindow->channeldb->size();
1324 if( items < 1 ) items = 1;
1325 progress = new ChannelProgress(this, 0, 0, path_w, path_h, items);
1326 add_subwindow(progress);
1327 progress->create_objects();
1328 ok = new ChannelInfoOK(this, ok_x, ok_y);
1330 channel_cron = new ChannelInfoCron(this, cron_x, cron_y, &iwindow->cron_enable);
1331 add_subwindow(channel_cron);
1332 channel_poweroff = new ChannelInfoPowerOff(this,
1333 power_x, power_y, &iwindow->poweroff_enable);
1334 add_subwindow(channel_poweroff);
1335 channel_find = new ChannelInfoFind(this, find_x, find_y);
1336 add_subwindow(channel_find);
1337 cancel = new ChannelInfoCancel(this, cancel_x, cancel_y);
1338 add_subwindow(cancel);
1339 batch_bay = new ChannelInfoGUIBatches(this,bay_x, bay_y, bay_w, bay_h);
1340 add_subwindow(batch_bay);
1341 iwindow->record_batches.gui = batch_bay;
1342 batch_bay->set_current_batch(-1);
1343 batch_bay->update_batches(-1);
1345 pad = BC_TextBox::calculate_h(this, MEDIUMFONT, 0, 1) + ys5;
1346 x0 = bay_x+bay_w + xs10;
1352 add_subwindow(directory_title = new BC_Title(x, y, _("Directory:")));
1353 ww = max(directory_title->get_w(), ww); y += pad;
1354 add_subwindow(path_title = new BC_Title(x, y, _("Path:")));
1355 ww = max(path_title->get_w(), ww); y += pad;
1356 add_subwindow(start_title = new BC_Title(x, y, _("Start:")));
1357 ww = max(start_title->get_w(), ww); y += pad;
1358 add_subwindow(duration_title = new BC_Title(x, y, _("Duration:")));
1359 ww = max(duration_title->get_w(), ww); y += pad;
1360 add_subwindow(source_title = new BC_Title(x, y, _("Source:")));
1361 ww = max(source_title->get_w(), ww); y += pad;
1364 int x1 = x0 + title_w + pad;
1365 x = x1; y = y0; ww = 0;
1367 char *dir = iwindow->record_batches.get_default_directory();
1368 add_subwindow(channel_dir = new ChannelDir(this, dir, x, y));
1369 ww = max(channel_dir->get_w(), ww); y += pad;
1370 add_subwindow(channel_path = new ChannelPath(this, x, y));
1371 ww = max(channel_path->get_w(), ww); y += pad;
1372 channel_start = new ChannelStart(this, x, y);
1373 channel_start->create_objects();
1374 ww = max(channel_start->get_w(), ww); y += pad;
1375 int w = BC_Title::calculate_w(this, (char*)"+00:00:00+", MEDIUMFONT);
1376 channel_duration = new ChannelDuration(this, x, y, w);
1377 channel_duration->create_objects();
1378 int x2 = x + channel_duration->get_w();
1379 double *early_margin = iwindow->record_batches.get_early_margin();
1380 early_time = new ChannelEarlyTime(this, x2, y, early_margin);
1381 early_time->create_objects();
1382 x2 += early_time->get_w();
1383 double *late_margin = iwindow->record_batches.get_late_margin();
1384 late_time = new ChannelLateTime(this, x2, y, late_margin);
1385 late_time->create_objects();
1386 x2 += late_time->get_w();
1387 ww = max(x2-x1, ww); y += pad;
1388 channel_source = new ChannelSource(this, x, y);
1389 channel_source->create_objects();
1390 ww = max(channel_source->get_w(), ww); y += pad;
1391 data_w = x1-x0 + ww;
1394 add_subwindow(channel_clear_batch = new ChannelClearBatch(this, x, y));
1395 x += channel_clear_batch->get_w() + xs10;
1396 add_subwindow(channel_new_batch = new ChannelNewBatch(this, x, y));
1397 x += channel_new_batch->get_w() + xs10;
1398 add_subwindow(channel_delete_batch = new ChannelDeleteBatch(this, x, y));
1399 x += channel_delete_batch->get_w();
1401 data_w = max(ww, data_w);
1403 channel_status = new ChannelStatus(this, x0+data_w, y0);
1404 add_subwindow(channel_status);
1405 channel_status->create_objects();
1406 status_w = channel_status->get_w();
1408 channel_search = new ChanSearch(iwindow);
1413 ChannelInfoGUI::ChannelInfoGUI(ChannelInfo *iwindow,
1414 int x, int y, int w, int h)
1415 : BC_Window(_(PROGRAM_NAME ": Channel Info"), x, y,
1416 w, h, xS(600), yS(400), 1, 0, 0 , -1,
1417 iwindow->mwindow->get_cwindow_display())
1419 int xs10 = xS(10), xs20 = xS(20);
1420 int ys5 = yS(5), ys10 = yS(10);
1421 this->iwindow = iwindow;
1427 channel_duration = 0;
1429 channel_clear_batch = 0;
1430 channel_new_batch = 0;
1431 channel_delete_batch = 0;
1432 early_time = late_time = 0;
1433 directory_title = 0;
1438 cron_caption = _("Start Cron");
1439 power_caption = _("Poweroff");
1443 path_w = 16*BC_Title::calculate_w(this, (char*)"X", MEDIUMFONT);
1444 path_h = BC_TextBox::calculate_h(this, MEDIUMFONT, 0, 1);
1445 x0 = y0 = title_w = data_w = status_w = pad = 0;
1446 ok_w = BC_OKButton::calculate_w();
1447 ok_h = BC_OKButton::calculate_h();
1449 ok_y = h - ok_h - ys10;
1450 BC_CheckBox::calculate_extents(this, &cron_w, &cron_h, cron_caption);
1452 cron_y = ok_y - cron_h - ys10;
1453 BC_CheckBox::calculate_extents(this, &power_w, &power_h, power_caption);
1455 power_y = cron_y - power_h - ys5;
1456 find_h = BC_GenericButton::calculate_h();
1458 find_y = power_y - find_h - ys10;
1459 cancel_w = BC_CancelButton::calculate_w();
1460 cancel_h = BC_CancelButton::calculate_h();
1461 cancel_x = w - cancel_w - xs10,
1462 cancel_y = h - cancel_h - ys10;
1463 max_bay_w = xS(700);
1465 bay_x = ok_w + xs20;
1466 int x1 = cron_x+cron_w + xs10;
1467 if( x1 > bay_x ) bay_x = x1;
1468 x1 = power_x+power_w + xs10;
1469 if( x1 > bay_x ) bay_x = x1;
1471 // data_w,status_w zero, updated in create_objects
1472 bay_w = (w-bay_x) - (data_w+xs10) - (max(cancel_w, status_w)+xs20);
1473 if( bay_w > max_bay_w ) bay_w = max_bay_w;
1475 panel_h = h - bay_h;
1476 // *** CONTEXT_HELP ***
1477 context_help_set_keyword("Capture at some Future Time via Batch");
1480 ChannelInfoGUI::~ChannelInfoGUI()
1483 channel_search->stop();
1485 delete channel_status;
1486 delete channel_search;
1487 delete channel_start;
1488 delete channel_duration;
1491 delete channel_source;
1494 void ChannelInfoGUI::stop(int v)
1496 if( !iwindow->gui_done ) {
1497 iwindow->gui_done = 1;
1502 int ChannelInfoGUI::translation_event()
1504 iwindow->mwindow->session->cswindow_x = get_x();
1505 iwindow->mwindow->session->cswindow_y = get_y();
1509 int ChannelInfoGUI::resize_event(int w, int h)
1511 int xs10 = xS(10), xs20 = xS(20);
1512 int ys5 = yS(5), ys10 = yS(10);
1513 iwindow->mwindow->session->cswindow_w = w;
1514 iwindow->mwindow->session->cswindow_h = h;
1516 panel_h = h - bay_h;
1517 panel->resize(panel_w,panel_h);
1518 panel->reposition_window(0,0,panel_w,panel_h);
1520 ok_y = h - ok_h - ys10;
1521 ok->reposition_window(ok_x, ok_y);
1523 cron_y = ok_y - cron_h - ys10;
1524 channel_cron->reposition_window(cron_x, cron_y);
1526 power_y = cron_y - power_h - ys5;
1527 channel_poweroff->reposition_window(power_x, power_y);
1529 find_y = power_y - find_h - ys10;
1530 channel_find->reposition_window(find_x, find_y);
1531 cancel_x = w - cancel_w - xs10,
1532 cancel_y = h - cancel_h - ys10;
1533 cancel->reposition_window(cancel_x, cancel_y);
1534 bay_x = ok_w + xs20;
1535 int x1 = cron_x+cron_w + xs10;
1536 if( x1 > bay_x ) bay_x = x1;
1537 x1 = power_x+power_w + xs10;
1538 if( x1 > bay_x ) bay_x = x1;
1540 bay_w = (w-bay_x) - (data_w+xs10) - (max(cancel_w, status_w)+xs20);
1541 if( bay_w > max_bay_w ) bay_w = max_bay_w;
1542 batch_bay->reposition_window(bay_x, bay_y, bay_w, bay_h);
1544 int x0 = bay_x+bay_w + xs10;
1545 int y0 = bay_y+ys10;
1549 directory_title->reposition_window(x, y); y += pad;
1550 path_title->reposition_window(x, y); y += pad;
1551 start_title->reposition_window(x, y); y += pad;
1552 duration_title->reposition_window(x, y); y += pad;
1553 source_title->reposition_window(x, y);
1555 x = x0 + title_w + pad;
1558 channel_dir->reposition_window(x, y); y += pad;
1559 channel_path->reposition_window(x, y); y += pad;
1560 channel_start->reposition_window(x, y); y += pad;
1561 channel_duration->reposition_window(x, y);
1562 int x2 = x + channel_duration->get_w();
1563 early_time->reposition_window(x2, y);
1564 x2 += early_time->get_w();
1565 late_time->reposition_window(x2, y); y += pad;
1566 channel_source->reposition_window(x, y); y += pad;
1569 channel_clear_batch->reposition_window(x, y);
1570 x += channel_clear_batch->get_w() + xs10;
1571 channel_new_batch->reposition_window(x, y);
1572 x += channel_new_batch->get_w() + xs10;
1573 channel_delete_batch->reposition_window(x, y);
1577 channel_status->reposition_window(x, y);
1581 int ChannelInfoGUI::close_event()
1587 void ChannelInfoGUI::update_channel_tools()
1589 Batch *batch = batch_bay->get_editing_batch();
1590 channel_path->update(batch->asset->path);
1591 channel_start->update(&batch->start_day, &batch->start_time);
1592 channel_duration->update(0, &batch->duration);
1593 channel_source->update(batch->get_source_text());
1597 void ChannelInfoGUI::incr_event(int start_time_incr, int duration_incr)
1599 Batch *batch = batch_bay->get_editing_batch();
1600 batch->start_time += start_time_incr;
1601 batch->duration += duration_incr;
1602 batch_bay->update_batches();
1603 update_channel_tools();
1607 ChannelInfo::ChannelInfo(MWindow *mwindow)
1609 record_batches(mwindow)
1611 this->mwindow = mwindow;
1612 this->record = mwindow->gui->record;
1613 scan_lock = new Condition(0,"ChannelInfo::scan_lock");
1614 window_lock = new Mutex("ChannelInfo::window_lock");
1615 vdevice_lock = new Mutex("ChannelInfo::vdevice_lock");
1616 progress_lock = new Mutex("ChannelInfo::progress_lock");
1624 poweroff_enable = 0;
1632 ChannelInfo::~ChannelInfo()
1636 delete gui; gui = 0;
1638 record_batches.clear();
1642 delete vdevice_lock;
1643 delete progress_lock;
1646 void ChannelInfo::run_scan()
1648 window_lock->lock("ChannelInfo::run_scan");
1650 gui->lock_window("ChannelInfo::run_scan");
1651 gui->raise_window();
1652 gui->unlock_window();
1655 scan_lock->unlock();
1656 window_lock->unlock();
1659 void ChannelInfo::toggle_scan()
1661 window_lock->lock("ChannelInfo::toggle_scan");
1665 scan_lock->unlock();
1666 window_lock->unlock();
1669 void ChannelInfo::start()
1671 if( !Thread::running() ) {
1677 void ChannelInfo::stop()
1679 if( Thread::running() ) {
1681 scan_lock->unlock();
1682 window_lock->lock("ChannelInfo::stop");
1683 if( gui ) gui->stop(1);
1684 window_lock->unlock();
1690 void ChannelInfo::run()
1692 int root_w = mwindow->gui->get_root_w(1);
1693 int root_h = mwindow->gui->get_root_h(1);
1699 if( record->Thread::running() ) {
1700 char string[BCTEXTLEN];
1701 sprintf(string,_("Recording in progress\n"));
1702 MainError::show_error(string);
1705 EDLSession *session = mwindow->edl->session;
1706 VideoInConfig *vconfig_in = session->vconfig_in;
1707 if( vconfig_in->driver != CAPTURE_DVB ) {
1708 char string[BCTEXTLEN];
1709 sprintf(string,_("capture driver not dvb\n"));
1710 MainError::show_error(string);
1713 int x = mwindow->session->cswindow_x;
1714 int y = mwindow->session->cswindow_y;
1715 int w = mwindow->session->cswindow_w;
1716 int h = mwindow->session->cswindow_h;
1717 if( w < xS(600) ) w = xS(600);
1718 if( h < yS(400) ) h = yS(400);
1719 int scr_x = mwindow->gui->get_screen_x(1, -1);
1720 int scr_w = mwindow->gui->get_screen_w(1, -1);
1721 if( x < scr_x ) x = scr_x;
1722 if( x > scr_x+scr_w ) x = scr_x+scr_w;
1723 if( x+w > root_w ) x = root_w - w;
1724 if( x < 0 ) { x = 0; w = scr_w; }
1725 if( y+h > root_h ) y = root_h - h;
1726 if( y < 0 ) { y = 0; h = root_h; }
1727 if( y+h > root_h ) h = root_h-y;
1728 mwindow->session->cswindow_x = x;
1729 mwindow->session->cswindow_y = y;
1730 mwindow->session->cswindow_w = w;
1731 mwindow->session->cswindow_h = h;
1733 poweroff_enable = 0;
1734 vdevice = new VideoDevice(mwindow);
1735 int result = vdevice->open_input(vconfig_in, 0, 0, 1., vconfig_in->in_framerate);
1736 dvb_input = result ? 0 : (DeviceDVBInput *)vdevice->mpeg_device();
1738 channeldb = new ChannelDB;
1739 VideoDevice::load_channeldb(channeldb, vconfig_in);
1740 record_batches.load_defaults(channeldb);
1742 window_lock->lock("ChannelInfo::run 0");
1744 gui = new ChannelInfoGUI(this, x, y, w, h);
1745 gui->lock_window("ChannelInfo::gui_create_objects");
1746 gui->create_objects();
1747 gui->set_icon(mwindow->theme->get_image("record_icon"));
1748 gui->reposition_window(x, y);
1749 gui->resize_event(w, h);
1750 dvb_input->set_signal_status(gui->channel_status);
1751 gui->unlock_window();
1752 thread = new ChannelThread(gui);
1754 window_lock->unlock();
1755 result = gui->run_window();
1756 delete thread; thread = 0;
1759 gui->unlock_window();
1760 window_lock->lock("ChannelInfo::run 1");
1761 delete gui; gui = 0;
1762 window_lock->unlock();
1763 record_batches.save_defaults(channeldb);
1765 record_batches.save_default_channel(channeldb);
1767 record->init_lock->lock();
1769 record->set_power_off(poweroff_enable);
1770 record->start_cron_thread();
1773 record_batches.clear();
1774 delete channeldb; channeldb = 0;
1778 char string[BCTEXTLEN];
1779 sprintf(string,_("cannot open dvb video device\n"));
1780 MainError::show_error(string);
1785 void ChannelInfo::close_vdevice()
1787 vdevice_lock->lock("ChannelInfo::close_vdevice");
1788 progress_lock->lock("ChannelInfo::close_vdevice");
1790 vdevice->close_all();
1791 delete vdevice; vdevice = 0;
1793 progress_lock->unlock();
1794 vdevice_lock->unlock();
1797 Batch *ChannelInfo::new_batch()
1799 Batch *batch = new Batch(gui->iwindow->mwindow, 0);
1800 batch->create_objects();
1801 batch->calculate_news();
1802 gui->iwindow->record_batches.append(batch);
1806 void ChannelInfo::delete_batch()
1808 // Abort if one batch left
1809 int edit_batch = editing_batch();
1810 int total_batches = record_batches.total();
1811 if( total_batches > 1 && edit_batch < total_batches ) {
1812 Batch *batch = record_batches[edit_batch];
1813 record_batches.remove(batch); delete batch;
1817 ChannelScan::ChannelScan(MWindow *mwindow)
1818 : BC_MenuItem(_("Scan..."), _("Ctrl-Alt-s"), 's')
1822 this->mwindow = mwindow;
1825 ChannelScan::~ChannelScan()
1829 int ChannelScan::handle_event()
1831 mwindow->gui->channel_info->run_scan();
1836 ChannelDir::ChannelDir(ChannelInfoGUI *gui, const char *dir, int x, int y)
1837 : RecordBatchesGUI::Dir(gui->iwindow->record_batches, dir, x, y)
1843 ChannelPath::ChannelPath(ChannelInfoGUI *gui, int x, int y)
1844 : RecordBatchesGUI::Path(gui->iwindow->record_batches, x, y)
1850 ChannelStart::ChannelStart(ChannelInfoGUI *gui, int x, int y)
1851 : RecordBatchesGUI::StartTime(gui, gui->iwindow->record_batches, x, y)
1857 ChannelDuration::ChannelDuration(ChannelInfoGUI *gui, int x, int y, int w)
1858 : RecordBatchesGUI::Duration(gui, gui->iwindow->record_batches, x, y, w)
1864 ChannelEarlyTime::ChannelEarlyTime(ChannelInfoGUI *gui, int x, int y,
1865 double *output_time)
1866 : TimeEntryTumbler(gui, x, y, 0, output_time, 15, TIME_MS2, xS(75))
1871 int ChannelEarlyTime::handle_up_event()
1873 gui->incr_event(incr,-incr);
1874 return TimeEntryTumbler::handle_up_event();
1877 int ChannelEarlyTime::handle_down_event()
1879 gui->incr_event(-incr,incr);
1880 return TimeEntryTumbler::handle_down_event();
1884 ChannelLateTime::ChannelLateTime(ChannelInfoGUI *gui, int x, int y,
1885 double *output_time)
1886 : TimeEntryTumbler(gui, x, y, 0, output_time, 15, TIME_MS2, xS(75))
1891 int ChannelLateTime::handle_up_event()
1893 gui->incr_event(0,incr);
1894 return TimeEntryTumbler::handle_up_event();
1897 int ChannelLateTime::handle_down_event()
1899 gui->incr_event(0,-incr);
1900 return TimeEntryTumbler::handle_down_event();
1904 ChannelSource::ChannelSource(ChannelInfoGUI *gui, int x, int y)
1905 : RecordBatchesGUI::Source(gui, gui->iwindow->record_batches, x, y)
1910 void ChannelSource::create_objects()
1912 RecordBatchesGUI::Source::create_objects();
1913 ChannelDB *channeldb = gui->iwindow->channeldb;
1914 sources.remove_all_objects();
1915 for(int i = 0; i < channeldb->size(); i++) {
1916 sources.append(new BC_ListBoxItem(channeldb->get(i)->title));
1918 update_list(&sources);
1921 int ChannelSource::handle_event()
1923 int chan_no = get_number();
1924 Channel *channel = gui->iwindow->channeldb->get(chan_no);
1926 Batch *batch = batches.get_editing_batch();
1927 if( batch ) batch->channel = channel;
1928 update(channel->title);
1930 return RecordBatchesGUI::Source::handle_event();
1934 ChannelClearBatch::ChannelClearBatch(ChannelInfoGUI *gui, int x, int y)
1935 : RecordBatchesGUI::ClearBatch(gui->iwindow->record_batches, x, y)
1938 set_tooltip(_("Delete all clips."));
1941 int ChannelClearBatch::handle_event()
1943 gui->iwindow->record_batches.clear();
1944 gui->iwindow->new_batch();
1945 gui->batch_bay->set_current_batch(-1);
1946 gui->batch_bay->set_editing_batch(0);
1947 gui->batch_bay->update_batches(0);
1948 return RecordBatchesGUI::ClearBatch::handle_event();
1952 ChannelNewBatch::ChannelNewBatch(ChannelInfoGUI *gui, int x, int y)
1953 : RecordBatchesGUI::NewBatch(gui->iwindow->record_batches, x, y)
1956 set_tooltip(_("Create new clip."));
1958 int ChannelNewBatch::handle_event()
1960 gui->iwindow->new_batch();
1961 return RecordBatchesGUI::NewBatch::handle_event();
1965 ChannelDeleteBatch::ChannelDeleteBatch(ChannelInfoGUI *gui, int x, int y)
1966 : RecordBatchesGUI::DeleteBatch(gui->iwindow->record_batches, x, y)
1969 set_tooltip(_("Delete clip."));
1972 int ChannelDeleteBatch::handle_event()
1974 gui->iwindow->delete_batch();
1975 return RecordBatchesGUI::DeleteBatch::handle_event();