LiVES  3.2.0
lives-yuv4mpeg.c
Go to the documentation of this file.
1 // yuv4mpeg.c
2 // LiVES
3 // (c) G. Finch 2004 - 2019 <salsaman+lives@gmail.com>
4 // released under the GNU GPL 3 or later
5 // see file ../COPYING or www.gnu.org for licensing details
6 
7 #include "main.h"
8 #include "interface.h"
9 #include "lives-yuv4mpeg.h"
10 #include "effects-weed.h"
11 
12 static boolean gotbroken;
13 
14 typedef struct y4data {
15  const char *filename;
16  lives_yuv4m_t *yuv4mpeg;
17 
18  int fd;
19  int i;
20 } y4data;
21 
22 static int yuvout, hsize_out, vsize_out;
23 
24 // lists of cards in use
25 static LiVESList *fw_cards = NULL;
26 
27 
28 static lives_yuv4m_t *lives_yuv4mpeg_alloc(void) {
29  lives_yuv4m_t *yuv4mpeg = (lives_yuv4m_t *) malloc(sizeof(lives_yuv4m_t));
30  if (!yuv4mpeg) return NULL;
31  yuv4mpeg->sar = y4m_sar_UNKNOWN;
32  yuv4mpeg->dar = y4m_dar_4_3;
33  y4m_init_stream_info(&(yuv4mpeg->streaminfo));
34  y4m_init_frame_info(&(yuv4mpeg->frameinfo));
35  yuv4mpeg->filename = NULL;
36  yuv4mpeg->name = NULL;
37  yuv4mpeg->fd = -1;
38  yuv4mpeg->ready = FALSE;
39  return yuv4mpeg;
40 }
41 
42 
43 static void *y4open_thread(void *arg) {
44  y4data *thread_data = (y4data *)arg;
45  int fd = lives_open2(thread_data->filename, O_RDONLY);
46  thread_data->fd = fd;
47  pthread_exit(NULL);
48 }
49 
50 
51 static void *y4header_thread(void *arg) {
52  y4data *thread_data = (y4data *)arg;
53  lives_yuv4m_t *yuv4mpeg = thread_data->yuv4mpeg;
54  thread_data->i = y4m_read_stream_header(yuv4mpeg->fd, &(yuv4mpeg->streaminfo));
55  pthread_exit(NULL);
56 }
57 
58 
59 static void fill_read(int fd, char *buf, size_t count) {
60  size_t bytes = 0;
61  ssize_t got;
62 
63  do {
64  got = read(fd, buf + bytes, count - bytes);
65  if (got < 0) return;
66  bytes += got;
67  } while (bytes < count);
68 }
69 
70 
71 static void *y4frame_thread(void *arg) {
72  y4data *thread_data = (y4data *)arg;
73  lives_yuv4m_t *yuv4mpeg = thread_data->yuv4mpeg;
74  char buff[5], bchar;
75 
76  thread_data->i = Y4M_OK;
77 
78  // read 5 bytes FRAME
79  fill_read(yuv4mpeg->fd, buff, 5);
80 
81  if (strncmp(buff, "FRAME", 5)) {
82  if (!gotbroken) {
83  thread_data->i = Y4M_ERR_MAGIC;
84  pthread_exit(NULL);
85  }
86 
87  do {
88  lives_memmove(buff, buff + 1, 4);
89  fill_read(yuv4mpeg->fd, buff + 4, 1);
90  } while (strncmp(buff, "FRAME", 5));
91  }
92 
93  do {
94  fill_read(yuv4mpeg->fd, &bchar, 1);
95  } while (strncmp(&bchar, "\n", 1));
96 
97  // read YUV420
98  fill_read(yuv4mpeg->fd, (char *)yuv4mpeg->pixel_data[0], yuv4mpeg->hsize * yuv4mpeg->vsize);
99  fill_read(yuv4mpeg->fd, (char *)yuv4mpeg->pixel_data[1], yuv4mpeg->hsize * yuv4mpeg->vsize / 4);
100  fill_read(yuv4mpeg->fd, (char *)yuv4mpeg->pixel_data[2], yuv4mpeg->hsize * yuv4mpeg->vsize / 4);
101 
102  pthread_exit(NULL);
103 }
104 
105 
106 static boolean lives_yuv_stream_start_read(lives_clip_t *sfile) {
107  double ofps = sfile->fps;
108 
109  lives_yuv4m_t *yuv4mpeg = (lives_yuv4m_t *)sfile->ext_src;
110 
111  pthread_t y4thread;
112 
113  char *filename = yuv4mpeg->filename, *tmp;
114 
115  ticks_t timeout;
116  lives_alarm_t alarm_handle = 0;
117 
118  int ohsize = sfile->hsize;
119  int ovsize = sfile->vsize;
120 
121  y4data thread_data;
122 
123  int i;
124 
125  if (!filename) return FALSE;
126 
127  if (yuv4mpeg->fd == -1) {
128  // create a thread to open the fifo
129 
130  thread_data.filename = filename;
131 
132  pthread_create(&y4thread, NULL, y4open_thread, (void *)&thread_data);
133 
134  alarm_handle = lives_alarm_set(LIVES_SHORTEST_TIMEOUT);
135 
136  d_print("");
137  d_print(_("Waiting for yuv4mpeg frames..."));
138 
139  gotbroken = FALSE;
140 
141  while ((timeout = lives_alarm_check(alarm_handle)) > 0 && !pthread_kill(y4thread, 0)) {
142  // wait for thread to complete or timeout
143  lives_usleep(prefs->sleep_time);
145  }
146  lives_alarm_clear(alarm_handle);
147 
148  if (timeout == 0) {
149  // timeout - kill thread and wait for it to terminateo
150  pthread_cancel(y4thread);
151  pthread_join(y4thread, NULL);
152 
153  d_print_failed();
154  d_print(_("Unable to open the incoming video stream\n"));
155 
156  yuv4mpeg->fd = thread_data.fd;
157 
158  if (yuv4mpeg->fd >= 0) {
159  close(yuv4mpeg->fd);
160  yuv4mpeg->fd = -1;
161  }
162  return FALSE;
163  }
164 
165  pthread_join(y4thread, NULL);
166 
167  yuv4mpeg->fd = thread_data.fd;
168 
169  if (yuv4mpeg->fd < 0) {
170  return FALSE;
171  }
172  }
173 
174  // create a thread to open the stream header
175  thread_data.yuv4mpeg = yuv4mpeg;
176  pthread_create(&y4thread, NULL, y4header_thread, &thread_data);
177  alarm_handle = lives_alarm_set(LIVES_SHORT_TIMEOUT);
178 
179  while ((timeout = lives_alarm_check(alarm_handle)) > 0 && !pthread_kill(y4thread, 0)) {
180  // wait for thread to complete or timeout
181  lives_usleep(prefs->sleep_time);
183  }
184  lives_alarm_clear(alarm_handle);
185 
186  if (timeout == 0) {
187  // timeout - kill thread and wait for it to terminate
188  pthread_cancel(y4thread);
189  pthread_join(y4thread, NULL);
190  d_print(_("Unable to read the stream header\n"));
191  return FALSE;
192  }
193 
194  pthread_join(y4thread, NULL);
195 
196  i = thread_data.i;
197 
198  if (i != Y4M_OK) {
199  char *tmp;
200  d_print((tmp = lives_strdup_printf("yuv4mpeg: %s\n", y4m_strerr(i))));
201  lives_free(tmp);
202  return FALSE;
203  }
204 
205  d_print(_("got header\n"));
206 
207  sfile->hsize = yuv4mpeg->hsize = y4m_si_get_width(&(yuv4mpeg->streaminfo));
208  sfile->vsize = yuv4mpeg->vsize = y4m_si_get_height(&(yuv4mpeg->streaminfo));
209 
210  sfile->fps = cfile->pb_fps = lives_strtod(lives_strdup_printf("%.8f", Y4M_RATIO_DBL
211  (y4m_si_get_framerate(&(yuv4mpeg->streaminfo)))), NULL);
212 
213  if (sfile->hsize * sfile->vsize == 0) {
214  do_error_dialog(lives_strdup_printf(_("Video dimensions: %d x %d are invalid. Stream cannot be opened"),
215  sfile->hsize, sfile->vsize));
216  return FALSE;
217  }
218 
219  if (sfile->hsize != ohsize || sfile->vsize != ovsize || sfile->fps != ofps) {
220  set_main_title(sfile->file_name, 0);
221  }
222 
223  d_print((tmp = lives_strdup_printf(_("Reset clip values for %s: size=%dx%d fps=%.3f\n"), yuv4mpeg->name,
224  cfile->hsize, yuv4mpeg->vsize, cfile->bpp, cfile->fps)));
225  lives_free(tmp);
226 
227  yuv4mpeg->ready = TRUE;
228 
229  return TRUE;
230 }
231 
232 
234  y4m_fini_stream_info(&(yuv4mpeg->streaminfo));
235  y4m_fini_frame_info(&(yuv4mpeg->frameinfo));
236  yuv4mpeg->sar = y4m_sar_UNKNOWN;
237  yuv4mpeg->dar = y4m_dar_4_3;
238  if (yuv4mpeg->fd != -1) close(yuv4mpeg->fd);
239 
240  if (yuv4mpeg->filename) {
241  lives_rm(yuv4mpeg->filename);
242  lives_free(yuv4mpeg->filename);
243  }
244 
245  if (yuv4mpeg->name) lives_free(yuv4mpeg->name);
246 
247  if (yuv4mpeg->type == YUV4_TYPE_FW) fw_cards = lives_list_remove(fw_cards, LIVES_INT_TO_POINTER(yuv4mpeg->cardno));
248  if (yuv4mpeg->type == YUV4_TYPE_TV) mainw->videodevs = lives_list_remove(mainw->videodevs,
249  LIVES_INT_TO_POINTER(yuv4mpeg->cardno));
250 }
251 
252 
254  lives_yuv4m_t *yuv4mpeg = (lives_yuv4m_t *)(sfile->ext_src);
255 
256  y4data thread_data;
257 
258  pthread_t y4thread;
259 
260  ticks_t timeout;
261 
262  lives_alarm_t alarm_handle;
263 
264  int error;
265 
266  if (!yuv4mpeg->ready) lives_yuv_stream_start_read(sfile);
267 
268  weed_set_int_value(layer, WEED_LEAF_WIDTH, sfile->hsize);
269  weed_set_int_value(layer, WEED_LEAF_HEIGHT, sfile->vsize);
270  weed_set_int_value(layer, WEED_LEAF_CURRENT_PALETTE, WEED_PALETTE_YUV420P);
271  weed_set_int_value(layer, WEED_LEAF_YUV_SUBSPACE, WEED_YUV_SUBSPACE_YCBCR);
272 
274 
275  if (!yuv4mpeg->ready) {
276  return;
277  }
278 
279  yuv4mpeg->pixel_data = weed_get_voidptr_array(layer, WEED_LEAF_PIXEL_DATA, &error);
280 
281  // create a thread to open the stream header
282 
283  thread_data.yuv4mpeg = yuv4mpeg;
284  pthread_create(&y4thread, NULL, y4frame_thread, &thread_data);
285 
286  alarm_handle = lives_alarm_set(LIVES_SHORTEST_TIMEOUT);
287 
288  while ((timeout = lives_alarm_check(alarm_handle)) > 0 && !pthread_kill(y4thread, 0)) {
289  // wait for thread to complete or timeout
290  lives_usleep(prefs->sleep_time);
291  }
292  lives_alarm_clear(alarm_handle);
293 
294  if (timeout == 0) {
295  // timeout - kill thread and wait for it to terminate
296  pthread_cancel(y4thread);
297  d_print(_("Unable to read the incoming video frame\n"));
298  gotbroken = TRUE;
299  } else gotbroken = FALSE;
300 
301  pthread_join(y4thread, NULL);
302 
303  lives_free(yuv4mpeg->pixel_data);
304  yuv4mpeg->pixel_data = NULL;
305 
306  weed_set_int_value(layer, WEED_LEAF_YUV_SAMPLING, WEED_YUV_SAMPLING_MPEG);
307 
308  return;
309 }
310 
311 
312 static boolean open_yuv4m_inner(const char *filename, const char *fname, int new_file, int type, int cardno) {
313  // create a virtual clip
314  int old_file = mainw->current_file;
315 
316  lives_yuv4m_t *yuv4mpeg;
317 
318  cfile->clip_type = CLIP_TYPE_YUV4MPEG;
319 
320  // get size of frames, arate, achans, asamps, signed endian
321  yuv4mpeg = lives_yuv4mpeg_alloc();
322 
323  yuv4mpeg->fd = -1;
324 
325  yuv4mpeg->filename = lives_strdup(filename);
326  yuv4mpeg->name = lives_strdup(fname);
327 
328  yuv4mpeg->type = type;
329  yuv4mpeg->cardno = cardno;
330 
331  cfile->ext_src = yuv4mpeg;
332  cfile->ext_src_type = LIVES_EXT_SRC_FIFO;
333 
334  cfile->bpp = 12;
335 
336  cfile->start = cfile->end = cfile->frames = 1;
337 
338  cfile->hsize = DEF_GEN_WIDTH;
339  cfile->vsize = DEF_GEN_HEIGHT;
340 
341  cfile->img_type = IMG_TYPE_BEST; // override the pref
342 
343  cfile->is_loaded = TRUE;
344 
345  add_to_clipmenu();
346 
347  switch_to_file((mainw->current_file = old_file), new_file);
348 
349  return TRUE;
350 }
351 
352 
353 void on_open_yuv4m_activate(LiVESMenuItem *menuitem, livespointer user_data) {
354  // open a general yuvmpeg stream
355  // start "playing" but open frames in yuv4mpeg format on stdin
356 
357  int old_file = mainw->current_file, new_file = mainw->first_free_file;
358  char *tmp;
359  char *filename;
360  char *fname;
361 
362  char *audio_real, *audio_fake;
363 
364  if (menuitem && !do_yuv4m_open_warning()) return;
365 
366  fname = (_("yuv4mpeg stream"));
367 
368  if (!get_new_handle(new_file, fname)) {
369  lives_free(fname);
370  return;
371  }
372 
373  mainw->current_file = new_file;
374 
375  if (!strlen(prefs->yuvin)) {
376  filename = choose_file(NULL, NULL, NULL, LIVES_FILE_CHOOSER_ACTION_OPEN, _("Open _yuv4mpeg stream (fifo)"), NULL);
377  if (!filename) return;
378  } else filename = lives_strdup(prefs->yuvin);
379 
380  mkfifo(filename, S_IRUSR | S_IWUSR);
381 
382  if (!open_yuv4m_inner(filename, fname, new_file, YUV4_TYPE_GENERIC, 0)) {
383  close_current_file(old_file);
384  lives_free(filename);
385  lives_free(fname);
386  return;
387  }
388 
389  lives_free(fname);
390 
391  if (!lives_yuv_stream_start_read(cfile)) {
392  close_current_file(old_file);
393  lives_free(filename);
394  return;
395  }
396 
397  new_file = mainw->current_file;
398 
399  lives_snprintf(cfile->type, 40, "%s", _("yu4mpeg stream in"));
400 
401  d_print((tmp = lives_strdup_printf(_("Opened yuv4mpeg stream on %s"), filename)));
402  lives_free(tmp);
403  lives_free(filename);
404 
405  d_print(_("Audio: "));
406 
407  if (cfile->achans == 0) {
408  d_print(_("none\n"));
409  } else {
410  d_print((tmp = lives_strdup_printf(P_("%d Hz %d channel %d bps\n", "%d Hz %d channels %d bps\n", cfile->achans),
411  cfile->arate, cfile->achans, cfile->asampsize)));
412  lives_free(tmp);
413  }
414 
415  // if not playing, start playing
416  if (!LIVES_IS_PLAYING) {
417  // temp kludge, symlink audiodump.pcm to wav file, then pretend we are playing
418  // an opening preview . Doesn't work with fifo.
419  // and we dont really care if it doesnt work
420 
421  // but what it means is, if we have an audio file or stream at
422  // "prefs->workdir/audiodump.pcm" we will try to play it
423 
424  // real is workdir/audiodump.pcm
425  audio_real = get_audio_file_name(-1, TRUE);
426  // fake is workdir/handle/audiodump.pcm
427  audio_fake = get_audio_file_name(mainw->current_file, TRUE);
428 
429  // fake file will go away when we close the current clip
430  lives_ln(audio_real, audio_fake);
431 
432  lives_free(audio_real);
433  lives_free(audio_fake);
434 
435  lives_free(tmp);
436 
437  mainw->pre_play_file = old_file;
438  // start playing
440  return;
441  }
442  // TODO - else...
443 
444  if (mainw->current_file != old_file && mainw->current_file != new_file)
445  old_file = mainw->current_file; // we could have rendered to a new file
446 
447  mainw->current_file = new_file;
448 
449  // close this temporary clip
450  close_current_file(old_file);
451 }
452 
453 
455 // write functions - not used currently
456 
457 boolean lives_yuv_stream_start_write(lives_yuv4m_t *yuv4mpeg, const char *filename, int hsize, int vsize, double fps) {
458  int i;
459 
460  if (mainw->fixed_fpsd > -1. && mainw->fixed_fpsd != fps) {
461  do_error_dialog(lives_strdup_printf(_("Unable to set display framerate to %.3f fps.\n\n"), fps));
462  return FALSE;
463  }
464  mainw->fixed_fpsd = fps;
465 
466  if (!filename) filename = lives_strdup_printf("%s/streamout.yuv", prefs->workdir);
467 
468  // TODO - do_threaded_dialog
469  if ((yuvout = creat(filename, O_CREAT)) < 0) {
470  do_error_dialog(lives_strdup_printf(_("Unable to open yuv4mpeg out stream %s\n"), filename));
471  return FALSE;
472  }
473 
474  if (mainw->fixed_fpsd > 23.9999 && mainw->fixed_fpsd < 24.0001) {
475  y4m_si_set_framerate(&(yuv4mpeg->streaminfo), y4m_fps_FILM);
476  } else return FALSE;
477  y4m_si_set_interlace(&(yuv4mpeg->streaminfo), Y4M_ILACE_NONE);
478 
479  y4m_si_set_width(&(yuv4mpeg->streaminfo), (hsize_out = hsize));
480  y4m_si_set_height(&(yuv4mpeg->streaminfo), (vsize_out = vsize));
481  y4m_si_set_sampleaspect(&(yuv4mpeg->streaminfo), yuv4mpeg->sar);
482 
483  i = y4m_write_stream_header(yuvout, &(yuv4mpeg->streaminfo));
484 
485  if (i != Y4M_OK) return FALSE;
486 
487  return TRUE;
488 }
489 
490 
491 boolean lives_yuv_stream_write_frame(lives_yuv4m_t *yuv4mpeg, void *pixel_data) {
492  // pixel_data is planar yuv420 data
493  int i;
494 
495  uint8_t *planes[3];
496  uint8_t *pixels = (uint8_t *)pixel_data;
497 
498  planes[0] = &(pixels[0]);
499  planes[1] = &(pixels[hsize_out * vsize_out]);
500  planes[2] = &(pixels[hsize_out * vsize_out * 5 / 4]);
501 
502  i = y4m_write_frame(yuvout, &(yuv4mpeg->streaminfo),
503  &(yuv4mpeg->frameinfo), (uint8_t **)&planes[0]);
504  if (i != Y4M_OK) return FALSE;
505  return TRUE;
506 }
507 
508 
510  y4m_fini_stream_info(&(yuv4mpeg->streaminfo));
511  y4m_fini_frame_info(&(yuv4mpeg->frameinfo));
512  close(yuvout);
513 }
514 
515 
517 
541 void on_live_tvcard_activate(LiVESMenuItem *menuitem, livespointer user_data) {
542  int cardno = 0;
543 
544  int new_file = mainw->first_free_file;
545 
546  int response;
547 
548  char *com, *tmp;
549  char *fifofile;
550 
551  char *chanstr;
552  char *devstr;
553 
554  char *fname;
555 
556  LiVESWidget *card_dialog;
557 
558  lives_tvcardw_t *tvcardw;
559 
560  if (!HAS_EXTERNAL_PLAYER || USE_MPV) {
562  return;
563  }
564 
565  fifofile = lives_strdup_printf("%s/tvpic_%d.y4m", prefs->workdir, capable->mainpid);
566 
568 
569  card_dialog = create_cdtrack_dialog(LIVES_DEVICE_TV_CARD, NULL);
570 
571  tvcardw = (lives_tvcardw_t *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(card_dialog), "tvcard_data");
572 
573  response = lives_dialog_run(LIVES_DIALOG(card_dialog));
574  if (response == LIVES_RESPONSE_CANCEL) {
575  lives_widget_destroy(card_dialog);
576  lives_free(fifofile);
577  lives_free(tvcardw);
578  return;
579  }
580 
581  cardno = (int)mainw->fx1_val;
582  chanstr = lives_strdup_printf("%d", (int)mainw->fx2_val);
583 
584  if (lives_list_find(mainw->videodevs, LIVES_INT_TO_POINTER(cardno))) {
585  lives_widget_destroy(card_dialog);
587  lives_free(chanstr);
588  lives_free(fifofile);
589  lives_free(tvcardw);
590  return;
591  }
592 
593  fname = lives_strdup_printf(_("TV card %d"), cardno);
594 
595  if (!get_new_handle(new_file, fname)) {
596  lives_widget_destroy(card_dialog);
597  lives_free(chanstr);
598  lives_free(fifofile);
599  lives_free(fname);
600  lives_free(tvcardw);
601  return;
602  }
603 
604  devstr = lives_strdup_printf("/dev/video%d", cardno);
605 
606  if (!check_dev_busy(devstr)) {
607  lives_widget_destroy(card_dialog);
608  do_dev_busy_error(fname);
609  lives_free(devstr);
610  lives_free(chanstr);
611  lives_free(fifofile);
612  lives_free(fname);
613  lives_free(tvcardw);
614  return;
615  }
616 
617  mainw->videodevs = lives_list_append(mainw->videodevs, LIVES_INT_TO_POINTER(cardno));
618 
619  mainw->current_file = new_file;
620 
621  cfile->deinterlace = mainw->open_deint;
622 
623  lives_rm(fifofile);
624  mkfifo(fifofile, S_IRUSR | S_IWUSR);
625 
626  if (!tvcardw->use_advanced) {
627  com = lives_strdup_printf("%s open_tv_card \"%s\" \"%s\" \"%s\" \"%s\"", prefs->backend, cfile->handle, chanstr,
628  devstr, fifofile);
629  } else {
630  double fps = 0.;
631  const char *driver = NULL, *outfmt = NULL;
632  int width = 0, height = 0;
633  int input = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(tvcardw->spinbuttoni));
634 
635  if (!lives_toggle_button_get_active(LIVES_TOGGLE_BUTTON(tvcardw->radiobuttond))) {
636  width = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(tvcardw->spinbuttonw));
637  height = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(tvcardw->spinbuttonh));
638  fps = lives_spin_button_get_value(LIVES_SPIN_BUTTON(tvcardw->spinbuttonf));
639  }
640 
641  driver = lives_combo_get_active_text(LIVES_COMBO(tvcardw->combod));
642  outfmt = lives_combo_get_active_text(LIVES_COMBO(tvcardw->comboo));
643 
644  com = lives_strdup_printf("%s open_tv_card \"%s\" \"%s\" \"%s\" \"%s\" %d %d %d %.3f \"%s\" \"%s\"",
645  prefs->backend, cfile->handle, chanstr,
646  devstr, fifofile, input, width, height, fps, driver, outfmt);
647  }
648  lives_widget_destroy(card_dialog);
649  lives_free(tvcardw);
650 
651  lives_system(com, FALSE);
652  lives_free(com);
653 
654  if (THREADVAR(com_failed)) {
655  THREADVAR(com_failed) = FALSE;
656  lives_free(fname);
657  lives_free(chanstr);
658  lives_free(fifofile);
659  lives_free(devstr);
660  return;
661  }
662 
663  if (!open_yuv4m_inner(fifofile, fname, new_file, YUV4_TYPE_TV, cardno)) {
664  lives_free(fname);
665  lives_free(chanstr);
666  lives_free(fifofile);
667  lives_free(devstr);
668  return;
669  }
670 
671  lives_snprintf(cfile->type, 40, "%s", fname);
672 
673  d_print((tmp = lives_strdup_printf(_("Opened TV card %d (%s)"), cardno, devstr)));
674 
675  lives_free(tmp);
676  lives_free(fname);
677  lives_free(chanstr);
678  lives_free(devstr);
679  lives_free(fifofile);
680 }
681 
682 
683 void on_live_fw_activate(LiVESMenuItem *menuitem, livespointer user_data) {
684  char *com, *tmp;
685  int cardno;
686  int cache = 1024;
687 
688  int new_file = mainw->first_free_file;
689 
690  int response;
691 
692  char *fifofile = lives_strdup_printf("%s/firew_%d.y4m", prefs->workdir, capable->mainpid);
693  char *fname;
694 
695  LiVESWidget *card_dialog;
696 
698 
699  card_dialog = create_cdtrack_dialog(LIVES_DEVICE_FW_CARD, NULL);
700  response = lives_dialog_run(LIVES_DIALOG(card_dialog));
701  if (response == LIVES_RESPONSE_CANCEL) {
702  lives_widget_destroy(card_dialog);
703  lives_free(fifofile);
704  return;
705  }
706 
707  cardno = (int)mainw->fx1_val;
708 
709  lives_widget_destroy(card_dialog);
710 
711  if (lives_list_find(fw_cards, LIVES_INT_TO_POINTER(cardno))) {
712  lives_free(fifofile);
714  return;
715  }
716 
717  fname = lives_strdup_printf(_("Firewire card %d"), cardno);
718 
719  if (!get_new_handle(new_file, fname)) {
720  lives_free(fifofile);
721  lives_free(fname);
722  return;
723  }
724 
725  fw_cards = lives_list_append(fw_cards, LIVES_INT_TO_POINTER(cardno));
726 
727  mainw->current_file = new_file;
728  cfile->deinterlace = mainw->open_deint;
729 
730  lives_rm(fifofile);
731  mkfifo(fifofile, S_IRUSR | S_IWUSR);
732 
733  com = lives_strdup_printf("%s open_fw_card \"%s\" %d %d \"%s\"", prefs->backend, cfile->handle, cardno, cache, fifofile);
734  lives_system(com, FALSE);
735  lives_free(com);
736 
737  if (THREADVAR(com_failed)) {
738  THREADVAR(com_failed) = FALSE;
739  lives_free(fname);
740  lives_free(fifofile);
741  return;
742  }
743 
744  if (!open_yuv4m_inner(fifofile, fname, new_file, YUV4_TYPE_FW, cardno)) {
745  lives_free(fname);
746  lives_free(fifofile);
747  return;
748  }
749 
750  lives_snprintf(cfile->type, 40, "%s", fname);
751 
752  d_print((tmp = lives_strdup_printf(_("Opened firewire card %d"), cardno)));
753 
754  lives_free(tmp);
755  lives_free(fname);
756  lives_free(fifofile);
757 }
lives_yuv_stream_start_write
boolean lives_yuv_stream_start_write(lives_yuv4m_t *yuv4mpeg, const char *filename, int hsize, int vsize, double fps)
not used
Definition: lives-yuv4mpeg.c:457
lives_tvcardw_t::combod
LiVESWidget * combod
Definition: interface.h:161
LIVES_IS_PLAYING
#define LIVES_IS_PLAYING
Definition: main.h:840
LIVES_DEVICE_TV_CARD
@ LIVES_DEVICE_TV_CARD
Definition: mainwindow.h:264
lives_tvcardw_t::spinbuttonh
LiVESWidget * spinbuttonh
Definition: interface.h:165
mainwindow::fixed_fpsd
double fixed_fpsd
<=0. means free playback
Definition: mainwindow.h:990
HAS_EXTERNAL_PLAYER
#define HAS_EXTERNAL_PLAYER
Definition: main.h:1113
lives_clip_t::file_name
char file_name[PATH_MAX]
input file
Definition: main.h:923
lives_free
#define lives_free
Definition: machinestate.h:52
choose_file
char * choose_file(const char *dir, const char *fname, char **const filt, LiVESFileChooserAction act, const char *title, LiVESWidget *extra_widget)
Definition: interface.c:4080
lives_yuv4m_t::name
char * name
Definition: lives-yuv4mpeg.h:25
lives_yuv4m_t::ready
boolean ready
Definition: lives-yuv4mpeg.h:31
lives_widget_destroy
LIVES_GLOBAL_INLINE boolean lives_widget_destroy(LiVESWidget *widget)
Definition: widget-helper.c:1553
_prefs::workdir
char workdir[PATH_MAX]
kept in locale encoding
Definition: preferences.h:61
mainwindow::videodevs
LiVESList * videodevs
Definition: mainwindow.h:1625
lives_spin_button_get_value_as_int
WIDGET_HELPER_GLOBAL_INLINE int lives_spin_button_get_value_as_int(LiVESSpinButton *button)
Definition: widget-helper.c:5091
mainwindow::current_file
int current_file
Definition: mainwindow.h:727
do_need_mplayer_dialog
LIVES_GLOBAL_INLINE void do_need_mplayer_dialog(void)
Definition: dialogs.c:3020
DEF_GEN_HEIGHT
#define DEF_GEN_HEIGHT
Definition: mainwindow.h:150
lives_clip_t::ext_src
void * ext_src
points to opaque source for non-disk types
Definition: main.h:1040
cfile
#define cfile
Definition: main.h:1833
lives_tvcardw_t::comboo
LiVESWidget * comboo
Definition: interface.h:162
prefs
_prefs * prefs
Definition: preferences.h:847
do_dev_busy_error
LIVES_GLOBAL_INLINE void do_dev_busy_error(const char *devstr)
Definition: dialogs.c:4294
_prefs::backend
char backend[PATH_MAX *4]
Definition: preferences.h:411
LIVES_EXT_SRC_FIFO
#define LIVES_EXT_SRC_FIFO
Definition: main.h:1046
lives_dialog_run
WIDGET_HELPER_GLOBAL_INLINE LiVESResponseType lives_dialog_run(LiVESDialog *dialog)
Definition: widget-helper.c:1783
lives_open2
int lives_open2(const char *pathname, int flags)
Definition: utils.c:99
USE_MPV
#define USE_MPV
some shared structures
Definition: main.h:1112
lives_alarm_clear
boolean lives_alarm_clear(lives_alarm_t alarm_handle)
Definition: utils.c:1732
add_to_clipmenu
void add_to_clipmenu(void)
Definition: gui.c:4512
set_main_title
void set_main_title(const char *file, int untitled)
Definition: main.c:5005
capability::mainpid
pid_t mainpid
Definition: main.h:591
mainwindow::fx2_val
double fx2_val
Definition: mainwindow.h:1049
weed_layer_set_from_yuv4m
void weed_layer_set_from_yuv4m(weed_layer_t *layer, lives_clip_t *sfile)
Definition: lives-yuv4mpeg.c:253
lives_alarm_t
int lives_alarm_t
Definition: mainwindow.h:696
YUV4_TYPE_GENERIC
#define YUV4_TYPE_GENERIC
Definition: lives-yuv4mpeg.h:13
lives_tvcardw_t::use_advanced
boolean use_advanced
Definition: interface.h:158
ticks_t
int64_t ticks_t
Definition: main.h:97
lives_yuv4m_t::pixel_data
void ** pixel_data
Definition: lives-yuv4mpeg.h:30
lives_yuv4m_t::dar
y4m_ratio_t dar
Definition: lives-yuv4mpeg.h:24
IMG_TYPE_BEST
#define IMG_TYPE_BEST
Definition: main.h:781
do_error_dialog
LIVES_GLOBAL_INLINE LiVESResponseType do_error_dialog(const char *text)
Definition: dialogs.c:749
create_cdtrack_dialog
LiVESWidget * create_cdtrack_dialog(int type, livespointer user_data)
Definition: interface.c:3138
LIVES_SHORTEST_TIMEOUT
#define LIVES_SHORTEST_TIMEOUT
Definition: mainwindow.h:41
TRUE
#define TRUE
Definition: videoplugin.h:59
lives_yuv_stream_write_frame
boolean lives_yuv_stream_write_frame(lives_yuv4m_t *yuv4mpeg, void *pixel_data)
Definition: lives-yuv4mpeg.c:491
THREADVAR
#define THREADVAR(var)
Definition: machinestate.h:531
lives_tvcardw_t::spinbuttonf
LiVESWidget * spinbuttonf
Definition: interface.h:166
lives_clip_t::fps
double fps
Definition: main.h:893
lives_yuv_stream_stop_write
void lives_yuv_stream_stop_write(lives_yuv4m_t *yuv4mpeg)
Definition: lives-yuv4mpeg.c:509
capable
capability * capable
Definition: main.h:627
lives_toggle_button_get_active
WIDGET_HELPER_GLOBAL_INLINE boolean lives_toggle_button_get_active(LiVESToggleButton *button)
Definition: widget-helper.c:4472
d_print
void d_print(const char *fmt,...)
Definition: utils.c:2542
close_current_file
void close_current_file(int file_to_switch_to)
close current file, and try to switch to file_to_switch_to
Definition: main.c:9373
switch_to_file
void switch_to_file(int old_file, int new_file)
Definition: main.c:9646
lives_yuv4m_t::sar
y4m_ratio_t sar
Definition: lives-yuv4mpeg.h:23
lives_spin_button_get_value
WIDGET_HELPER_GLOBAL_INLINE double lives_spin_button_get_value(LiVESSpinButton *button)
Definition: widget-helper.c:5083
create_empty_pixel_data
boolean create_empty_pixel_data(weed_layer_t *layer, boolean black_fill, boolean may_contig)
creates pixel data for layer
Definition: colourspace.c:9058
lives_yuv4m_t::frameinfo
y4m_frame_info_t frameinfo
Definition: lives-yuv4mpeg.h:22
on_live_tvcard_activate
void on_live_tvcard_activate(LiVESMenuItem *menuitem, livespointer user_data)
add live input peripherals
Definition: lives-yuv4mpeg.c:541
interface.h
d_print_failed
void d_print_failed(void)
Definition: utils.c:2615
P_
#define P_(String, StringPlural, n)
Definition: support.h:46
mainwindow::first_free_file
int first_free_file
Definition: mainwindow.h:728
check_dev_busy
boolean check_dev_busy(char *devstr)
Definition: machinestate.c:876
error
error("LSD_RANDFUNC(ptr, size) must be defined")
on_live_fw_activate
void on_live_fw_activate(LiVESMenuItem *menuitem, livespointer user_data)
Definition: lives-yuv4mpeg.c:683
lives_tvcardw_t::spinbuttoni
LiVESWidget * spinbuttoni
Definition: interface.h:163
lives_yuv4m_t::filename
char * filename
Definition: lives-yuv4mpeg.h:26
LIVES_DEVICE_FW_CARD
@ LIVES_DEVICE_FW_CARD
Definition: mainwindow.h:265
lives_strdup_printf
#define lives_strdup_printf(fmt,...)
Definition: support.c:27
weed_layer_t
weed_plant_t weed_layer_t
Definition: colourspace.h:71
lives_clip_t::hsize
int hsize
frame width (horizontal) in pixels (NOT macropixels !)
Definition: main.h:896
YUV4_TYPE_TV
#define YUV4_TYPE_TV
Definition: lives-yuv4mpeg.h:15
lives_yuv4m_t::cardno
int cardno
Definition: lives-yuv4mpeg.h:20
lives_memmove
#define lives_memmove
Definition: machinestate.h:64
lives_alarm_check
ticks_t lives_alarm_check(lives_alarm_t alarm_handle)
Definition: utils.c:1687
LIVES_SHORT_TIMEOUT
#define LIVES_SHORT_TIMEOUT
Definition: mainwindow.h:42
lives_ln
int lives_ln(const char *from, const char *to)
Definition: utils.c:4464
CLIP_TYPE_YUV4MPEG
@ CLIP_TYPE_YUV4MPEG
yuv4mpeg stream
Definition: main.h:769
DEF_GEN_WIDTH
#define DEF_GEN_WIDTH
Definition: mainwindow.h:149
YUV4_TYPE_FW
#define YUV4_TYPE_FW
Definition: lives-yuv4mpeg.h:14
main.h
lives_yuv4m_t::hsize
int hsize
Definition: lives-yuv4mpeg.h:28
lives_yuv4m_t
Definition: lives-yuv4mpeg.h:18
lives_combo_get_active_text
WIDGET_HELPER_GLOBAL_INLINE const char * lives_combo_get_active_text(LiVESCombo *combo)
Definition: widget-helper.c:3874
_prefs::sleep_time
int sleep_time
Definition: preferences.h:176
mainw
mainwindow * mainw
Definition: main.c:103
mainwindow::pre_play_file
int pre_play_file
the current file before playback started
Definition: mainwindow.h:973
lives-yuv4mpeg.h
lives_tvcardw_t
Definition: interface.h:157
on_open_yuv4m_activate
void on_open_yuv4m_activate(LiVESMenuItem *menuitem, livespointer user_data)
Definition: lives-yuv4mpeg.c:353
lives_yuv4m_t::streaminfo
y4m_stream_info_t streaminfo
Definition: lives-yuv4mpeg.h:21
lives_yuv_stream_stop_read
void lives_yuv_stream_stop_read(lives_yuv4m_t *yuv4mpeg)
Definition: lives-yuv4mpeg.c:233
lives_system
int lives_system(const char *com, boolean allow_error)
Definition: utils.c:145
lives_clip_t::vsize
int vsize
frame height (vertical) in pixels
Definition: main.h:897
lives_clip_t
corresponds to one clip in the GUI
Definition: main.h:877
mainwindow::open_deint
boolean open_deint
Definition: mainwindow.h:907
effects-weed.h
mainwindow::fx1_val
double fx1_val
Definition: mainwindow.h:1049
lives_yuv4m_t::type
int type
Definition: lives-yuv4mpeg.h:19
lives_tvcardw_t::spinbuttonw
LiVESWidget * spinbuttonw
Definition: interface.h:164
do_card_in_use_error
LIVES_GLOBAL_INLINE void do_card_in_use_error(void)
Definition: dialogs.c:4289
lives_yuv4m_t::fd
int fd
Definition: lives-yuv4mpeg.h:27
FALSE
#define FALSE
Definition: videoplugin.h:60
lives_tvcardw_t::radiobuttond
LiVESWidget * radiobuttond
Definition: interface.h:167
get_audio_file_name
LIVES_GLOBAL_INLINE char * get_audio_file_name(int fnum, boolean opening)
Definition: audio.c:38
lives_alarm_set
lives_alarm_t lives_alarm_set(ticks_t ticks)
set alarm for now + delta ticks (10 nanosec) param ticks (10 nanoseconds) is the offset when we want ...
Definition: utils.c:1643
_
#define _(String)
Definition: support.h:44
start_playback_async
void start_playback_async(int type)
Definition: saveplay.c:96
lives_rm
int lives_rm(const char *file)
Definition: utils.c:4395
lives_widget_context_update
boolean lives_widget_context_update(void)
Definition: widget-helper.c:11878
do_yuv4m_open_warning
boolean do_yuv4m_open_warning(void)
Definition: dialogs.c:3270
get_new_handle
boolean get_new_handle(int index, const char *name)
Definition: saveplay.c:3821
lives_yuv4m_t::vsize
int vsize
Definition: lives-yuv4mpeg.h:29