Esempio n. 1
0
void widget_add_framedraw(LiVESVBox *box, int start, int end, boolean add_preview_button, int width, int height) {
  // adds the frame draw widget to box
  // the redraw button should be connected to an appropriate redraw function
  // after calling this function

  // an example of this is in 'trim frames'

  LiVESWidget *vseparator;
  LiVESWidget *vbox;
  LiVESWidget *hbox;
  LiVESWidget *label;
  LiVESAdjustment *spinbutton_adj;
  LiVESWidget *frame;

  lives_rfx_t *rfx;

  double fd_scale;

  b1_held=FALSE;

  mainw->framedraw_reset=NULL;

  vseparator = lives_vseparator_new();
  lives_box_pack_start(LIVES_BOX(lives_widget_get_parent(LIVES_WIDGET(box))), vseparator, FALSE, FALSE, 0);
  lives_widget_show(vseparator);

  vbox = lives_vbox_new(FALSE, 0);
  lives_box_pack_start(LIVES_BOX(lives_widget_get_parent(LIVES_WIDGET(box))), vbox, FALSE, FALSE, 0);
  lives_container_set_border_width(LIVES_CONTAINER(vbox), widget_opts.border_width);

  fd_scale=calc_fd_scale(width,height);
  width/=fd_scale;
  height/=fd_scale;

  hbox = lives_hbox_new(FALSE, 0);
  lives_box_pack_start(LIVES_BOX(vbox), hbox, FALSE, FALSE, 0);

  fbord_eventbox=lives_event_box_new();
  lives_container_set_border_width(LIVES_CONTAINER(fbord_eventbox),widget_opts.border_width);

  frame = lives_frame_new(NULL);

  lives_box_pack_start(LIVES_BOX(hbox), frame, FALSE, FALSE, 0);

  if (palette->style&STYLE_1) {
    lives_widget_set_bg_color(fbord_eventbox, LIVES_WIDGET_STATE_NORMAL, &palette->normal_fore);
    lives_widget_set_bg_color(frame, LIVES_WIDGET_STATE_NORMAL, &palette->normal_back);
    lives_widget_set_fg_color(frame, LIVES_WIDGET_STATE_NORMAL, &palette->normal_fore);
  }

  mainw->fd_frame=frame;

  label = lives_standard_label_new(_("Preview"));
  lives_frame_set_label_widget(LIVES_FRAME(frame), label);

  lives_frame_set_shadow_type(LIVES_FRAME(frame), LIVES_SHADOW_NONE);

  mainw->framedraw=lives_event_box_new();
  lives_widget_set_size_request(mainw->framedraw, width, height);
  lives_container_set_border_width(LIVES_CONTAINER(mainw->framedraw),1);

  lives_widget_set_events(mainw->framedraw, LIVES_BUTTON1_MOTION_MASK | LIVES_BUTTON_RELEASE_MASK |
                          LIVES_BUTTON_PRESS_MASK| LIVES_ENTER_NOTIFY_MASK | LIVES_LEAVE_NOTIFY_MASK);

  mainw->framedraw_frame=start;

  lives_container_add(LIVES_CONTAINER(frame), fbord_eventbox);
  lives_container_add(LIVES_CONTAINER(fbord_eventbox), mainw->framedraw);

  if (palette->style&STYLE_1) {
    lives_widget_set_bg_color(mainw->framedraw, LIVES_WIDGET_STATE_NORMAL, &palette->normal_back);
    lives_widget_set_fg_color(mainw->framedraw, LIVES_WIDGET_STATE_NORMAL, &palette->normal_fore);
  }

  lives_signal_connect_after(LIVES_GUI_OBJECT(mainw->framedraw), LIVES_WIDGET_EXPOSE_EVENT,
                             LIVES_GUI_CALLBACK(expose_fd_event), NULL);


  hbox = lives_hbox_new(FALSE, 2);
  lives_box_pack_start(LIVES_BOX(vbox), hbox, FALSE, FALSE, 0);

  mainw->framedraw_spinbutton = lives_standard_spin_button_new(_("_Frame"),
                                TRUE,start,start,end,1.,10.,0,LIVES_BOX(hbox),NULL);

  spinbutton_adj=lives_spin_button_get_adjustment(LIVES_SPIN_BUTTON(mainw->framedraw_spinbutton));

  mainw->framedraw_scale=lives_hscale_new(LIVES_ADJUSTMENT(spinbutton_adj));
  lives_box_pack_start(LIVES_BOX(hbox), mainw->framedraw_scale, TRUE, TRUE, 0);
  lives_scale_set_draw_value(LIVES_SCALE(mainw->framedraw_scale),FALSE);

  rfx=(lives_rfx_t *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(lives_widget_get_toplevel(LIVES_WIDGET(box))),"rfx");
  mainw->framedraw_preview = lives_button_new_from_stock(LIVES_STOCK_REFRESH,_("_Preview"));
  lives_box_pack_start(LIVES_BOX(hbox), mainw->framedraw_preview, TRUE, FALSE, 0);
  lives_widget_set_sensitive(mainw->framedraw_spinbutton,FALSE);
  lives_widget_set_sensitive(mainw->framedraw_scale,FALSE);
  lives_signal_connect(mainw->framedraw_preview, LIVES_WIDGET_CLICKED_SIGNAL,LIVES_GUI_CALLBACK(start_preview),rfx);

  lives_widget_show_all(vbox);

  if (!add_preview_button) {
    lives_widget_hide(mainw->framedraw_preview);
  }

}
Esempio n. 2
0
void on_live_tvcard_activate(LiVESMenuItem *menuitem, livespointer user_data) {
  int cardno=0;

  int new_file=mainw->first_free_file;

  int response;

  char *com,*tmp;
  char *fifofile=lives_strdup_printf("%s/tvpic.%d",prefs->tmpdir,capable->mainpid);

  char *chanstr;
  char *devstr;

  char *fname;

  LiVESWidget *card_dialog;

  lives_tvcardw_t *tvcardw;

  mainw->open_deint=FALSE;

  card_dialog=create_cdtrack_dialog(4,NULL);

  tvcardw=(lives_tvcardw_t *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(card_dialog),"tvcard_data");


  response=lives_dialog_run(LIVES_DIALOG(card_dialog));
  if (response==LIVES_RESPONSE_CANCEL) {
    lives_widget_destroy(card_dialog);
    lives_free(fifofile);
    lives_free(tvcardw);
    return;
  }

  cardno=(int)mainw->fx1_val;
  chanstr=lives_strdup_printf("%d",(int)mainw->fx2_val);

  if (lives_list_find(mainw->videodevs,LIVES_INT_TO_POINTER(cardno))) {
    lives_widget_destroy(card_dialog);
    do_card_in_use_error();
    lives_free(chanstr);
    lives_free(fifofile);
    lives_free(tvcardw);
    return;
  }

  fname=lives_strdup_printf(_("TV card %d"),cardno);

  if (!get_new_handle(new_file,fname)) {
    lives_widget_destroy(card_dialog);
    lives_free(chanstr);
    lives_free(fifofile);
    lives_free(fname);
    lives_free(tvcardw);
    return;
  }

  devstr=lives_strdup_printf("/dev/video%d",cardno);

  if (!check_dev_busy(devstr)) {
    lives_widget_destroy(card_dialog);
    do_dev_busy_error(fname);
    lives_free(devstr);
    lives_free(chanstr);
    lives_free(fifofile);
    lives_free(fname);
    lives_free(tvcardw);
    return;
  }

  mainw->videodevs=lives_list_append(mainw->videodevs,LIVES_INT_TO_POINTER(cardno));

  mainw->current_file=new_file;

  cfile->deinterlace=mainw->open_deint;

  unlink(fifofile);
  mkfifo(fifofile,S_IRUSR|S_IWUSR);

  if (!tvcardw->use_advanced) {
    com=lives_strdup_printf("%s open_tv_card \"%s\" \"%s\" \"%s\" \"%s\"",prefs->backend,cfile->handle,chanstr,
                            devstr,fifofile);
  } else {
    double fps=0.;
    char *driver=NULL,*outfmt=NULL;
    int width=0,height=0;
    int input=lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(tvcardw->spinbuttoni));

    if (!lives_toggle_button_get_active(LIVES_TOGGLE_BUTTON(tvcardw->radiobuttond))) {
      width=lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(tvcardw->spinbuttonw));
      height=lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(tvcardw->spinbuttonh));
      fps=lives_spin_button_get_value(LIVES_SPIN_BUTTON(tvcardw->spinbuttonf));
    }

    driver=lives_combo_get_active_text(LIVES_COMBO(tvcardw->combod));
    outfmt=lives_combo_get_active_text(LIVES_COMBO(tvcardw->comboo));

    com=lives_strdup_printf("%s open_tv_card \"%s\" \"%s\" \"%s\" \"%s\" %d %d %d %.3f \"%s\" \"%s\"",
                            prefs->backend,cfile->handle,chanstr,
                            devstr,fifofile,input,width,height,fps,driver,outfmt);
    lives_free(driver);
    lives_free(outfmt);

  }
  lives_widget_destroy(card_dialog);
  lives_free(tvcardw);

  mainw->com_failed=FALSE;
  lives_system(com,FALSE);
  lives_free(com);

  if (mainw->com_failed) {
    mainw->com_failed=FALSE;
    lives_free(fname);
    lives_free(chanstr);
    lives_free(fifofile);
    lives_free(devstr);
    return;
  }

  if (!open_yuv4m_inner(fifofile,fname,new_file,YUV4_TYPE_TV,cardno)) {
    lives_free(fname);
    lives_free(chanstr);
    lives_free(fifofile);
    lives_free(devstr);
    return;
  }

  lives_snprintf(cfile->type,40,"%s",fname);

  d_print((tmp=lives_strdup_printf(_("Opened TV card %d (%s)"),cardno,devstr)));

  lives_free(tmp);
  lives_free(fname);
  lives_free(chanstr);
  lives_free(devstr);
  lives_free(fifofile);

}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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;


#define LIVES_RFX_TIMER 10*U_SEC

  if (cfile->clip_type==CLIP_TYPE_FILE&&vend<=cfile->end) {
    // pull some frames for 10 seconds
    alarm_handle=lives_alarm_set(LIVES_RFX_TIMER);
    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="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;
}
Esempio n. 5
0
void framedraw_redraw(lives_special_framedraw_rect_t *framedraw, boolean reload, LiVESPixbuf *pixbuf) {
  // this will draw the mask (framedraw_bitmap) and optionally reload the image
  // and then combine them

  int fd_height;
  int fd_width;
  int width,height;

  double xstartf,ystartf,xendf,yendf;

  lives_painter_t *cr;

  if (mainw->current_file<1||cfile==NULL) return;

  if (framedraw->rfx->source_type==LIVES_RFX_SOURCE_RFX)
    if (noupdate) return;

  fd_width=lives_widget_get_allocation_width(mainw->framedraw);
  fd_height=lives_widget_get_allocation_height(mainw->framedraw);

  width=cfile->hsize;
  height=cfile->vsize;

  calc_maxspect(fd_width,fd_height,&width,&height);

  // copy from orig, resize
  // copy orig layer to layer
  if (mainw->fd_layer!=NULL) {
    weed_layer_free(mainw->fd_layer);
    mainw->fd_layer=NULL;
  }

  if (reload||mainw->fd_layer_orig==NULL) load_framedraw_image(pixbuf);

  mainw->fd_layer=weed_layer_copy(NULL,mainw->fd_layer_orig);
  // resize to correct size
  resize_layer(mainw->fd_layer, width, height, LIVES_INTERP_BEST, WEED_PALETTE_END, 0);

  cr=layer_to_lives_painter(mainw->fd_layer);


  // draw on the lives_painter

  // her we dont offset because we are drawing in the pixbuf, not the widget

  switch (framedraw->type) {
  case LIVES_PARAM_SPECIAL_TYPE_RECT_MULTRECT: // deprecated
    // scale values
    if (framedraw->xstart_param->dp==0) {
      xstartf=(double)lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(framedraw->xstart_param->widgets[0]));
      xstartf=xstartf/(double)cfile->hsize*(double)width;
    } else {
      xstartf=lives_spin_button_get_value(LIVES_SPIN_BUTTON(framedraw->xstart_param->widgets[0]));
      xstartf=xstartf*(double)width;
    }

    if (framedraw->xend_param->dp==0) {
      xendf=(double)lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(framedraw->xend_param->widgets[0]));
      xendf=xendf/(double)cfile->hsize*(double)width;
    } else {
      xendf=lives_spin_button_get_value(LIVES_SPIN_BUTTON(framedraw->xend_param->widgets[0]));
      xendf=xendf*(double)width;
    }

    if (framedraw->ystart_param->dp==0) {
      ystartf=(double)lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(framedraw->ystart_param->widgets[0]));
      ystartf=ystartf/(double)cfile->vsize*(double)height;
    } else {
      ystartf=lives_spin_button_get_value(LIVES_SPIN_BUTTON(framedraw->ystart_param->widgets[0]));
      ystartf=ystartf*(double)height;
    }

    if (framedraw->yend_param->dp==0) {
      yendf=lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(framedraw->yend_param->widgets[0]));
      yendf=yendf/(double)cfile->vsize*(double)height;
    } else {
      yendf=lives_spin_button_get_value(LIVES_SPIN_BUTTON(framedraw->yend_param->widgets[0]));
      yendf=yendf*(double)height;
    }

    lives_painter_set_source_rgb(cr, 1., 0., 0.);
    lives_painter_rectangle(cr,xstartf-1.,ystartf-1.,xendf+2.,yendf+2.);
    lives_painter_stroke(cr);

    break;
  case LIVES_PARAM_SPECIAL_TYPE_RECT_MULTIRECT:
  case LIVES_PARAM_SPECIAL_TYPE_RECT_DEMASK:

    if (framedraw->xstart_param->dp==0) {
      xstartf=(double)lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(framedraw->xstart_param->widgets[0]));
      xstartf=xstartf/(double)cfile->hsize*(double)width;
    } else {
      xstartf=lives_spin_button_get_value(LIVES_SPIN_BUTTON(framedraw->xstart_param->widgets[0]));
      xstartf=xstartf*(double)width;
    }

    if (framedraw->xend_param->dp==0) {
      xendf=(double)lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(framedraw->xend_param->widgets[0]));
      xendf=xendf/(double)cfile->hsize*(double)width;
    } else {
      xendf=lives_spin_button_get_value(LIVES_SPIN_BUTTON(framedraw->xend_param->widgets[0]));
      xendf=xendf*(double)width;
    }

    if (framedraw->ystart_param->dp==0) {
      ystartf=(double)lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(framedraw->ystart_param->widgets[0]));
      ystartf=ystartf/(double)cfile->vsize*(double)height;
    } else {
      ystartf=lives_spin_button_get_value(LIVES_SPIN_BUTTON(framedraw->ystart_param->widgets[0]));
      ystartf=ystartf*(double)height;
    }

    if (framedraw->yend_param->dp==0) {
      yendf=(double)lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(framedraw->yend_param->widgets[0]));
      yendf=yendf/(double)cfile->vsize*(double)height;
    } else {
      yendf=lives_spin_button_get_value(LIVES_SPIN_BUTTON(framedraw->yend_param->widgets[0]));
      yendf=yendf*(double)height;
    }

    if (b1_held||framedraw->type==LIVES_PARAM_SPECIAL_TYPE_RECT_MULTIRECT) {
      lives_painter_set_source_rgb(cr, 1., 0., 0.);
      lives_painter_rectangle(cr,xstartf-1.,ystartf-1.,xendf-xstartf+2.,yendf-ystartf+2.);
      lives_painter_stroke(cr);
    } else {
      if (!b1_held) {
        // create a mask which is only opaque within the clipping area

        lives_painter_rectangle(cr,0,0,width,height);
        lives_painter_rectangle(cr,xstartf,ystartf,xendf-xstartf+1.,yendf-ystartf+1.);
        lives_painter_set_operator(cr, LIVES_PAINTER_OPERATOR_DEST_OUT);
        lives_painter_set_source_rgba(cr, .0, .0, .0, .5);
        lives_painter_set_fill_rule(cr, LIVES_PAINTER_FILL_RULE_EVEN_ODD);
        lives_painter_fill(cr);
      }
    }

    break;
  case LIVES_PARAM_SPECIAL_TYPE_SINGLEPOINT:

    if (framedraw->xstart_param->dp==0) {
      xstartf=(double)lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(framedraw->xstart_param->widgets[0]));
      xstartf=xstartf/(double)cfile->hsize*(double)width;
    } else {
      xstartf=lives_spin_button_get_value(LIVES_SPIN_BUTTON(framedraw->xstart_param->widgets[0]));
      xstartf=xstartf*(double)width;
    }

    if (framedraw->ystart_param->dp==0) {
      ystartf=(double)lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(framedraw->ystart_param->widgets[0]));
      ystartf=ystartf/(double)cfile->vsize*(double)height;
    } else {
      ystartf=lives_spin_button_get_value(LIVES_SPIN_BUTTON(framedraw->ystart_param->widgets[0]));
      ystartf=ystartf*(double)height;
    }

    lives_painter_set_source_rgb(cr, 1., 0., 0.);

    lives_painter_move_to(cr,xstartf,ystartf-3);
    lives_painter_line_to(cr,xstartf,ystartf+3);

    lives_painter_stroke(cr);

    lives_painter_move_to(cr,xstartf-3,ystartf);
    lives_painter_line_to(cr,xstartf+3,ystartf);

    lives_painter_stroke(cr);

    break;

  default:

    break;

  }

  lives_painter_to_layer(cr, mainw->fd_layer);

  lives_painter_destroy(cr);

  redraw_framedraw_image();
}