r956: README.BUILD - add more library recommendations
[cinelerra_cv/ct.git] / cinelerra / devicedvbinput.C
blobca88d71d41d49fe9539d6edcf95095cc01257eaa
1 #include "channel.h"
2 #include "condition.h"
3 #include "devicedvbinput.h"
4 #include "devicedvbinput.inc"
5 #include "edl.h"
6 #include "edlsession.h"
7 #include "mutex.h"
8 #include "mwindow.h"
9 #include "recordconfig.h"
10 #include "renderfarm.h"
14 #include <errno.h>
15 #include <netdb.h>
16 #include <netinet/in.h>
17 #include <string.h>
18 #include <sys/socket.h>
19 #include <unistd.h>
24 DeviceDVBInput::DeviceDVBInput(MWindow *mwindow, VideoInConfig *config)
25  : GarbageObject("DeviceDVBInput")
27         reset();
28         this->config = config;
29         this->mwindow = mwindow;
30         signal_lock = new Condition(0, "DeviceDVBInput::signal_lock", 0);
31         channel = new Channel;
34 DeviceDVBInput::~DeviceDVBInput()
36         close();
37         delete signal_lock;
38 // Because MWindow::dvb_input_lock must be locked before 
39 // Garbage::delete_object,
40 // MWindow::dvb_input_lock is always going to be locked when this is called.
41         mwindow->dvb_input = 0;
42         delete channel;
46 void DeviceDVBInput::reset()
48         tuner_fd = -1;
49         want_signal = 0;
50         signal_lock = 0;
51         lock_result = 0;
52         signal_result = 0;
53         channel_changed = 0;
56 DeviceDVBInput* DeviceDVBInput::get_input_thread(MWindow *mwindow)
58         DeviceDVBInput *input_thread = 0;
59         mwindow->dvb_input_lock->lock("DeviceDVBInput::get_input_thread");
60 // reference existing input if it exists
61         if(mwindow->dvb_input) 
62         {
63                 input_thread = mwindow->dvb_input;
64                 input_thread->add_user();
65         }
66         else
67 // create shared input if it doesn't exist
68         {
69                 input_thread = mwindow->dvb_input = 
70                         new DeviceDVBInput(mwindow, mwindow->edl->session->vconfig_in);
71                 input_thread->GarbageObject::add_user();
74         }
75         mwindow->dvb_input_lock->unlock();
76         return input_thread;
79 void DeviceDVBInput::put_input_thread(MWindow *mwindow)
81         mwindow->dvb_input_lock->lock("DeviceDVBInput::put_input_thread");
82         mwindow->dvb_input->GarbageObject::remove_user();
83         Garbage::delete_object(mwindow->dvb_input);
84         mwindow->dvb_input_lock->unlock();
87 int DeviceDVBInput::close()
89         if(tuner_fd >= 0)
90         {
91 // Stop streaming
92                 ::close(tuner_fd);
93                 tuner_fd = -1;
94         }
95         return 0;
98 int DeviceDVBInput::try_tuner()
100         int error = 0;
101 printf("DeviceDVBInput::try_tuner 1\n");
102         tuner_fd = RenderFarmServerThread::open_client(config->dvb_in_host, 
103                 config->dvb_in_port);
105 printf("DeviceDVBInput::try_tuner 10\n");
106         if(tuner_fd < 0) return 1;
109 // Send command for tuner mode
110         error = write_int64(RENDERFARM_TUNER);
111         if(error)
112         {
113                 ::close(tuner_fd);
114                 tuner_fd = -1;
115                 return 1;
116         }
118 printf("DeviceDVBInput::try_tuner 20\n");
119 // Read status from tuner
121         int available = !read_int64(&error);
123         if(!available || error)
124         {
125                 printf("DeviceDVBInput::try_tuner available=%d error=%d\n", available, error);
126                 ::close(tuner_fd);
127                 tuner_fd = -1;
128                 return 1;
129         }
131         return 0;
136 int DeviceDVBInput::reopen_tuner()
138 // Reopen driver
140         if(tuner_fd >= 0)
141         {
142                 ::close(tuner_fd);
143                 tuner_fd = -1;
144         }
149 // Try tuner until it works.
150         for(int attempts = 0; attempts < 3; attempts++)
151         {
152                 if(!try_tuner()) break;
154                 if(tuner_fd >= 0)
155                 {
156                         break;
157                 }
159                 sleep(1);
160         }
162 // No tuner available
163         if(tuner_fd < 0)
164         {
165                 printf("DeviceDVBInput::reopen_tuner: tuner '%s' not available\n", 
166                         config->dvb_in_host);
167                 return 1;
168         }
171 // Set the channel.
172 // Extra parameters should come before the NETTUNE_CHANNEL command
173 // in the form of NETTUNE_SET commands.
174         if(write_int64(NETTUNE_SET_CHANNEL)) return 1;
175         if(write_int64(channel->entry)) return 1;
177         if(write_int64(NETTUNE_SET_TABLE)) return 1;
178         if(write_int64(channel->freqtable)) return 1;
180         if(write_int64(NETTUNE_SET_AUDIO_PID)) return 1;
181         if(write_int64(channel->audio_pid)) return 1;
183         if(write_int64(NETTUNE_SET_VIDEO_PID)) return 1;
184         if(write_int64(channel->video_pid)) return 1;
187 // Open the tuner
188         if(write_int64(NETTUNE_OPEN)) return 1;
190         if(read_int64(0)) 
191         {
192                 printf("DeviceDVBInput::reopen_tuner: open failed\n");
193                 return 1;
194         }
198         return 0;
201 int DeviceDVBInput::get_signal_strength(int channel, int tuner_id)
203     sleep(5);
205         want_signal = 1;
206         signal_lock->lock("NetTune::get_signal_strength");
211 // Zero power if no lock
212     if(lock_result)
213         {
214                 if(!signal_result)
215                 {
216                         signal_result = 1;
217                 }
218         }
219         else
220         {
221                 signal_result = 0;
222         }
224         return signal_result;
230 int64_t DeviceDVBInput::read_int64(int *error)
232         int temp = 0;
233         if(!error) error = &temp;
235         unsigned char data[sizeof(int64_t)];
236         *error = (read_tuner(data, sizeof(int64_t)) != sizeof(int64_t));
238 // Make it return 1 if error so it can be used to read a result code from the
239 // server.
240         int64_t result = 1;
241         if(!*error)
242         {
243                 result = (((int64_t)data[0]) << 56) |
244                         (((uint64_t)data[1]) << 48) | 
245                         (((uint64_t)data[2]) << 40) |
246                         (((uint64_t)data[3]) << 32) |
247                         (((uint64_t)data[4]) << 24) |
248                         (((uint64_t)data[5]) << 16) |
249                         (((uint64_t)data[6]) << 8)  |
250                         data[7];
251         }
252         return result;
255 int DeviceDVBInput::write_int64(int64_t value)
257         unsigned char data[sizeof(int64_t)];
258         data[0] = (value >> 56) & 0xff;
259         data[1] = (value >> 48) & 0xff;
260         data[2] = (value >> 40) & 0xff;
261         data[3] = (value >> 32) & 0xff;
262         data[4] = (value >> 24) & 0xff;
263         data[5] = (value >> 16) & 0xff;
264         data[6] = (value >> 8) & 0xff;
265         data[7] = value & 0xff;
266 // printf("DeviceDVBInput::write_int64 %02x %02x %02x %02x %02x %02x %02x %02x\n",
267 // data[0],
268 // data[1],
269 // data[2],
270 // data[3],
271 // data[4],
272 // data[5],
273 // data[6],
274 // data[7]);
275         return (write_tuner(data, sizeof(int64_t)) != sizeof(int64_t));
278 int DeviceDVBInput::write_tuner(unsigned char *data, int size)
280         return write(tuner_fd, data, size);
283 int DeviceDVBInput::read_stream(unsigned char *data, int size)
285         int result = 0;
286         if(tuner_fd < 0 || channel_changed)
287         {
288                 int result2 = reopen_tuner();
290                 if(result2)
291                 {
292                         close();
293                         return 0;
294                 }
296                 channel_changed = 0;
297         }
299 // Read stream
302         return result;
305 int DeviceDVBInput::read_tuner(unsigned char *data, int size)
307         int bytes_read = 0;
308         int offset = 0;
309         while(size > 0)
310         {
311                 bytes_read = ::read(tuner_fd, data + offset, size);
312                 if(bytes_read > 0)
313                 {
314                         offset += bytes_read;
315                         size -= bytes_read;
316                 }
317                 else
318                 if(bytes_read <= 0)
319                 {
320                         printf("NetTune::read_tuner connection closed\n");
321                         ::close(tuner_fd);
322                         tuner_fd = -1;
323                         break;
324                 }
325         }
326         return offset;