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 X10TV::X10TV(MWindow *mwindow, int *fds, int nfds)
45 this->mwindow = mwindow;
46 this->ifds = new int[nfds];
48 for( int i=0; i<nfds; ++i ) this->ifds[i] = fds[i];
51 memset(ev, 0, sizeof(*ev));
69 for( int i=nfds; --i>=0; ) {
70 ioctl(ifds[i], EVIOCGRAB, 0);
84 for( int i=nfds; --i>=0; ) {
86 ioctl(fd, EVIOCGRAB, 1);
87 if( fd >= mfd ) mfd = fd+1;
94 int X10TV::open_usb_inputs(int vendor, int product, int &version,
98 const char *dev_input = "/dev/input";
99 DIR *dir = opendir(dev_input);
100 if( !dir ) return ret;
103 struct input_id dev_id;
105 while( nfds < mxfds && (dp = readdir64(dir)) != 0 ) {
106 char *fn = dp->d_name;
107 if( !strcmp(fn, ".") || !strcmp(fn, "..") ) continue;
108 char path[PATH_MAX]; struct stat st;
109 snprintf(path, PATH_MAX, "%s/%s", dev_input, fn);
110 if( stat(path, &st) < 0 ) continue;
111 if( !S_ISCHR(st.st_mode) ) continue;
112 int fd = open(path, O_RDONLY);
113 if( fd < 0 ) continue;
114 if( !ioctl(fd, EVIOCGID, &dev_id) ) {
115 if( dev_id.bustype == BUS_USB &&
116 dev_id.vendor == vendor &&
117 dev_id.product == product ) {
119 // quirk, reports pointing_stick for keys
121 (1<<INPUT_PROP_POINTING_STICK);
122 int ret = ioctl(fd, EVIOCGPROP(sizeof(props)), &props);
123 if( ret == sizeof(props) && (props & mptrs) ) {
124 version = dev_id.version;
137 X10TV *X10TV::probe(MWindow *mwindow)
139 int ver = -1, ifds[16];
140 int nfds = open_usb_inputs(0x0bc7, 0x0004, ver, ifds, 16);
141 if( nfds <= 0 ) return 0;
142 printf("detected ATI X10 remote, ver=0x%04x\n", ver);
143 return new X10TV(mwindow, ifds, nfds);
151 int ret = select(mfd, &rds, 0, 0, 0);
153 int fd = -1, k = ret > 0 ? nfds : 0;
156 if( FD_ISSET(ifd, &rds) ) {
161 printf("select failed\n");
162 usleep(100000); continue;
164 ret = read(fd, ev, sizeof(*ev));
166 if( ret != sizeof(*ev) ) {
167 if( ret < 0 ) { perror("read event"); break; }
168 fprintf(stderr, "bad read: %d\n", ret);
175 int X10TV::check_menu_keys(int code)
183 Record *record = mwindow->gui->record;
184 if( !record->running() )
187 record->record_gui->interrupt_thread->start(0);
191 mwindow->gui->channel_info->toggle_scan();
195 RemoteControl *remote_control = mwindow->gui->remote_control;
196 if( !remote_control->deactivate() )
197 remote_control->activate();
205 void X10TV::handle_event(int fd)
209 if( !ev->value ) break;
210 this->last_code = this->code;
211 this->code = ev->code;
212 if( check_menu_keys(code) ) break;
213 RemoteHandler *handler = mwindow->gui->remote_control->handler;
215 handler->process_key(ev->code);
221 time_t t = ev->time.tv_sec;
222 struct tm *tp = localtime(&t);
223 printf("x10tv event %d: %4d/%02d/%02d %02d:%02d:%02d.%03d = (%d, %d, 0x%x)\n",
224 fd, tp->tm_year+1900, tp->tm_mon+1, tp->tm_mday,
225 tp->tm_hour, tp->tm_min, tp->tm_sec,
226 (int)ev->time.tv_usec/1000, ev->type, ev->code, ev->value);
232 int X10TVCWindowHandler::x10tv_process_code(int code)
234 MWindow *mwindow = x10tv->mwindow;
235 EDL *edl = mwindow->edl;
237 PlayTransport *transport = mwindow->gui->mbuttons->transport;
238 if( !transport->get_edl() ) return 0;
239 PlaybackEngine *engine = transport->engine;
240 double position = engine->get_tracking_position();
241 double length = edl->tracks->total_length();
242 int next_command = -1;
247 case X10_POWER: break;
251 case X10_BOOK: break;
252 case X10_EDIT: break;
253 case X10_VOLDN: return 1;
254 case X10_VOLUP: return 1;
255 case X10_MUTE: break;
256 case X10_CH_DN: break;
257 case X10_CH_UP: break;
258 // select window tile config = BACK 1,2,3
259 case X10_1: case X10_2: case X10_3:
260 if( mwindow->x10tv->last_code == X10_MENU ) {
261 RemoteGUI *rgui = mwindow->gui->cwindow_remote_handler->gui;
262 rgui->tile_windows(code - X10_1);
265 // select asset program config = TEXT 1,2,3,4,5,6
266 case X10_4: case X10_5: case X10_6:
267 if( mwindow->x10tv->last_code == X10_SETUP ) {
268 mwindow->select_asset(code - X10_1, 1);
271 case X10_7: case X10_8: case X10_9:
273 // select position in 10 percent units
274 position = length * (code - X10_0)/10.0;
276 case X10_MENU: return 0;
277 case X10_SETUP: return 0;
278 case X10_C: return 1;
279 case X10_UP: position += 60.0; break;
280 case X10_D: return 1;
281 case X10_PROPS: return 1;
282 case X10_LT: position -= 10.0; break;
283 case X10_OK: return 1;
284 case X10_RT: position += 10.0; break;
286 CWindowCanvas *canvas = mwindow->cwindow->gui->canvas;
287 int on = canvas->get_fullscreen() ? 0 : 1;
288 canvas->Canvas::set_fullscreen(on, 0);
290 case X10_E: return 1;
291 case X10_DN: position -= 60.0; break;
292 case X10_F: return 1;
293 case X10_REW: next_command = FAST_REWIND; break;
294 case X10_PLAY: next_command = NORMAL_FWD; break;
295 case X10_FWD: next_command = FAST_FWD; break;
296 case X10_REC: next_command = SLOW_REWIND; break;
297 case X10_STOP: next_command = STOP; break;
298 case X10_PAUSE: next_command = SLOW_FWD; break;
301 printf("x10tv cwindow: unknown code: %04x\n", code);
305 if( next_command < 0 ) {
306 if( position < 0 ) position = 0;
307 transport->change_position(position);
310 transport->handle_transport(next_command);
314 int X10TVCWindowHandler::process_key(int key)
316 return x10tv_process_code(key);
319 int X10TVRecordHandler::process_key(int key)
321 Record *record = x10tv->mwindow->gui->record;
322 return record->x10tv_process_code(key);
326 X10TVRecordHandler::X10TVRecordHandler(X10TV *x10tv, RemoteControl *remote_control)
327 : RemoteHandler(remote_control->gui, GREEN)
332 X10TVCWindowHandler::X10TVCWindowHandler(X10TV *x10tv, RemoteControl *remote_control)
333 : RemoteHandler(remote_control->gui, BLUE)