Credit Andrew - fix vorbis audio which was scratchy and ensure aging plugin does...
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / wintv.C
1 /*
2  * CINELERRA
3  * Copyright (C) 2016-2020 William Morrow
4  *
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.
9  *
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.
14  *
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
18  * USA
19  */
20
21 #ifdef HAVE_WINTV
22
23 #include "channelinfo.h"
24 #include "cwindow.h"
25 #include "cwindowgui.h"
26 #include "edl.h"
27 #include "mbuttons.h"
28 #include "mwindow.h"
29 #include "mwindowgui.h"
30 #include "language.h"
31 #include "playbackengine.h"
32 #include "playtransport.h"
33 #include "record.h"
34 #include "recordgui.h"
35 #include "recordmonitor.h"
36 #include "remotecontrol.h"
37 #include "tracks.h"
38 #include "wintv.h"
39
40 #include <dirent.h>
41 #include <linux/input.h>
42
43 WinTV::WinTV(MWindow *mwindow, int ifd)
44 {
45         this->mwindow = mwindow;
46         this->ifd = ifd;
47
48         ev = new input_event;
49         memset(ev, 0, sizeof(*ev));
50         ev->code = -1;
51         done = -1;
52         last_code = -1;
53         code = -1;
54 }
55
56 WinTV::~WinTV()
57 {
58         stop();
59         delete ev;
60 }
61
62 void WinTV::stop()
63 {
64         if( ifd >= 0 ) {
65                 ioctl(ifd, EVIOCGRAB, 0);
66                 close(ifd);
67                 ifd = -1;
68         }
69         if( running() && !done ) {
70                 done = 1;
71                 cancel();
72                 join();
73         }
74 }
75
76 void WinTV::start()
77 {
78         ioctl(ifd, EVIOCGRAB, 1);
79         done = 0;
80         Thread::start();
81 }
82
83 int WinTV::open_usb_input(int vendor, int product, int &version)
84 {
85         int ret = -1;
86         const char *dev_input = "/dev/input";
87         DIR *dir = opendir(dev_input);
88         if( !dir ) return ret;
89
90         struct dirent64 *dp;
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;
106                                 ret = fd;
107                                 break;
108                         }
109                 }
110                 close(fd);
111         }
112         closedir(dir);
113         return ret;
114 }
115
116 WinTV *WinTV::probe(MWindow *mwindow)
117 {
118         int ver = -1;
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);
123 }
124
125 void WinTV::run()
126 {
127         enable_cancel();
128         while( !done ) {
129                 int ret = read(ifd, ev, sizeof(*ev));
130                 if( done ) break;
131                 if( ret != sizeof(*ev) ) {
132                         if( ret < 0 ) { perror("read event"); break; }
133                         fprintf(stderr, "bad read: %d\n", ret);
134                         break;
135                 }
136                 handle_event();
137         }
138 }
139
140 int WinTV::check_menu_keys(int code)
141 {
142         int result = 1;
143         switch( code ) {
144         case WTV_POWER:
145                 mwindow->quit();
146                 break;
147         case WTV_TV: {
148                 Record *record = mwindow->gui->record;
149                 if( !record->running() )
150                         record->start();
151                 else
152                         record->record_gui->interrupt_thread->start(0);
153                 break; }
154         case WTV_MENU:
155 #ifdef HAVE_DVB
156                 mwindow->gui->channel_info->toggle_scan();
157 #endif
158                 break;
159         case WTV_RED: {
160                 RemoteControl *remote_control = mwindow->gui->remote_control;
161                 if( !remote_control->deactivate() )
162                         remote_control->activate();
163                 break; }
164         default:
165                 result = 0;
166         }
167         return result;
168 }
169
170 void WinTV::handle_event()
171 {
172         switch(ev->type) {
173         case EV_KEY: {
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;
179                 if( handler )
180                         handler->process_key(ev->code);
181                 break; }
182         case EV_SYN:
183         case EV_MSC:
184                 break;
185         default: {
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);
192                 break; }
193         }
194 }
195
196
197 int WinTVCWindowHandler::wintv_process_code(int code)
198 {
199         MWindow *mwindow = wintv->mwindow;
200         EDL *edl = mwindow->edl;
201         if( !edl ) return 0;
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;
208
209         switch( code ) {
210         case WTV_OK:
211                 break;
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);
217                         return 1;
218                 } // fall thru
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);
223                         break;
224                 } // fall thru
225 // select position in 10 percent units
226         case WTV_7: case WTV_8: case WTV_9:
227         case WTV_0:
228                 position = length * (code - WTV_0)/10.0;
229                 break;
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;
236         case WTV_HOME: {
237                 CWindowCanvas *canvas = mwindow->cwindow->gui->canvas;
238                 int on = canvas->get_fullscreen() ? 0 : 1;
239                 canvas->Canvas::set_fullscreen(on, 0);
240                 return 1; }
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;
255         default:
256                 printf("wintv cwindow: unknown code: %04x\n", code);
257                 return -1;
258         }
259
260         if( next_command < 0 ) {
261                 if( position < 0 ) position = 0;
262                 transport->change_position(position);
263         }
264         else
265                 transport->handle_transport(next_command);
266         return 0;
267 }
268
269 int WinTVCWindowHandler::process_key(int key)
270 {
271         return wintv_process_code(key);
272 }
273
274 int WinTVRecordHandler::process_key(int key)
275 {
276         Record *record = wintv->mwindow->gui->record;
277         return record->wintv_process_code(key);
278 }
279
280
281 WinTVRecordHandler::WinTVRecordHandler(WinTV *wintv, RemoteControl *remote_control)
282  : RemoteHandler(remote_control->gui, GREEN)
283 {
284         this->wintv = wintv;
285 }
286
287 WinTVCWindowHandler::WinTVCWindowHandler(WinTV *wintv, RemoteControl *remote_control)
288  : RemoteHandler(remote_control->gui, BLUE)
289 {
290         this->wintv = wintv;
291 }
292
293 // HAVE_WINTV
294 #endif