void after_framedraw_frame_spinbutton_changed(LiVESSpinButton *spinbutton, lives_special_framedraw_rect_t *framedraw) { // update the single frame/framedraw preview // after the "frame number" spinbutton has changed mainw->framedraw_frame=lives_spin_button_get_value_as_int(spinbutton); if (lives_widget_is_visible(mainw->framedraw_preview)) { if (mainw->framedraw_preview!=NULL) lives_widget_set_sensitive(mainw->framedraw_preview,FALSE); lives_widget_context_update(); load_rfx_preview(framedraw->rfx); } else framedraw_redraw(framedraw, TRUE, NULL); }
static void start_preview(LiVESButton *button, lives_rfx_t *rfx) { int i; char *com; lives_widget_set_sensitive(mainw->framedraw_preview,FALSE); lives_widget_context_update(); if (mainw->did_rfx_preview) { lives_kill_subprocesses(cfile->handle,TRUE); if (cfile->start==0) { cfile->start=1; cfile->end=cfile->frames; } do_rfx_cleanup(rfx); } com=lives_strdup_printf("%s clear_pre_files \"%s\" 2>%s",prefs->backend_sync,cfile->handle,LIVES_DEVNULL); lives_system(com,TRUE); // clear any .pre files from before for (i=0; i<rfx->num_params; i++) { rfx->params[i].changed=FALSE; } mainw->cancelled=CANCEL_NONE; mainw->error=FALSE; // within do_effect() we check and if do_effect(rfx,TRUE); // actually start effect processing in the background lives_widget_set_sensitive(mainw->framedraw_spinbutton,TRUE); lives_widget_set_sensitive(mainw->framedraw_scale,TRUE); if (mainw->framedraw_frame>cfile->start&&!(cfile->start==0&&mainw->framedraw_frame==1)) lives_spin_button_set_value(LIVES_SPIN_BUTTON(mainw->framedraw_spinbutton),cfile->start); else { load_rfx_preview(rfx); } mainw->did_rfx_preview=TRUE; }
void clean_images_from_virtual(lives_clip_t *sfile, int oldframes) { // remove images on disk where the frame_index points to a frame in // the original clip // only needed if frames were reordered when rendered and the process is // then undone // in future, a smarter function could trace the images back to their // original source frames, and just rename them // should be threadsafe register int i; char *iname=NULL,*com; if (sfile==NULL||sfile->frame_index==NULL) return; for (i=0; i<oldframes; i++) { threaded_dialog_spin(); lives_widget_context_update(); threaded_dialog_spin(); if ((i<sfile->frames&&sfile->frame_index[i]!=-1)||i>=sfile->frames) { iname=lives_strdup_printf("%s/%s/%08d.%s",prefs->tmpdir,sfile->handle,i,get_image_ext_for_type(sfile->img_type)); #ifndef IS_MINGW com=lives_strdup_printf("/bin/rm -f \"%s\"",iname); #else com=lives_strdup_printf("rm.exe -f \"%s\"",iname); #endif lives_system(com,FALSE); lives_free(com); } } }
boolean virtual_to_images(int sfileno, int sframe, int eframe, boolean update_progress, LiVESPixbuf **pbr) { // pull frames from a clip to images // from sframe to eframe inclusive (first frame is 1) // if update_progress, set mainw->msg with number of frames pulled // should be threadsafe apart from progress update // if pbr is non-null, it will be set to point to the pulled pixbuf ( // return FALSE on write error register int i; lives_clip_t *sfile=mainw->files[sfileno]; LiVESPixbuf *pixbuf=NULL; LiVESError *error=NULL; char *oname; int retval; int progress=1; if (sframe<1) sframe=1; for (i=sframe; i<=eframe; i++) { if (i>sfile->frames) break; if (sfile->frame_index[i-1]>=0) { oname=NULL; if (update_progress) { threaded_dialog_spin(); lives_widget_context_update(); } if (pbr!=NULL&&pixbuf!=NULL) lives_object_unref(pixbuf); pixbuf=pull_lives_pixbuf_at_size(sfileno,i,get_image_ext_for_type(sfile->img_type), q_gint64((i-1.)/sfile->fps,sfile->fps),sfile->hsize,sfile->vsize,LIVES_INTERP_BEST); oname=lives_strdup_printf("%s/%s/%08d.%s",prefs->tmpdir,sfile->handle,i,get_image_ext_for_type(sfile->img_type)); do { retval=0; lives_pixbuf_save(pixbuf, oname, sfile->img_type, 100-prefs->ocp, TRUE, &error); if (error!=NULL&&pbr==NULL) { retval=do_write_failed_error_s_with_retry(oname,error->message,NULL); lives_error_free(error); error=NULL; } } while (retval==LIVES_RESPONSE_RETRY); if (oname!=NULL) lives_free(oname); if (pbr==NULL) { if (pixbuf!=NULL) lives_object_unref(pixbuf); pixbuf=NULL; } if (retval==LIVES_RESPONSE_CANCEL) return FALSE; // another thread may have called check_if_non_virtual - TODO : use a mutex if (sfile->frame_index==NULL) break; sfile->frame_index[i-1]=-1; if (update_progress) { // sig_progress... lives_snprintf(mainw->msg,256,"%d",progress++); threaded_dialog_spin(); lives_widget_context_update(); } if (mainw->cancelled!=CANCEL_NONE) { if (!check_if_non_virtual(sfileno,1,sfile->frames)) save_frame_index(sfileno); if (pbr!=NULL) *pbr=pixbuf; return TRUE; } } } if (pbr!=NULL) *pbr=pixbuf; if (!check_if_non_virtual(sfileno,1,sfile->frames)) if (!save_frame_index(sfileno)) return FALSE; return TRUE; }
void load_rfx_preview(lives_rfx_t *rfx) { // load a preview of an rfx (rendered effect) in clip editor LiVESPixbuf *pixbuf; FILE *infofile=NULL; int max_frame=0,tot_frames=0; int vend=cfile->start; int retval; int alarm_handle; int current_file=mainw->current_file; boolean retb; boolean timeout; weed_timecode_t tc; const char *img_ext; if (mainw->framedraw_frame==0) mainw->framedraw_frame=1; lives_set_cursor_style(LIVES_CURSOR_BUSY,NULL); clear_mainw_msg(); mainw->write_failed=FALSE; if (cfile->clip_type==CLIP_TYPE_FILE&&vend<=cfile->end) { // pull some frames for 10 seconds alarm_handle=lives_alarm_set(LIVES_DEFAULT_TIMEOUT); do { lives_widget_context_update(); if (is_virtual_frame(mainw->current_file,vend)) { retb=virtual_to_images(mainw->current_file,vend,vend,FALSE,NULL); if (!retb) return; } vend++; timeout=lives_alarm_get(alarm_handle); } while (vend<=cfile->end&&!timeout&&!mainw->cancelled); lives_alarm_clear(alarm_handle); } if (mainw->cancelled) { lives_set_cursor_style(LIVES_CURSOR_NORMAL,NULL); return; } // get message from back end processor while (!(infofile=fopen(cfile->info_file,"r"))&&!mainw->cancelled) { // wait until we get at least 1 frame lives_widget_context_update(); if (cfile->clip_type==CLIP_TYPE_FILE&&vend<=cfile->end) { // if we have a virtual clip (frames inside a video file) // pull some more frames to images to get us started do { retb=FALSE; if (is_virtual_frame(mainw->current_file,vend)) { retb=virtual_to_images(mainw->current_file,vend,vend,FALSE,NULL); if (!retb) { fclose(infofile); return; } } vend++; } while (vend<=cfile->end&&!retb); } else { // otherwise wait lives_usleep(prefs->sleep_time); } } if (mainw->cancelled) { if (infofile) fclose(infofile); lives_set_cursor_style(LIVES_CURSOR_NORMAL,NULL); return; } do { retval=0; mainw->read_failed=FALSE; lives_fgets(mainw->msg,512,infofile); if (mainw->read_failed) retval=do_read_failed_error_s_with_retry(cfile->info_file,NULL,NULL); } while (retval==LIVES_RESPONSE_RETRY); fclose(infofile); if (strncmp(mainw->msg,"completed",9)) { if (rfx->num_in_channels>0) { max_frame=atoi(mainw->msg); } else { int numtok=get_token_count(mainw->msg,'|'); if (numtok>4) { char **array=lives_strsplit(mainw->msg,"|",numtok); max_frame=atoi(array[0]); cfile->hsize=atoi(array[1]); cfile->vsize=atoi(array[2]); cfile->fps=cfile->pb_fps=strtod(array[3],NULL); if (cfile->fps==0) cfile->fps=cfile->pb_fps=prefs->default_fps; tot_frames=atoi(array[4]); lives_strfreev(array); } } } else { max_frame=cfile->end; } lives_set_cursor_style(LIVES_CURSOR_NORMAL,NULL); if (max_frame>0) { if (rfx->num_in_channels==0) { int maxlen=calc_spin_button_width(1.,(double)tot_frames,0); lives_spin_button_set_range(LIVES_SPIN_BUTTON(mainw->framedraw_spinbutton),1,tot_frames); lives_entry_set_width_chars(LIVES_ENTRY(mainw->framedraw_spinbutton),maxlen); lives_widget_queue_draw(mainw->framedraw_spinbutton); lives_widget_queue_draw(mainw->framedraw_scale); } if (mainw->framedraw_frame>max_frame) { lives_spin_button_set_value(LIVES_SPIN_BUTTON(mainw->framedraw_spinbutton),max_frame); mainw->current_file=current_file; return; } } if (rfx->num_in_channels>0) { img_ext=LIVES_FILE_EXT_PRE; } else { img_ext=get_image_ext_for_type(cfile->img_type); } tc=((mainw->framedraw_frame-1.))/cfile->fps*U_SECL; pixbuf=pull_lives_pixbuf_at_size(mainw->current_file,mainw->framedraw_frame,(char *)img_ext, tc,(double)cfile->hsize, (double)cfile->vsize,LIVES_INTERP_BEST); load_framedraw_image(pixbuf); redraw_framedraw_image(); mainw->current_file=current_file; }
static boolean lives_yuv_stream_start_read(lives_clip_t *sfile) { double ofps=sfile->fps; lives_yuv4m_t *yuv4mpeg=(lives_yuv4m_t *)sfile->ext_src; pthread_t y4thread; char *filename=yuv4mpeg->filename,*tmp; int alarm_handle=0; int ohsize=sfile->hsize; int ovsize=sfile->vsize; y4data thread_data; register int i; if (filename==NULL) return FALSE; if (yuv4mpeg->fd==-1) { // create a thread to open the fifo thread_data.filename=filename; pthread_create(&y4thread,NULL,y4open_thread,(void *)&thread_data); alarm_handle=lives_alarm_set(YUV4_O_TIME); d_print(""); d_print(_("Waiting for yuv4mpeg frames...")); while (!lives_alarm_get(alarm_handle)&&!pthread_kill(y4thread,0)) { // wait for thread to complete or timeout lives_usleep(prefs->sleep_time); lives_widget_context_update(); } if (lives_alarm_get(alarm_handle)) { // timeout - kill thread and wait for it to terminate pthread_cancel(y4thread); pthread_join(y4thread,NULL); lives_alarm_clear(alarm_handle); d_print_failed(); d_print(_("Unable to open the incoming video stream\n")); yuv4mpeg->fd=thread_data.fd; if (yuv4mpeg->fd>=0) { close(yuv4mpeg->fd); yuv4mpeg->fd=-1; } return FALSE; } pthread_join(y4thread,NULL); lives_alarm_clear(alarm_handle); yuv4mpeg->fd=thread_data.fd; if (yuv4mpeg->fd<0) { return FALSE; } } // create a thread to open the stream header thread_data.yuv4mpeg=yuv4mpeg; pthread_create(&y4thread,NULL,y4header_thread,&thread_data); alarm_handle=lives_alarm_set(YUV4_H_TIME); while (!lives_alarm_get(alarm_handle)&&!pthread_kill(y4thread,0)) { // wait for thread to complete or timeout lives_usleep(prefs->sleep_time); lives_widget_context_update(); } if (lives_alarm_get(alarm_handle)) { // timeout - kill thread and wait for it to terminate pthread_cancel(y4thread); pthread_join(y4thread,NULL); lives_alarm_clear(alarm_handle); d_print(_("Unable to read the stream header\n")); return FALSE; } pthread_join(y4thread,NULL); lives_alarm_clear(alarm_handle); i=thread_data.i; if (i != Y4M_OK) { char *tmp; d_print((tmp=lives_strdup_printf("yuv4mpeg: %s\n", y4m_strerr(i)))); lives_free(tmp); return FALSE; } d_print(_("got header\n")); sfile->hsize = yuv4mpeg->hsize = y4m_si_get_width(&(yuv4mpeg->streaminfo)); sfile->vsize = yuv4mpeg->vsize = y4m_si_get_height(&(yuv4mpeg->streaminfo)); sfile->fps=cfile->pb_fps=lives_strtod(lives_strdup_printf("%.8f",Y4M_RATIO_DBL (y4m_si_get_framerate(&(yuv4mpeg->streaminfo)))),NULL); if (!(sfile->hsize*sfile->vsize)) { do_error_dialog(lives_strdup_printf(_("Video dimensions: %d x %d are invalid. Stream cannot be opened"), sfile->hsize,sfile->vsize)); return FALSE; } if (sfile->hsize!=ohsize||sfile->vsize!=ovsize||sfile->fps!=ofps) { set_main_title(sfile->file_name,0); } d_print((tmp=lives_strdup_printf(_("Reset clip values for %s: size=%dx%d fps=%.3f\n"),yuv4mpeg->name, cfile->hsize,yuv4mpeg->vsize,cfile->bpp,cfile->fps))); lives_free(tmp); yuv4mpeg->ready=TRUE; return TRUE; }
static void start_preview(LiVESButton *button, lives_rfx_t *rfx) { int i; char *com; lives_widget_set_sensitive(mainw->framedraw_preview,FALSE); lives_widget_context_update(); if (mainw->did_rfx_preview) { #ifndef IS_MINGW com=lives_strdup_printf("%s stopsubsub \"%s\" 2>/dev/null",prefs->backend_sync,cfile->handle); lives_system(com,TRUE); // try to stop any in-progress preview #else // get pid from backend FILE *rfile; ssize_t rlen; char val[16]; int pid; com=lives_strdup_printf("%s get_pid_for_handle \"%s\"",prefs->backend_sync,cfile->handle); rfile=popen(com,"r"); rlen=fread(val,1,16,rfile); pclose(rfile); memset(val+rlen,0,1); pid=atoi(val); lives_win32_kill_subprocesses(pid,TRUE); #endif lives_free(com); if (cfile->start==0) { cfile->start=1; cfile->end=cfile->frames; } do_rfx_cleanup(rfx); } #ifndef IS_MINGW com=lives_strdup_printf("%s clear_pre_files \"%s\" 2>/dev/null",prefs->backend_sync,cfile->handle); #else com=lives_strdup_printf("%s clear_pre_files \"%s\" 2>NUL",prefs->backend_sync,cfile->handle); #endif lives_system(com,TRUE); // clear any .pre files from before for (i=0; i<rfx->num_params; i++) { rfx->params[i].changed=FALSE; } mainw->cancelled=CANCEL_NONE; mainw->error=FALSE; // within do_effect() we check and if do_effect(rfx,TRUE); // actually start effect processing in the background lives_widget_set_sensitive(mainw->framedraw_spinbutton,TRUE); lives_widget_set_sensitive(mainw->framedraw_scale,TRUE); if (mainw->framedraw_frame>cfile->start&&!(cfile->start==0&&mainw->framedraw_frame==1)) lives_spin_button_set_value(LIVES_SPIN_BUTTON(mainw->framedraw_spinbutton),cfile->start); else { load_rfx_preview(rfx); } mainw->did_rfx_preview=TRUE; }