no longer need ffmpeg patch0 which was for Termux
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / wintv.C
1 #ifdef HAVE_WINTV
2
3 #include "channelinfo.h"
4 #include "cwindow.h"
5 #include "cwindowgui.h"
6 #include "edl.h"
7 #include "mbuttons.h"
8 #include "mwindow.h"
9 #include "mwindowgui.h"
10 #include "language.h"
11 #include "playbackengine.h"
12 #include "playtransport.h"
13 #include "record.h"
14 #include "recordgui.h"
15 #include "recordmonitor.h"
16 #include "remotecontrol.h"
17 #include "tracks.h"
18 #include "wintv.h"
19
20 #include <dirent.h>
21 #include <linux/input.h>
22
23 WinTV::WinTV(MWindow *mwindow, int ifd)
24 {
25         this->mwindow = mwindow;
26         this->ifd = ifd;
27
28         ev = new input_event;
29         memset(ev, 0, sizeof(*ev));
30         ev->code = -1;
31         done = -1;
32         last_code = -1;
33         code = -1;
34 }
35
36 WinTV::~WinTV()
37 {
38         stop();
39         delete ev;
40 }
41
42 void WinTV::stop()
43 {
44         if( ifd >= 0 ) {
45                 ioctl(ifd, EVIOCGRAB, 0);
46                 close(ifd);
47                 ifd = -1;
48         }
49         if( running() && !done ) {
50                 done = 1;
51                 cancel();
52                 join();
53         }
54 }
55
56 void WinTV::start()
57 {
58         ioctl(ifd, EVIOCGRAB, 1);
59         done = 0;
60         Thread::start();
61 }
62
63 int WinTV::open_usb_input(int vendor, int product, int &version)
64 {
65         int ret = -1;
66         const char *dev_input = "/dev/input";
67         DIR *dir = opendir(dev_input);
68         if( !dir ) return ret;
69
70         struct dirent64 *dp;
71         struct input_id dev_id;
72         while( (dp = readdir64(dir)) != 0 ) {
73                 char *fn = dp->d_name;
74                 if( !strcmp(fn, ".") || !strcmp(fn, "..") ) continue;
75                 char path[PATH_MAX];  struct stat st;
76                 snprintf(path, PATH_MAX, "%s/%s", dev_input, fn);
77                 if( stat(path, &st) < 0 ) continue;
78                 if( !S_ISCHR(st.st_mode) ) continue;
79                 int fd = open(path, O_RDONLY);
80                 if( fd < 0 ) continue;
81                 if( !ioctl(fd, EVIOCGID, &dev_id) ) {
82                         if( dev_id.bustype == BUS_USB &&
83                             dev_id.vendor == vendor &&
84                             dev_id.product == product ) {
85                                 version = dev_id.version;
86                                 ret = fd;
87                                 break;
88                         }
89                 }
90                 close(fd);
91         }
92         closedir(dir);
93         return ret;
94 }
95
96 WinTV *WinTV::probe(MWindow *mwindow)
97 {
98         int ver = -1;
99         int ifd = open_usb_input(0x2040, 0x826d, ver);
100         if( ifd < 0 ) return 0;
101         printf("detected hauppauge WinTV Model 1657, ver=0x%04x\n", ver);
102         return new WinTV(mwindow, ifd);
103 }
104
105 void WinTV::run()
106 {
107         enable_cancel();
108         while( !done ) {
109                 int ret = read(ifd, ev, sizeof(*ev));
110                 if( done ) break;
111                 if( ret != sizeof(*ev) ) {
112                         if( ret < 0 ) { perror("read event"); break; }
113                         fprintf(stderr, "bad read: %d\n", ret);
114                         break;
115                 }
116                 handle_event();
117         }
118 }
119
120 int WinTV::check_menu_keys(int code)
121 {
122         int result = 1;
123         switch( code ) {
124         case WTV_POWER:
125                 mwindow->quit();
126                 break;
127         case WTV_TV: {
128                 Record *record = mwindow->gui->record;
129                 if( !record->running() )
130                         record->start();
131                 else
132                         record->record_gui->interrupt_thread->start(0);
133                 break; }
134         case WTV_MENU:
135 #ifdef HAVE_DVB
136                 mwindow->gui->channel_info->toggle_scan();
137 #endif
138                 break;
139         case WTV_RED: {
140                 RemoteControl *remote_control = mwindow->gui->remote_control;
141                 if( !remote_control->deactivate() )
142                         remote_control->activate();
143                 break; }
144         default:
145                 result = 0;
146         }
147         return result;
148 }
149
150 void WinTV::handle_event()
151 {
152         switch(ev->type) {
153         case EV_KEY: {
154                 if( !ev->value ) break;
155                 this->last_code = this->code;
156                 this->code = ev->code;
157                 if( check_menu_keys(code) ) break;
158                 RemoteHandler *handler = mwindow->gui->remote_control->handler;
159                 if( handler )
160                         handler->process_key(ev->code);
161                 break; }
162         case EV_SYN:
163         case EV_MSC:
164                 break;
165         default: {
166                 time_t t = ev->time.tv_sec;
167                 struct tm *tp = localtime(&t);
168                 printf("wintv event: %4d/%02d/%02d %02d:%02d:%02d.%03d = (%d, %d, 0x%x)\n",
169                         tp->tm_year+1900, tp->tm_mon+1, tp->tm_mday,
170                         tp->tm_hour, tp->tm_min, tp->tm_sec,
171                         (int)ev->time.tv_usec/1000, ev->type, ev->code, ev->value);
172                 break; }
173         }
174 }
175
176
177 int WinTVCWindowHandler::wintv_process_code(int code)
178 {
179         MWindow *mwindow = wintv->mwindow;
180         EDL *edl = mwindow->edl;
181         if( !edl ) return 0;
182         PlayTransport *transport = mwindow->gui->mbuttons->transport;
183         if( !transport->get_edl() ) return 0;
184         PlaybackEngine *engine = transport->engine;
185         double position = engine->get_tracking_position();
186         double length = edl->tracks->total_length();
187         int next_command = -1;
188
189         switch( code ) {
190         case WTV_OK:
191                 break;
192 // select window tile config = BACK 1,2,3
193         case WTV_1: case WTV_2: case WTV_3:
194                 if( mwindow->wintv->last_code == WTV_BACK ) {
195                         RemoteGUI *rgui = mwindow->gui->cwindow_remote_handler->gui;
196                         rgui->tile_windows(code - WTV_1);
197                         return 1;
198                 } // fall thru
199 // select asset program config = TEXT 1,2,3,4,5,6
200         case WTV_4: case WTV_5: case WTV_6:
201                 if( mwindow->wintv->last_code == WTV_TEXT ) {
202                         mwindow->select_asset(code - WTV_1, 1);
203                         break;
204                 } // fall thru
205 // select position in 10 percent units
206         case WTV_7: case WTV_8: case WTV_9:
207         case WTV_0:
208                 position = length * (code - WTV_0)/10.0;
209                 break;
210 // jump +- 10/60 secs
211         case WTV_LT:  position -= 10.0;  break;
212         case WTV_UP:  position += 60.0;  break;
213         case WTV_RT:  position += 10.0;  break;
214         case WTV_DN:  position -= 60.0;  break;
215         case WTV_BACK: return 1;
216         case WTV_HOME: {
217                 CWindowCanvas *canvas = mwindow->cwindow->gui->canvas;
218                 int on = canvas->get_fullscreen() ? 0 : 1;
219                 canvas->Canvas::set_fullscreen(on, 0);
220                 return 1; }
221         case WTV_VOLUP: return 1;
222         case WTV_VOLDN: return 1;
223         case WTV_CH_UP: return 1;
224         case WTV_CH_DN: return 1;
225         case WTV_TEXT:  return 1;
226         case WTV_CC:    return 1;
227         case WTV_BOX:   return 1;
228         case WTV_START: next_command = SLOW_REWIND;  break;
229         case WTV_REV:   next_command = FAST_REWIND;  break;
230         case WTV_STOP:  next_command = STOP;         break;
231         case WTV_PLAY:  next_command = NORMAL_FWD;   break;
232         case WTV_FWD:   next_command = FAST_FWD;     break;
233         case WTV_END:   next_command = SLOW_FWD;     break;
234         case WTV_MUTE:  return 1;
235         default:
236                 printf("wintv cwindow: unknown code: %04x\n", code);
237                 return -1;
238         }
239
240         if( next_command < 0 ) {
241                 if( position < 0 ) position = 0;
242                 transport->change_position(position);
243         }
244         else
245                 transport->handle_transport(next_command);
246         return 0;
247 }
248
249 int WinTVCWindowHandler::process_key(int key)
250 {
251         return wintv_process_code(key);
252 }
253
254 int WinTVRecordHandler::process_key(int key)
255 {
256         Record *record = wintv->mwindow->gui->record;
257         return record->wintv_process_code(key);
258 }
259
260
261 WinTVRecordHandler::WinTVRecordHandler(WinTV *wintv, RemoteControl *remote_control)
262  : RemoteHandler(remote_control->gui, GREEN)
263 {
264         this->wintv = wintv;
265 }
266
267 WinTVCWindowHandler::WinTVCWindowHandler(WinTV *wintv, RemoteControl *remote_control)
268  : RemoteHandler(remote_control->gui, BLUE)
269 {
270         this->wintv = wintv;
271 }
272
273 // HAVE_WINTV
274 #endif