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
23 #include "channelinfo.h"
25 #include "cwindowgui.h"
29 #include "mwindowgui.h"
31 #include "playbackengine.h"
32 #include "playtransport.h"
34 #include "recordgui.h"
35 #include "recordmonitor.h"
36 #include "remotecontrol.h"
41 #include <linux/input.h>
43 WinTV::WinTV(MWindow *mwindow, int ifd)
45 this->mwindow = mwindow;
49 memset(ev, 0, sizeof(*ev));
65 ioctl(ifd, EVIOCGRAB, 0);
69 if( running() && !done ) {
78 ioctl(ifd, EVIOCGRAB, 1);
83 int WinTV::open_usb_input(int vendor, int product, int &version)
86 const char *dev_input = "/dev/input";
87 DIR *dir = opendir(dev_input);
88 if( !dir ) return ret;
91 struct input_id dev_id;
92 while( (dp = readdir64(dir)) != 0 ) {
93 char *fn = dp->d_name;
94 if( !strcmp(fn, ".") || !strcmp(fn, "..") ) continue;
95 char path[PATH_MAX]; struct stat st;
96 snprintf(path, PATH_MAX, "%s/%s", dev_input, fn);
97 if( stat(path, &st) < 0 ) continue;
98 if( !S_ISCHR(st.st_mode) ) continue;
99 int fd = open(path, O_RDONLY);
100 if( fd < 0 ) continue;
101 if( !ioctl(fd, EVIOCGID, &dev_id) ) {
102 if( dev_id.bustype == BUS_USB &&
103 dev_id.vendor == vendor &&
104 dev_id.product == product ) {
105 version = dev_id.version;
116 WinTV *WinTV::probe(MWindow *mwindow)
119 int ifd = open_usb_input(0x2040, 0x826d, ver);
120 if( ifd < 0 ) return 0;
121 printf("detected hauppauge WinTV Model 1657, ver=0x%04x\n", ver);
122 return new WinTV(mwindow, ifd);
129 int ret = read(ifd, ev, sizeof(*ev));
131 if( ret != sizeof(*ev) ) {
132 if( ret < 0 ) { perror("read event"); break; }
133 fprintf(stderr, "bad read: %d\n", ret);
140 int WinTV::check_menu_keys(int code)
148 Record *record = mwindow->gui->record;
149 if( !record->running() )
152 record->record_gui->interrupt_thread->start(0);
156 mwindow->gui->channel_info->toggle_scan();
160 RemoteControl *remote_control = mwindow->gui->remote_control;
161 if( !remote_control->deactivate() )
162 remote_control->activate();
170 void WinTV::handle_event()
174 if( !ev->value ) break;
175 this->last_code = this->code;
176 this->code = ev->code;
177 if( check_menu_keys(code) ) break;
178 RemoteHandler *handler = mwindow->gui->remote_control->handler;
180 handler->process_key(ev->code);
186 time_t t = ev->time.tv_sec;
187 struct tm *tp = localtime(&t);
188 printf("wintv event: %4d/%02d/%02d %02d:%02d:%02d.%03d = (%d, %d, 0x%x)\n",
189 tp->tm_year+1900, tp->tm_mon+1, tp->tm_mday,
190 tp->tm_hour, tp->tm_min, tp->tm_sec,
191 (int)ev->time.tv_usec/1000, ev->type, ev->code, ev->value);
197 int WinTVCWindowHandler::wintv_process_code(int code)
199 MWindow *mwindow = wintv->mwindow;
200 EDL *edl = mwindow->edl;
202 PlayTransport *transport = mwindow->gui->mbuttons->transport;
203 if( !transport->get_edl() ) return 0;
204 PlaybackEngine *engine = transport->engine;
205 double position = engine->get_tracking_position();
206 double length = edl->tracks->total_length();
207 int next_command = -1;
212 // select window tile config = BACK 1,2,3
213 case WTV_1: case WTV_2: case WTV_3:
214 if( mwindow->wintv->last_code == WTV_BACK ) {
215 RemoteGUI *rgui = mwindow->gui->cwindow_remote_handler->gui;
216 rgui->tile_windows(code - WTV_1);
219 // select asset program config = TEXT 1,2,3,4,5,6
220 case WTV_4: case WTV_5: case WTV_6:
221 if( mwindow->wintv->last_code == WTV_TEXT ) {
222 mwindow->select_asset(code - WTV_1, 1);
225 // select position in 10 percent units
226 case WTV_7: case WTV_8: case WTV_9:
228 position = length * (code - WTV_0)/10.0;
230 // jump +- 10/60 secs
231 case WTV_LT: position -= 10.0; break;
232 case WTV_UP: position += 60.0; break;
233 case WTV_RT: position += 10.0; break;
234 case WTV_DN: position -= 60.0; break;
235 case WTV_BACK: return 1;
237 CWindowCanvas *canvas = mwindow->cwindow->gui->canvas;
238 int on = canvas->get_fullscreen() ? 0 : 1;
239 canvas->Canvas::set_fullscreen(on, 0);
241 case WTV_VOLUP: return 1;
242 case WTV_VOLDN: return 1;
243 case WTV_CH_UP: return 1;
244 case WTV_CH_DN: return 1;
245 case WTV_TEXT: return 1;
246 case WTV_CC: return 1;
247 case WTV_BOX: return 1;
248 case WTV_START: next_command = SLOW_REWIND; break;
249 case WTV_REV: next_command = FAST_REWIND; break;
250 case WTV_STOP: next_command = STOP; break;
251 case WTV_PLAY: next_command = NORMAL_FWD; break;
252 case WTV_FWD: next_command = FAST_FWD; break;
253 case WTV_END: next_command = SLOW_FWD; break;
254 case WTV_MUTE: return 1;
256 printf("wintv cwindow: unknown code: %04x\n", code);
260 if( next_command < 0 ) {
261 if( position < 0 ) position = 0;
262 transport->change_position(position);
265 transport->handle_transport(next_command);
269 int WinTVCWindowHandler::process_key(int key)
271 return wintv_process_code(key);
274 int WinTVRecordHandler::process_key(int key)
276 Record *record = wintv->mwindow->gui->record;
277 return record->wintv_process_code(key);
281 WinTVRecordHandler::WinTVRecordHandler(WinTV *wintv, RemoteControl *remote_control)
282 : RemoteHandler(remote_control->gui, GREEN)
287 WinTVCWindowHandler::WinTVCWindowHandler(WinTV *wintv, RemoteControl *remote_control)
288 : RemoteHandler(remote_control->gui, BLUE)