/* Gveejay Reloaded - graphical interface for VeeJay * (C) 2002-2004 Niels Elburg * (C) 2005 Thomas Rheinhold * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //if gtk2_6 is not defined, 2.4 is assumed. #ifdef GTK_CHECK_VERSION #if GTK_MINOR_VERSION >= 6 #define HAVE_GTK2_6 1 #endif #endif static int TIMEOUT_SECONDS = 0; #define STATUS_BYTES 100 #define STATUS_TOKENS 19 #define VEEJAY_CODENAME "Resume build" /* Status bytes */ #define ELAPSED_TIME 0 #define PLAY_MODE 2 #define CURRENT_ID 3 #define SAMPLE_FX 4 #define SAMPLE_START 5 #define SAMPLE_END 6 #define SAMPLE_SPEED 7 #define SAMPLE_LOOP 8 #define SAMPLE_MARKER_START 13 #define STREAM_TYPE 13 #define SAMPLE_MARKER_END 14 #define FRAME_NUM 1 #define TOTAL_FRAMES 6 #define TOTAL_SLOTS 16 #define CURRENT_ENTRY 15 #define MODE_PLAIN 2 #define MODE_SAMPLE 0 #define MODE_PATTERN 3 #define MODE_STREAM 1 #define STREAM_COL_R 5 #define STREAM_COL_G 6 #define STREAM_COL_B 7 #define STREAM_RECORDED 11 #define STREAM_DURATION 10 #define STREAM_RECORDING 9 /* Stream type identifiers */ void vj_gui_set_timeout(int timer) { TIMEOUT_SECONDS = timer; } enum { STREAM_NO_STREAM = 0, STREAM_RED = 9, STREAM_GREEN = 8, STREAM_YELLOW = 7, STREAM_BLUE = 6, STREAM_WHITE = 4, STREAM_VIDEO4LINUX = 2, STREAM_DV1394 = 17, STREAM_NETWORK = 13, STREAM_MCAST = 14, STREAM_YUV4MPEG = 1, STREAM_AVFORMAT = 12, STREAM_PICTURE = 5 }; enum { COLUMN_INT = 0, COLUMN_STRING0, COLUMN_STRINGA , COLUMN_STRINGB, COLUMN_STRINGC, N_COLUMNS }; enum { ENTRY_FXID = 0, ENTRY_ISVIDEO = 1, ENTRY_NUM_PARAMETERS = 2, ENTRY_P0 = 3, ENTRY_P1 = 4, ENTRY_P2 = 5, ENTRY_P3 = 6, ENTRY_P4 = 7, ENTRY_P5 = 8, ENTRY_P6 = 9, ENTRY_P7 = 10, ENTRY_UNUSED = 11, ENTRY_FXSTATUS = 12, ENTRY_UNUSED2 = 13, ENTRY_SOURCE = 14, ENTRY_CHANNEL = 15 }; enum { SL_ID = 0, SL_DESCR = 1, SL_TIMECODE = 2 }; enum { HINT_CHAIN = 0, HINT_EL = 1, HINT_MIXLIST = 2, HINT_SAMPLELIST = 3, HINT_ENTRY = 4, HINT_SAMPLE = 5, HINT_SLIST = 6, HINT_V4L = 7, HINT_RECORDING = 8, HINT_RGBSOLID = 9, HINT_BUNDLES = 10, HINT_HISTORY = 11, HINT_MARKER = 12, HINT_KF = 13, NUM_HINTS = 14 }; enum { PAGE_CONSOLE =0, PAGE_FX = 3, PAGE_EL = 1, PAGE_SAMPLEEDIT = 2, }; typedef struct { int channel; int dev; } stream_templ_t; enum { V4L_DEVICE=0, DV1394_DEVICE=1, }; typedef struct { int selected_chain_entry; int selected_el_entry; int selected_vims_entry; int selected_key_mod; int selected_key_sym; int selected_vims_id; int render_record; int entry_tokens[STATUS_TOKENS]; int iterator; int selected_effect_id; int reload_hint[NUM_HINTS]; bool reload_force_avoid; int playmode; int sample_rec_duration; int streams[4096]; int recording[2]; int selected_mix_sample_id; int selected_mix_stream_id; int selected_rgbkey; int priout_lock; int pressed_key; int pressed_mod; int keysnoop; int randplayer; char *selected_arg_buf; int expected_slots; stream_templ_t strtmpl[2]; // v4l, dv1394 int selected_parameter_id; // current kf } veejay_user_ctrl_t; typedef struct { float fps; int num_files; int *offsets; int num_frames; int width; int height; } veejay_el_t; enum { RUN_STATE_LOCAL = 1, RUN_STATE_REMOTE = 2, }; typedef struct { gint event_id; gint params; gchar *format; gchar *descr; } vims_t; typedef struct { gint keyval; gint state; gchar *args; gint event_id; } vims_keys_t; static int skin__ = 0; // Have room for only 200 samples #define NUM_BANKS 20 #define NUM_PAGES 10 #define NUM_SAMPLES_PER_PAGE 12 #define NUM_SAMPLES_PER_COL 3 #define NUM_SAMPLES_PER_ROW 4 #define MOD_OFFSET 200 #define SEQUENCE_LENGTH 1024 static vims_t vj_event_list[VIMS_MAX]; static vims_keys_t vims_keys_list[VIMS_MAX]; static int vims_verbosity = 0; typedef struct { GtkLabel *title; GtkLabel *timecode; GtkLabel *hotkey; // GtkWidget *edit_button; GtkTooltips *tips; GtkWidget *image; GtkFrame *frame; GtkWidget *event_box; GtkWidget *main_vbox; GtkWidget *upper_hbox; GtkWidget *upper_vbox; } sample_gui_slot_t; typedef struct { gint w; gint h; gdouble fps; gint pixel_format; gint sampling; gint audio_rate; gint norm; gint sync; gint timer; gint deinter; gchar *mcast_osc; gchar *mcast_vims; gint osc; gint vims; } config_settings_t; typedef struct { GtkFrame *frame; GtkWidget *image; GtkWidget *event_box; GtkWidget *main_vbox; GdkPixbuf *pixbuf_ref; gint sample_id; gint sample_type; } sequence_gui_slot_t; typedef struct { gint slot_number; gint sample_id; gint sample_type; gchar *title; gchar *timecode; gint refresh_image; GdkPixbuf *pixbuf; guchar *rawdata; key_chain_t *ec; } sample_slot_t; typedef struct { gint seq_start; gint seq_end; gint w; gint h; sequence_gui_slot_t **gui_slot; sample_slot_t *selected; gint envelope_size; } sequence_envelope; typedef struct { sample_slot_t *sample; } sequence_slot_t; typedef struct { gint bank_number; gint page_num; sample_slot_t **slot; sample_gui_slot_t **gui_slot; } sample_bank_t; typedef struct { GladeXML *main_window; vj_client *client; char status_msg[STATUS_BYTES]; int status_tokens[STATUS_TOKENS]; /* current status tokens */ int *history_tokens[3]; /* list last known status tokens */ int status_passed; int status_lock; int slider_lock; int parameter_lock; int entry_lock; int sample[2]; int selection[3]; gint status_pipe; int state; int sensitive; int launch_sensitive; struct timeval alarm; struct timeval timer; GIOChannel *channel; GdkColormap *color_map; gint connecting; gint logging; gint streamrecording; gint samplerecording; gint cpumeter; gint imageA; veejay_el_t el; veejay_user_ctrl_t uc; GList *effect_info; GList *devlist; GList *chalist; GList *editlist; GList *elref; long window_id; int run_state; int play_direction; int load_image_slot; GtkWidget *sample_bank_pad; GtkWidget *quick_select; sample_bank_t **sample_banks; sample_slot_t *selected_slot; sample_slot_t *selection_slot; sample_gui_slot_t *selected_gui_slot; sample_gui_slot_t *selection_gui_slot; sequence_envelope *sequence_view; gint current_sequence_slot; GtkKnob *audiovolume_knob; // GtkKnob *speed_knob; int image_dimensions[2]; guchar *rawdata; int prev_mode; GtkWidget *tl; config_settings_t config; int status_frame; int key_id; int preview_ready; int preview_size_w; int preview_size_h; GdkColor *fg_; gboolean key_now; } vj_gui_t; enum { STATE_STOPPED = 0, STATE_RECONNECT = 1, STATE_PLAYING = 2, STATE_IDLE = 3 }; enum { FXC_ID = 0, FXC_FXID = 1, FXC_FXSTATUS = 2, FXC_KF =3, FXC_N_COLS, }; enum { V4L_NUM=0, V4L_NAME=1, V4L_SPINBOX=2, V4L_BUTTON=3, }; enum { VIMS_ID=0, VIMS_DESCR=1, VIMS_KEY=2, VIMS_MOD=3, VIMS_PARAMS=4, VIMS_FORMAT=5, VIMS_CONTENTS=6, }; #define MAX_PATH_LEN 1024 #define VEEJAY_MSG_OUTPUT 4 static vj_gui_t *info = NULL; /* global pointer to the sample-bank */ /* global pointer to the effects-source-list */ static GtkWidget *effect_sources_tree; static GtkListStore *effect_sources_store; static GtkTreeModel *effect_sources_model; static int preview_priority_ = 0; /* global pointer to the editlist-tree */ static GtkWidget *editlist_tree; static GtkListStore *editlist_store; static GtkTreeModel *editlist_model; /* global pointer to the actual selected slot in the sample_bank */ static int get_slider_val(const char *name); static void vj_msg(int type, const char format[], ...); static void vj_msg_detail(int type, const char format[], ...); static void msg_vims(char *message); static void multi_vims(int id, const char format[],...); static void single_vims(int id); static gdouble get_numd(const char *name); static void vj_kf_delete_parameter(int idx); static void vj_akf_delete(void); static void vj_kf_select_parameter(int id); static int interpolate_parameters(void); static int get_nums(const char *name); static gchar *get_text(const char *name); static void put_text(const char *name, char *text); static int is_button_toggled(const char *name); static void set_toggle_button(const char *name, int status); static void update_slider_gvalue(const char *name, gdouble value ); static void update_slider_value(const char *name, gint value, gint scale); static void update_slider_range(const char *name, gint min, gint max, gint value, gint scaled); static void update_knob_range( GtkWidget *w, gdouble min, gdouble max, gdouble value, gint scaled ); static void update_spin_range(const char *name, gint min, gint max, gint val); static void update_spin_incr(const char *name, gdouble step, gdouble page); static void update_knob_value(GtkWidget *w, gdouble value, gdouble scale ); static void update_spin_value(const char *name, gint value); static void update_label_i(const char *name, int num, int prefix); static void update_label_f(const char *name, float val); static void update_label_str(const char *name, gchar *text); static void update_globalinfo(); static void update_sampleinfo(); static void update_streaminfo(); static void update_plaininfo(); static gint load_parameter_info(); static void load_v4l_info(); static void reload_editlist_contents(); static void load_effectchain_info(); static void load_effectlist_info(); static void load_samplelist_info(gboolean with_reset_slotselection); static void load_editlist_info(); static void disable_widget( const char *name ); static void enable_widget(const char *name ); static void setup_tree_spin_column(const char *tree_name, int type, const char *title); static void setup_tree_text_column( const char *tree_name, int type, const char *title ); static void setup_tree_pixmap_column( const char *tree_name, int type, const char *title ); static gchar *_utf8str( char *c_str ); static gchar *recv_vims(int len, int *bytes_written); static int recv_vims_binary(int len, int *bytes_written, guchar *buf); static void disable_widget_by_pointer(GtkWidget *w); static void enable_widget_by_pointer(GtkWidget *w); static GdkPixbuf * update_pixmap_kf( int status ); static GdkPixbuf * update_pixmap_entry( int status ); static gboolean chain_update_row(GtkTreeModel * model, GtkTreePath * path, GtkTreeIter * iter, gpointer data); void vj_gui_stop_launch(); static void get_gd(char *buf, char *suf, const char *filename); static void update_cached_slots(void); int resize_primary_ratio_y(); int resize_primary_ratio_x(); static void setup_tree_texteditable_column( const char *tree_name, int type, const char *title, void (*callbackfunction)() ); static void update_rgbkey(); static int count_textview_buffer(const char *name); static void clear_textview_buffer(const char *name); static void init_recorder(int total_frames, gint mode); static void reload_bundles(); static void update_rgbkey_from_slider(); void vj_launch_toggle(gboolean value); static gchar *get_textview_buffer(const char *name); static void create_slot(gint bank_nr, gint slot_nr, gint w, gint h); static void setup_samplebank(gint c, gint r); static int add_sample_to_sample_banks( int bank_page,sample_slot_t *slot ); static void update_sample_slot_data(int bank_num, int slot_num, int id, gint sample_type, gchar *title, gchar *timecode); static gint compare_index(gint *index_1, gint *index_2 ); static gboolean on_slot_activated_by_key (GtkWidget *widget, GdkEventKey *event, gpointer user_data); static gboolean on_slot_activated_by_mouse (GtkWidget *widget, GdkEventButton *event, gpointer user_data); static void vj_gui_add_sample(gchar *filename, gint mode); static sample_slot_t *vj_gui_get_sample_info(gint which_one, gint mode ); static void add_sample_to_effect_sources_list(gint id, gint type, gchar *title, gchar *timecode); static void add_sample_to_editlist(guint row_number, gchar *timeline, gchar *fname, gchar *timecode, gchar *gfourcc); static void set_activation_of_slot_in_samplebank(gboolean activate); int gveejay_new_slot(int stream); static int selected_is_playing(); static struct { const char *name; } capt_card_set[] = { { "v4l_expander" }, { "v4l_brightness" }, { "v4l_hue" }, { "v4l_contrast" }, { "v4l_color" }, { "v4l_white" } }; // REFAC static int no_preview_ = 1; static int no_draw_ = 0; static struct { const char *name; } gwidgets[] = { {"button_sendvims"}, {"button_087"}, {"button_086"}, {"button_081"}, {"button_082"}, {"button_080"}, {"button_085"}, // {"button_036"}, {"button_084"}, {"button_083"}, {"button_084"}, {"button_088"}, // {"videobar"}, {"button_samplestart"}, {"button_sampleend"}, {"button_fadeout"}, {"button_fadein"}, {"button_5_4"}, {"button_200"}, {"button_001"}, {"button_252"}, {"button_251"}, {"button_054"}, {"new_colorstream"}, // {"audiovolume"}, {"manualopacity"}, {"button_fadedur"}, {"vimsmessage"}, {"frame_fxtree"}, {"button_clipcopy"}, {"button_sample_play"}, {"button_samplelist_open"}, {"button_samplelist_save"}, {"button_sample_del"}, {"samplerand"}, {"freestyle"}, {"frame_sampleproperties"}, {"frame_samplerecord"}, {"frame132"}, // edl {"colorselection"}, {"frame_streamproperties"}, {"frame_streamrecord"}, {"loglinear"}, {"curve"}, {"curve_toggleglobal"}, {"curve_table"}, {"curve_toggleentry"}, {"streamnew"}, {"sampleadd"}, {"samplepage"}, // {"button_clearmarker"}, // {"check_marker_bind"}, {NULL} }; static struct { const char *name; } videowidgets[] = { {"button_sendvims"}, {"button_087"}, {"button_086"}, {"button_081"}, {"button_082"}, {"button_080"}, {"button_085"}, {"button_084"}, {"button_083"}, {"button_084"}, {"button_088"}, // {"videobar"}, {"button_samplestart"}, {"button_sampleend"}, // {"speedslider"}, {NULL} }; static struct { const char *name; } plainwidgets[] = { {"manualopacity"}, {"loglinear"}, {"frame_fxtree"}, {NULL} }; enum { TC_SAMPLE_L = 0, TC_SAMPLE_F = 1, TC_SAMPLE_S = 2, TC_SAMPLE_M = 3, TC_SAMPLE_H = 4, TC_STREAM_F = 5, TC_STREAM_M = 6, TC_STREAM_H = 7 }; /* Function to see if selected is playing */ static int selected_is_playing() { int *history = info->history_tokens[ (info->status_tokens[PLAY_MODE]) ]; if(!info->selected_slot) { return 0; } if(info->selected_slot->sample_id == info->status_tokens[CURRENT_ID] && info->selected_slot->sample_type == info->status_tokens[PLAY_MODE] && history[CURRENT_ID] == info->status_tokens[CURRENT_ID]) { return 1; } return 0; } /* todo: * generalize tree view usage (cleans up a lot of code) */ /* void on_samplelist_edited(GtkCellRendererText *cell, gchar *path_string, gchar *new_text, gpointer user_data); */ static gchar *_utf8str(char *c_str) { gint bytes_read; gint bytes_written; GError *error = NULL; if(!c_str) return NULL; gchar *result = g_locale_to_utf8( c_str, -1, &bytes_read, &bytes_written, &error ); if(error) { veejay_msg(VEEJAY_MSG_DEBUG, "%s cannot convert [%s] : %s",__FUNCTION__ , c_str, error->message); g_free(error); if( result ) g_free(result); result = NULL; } return result; } GdkColor *widget_get_fg(GtkWidget *w ) { if(!w) return NULL; GdkColor *c = (GdkColor*)vj_malloc(sizeof(GdkColor)); memset(c, 0, sizeof(GdkColor)); GtkStyle *s = gtk_widget_get_style( w); c->red = s->fg[0].red; c->green = s->fg[0].green; c->blue = s->fg[0].blue; return c; } // dirty function to get name or channel static int read_file(const char *filename, int what, void *dst) { int fd = open (filename, O_RDONLY ); if(fd <= 0) return 0; char buf[256]; bzero(buf,256); int n = read( fd, buf, 256 ); if(n > 0) { if(what == 0) { char *dst_= (char*) dst; snprintf(dst_, n, "%s", buf ); close(fd); return n; } if(what == 1) { int *cha = (int*) dst; int major=0,minor=0; char delim; int nt = sscanf( buf, "%2d%c%d",&major,&delim,&minor ); if(nt > 0) { *(cha) = minor; return 1; } close(fd); } } close(fd); return 0; } static void break_here(void) { } GtkWidget *glade_xml_get_widget_( GladeXML *m, const char *name ) { GtkWidget *widget = glade_xml_get_widget( m , name ); if(!widget) { fprintf(stderr,"gveejay fatal: widget '%s' does not exist\n",name); break_here(); exit(0); } return widget; } static void scan_devices( const char *name) { struct stat v4ldir; int n; GtkWidget *tree = glade_xml_get_widget_(info->main_window,name); GtkListStore *store; GtkTreeIter iter; GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW(tree)); store = GTK_LIST_STORE(model); // kernel 2.6 const char *v4lpath = "/sys/class/video4linux/"; n = stat( v4lpath, &v4ldir ); if(n < 0) return; if( S_ISDIR(v4ldir.st_mode)) { char dirname[20]; char abspath[1024]; char filename[1024]; int i = 0; for( i = 0; i < 8 ; i ++ ) { struct stat v4ldev; sprintf(dirname, "video%d/", i ); sprintf(abspath, "%s%s",v4lpath,dirname); n = stat(abspath, &v4ldev ); if(n < 0) continue; if( S_ISDIR( v4ldev.st_mode )) { bzero(filename,1024); sprintf(filename, "%sname",abspath); char devicename[1024]; bzero(devicename,1024); read_file(filename, 0, devicename ); gdouble gchannel = 1.0; // default to composite gchar *thename = _utf8str( devicename ); gtk_list_store_append( store, &iter); gtk_list_store_set( store, &iter, V4L_NUM, i, V4L_NAME, thename, V4L_SPINBOX, gchannel, -1); g_free(thename); } } } else { // if on linux ,scan proc for devices. // on 2.6 , /sys/class/video4linux/video0/dev , name // if reading fails, fill a bogus list and test for /dev/video0 char filename[1024]; int i; for( i = 0; i < 8 ; i ++ ) { sprintf(filename, "/dev/video%d", i); struct stat v4lfile; int n = stat( filename, &v4lfile ); if( n > 0) continue; if( S_ISREG( v4lfile.st_mode ) ) { /* add device*/ } } } /* TODO: Put DV 1394 device here too !! har har must do cleanup refactor all gtk tree related code into a more generic function set */ // const char *dvpath = "/proc/bus/ieee1394/dv"; gtk_tree_view_set_model(GTK_TREE_VIEW(tree), model ); } void on_devicelist_row_activated(GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *col, gpointer user_data) { GtkTreeModel *model; GtkTreeIter iter; model = gtk_tree_view_get_model(treeview); if(gtk_tree_model_get_iter(model,&iter,path)) { gint num = 0; gtk_tree_model_get(model,&iter, V4L_NUM, &num, -1); if( num == info->uc.strtmpl[V4L_DEVICE].dev ) { multi_vims( VIMS_STREAM_NEW_V4L,"%d %d", info->uc.strtmpl[V4L_DEVICE].dev, info->uc.strtmpl[V4L_DEVICE].channel ); gveejay_new_slot(MODE_STREAM); } } } static void setup_v4l_devices() { GtkWidget *tree = glade_xml_get_widget_( info->main_window, "tree_v4ldevices"); GtkListStore *store = gtk_list_store_new( 3, G_TYPE_INT, G_TYPE_STRING, G_TYPE_FLOAT ); gtk_tree_view_set_model( GTK_TREE_VIEW(tree), GTK_TREE_MODEL(store)); g_object_unref( G_OBJECT( store )); setup_tree_text_column( "tree_v4ldevices", V4L_NUM, "num" ); setup_tree_text_column( "tree_v4ldevices", V4L_NAME, "Device name"); setup_tree_spin_column( "tree_v4ldevices", V4L_SPINBOX, "Channel"); g_signal_connect( tree, "row-activated", (GCallback) on_devicelist_row_activated, NULL ); scan_devices( "tree_v4ldevices" ); } static gchar* format_time(int frame_num); static gchar* format_selection_time(int start, int end); typedef struct { int id; int nl; long n1; long n2; int tf; } el_ref; typedef struct { int pos; char *filename; char *fourcc; int num_frames; } el_constr; typedef struct { int defaults[10]; int min[10]; int max[10]; char description[150]; int id; int is_video; int num_arg; int has_rgb; } effect_constr; int _effect_get_mix(int effect_id) { int n = g_list_length(info->effect_info); int i; if(effect_id < 0) return -1; for(i=0; i <= n; i++) { effect_constr *ec = g_list_nth_data( info->effect_info, i ); if(ec != NULL) { if(ec->id == effect_id) return ec->is_video; } } return 0; } int _effect_get_rgb(int effect_id) { int n = g_list_length(info->effect_info); int i; if(effect_id < 0) return -1; for(i=0; i <= n; i++) { effect_constr *ec = g_list_nth_data( info->effect_info, i ); if(ec != NULL) { if(ec->id == effect_id) return ec->has_rgb; } } return 0; } int _effect_get_np(int effect_id) { int n = g_list_length(info->effect_info); int i; if(effect_id < 0) return -1; for(i=0; i <= n; i++) { effect_constr *ec = g_list_nth_data( info->effect_info, i ); if(ec != NULL) { if(ec->id == effect_id) return ec->num_arg; } } return 0; } int _effect_get_minmax( int effect_id, int *min, int *max, int index ) { int n = g_list_length(info->effect_info); int i; if(effect_id < 0) return 0; for(i=0; i <= n; i++) { effect_constr *ec = g_list_nth_data( info->effect_info, i ); if(ec != NULL) { if(ec->id == effect_id) { if( index > ec->num_arg ) return 0; *min = ec->min[index]; *max = ec->max[index]; return 1; } } } return 0; } char *_effect_get_description(int effect_id) { int n = g_list_length( info->effect_info ); int i; for(i = 0;i <= n ; i++) { effect_constr *ec = g_list_nth_data(info->effect_info, i); if(ec != NULL) { if(effect_id == ec->id ) return ec->description; } } return ""; } el_constr *_el_entry_new( int pos, char *file, int nf , char *fourcc) { el_constr *el = g_new( el_constr , 1 ); el->filename = strdup( file ); el->num_frames = nf; el->pos = pos; el->fourcc = strdup(fourcc); return el; } void _el_entry_free( el_constr *entry ) { if(entry) { if(entry->filename) free(entry->filename); if(entry->fourcc) free(entry->fourcc); free(entry); } } void _el_entry_reset( ) { if(info->editlist != NULL) { int n = g_list_length( info->editlist ); int i; for( i = 0; i <= n ; i ++) _el_entry_free( g_list_nth_data( info->editlist, i ) ); g_list_free(info->editlist); info->editlist=NULL; } } int _el_get_nframes( int pos ) { int n = g_list_length( info->editlist ); int i; for( i = 0; i <= n ; i ++) { el_constr *el = g_list_nth_data( info->editlist, i ); if(!el) return 0; if(el->pos == pos) return el->num_frames; } return 0; } el_ref *_el_ref_new( int row_num,int nl, long n1, long n2, int tf) { el_ref *el = g_new( el_ref , 1 ); el->id = row_num; el->nl = nl; el->n1 = n1; el->n2 = n2; el->tf = tf; return el; } void _el_ref_free( el_ref *entry ) { if(entry) free(entry); } void _el_ref_reset() { if(info->elref != NULL) { int i; int n = g_list_length( info->elref ); for(i = 0; i <= n; i ++ ) _el_ref_free( g_list_nth_data( info->elref, i ) ); g_list_free(info->elref); info->elref = NULL; } } int _el_ref_end_frame( int row_num ) { int n = g_list_length( info->elref ); int i; for ( i = 0 ; i <= n; i ++ ) { el_ref *el = g_list_nth_data( info->elref, i ); if(el->id == row_num ) { // int offset = info->el.offsets[ el->nl ]; // return (offset + el->n1 + el->n2 ); return (el->tf + el->n2 - el->n1); } } return 0; } int _el_ref_start_frame( int row_num ) { int n = g_list_length( info->elref ); int i; for ( i = 0 ; i <= n; i ++ ) { el_ref *el = g_list_nth_data( info->elref, i ); if(el->id == row_num ) { // int offset = info->el.offsets[ el->nl ]; // return (offset + el->n1 ); // printf("Start pos of row %d : %d = n1, %d = n2, %d = tf\n", // row_num,el->n1,el->n2, el->tf ); return (el->tf); } } return 0; } char *_el_get_fourcc( int pos ) { int n = g_list_length( info->editlist ); int i; for( i = 0; i <= n; i ++ ) { el_constr *el = g_list_nth_data( info->editlist, i ); if(el->pos == pos) return el->fourcc; } return NULL; } char *_el_get_filename( int pos ) { int n = g_list_length( info->editlist ); int i; for( i = 0; i <= n; i ++ ) { el_constr *el = g_list_nth_data( info->editlist, i ); if(el->pos == pos) return el->filename; } return NULL; } effect_constr* _effect_new( char *effect_line ) { effect_constr *ec; int descr_len = 0; int p; int tokens = 0; char len[4]; char line[100]; int offset = 0; bzero( len, 4 ); bzero( line, 100 ); if(!effect_line) return NULL; strncpy(len, effect_line, 3); sscanf(len, "%03d", &descr_len); if(descr_len <= 0) return NULL; ec = g_new( effect_constr, 1); bzero( ec->description, 150 ); strncpy( ec->description, effect_line+3, descr_len ); tokens = sscanf(effect_line+(descr_len+3), "%03d%1d%1d%02d", &(ec->id),&(ec->is_video), &(ec->has_rgb), &(ec->num_arg)); offset = descr_len + 10; for(p=0; p < ec->num_arg; p++) { sscanf(effect_line+offset,"%06d%06d%06d", &(ec->min[p]), &(ec->max[p]),&(ec->defaults[p]) ); offset+=18; } return ec; } void _effect_free( effect_constr *effect ) { if(effect) { free(effect); } } void _effect_reset(void) { if( info->effect_info != NULL) { int n = g_list_length(info->effect_info); int i; for( i = 0; i <=n ; i ++ ) _effect_free( g_list_nth_data( info->effect_info , i ) ); g_list_free( info->effect_info ); info->effect_info = NULL; } } gboolean is_alive(gpointer data); static gchar *get_relative_path(char *path) { return _utf8str( basename( path )); } gchar *dialog_save_file(const char *title ) { GtkWidget *parent_window = glade_xml_get_widget_( info->main_window, "gveejay_window" ); GtkWidget *dialog = gtk_file_chooser_dialog_new( title, parent_window, GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); if( gtk_dialog_run( GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { gchar *file = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(dialog) ); gtk_widget_destroy(dialog); return file; } gtk_widget_destroy(dialog); return NULL; } static void clear_progress_bar( const char *name, gdouble val ) { GtkWidget *w = glade_xml_get_widget_( info->main_window, name ); gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR(w), val ); } static struct { const char *descr; const char *filter; } content_file_filters[] = { { "AVI Files (*.avi)", "*.avi", }, { "Digital Video Files (*.dv)", "*.dv" }, { "Edit Decision List Files (*.edl)", "*.edl" }, { "PNG (Portable Network Graphics) (*.png)", "*.png" }, { "JPG (Joint Photographic Experts Group) (*.jpg)", "*.jpg" }, { NULL, NULL }, }; static void add_file_filters(GtkWidget *dialog, int type ) { GtkFileFilter *filter = NULL; if(type == 0 ) { int i; for( i = 0; content_file_filters[i].descr != NULL ; i ++ ) { filter = gtk_file_filter_new(); gtk_file_filter_set_name( filter, content_file_filters[i].descr); gtk_file_filter_add_pattern( filter, content_file_filters[i].filter); gtk_file_chooser_add_filter( GTK_FILE_CHOOSER(dialog), filter ); } } if(type == 1 ) { filter = gtk_file_filter_new(); gtk_file_filter_set_name( filter, "Sample List Files (*.sl)"); gtk_file_filter_add_pattern( filter, "*.sl"); gtk_file_chooser_add_filter( GTK_FILE_CHOOSER(dialog), filter); } if(type == 2 ) { filter = gtk_file_filter_new(); gtk_file_filter_set_name( filter, "Action Files (*.xml)"); gtk_file_filter_add_pattern( filter, "*.xml"); gtk_file_chooser_add_filter( GTK_FILE_CHOOSER(dialog), filter); } if(type == 3 ) { //ffmpeg } filter = gtk_file_filter_new(); gtk_file_filter_set_name( filter, "All Files (*.*)"); gtk_file_filter_add_pattern( filter, "*"); gtk_file_chooser_add_filter( GTK_FILE_CHOOSER(dialog), filter); } gchar *dialog_open_file(const char *title, int type) { static gchar *_file_path = NULL; GtkWidget *parent_window = glade_xml_get_widget_( info->main_window, "gveejay_window" ); GtkWidget *dialog = gtk_file_chooser_dialog_new( title, parent_window, GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); add_file_filters(dialog, type ); gchar *file = NULL; if( _file_path ) { gtk_file_chooser_set_current_folder_uri(GTK_FILE_CHOOSER(dialog), _file_path); g_free(_file_path); } if( gtk_dialog_run( GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { file = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(dialog) ); _file_path = gtk_file_chooser_get_current_folder_uri(GTK_FILE_CHOOSER(dialog)); } gtk_widget_destroy(GTK_WIDGET(dialog)); return file; } void about_dialog() { const gchar *artists[] = { "Matthijs v. Henten (glade, pixmaps) ", "Dursun Koca (logo)", NULL }; const gchar *authors[] = { "Niels Elburg ", "Thomas Reinhold ", NULL }; const gchar *license = { "This program is Free Software; You can redistribute it and/or modify\n" \ "under the terms of the GNU General Public License as published by\n" \ "the Free Software Foundation; either version 2, or (at your option)\n"\ "any later version.\n\n"\ "This program is distributed in the hope it will be useful,\n"\ "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"\ "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"\ "See the GNU General Public License for more details.\n\n"\ "For more information , see also: http://www.gnu.org\n" }; #ifdef HAVE_GTK2_6 char path[MAX_PATH_LEN]; bzero(path,MAX_PATH_LEN); get_gd( path, NULL, "veejay-logo.png" ); GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file ( path, NULL ); GtkWidget *about = g_object_new( GTK_TYPE_ABOUT_DIALOG, "name", "GVeejay Reloaded", "version", VERSION, "copyright", "(C) 2004 - 2005 N. Elburg et all.", "comments", "Another graphical interface for Veejay", "authors", authors, "artists", artists, "license", license, "logo", pixbuf, NULL ); g_object_unref(pixbuf); g_signal_connect( about , "response", G_CALLBACK( gtk_widget_destroy),NULL); gtk_window_present( GTK_WINDOW( about ) ); #else int i; vj_msg_detail( VEEJAY_MSG_INFO, "Gveejay Reloaded %s %d%d%d", VEEJAY_CODENAME,VEEJAY_MAJOR_VERSION,VEEJAY_MINOR_VERSION,VEEJAY_MICRO_VERSION ); vj_msg_detail( VEEJAY_MSG_INFO, "%s", license ); for(i = 0; artists[i] != NULL ; i ++ ) vj_msg_detail( VEEJAY_MSG_INFO, "%s", artists[i] ); for(i = 0; authors[i] != NULL ; i ++ ) vj_msg_detail( VEEJAY_MSG_INFO, "%s", authors[i] ); vj_msg_detail( VEEJAY_MSG_INFO, "Copyright (C) 2004 - 2005. N. Elburg et all." ); vj_msg_detail( VEEJAY_MSG_INFO, "GVeejay Reloaded - Another graphical interface for Veejay"); #endif } gboolean dialogkey_snooper( GtkWidget *w, GdkEventKey *event, gpointer user_data) { GtkWidget *entry = (GtkWidget*) user_data; if(gtk_widget_is_focus(entry) == FALSE ) { // entry doesnt have focus, bye! return FALSE; } if(event->type == GDK_KEY_PRESS) { gchar tmp[100]; bzero(tmp,100); info->uc.pressed_key = event->keyval; info->uc.pressed_mod = event->state; gchar *text = gdkkey_by_id( event->keyval ); gchar *mod = gdkmod_by_id( event->state ); if( mod != NULL ) { if(strlen(mod) < 2 ) sprintf(tmp, "%s", text ); else sprintf(tmp, "%s + %s", text,mod); gchar *utf8_text = _utf8str( tmp ); gtk_entry_set_text( GTK_ENTRY(entry), utf8_text); g_free(utf8_text); } } return FALSE; } gboolean key_handler( GtkWidget *w, GdkEventKey *event, gpointer user_data) { if(!info->key_now) return FALSE; if(event->type != GDK_KEY_PRESS) return FALSE; /* translate GDK keys to veejay's SDL set */ int gdk_keyval = gdk2sdl_key( event->keyval ); int gdk_state = gdk2sdl_mod( event->state ); if(gdk_keyval == 0) return FALSE; int i; for( i = 0; i main_window, "gveejay_window"); GtkWidget *dialog = gtk_dialog_new_with_buttons( title, GTK_WINDOW( mainw ), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_NO, GTK_RESPONSE_REJECT, GTK_STOCK_YES, GTK_RESPONSE_ACCEPT, NULL); GtkWidget *keyentry = gtk_entry_new(); gtk_entry_set_text( GTK_ENTRY(keyentry), ""); gtk_editable_set_editable( GTK_ENTRY(keyentry), FALSE ); gtk_dialog_set_default_response( GTK_DIALOG(dialog), GTK_RESPONSE_REJECT ); gtk_window_set_resizable( GTK_WINDOW(dialog), FALSE ); g_signal_connect( G_OBJECT(dialog), "response", G_CALLBACK( gtk_widget_hide ), G_OBJECT(dialog ) ); GtkWidget *hbox1 = gtk_hbox_new( FALSE, 12 ); gtk_container_set_border_width( GTK_CONTAINER( hbox1 ), 6 ); GtkWidget *hbox2 = gtk_hbox_new( FALSE, 12 ); gtk_container_set_border_width( GTK_CONTAINER( hbox2 ), 6 ); GtkWidget *icon = gtk_image_new_from_file( pixmap ); GtkWidget *label = gtk_label_new( msg ); gtk_container_add( GTK_CONTAINER( hbox1 ), icon ); gtk_container_add( GTK_CONTAINER( hbox1 ), label ); gtk_container_add( GTK_CONTAINER( hbox1 ), keyentry ); if( info->uc.selected_vims_entry && (info->uc.selected_key_mod || info->uc.selected_key_sym )) { char tmp[100]; sprintf(tmp,"VIMS %d : %s + %s", info->uc.selected_vims_entry, sdlmod_by_id( info->uc.selected_key_mod ), sdlkey_by_id( info->uc.selected_key_sym ) ); GtkWidget *current = gtk_label_new( tmp ); gtk_container_add( GTK_CONTAINER( hbox1 ), current ); if( vj_event_list[ info->uc.selected_vims_entry ].params > 0 ) { GtkWidget *arglabel = gtk_label_new("Enter arguments for VIMS"); GtkWidget *argentry = gtk_entry_new(); gtk_entry_set_text( GTK_ENTRY(argentry), info->uc.selected_arg_buf ); gtk_container_add( GTK_CONTAINER( hbox2 ), arglabel ); gtk_container_add( GTK_CONTAINER( hbox2 ), argentry ); } } gtk_container_add( GTK_CONTAINER( GTK_DIALOG( dialog )->vbox ), hbox1 ); gtk_container_add( GTK_CONTAINER( GTK_DIALOG( dialog )->vbox ), hbox2 ); gtk_widget_show_all( dialog ); int id = gtk_key_snooper_install( dialogkey_snooper, (gpointer*) keyentry ); int n = gtk_dialog_run(GTK_DIALOG(dialog)); gtk_key_snooper_remove( id ); gtk_widget_destroy(dialog); return n; } void message_dialog( const char *title, char *msg ) { GtkWidget *mainw = glade_xml_get_widget_(info->main_window, "gveejay_window"); GtkWidget *dialog = gtk_dialog_new_with_buttons( title, GTK_WINDOW( mainw ), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, GTK_RESPONSE_NONE, NULL); GtkWidget *label = gtk_label_new( msg ); g_signal_connect_swapped( dialog, "response", G_CALLBACK(gtk_widget_destroy),dialog); gtk_container_add( GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label ); gtk_widget_show_all(dialog); } int prompt_dialog(const char *title, char *msg) { GtkWidget *mainw = glade_xml_get_widget_(info->main_window, "gveejay_window"); GtkWidget *dialog = gtk_dialog_new_with_buttons( title, GTK_WINDOW( mainw ), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_NO, GTK_RESPONSE_REJECT, GTK_STOCK_YES, GTK_RESPONSE_ACCEPT, NULL); gtk_dialog_set_default_response( GTK_DIALOG(dialog), GTK_RESPONSE_REJECT ); gtk_window_set_resizable( GTK_WINDOW(dialog), FALSE ); g_signal_connect( G_OBJECT(dialog), "response", G_CALLBACK( gtk_widget_hide ), G_OBJECT(dialog ) ); GtkWidget *hbox1 = gtk_hbox_new( FALSE, 12 ); gtk_container_set_border_width( GTK_CONTAINER( hbox1 ), 6 ); GtkWidget *icon = gtk_image_new_from_stock( GTK_STOCK_DIALOG_QUESTION, GTK_ICON_SIZE_DIALOG ); GtkWidget *label = gtk_label_new( msg ); gtk_container_add( GTK_CONTAINER( hbox1 ), icon ); gtk_container_add( GTK_CONTAINER( hbox1 ), label ); gtk_container_add( GTK_CONTAINER( GTK_DIALOG( dialog )->vbox ), hbox1 ); gtk_widget_show_all( dialog ); int n = gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); return n; } void veejay_quit( ) { if( prompt_dialog("Quit veejay", "Close Veejay ? All unsaved work will be lost." ) == GTK_RESPONSE_REJECT ) return; single_vims( 600 ); vj_gui_disconnect(); clear_progress_bar( "cpumeter",0.0 ); clear_progress_bar( "connecting",0.0 ); clear_progress_bar( "samplerecord_progress",0.0 ); clear_progress_bar( "streamrecord_progress",0.0 ); // g_source_remove( info->samplerecording ); // g_source_remove( info->streamrecording ); // g_source_remove( info->logging ); // g_source_remove( info->cpumeter ); // g_source_remove( info->imageA ); // g_io_channel_shutdown( info->channel, FALSE, NULL ); } gboolean gveejay_quit( GtkWidget *widget, gpointer user_data) { if( info->state == STATE_PLAYING) { if( prompt_dialog("Quit gveejay", "Are you sure?" ) == GTK_RESPONSE_REJECT) return TRUE; if(info->run_state == RUN_STATE_LOCAL) veejay_quit(); } vj_gui_disconnect(); vj_gui_free(); return FALSE; } /* Free the slot */ static void free_slot( sample_slot_t *slot ) { if(slot) { if(slot->title) free(slot->title); if(slot->timecode) free(slot->timecode); if(slot->ec) del_chain( slot->ec ); free(slot); } } /* Allocate some memory and create a temporary slot */ sample_slot_t *create_temporary_slot( gint slot_id, gint id, gint type, gchar *title, gchar *timecode ) { sample_slot_t *slot = (sample_slot_t*) vj_malloc(sizeof(sample_slot_t)); memset(slot, 0, sizeof(sample_slot_t)); if(id>0) { slot->sample_id = id; slot->sample_type = type; slot->timecode = strdup(timecode); slot->title = strdup(title); slot->slot_number = slot_id; } return slot; } /* Create a new slot in the sample bank, This function is called by all VIMS commands that create a new stream or a new sample */ int gveejay_new_slot(int mode) { int id = 0; int result_len = 0; gchar *result = recv_vims( 3, &result_len ); if(result_len > 0 ) { sscanf( result, "%d", &id ); g_free(result); if(id > 0 ) vj_msg(VEEJAY_MSG_INFO, "Created new %s %d", (mode == MODE_SAMPLE ? "Sample" : "Stream"), id); else { char message[100]; sprintf(message, "Failed to create new %s", (mode == MODE_SAMPLE ? "Sample" : "Stream" ) ); message_dialog( "Error", message ); } if( id > 0 ) { /* Add the sample/stream to a sample bank */ int poke_slot = 0; int bank_page = 0; verify_bank_capacity( &bank_page, &poke_slot, id, mode ); sample_slot_t *tmp_slot = vj_gui_get_sample_info(id, mode ); if(tmp_slot) { tmp_slot->slot_number = poke_slot; add_sample_to_sample_banks( bank_page, tmp_slot ); free_slot( tmp_slot ); info->uc.expected_slots = info->status_tokens[TOTAL_SLOTS] + 1; } } } return id; } /* Redraw the image on update, */ void gveejay_update_image( sample_slot_t *slot, sample_gui_slot_t *gui_slot, gint w, gint h ) { if(info->selected_gui_slot) gtk_widget_queue_draw( info->selected_gui_slot->image ); } /* Load an image from Veejay */ GdkPixbuf * gveejay_update_image2( GtkWidget *img, gint w, gint h ) { gint row_strides = 3 * w; gint bw = 0; // veejay sends current frame as image in RGB, 8 bytes per sample // send 'get image' message multi_vims( VIMS_RGB24_IMAGE, "%d %d", w ,h ); recv_vims_binary( 6, &bw, info->rawdata ); // read image from socket, store length of image in bw if(bw<=0 || bw != (w*h*3)) { return NULL ; } GtkImage *image = GTK_IMAGE(img); GtkImageType type = gtk_image_get_storage_type( image ); if(type == GTK_IMAGE_EMPTY || type == GTK_IMAGE_PIXBUF ) { //GdkPixbuf *pixbuf = gtk_image_get_pixbuf( image ); GdkPixbuf *new_pixbuf = gdk_pixbuf_new_from_data( info->rawdata,GDK_COLORSPACE_RGB, false,8,w,h,row_strides,NULL,NULL ); if(!new_pixbuf) return NULL; //if(pixbuf != NULL ) // gdk_pixbuf_unref(pixbuf); if(image) gtk_image_set_from_pixbuf( image, new_pixbuf ); no_draw_ = 0; return new_pixbuf; } else fprintf(stderr, "Image type invalid %d\n", type ); return NULL; } #include "callback.c" enum { COLOR_RED=0, COLOR_BLUE=1, COLOR_GREEN=2, COLOR_BLACK=3, COLOR_NUM }; static int line_count = 1; static void vj_msg(int type, const char format[], ...) { if( type == VEEJAY_MSG_DEBUG && vims_verbosity == 0 ) return; char tmp[1024]; char buf[1024]; char prefix[20]; va_list args; gchar level[6]; bzero(level,0); bzero(tmp, 1024); bzero(buf, 1024); va_start( args,format ); vsnprintf( tmp, sizeof(tmp), format, args ); switch(type) { case 2: sprintf(prefix,"Info : ");break; case 1: sprintf(prefix,"Warning: ");break; case 0: sprintf(prefix,"Error : ");break; case 3: sprintf(prefix,"Debug : ");break; case 4: sprintf(prefix, " ");break; } snprintf(buf, sizeof(buf), "%s %s\n",prefix,tmp ); int nr,nw; gchar *text = g_locale_to_utf8( buf, -1, &nr, &nw, NULL); text[strlen(text)-1] = '\0'; // put_text( "lastmessage", text ); GtkWidget *sb = glade_xml_get_widget_( info->main_window, "statusbar"); gtk_statusbar_push( GTK_STATUSBAR(sb),0, text ); g_free( text ); va_end(args); } static void vj_msg_detail(int type, const char format[], ...) { GtkWidget *view = glade_xml_get_widget_( info->main_window,"veejaytext"); GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view)); GtkTextIter iter; //if( type == VEEJAY_MSG_DEBUG && vims_verbosity == 0 ) // return; char tmp[1024]; char buf[1024]; char prefix[20]; va_list args; gchar level[6]; bzero(level,0); int color = -1; bzero(tmp, 1024); bzero(buf, 1024); va_start( args,format ); vsnprintf( tmp, sizeof(tmp), format, args ); gtk_text_buffer_get_end_iter(buffer, &iter); switch(type) { case 2: sprintf(prefix,"Info : ");sprintf(level, "infomsg"); color=COLOR_GREEN; break; case 1: sprintf(prefix,"Warning: ");sprintf(level, "warnmsg"); color=COLOR_RED; break; case 0: sprintf(prefix,"Error : ");sprintf(level, "errormsg"); color=COLOR_RED; break; case 3: sprintf(prefix,"Debug : ");sprintf(level, "debugmsg"); color=COLOR_BLUE; break; } if(type==4) snprintf(buf,sizeof(buf),"gveejay: %s",tmp); else snprintf(buf, sizeof(buf), "%s %s\n",prefix,tmp ); int nr,nw; gchar *text = g_locale_to_utf8( buf, -1, &nr, &nw, NULL); gtk_text_buffer_insert( buffer, &iter, text, nw ); GtkTextIter enditer; gtk_text_buffer_get_end_iter(buffer, &enditer); gtk_text_view_scroll_to_iter( GTK_TEXT_VIEW(view), &enditer, 0.0, FALSE, 0.0, 0.0 ); g_free( text ); va_end(args); } static void msg_vims(char *message) { if(!info->client) return; vj_client_send(info->client, V_CMD, message); } int get_loop_value() { if( is_button_toggled( "loop_none" ) ) { return 0; } else { if( is_button_toggled( "loop_normal" )) return 1; else if( is_button_toggled( "loop_pingpong" )) return 2; } return 1; } static void multi_vims(int id, const char format[],...) { char block[1024]; char tmp[1024]; va_list args; if(!info->client) return; va_start(args, format); vsnprintf(tmp, sizeof(tmp)-1, format, args ); snprintf(block, sizeof(block)-1, "%03d:%s;",id,tmp); va_end(args); vj_client_send( info->client, V_CMD, block); } static void single_vims(int id) { char block[10]; if(!info->client) return; sprintf(block, "%03d:;",id); vj_client_send( info->client, V_CMD, block ); } static gchar *recv_vims(int slen, int *bytes_written) { int tmp_len = slen+1; gchar tmp[tmp_len]; bzero(tmp,tmp_len); int ret = vj_client_read( info->client, V_CMD, tmp, slen ); int len = 0; sscanf( tmp, "%d", &len ); gchar *result = NULL; if( len <= 0 || slen <= 0) { return result; } result = (gchar*) vj_malloc(sizeof(gchar) * (len + 1) ); bzero(result, (len+1)); int bytes_left = len; *bytes_written = 0; while( bytes_left > 0) { int n = vj_client_read( info->client, V_CMD, result + (*bytes_written), bytes_left ); if( n <= 0 ) { bytes_left = 0; } if( n > 0 ) { *bytes_written +=n; bytes_left -= n; } } return result; } static int recv_vims_binary(int slen, int *bytes_written, guchar *buf) { int tmp_len = slen+1; gchar tmp[tmp_len]; bzero(tmp,tmp_len); int ret = vj_client_read( info->client, V_CMD, tmp, slen ); // int len = atoi(tmp); int len = 0; sscanf( tmp, "%6d",&len); gchar *result = NULL; if( len <= 0 || slen == NULL) return 0; int bytes_to_recv = len; int bw = 0; *bytes_written = 0; guchar *ptr = buf; while( bw < len) { int n = vj_client_read( info->client, V_CMD, ptr, bytes_to_recv ); if( n <= 0 ) return 0; bw += n; bytes_to_recv -= n; ptr += bw; } *bytes_written = bw; return 1; } static gchar *recv_log_vims(int slen, int *bytes_written) { gchar tmp[slen+1]; bzero(tmp,slen+1); int ret = vj_client_read( info->client, V_MSG, tmp, slen ); int len = atoi(tmp); gchar *result = NULL; int n = 0; if(len > 0) { result = g_new( gchar, len+1 ); n = vj_client_read( info->client, V_MSG, result, len ); *bytes_written = n; result[len] = '\0'; } return result; } /* read playmode, parse tokens in status_tokens */ static gdouble get_numd(const char *name) { GtkWidget *w = glade_xml_get_widget_( info->main_window, name); if(!w) return 0; return (gdouble) gtk_spin_button_get_value( GTK_SPIN_BUTTON( w ) ); } static int get_slider_val(const char *name) { GtkWidget *w = glade_xml_get_widget_( info->main_window, name ); if(!w) return 0; return ((gint)GTK_ADJUSTMENT(GTK_RANGE(w)->adjustment)->value); } static void vj_kf_delete_parameter(int idx) { sample_slot_t *s = info->selected_slot; int i; for( i = 0;i < MAX_PARAMETERS; i ++ ) { key_parameter_t *key = s->ec->effects[idx]->parameters[i]; clear_parameter_values ( key ); } } static void vj_akf_delete() { sample_slot_t *s = info->selected_slot; if(!s) return; int i,j; for(i = 0; i < MAX_CHAIN_LEN; i ++) vj_kf_delete_parameter(i); } static void vj_kf_select_parameter(int num) { sample_slot_t *s = info->selected_slot; /* Parameter changed !*/ if( num < 0 ) /* Reset to default parameter */ info->uc.selected_parameter_id = 0; else info->uc.selected_parameter_id = num; // Effect chain parameter key key_parameter_t *key = s->ec->effects[(info->uc.selected_chain_entry)]->parameters[(info->uc.selected_parameter_id)]; GtkWidget *curve = glade_xml_get_widget_(info->main_window, "curve"); if(num >= 0) { update_curve_surroundings(); update_curve_widget("curve"); update_curve_accessibility("curve"); } char name[20]; sprintf(name, "P%d", info->uc.selected_parameter_id); update_label_str( "curve_parameter", name ); } void curve_len_changed( int len ) { sample_slot_t *s = info->selected_slot; if(!s) return 0; int i,j; GtkWidget *curve = glade_xml_get_widget_( info->main_window, "curve"); for( i = 0; i < MAX_CHAIN_LEN; i ++ ) { for( j = 0; j < MAX_PARAMETERS; j ++ ) { key_parameter_t *p = s->ec->effects[i]->parameters[j]; if(p->curve_len != len ) curve_timeline_preserve( p, len ); if( info->uc.selected_chain_entry == i ) { set_points_in_curve( p, curve ); } } } } static int interpolate_parameters(void) { sample_slot_t *s = info->selected_slot; if(!s || !s->ec) return 0; int i,j; int res = 0; GtkWidget *curve = glade_xml_get_widget_( info->main_window, "curve" ); /* If current effect chain is not enabled, return now */ if(!s->ec->enabled) return 0; char params[255]; bzero(params,255); /* Iterate chain for KF */ for( i = 0; i < MAX_CHAIN_LEN; i ++ ) { int values[MAX_PARAMETERS]; int skip = 1; int id = 0; char slider_name[20]; if(s->ec->effects[i]->enabled) { /* Get current values */ for( j = 0; j < MAX_PARAMETERS; j ++ ) { sprintf(slider_name, "slider_p%d", j ); values[j] = get_slider_val ( slider_name ); } /* Get keyframed values */ for( j = 0; j < MAX_PARAMETERS; j ++ ) { key_parameter_t *p = s->ec->effects[i]->parameters[j]; if( p->running == 1 && parameter_for_frame(p, info->status_frame) ) { int min,max; if(_effect_get_minmax( p->parameter_id, &min, &max, j )) { float scale = 0.0; if(get_parameter_key_value( p, info->status_frame, &scale ) ) { float min_value = (float)min; float max_value = (float)max; float max_range = fabs( min_value ) + fabs( max_value ); float value = scale * max_range; value += min_value; values[j] =(int) value; skip = 0; id = p->parameter_id; if(info->uc.selected_chain_entry == i ) { // Update slider values of current selected chain entry sprintf(slider_name, "slider_p%d", j ); update_slider_value( slider_name, values[j],0 ); } } } } } if(!skip) // Put KF to veejay { // sample, chain entry, effect_id, arg i .. arg n int np = _effect_get_np( id ); char token[10]; sprintf(params, "%03d:%d %d %d ", VIMS_CHAIN_ENTRY_SET_PRESET,s->sample_id,i,id ); int k; for(k = 0; k < np; k ++ ) { sprintf(token, "%d ", values[k] ); strncat( params, token, strlen(token)); } int len = strlen( params ); params[len-1] = ';'; params[len] = '\0'; msg_vims( params ); res ++; } } } return res; } static void update_curve_surroundings() { sample_slot_t *s = info->selected_slot; if(!s) return; int i = info->uc.selected_chain_entry; /* chain entry */ int j = info->uc.selected_parameter_id; if(!s->ec) return; key_parameter_t *key = s->ec->effects[i]->parameters[j]; if(!key) return; /* Restore AKF status */ set_toggle_button( "curve_toggleglobal", s->ec->enabled ); /* Restore AKF entry toggle */ set_toggle_button( "curve_toggleentry", s->ec->effects[i]->enabled ); /* Positions changed (sample/marker) */ int changed = 0; int old_len = key->curve_len; int nl = 0; if(info->status_tokens[PLAY_MODE] == MODE_SAMPLE ) { nl = info->status_tokens[SAMPLE_END] + 1; if(nl != old_len) { update_spin_range( "curve_spinstart", info->status_tokens[SAMPLE_START], info->status_tokens[SAMPLE_END], info->status_tokens[SAMPLE_START] ); update_spin_range( "curve_spinend", info->status_tokens[SAMPLE_START], info->status_tokens[SAMPLE_END] , info->status_tokens[SAMPLE_END] ); curve_len_changed( nl ); } } else { nl = get_nums("stream_length") + 1 ; if( nl != old_len ) { update_spin_range( "curve_spinstart", 0, nl-1, 0 ); update_spin_range( "curve_spinend", 0,nl-1, nl-1); curve_len_changed( nl ); } } // Set start/end timecodes /* gchar *start_time = format_time( key->start_pos ); gchar *end_time = format_time( key->end_pos ); update_label_str( "curve_starttime", start_time ); update_label_str( "curve_endtime", end_time ); g_free(start_time); g_free(end_time);*/ struct tog_w { const char *name; } tog_w[] = { {"curve_typelinear"}, {"curve_typespline"}, {"curve_typefreehand"}, {NULL } }; // Check me: on the fly redraw of curve ! if( key->type == GTK_CURVE_TYPE_LINEAR ) set_toggle_button( tog_w[0].name,1 ); else if(key->type == GTK_CURVE_TYPE_SPLINE ) set_toggle_button( tog_w[1].name ,1); else set_toggle_button( tog_w[2].name ,1); if(!key->vector) key->running = 0; if(!key->vector) disable_widget( "curve_togglerun"); else enable_widget( "curve_togglerun" ); set_toggle_button( "curve_togglerun" , key->running ); } static void update_curve_widget(const char *name) { GtkWidget *curve = glade_xml_get_widget_( info->main_window,name); sample_slot_t *s = info->selected_slot; if(!s || !s->ec) return; int i = info->uc.selected_chain_entry; /* chain entry */ int j = info->uc.selected_parameter_id; key_parameter_t *key = s->ec->effects[i]->parameters[j]; reset_curve(key,curve); set_points_in_curve( key, curve ); } static void update_curve_accessibility(const char *name) { GtkWidget *curve = glade_xml_get_widget_( info->main_window,name); sample_slot_t *s = info->selected_slot; if(!s) return; if( info->uc.entry_tokens[ENTRY_FXID] <= 0 || !info->selected_slot) { disable_widget( "curve_table" ); disable_widget( "curve" ); } else { if( info->status_tokens[PLAY_MODE] != MODE_PLAIN) { enable_widget( "curve_table" ); enable_widget( "curve" ); } } } static int get_nums(const char *name) { GtkWidget *w = glade_xml_get_widget_( info->main_window, name); if(!w) return 0; return (int) gtk_spin_button_get_value( GTK_SPIN_BUTTON( w ) ); } static int count_textview_buffer(const char *name) { GtkWidget *view = glade_xml_get_widget_( info->main_window, name ); if(view) { GtkTextBuffer *tb = NULL; tb = gtk_text_view_get_buffer( GTK_TEXT_VIEW(view) ); return gtk_text_buffer_get_char_count( tb ); } return 0; } static void clear_textview_buffer(const char *name) { GtkWidget *view = glade_xml_get_widget_( info->main_window, name ); if(view) { GtkTextBuffer *tb = NULL; tb = gtk_text_view_get_buffer( GTK_TEXT_VIEW(view) ); GtkTextIter iter1,iter2; gtk_text_buffer_get_start_iter( tb, &iter1 ); gtk_text_buffer_get_end_iter( tb, &iter2 ); gtk_text_buffer_delete( tb, &iter1, &iter2 ); } } static gchar *get_textview_buffer(const char *name) { GtkWidget *view = glade_xml_get_widget_( info->main_window,name ); if(view) { GtkTextBuffer *tb = NULL; tb = gtk_text_view_get_buffer( GTK_TEXT_VIEW(view) ); GtkTextIter iter1,iter2; gtk_text_buffer_get_start_iter(tb, &iter1); gtk_text_buffer_get_end_iter( tb, &iter2); gchar *res = gtk_text_buffer_get_text( tb, &iter1,&iter2 , TRUE ); return res; } return NULL; } static void set_textview_buffer(const char *name, gchar *utf8text) { GtkWidget *view = glade_xml_get_widget_( info->main_window, name ); if(view) { GtkTextBuffer *tb = gtk_text_view_get_buffer( GTK_TEXT_VIEW(view) ); gtk_text_buffer_set_text( tb, utf8text, -1 ); } } static gchar *get_text(const char *name) { GtkWidget *w = glade_xml_get_widget_(info->main_window, name ); if(!w) return NULL; return (gchar*) gtk_entry_get_text( GTK_ENTRY(w)); } static void put_text(const char *name, char *text) { GtkWidget *w = glade_xml_get_widget_(info->main_window, name ); if(w) { gchar *utf8_text = _utf8str( text ); gtk_entry_set_text( GTK_ENTRY(w), utf8_text ); g_free(utf8_text); } } static int is_button_toggled(const char *name) { GtkWidget *w = glade_xml_get_widget_( info->main_window, name); if(!w) return 0; if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(w) ) == TRUE ) return 1; return 0; } static void set_toggle_button(const char *name, int status) { GtkWidget *w = glade_xml_get_widget_(info->main_window, name ); if(w) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), (status==1 ? TRUE: FALSE)); } } static void update_slider_gvalue(const char *name, gdouble value) { GtkWidget *w = glade_xml_get_widget_( info->main_window, name ); if(!w) return; gtk_adjustment_set_value( GTK_ADJUSTMENT(GTK_RANGE(w)->adjustment), value ); } static void update_slider_value(const char *name, gint value, gint scale) { GtkWidget *w = glade_xml_get_widget_( info->main_window, name ); if(!w) return; gdouble gvalue; if(scale) { GtkAdjustment *adj = GTK_ADJUSTMENT(GTK_RANGE(w)->adjustment ); gvalue = (gdouble) value / (gdouble) scale; } else gvalue = (gdouble) value; gtk_adjustment_set_value( GTK_ADJUSTMENT(GTK_RANGE(w)->adjustment), gvalue ); } static void update_knob_value(GtkWidget *w, gdouble value, gdouble scale) { GtkAdjustment *adj = gtk_knob_get_adjustment(w); gdouble gvalue; if(scale) gvalue = (gdouble) value / (gdouble) scale; else gvalue = (gdouble) value; gtk_adjustment_set_value(adj, gvalue ); } static void update_knob_range(GtkWidget *w, gdouble min, gdouble max, gdouble value, gint scaled) { GtkAdjustment *adj = gtk_knob_get_adjustment(w); if(!scaled) { adj->lower = min; adj->upper = max; adj->value = value; } else { gdouble gmin =0.0; gdouble gmax =100.0; gdouble gval = gmax / value; adj->lower = gmin; adj->upper = gmax; adj->value = gval; } } static void update_spin_incr( const char *name, gdouble step, gdouble page ) { GtkWidget *w = glade_xml_get_widget_( info->main_window, name ); if(!w) return; gtk_spin_button_set_increments(GTK_SPIN_BUTTON(w),step,page ); } static void update_spin_range(const char *name, gint min, gint max, gint val) { GtkWidget *w = glade_xml_get_widget_( info->main_window, name ); if(!w) return; gtk_spin_button_set_range( GTK_SPIN_BUTTON(w), (gdouble)min, (gdouble) max ); gtk_spin_button_set_value( GTK_SPIN_BUTTON(w), (gdouble)val); } static int get_mins(const char *name) { GtkWidget *w = glade_xml_get_widget_( info->main_window, name ); if(!w) return 0; GtkAdjustment *adj = gtk_spin_button_get_adjustment( GTK_SPIN_BUTTON(w) ); return (int) adj->lower; } static int get_maxs(const char *name) { GtkWidget *w = glade_xml_get_widget_( info->main_window, name ); if(!w) return 0; GtkAdjustment *adj = gtk_spin_button_get_adjustment( GTK_SPIN_BUTTON(w) ); return (int) adj->upper; } static void update_spin_value(const char *name, gint value ) { GtkWidget *w = glade_xml_get_widget_(info->main_window, name ); if(w) { gtk_spin_button_set_value( GTK_SPIN_BUTTON(w), (gdouble) value ); } } static void update_slider_range(const char *name, gint min, gint max, gint value, gint scaled) { GtkWidget *w = glade_xml_get_widget_( info->main_window, name ); GtkRange *range = GTK_RANGE(w); if(!w) return; if(!scaled) { gtk_range_set_range(range, (gdouble) min, (gdouble) max ); gtk_range_set_value(range, value ); } else { gdouble gmin =0.0; gdouble gmax =100.0; gdouble gval = gmax / value; gtk_range_set_range(range, gmin, gmax); gtk_range_set_value(range, gval ); } gtk_range_set_adjustment(range, GTK_ADJUSTMENT(GTK_RANGE(w)->adjustment ) ); } static void update_label_i(const char *name, int num, int prefix) { GtkWidget *label = glade_xml_get_widget_( info->main_window, name); if(!label) return; char str[20]; if(prefix) g_snprintf( str,20, "%011d", num ); else g_snprintf( str,20, "%d", num ); gchar *utf8_value = _utf8str( str ); gtk_label_set_text( GTK_LABEL(label), utf8_value); g_free( utf8_value ); } static void update_label_f(const char *name, float val ) { GtkWidget *label = glade_xml_get_widget_( info->main_window, name); if(!label) return; char value[10]; snprintf( value, sizeof(value)-1, "%2.2f", val ); gchar *utf8_value = _utf8str( value ); gtk_label_set_text( GTK_LABEL(label), utf8_value ); g_free(utf8_value); } static void update_label_str(const char *name, gchar *text) { GtkWidget *label = glade_xml_get_widget_( info->main_window, name); if(!label) return; gchar *utf8_text = _utf8str( text ); gtk_label_set_text( GTK_LABEL(label), utf8_text); g_free(utf8_text); } static void selection_get_paths(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data) { GSList **paths = data; *paths = g_slist_prepend(*paths, gtk_tree_path_copy(path)); } GSList *gui_tree_selection_get_paths(GtkTreeView *view) { GtkTreeSelection *sel; GSList *paths; /* get paths of selected rows */ paths = NULL; sel = gtk_tree_view_get_selection(view); gtk_tree_selection_selected_foreach(sel, selection_get_paths, &paths); return paths; } static void update_colorselection() { GtkWidget *colorsel = glade_xml_get_widget_( info->main_window, "colorselection"); GdkColor color; color.red = 255 * info->status_tokens[STREAM_COL_R]; color.green = 255 * info->status_tokens[STREAM_COL_G]; color.blue = 255 * info->status_tokens[STREAM_COL_B]; gtk_color_selection_set_current_color( GTK_COLOR_SELECTION( colorsel ), &color ); } int resize_primary_ratio_y() { float ratio = (float)info->el.width / (float)info->el.height; float result = (float) get_nums( "priout_width" ) / ratio; return (int) result; } int resize_primary_ratio_x() { float ratio = (float)info->el.height / (float)info->el.width; float result = (float) get_nums( "priout_height" ) / ratio; return (int) result; } static void update_rgbkey() { if(!info->entry_lock) { info->entry_lock =1; GtkWidget *colorsel = glade_xml_get_widget_( info->main_window, "rgbkey"); GdkColor color; /* update from entry tokens (delivered by GET_CHAIN_ENTRY */ int *p = &(info->uc.entry_tokens[0]); /* 0 = effect_id, 1 = has second input, 2 = num parameters, 3 = p0 , 4 = p1, 5 = p2, 6 = p3 ... */ color.red = 255 * p[3]; color.green = 255 * p[4]; color.blue = 255 * p[5]; gtk_color_selection_set_current_color( GTK_COLOR_SELECTION( colorsel ), &color ); info->entry_lock = 0; } } static void update_rgbkey_from_slider() { if(!info->entry_lock) { GtkWidget *colorsel = glade_xml_get_widget_( info->main_window, "rgbkey"); info->entry_lock = 1; GdkColor color; color.red = 255 * ( get_slider_val( "slider_p1" ) ); color.green = 255 * ( get_slider_val( "slider_p2" ) ); color.blue = 255 * ( get_slider_val( "slider_p3" ) ); gtk_color_selection_set_current_color( GTK_COLOR_SELECTION( colorsel ), &color ); info->entry_lock = 0; } } static void v4l_expander_toggle(int mode) { // we can set the expanded of the ABC expander GtkWidget *exp = glade_xml_get_widget_( info->main_window, "v4l_expander"); GtkExpander *e = GTK_EXPANDER(exp); gtk_expander_set_expanded( e ,(mode==0 ? FALSE : TRUE) ); } static GdkPixbuf *update_pixmap_kf( int status ) { char path[MAX_PATH_LEN]; char filename[MAX_PATH_LEN]; bzero(path,MAX_PATH_LEN); sprintf(filename, "fx_entry_%s.png", ( status == 1 ? "on" : "off" )); get_gd(path,NULL, filename); GError *error = NULL; GdkPixbuf *toggle = gdk_pixbuf_new_from_file( path , &error); if(error) return NULL; return toggle; } static GdkPixbuf *update_pixmap_entry( int status ) { char path[MAX_PATH_LEN]; char filename[MAX_PATH_LEN]; bzero(path,MAX_PATH_LEN); sprintf(filename, "fx_entry_%s.png", ( status == 1 ? "on" : "off" )); get_gd(path,NULL, filename); GError *error = NULL; GdkPixbuf *icon = gdk_pixbuf_new_from_file(path, &error); if(error) return 0; return icon; } static gboolean chain_update_row(GtkTreeModel * model, GtkTreePath * path, GtkTreeIter * iter, gpointer data) { vj_gui_t *gui = (vj_gui_t*) data; int entry = info->uc.selected_chain_entry; int effect_id = gui->uc.entry_tokens[ ENTRY_FXID ]; gint gentry = 0; gtk_tree_model_get (model, iter, FXC_ID, &gentry, -1); if(gentry == entry) { int effect_id = gui->uc.entry_tokens[ ENTRY_FXID ]; if( effect_id <= 0 ) { gtk_list_store_set( GTK_LIST_STORE(model),iter, FXC_ID, entry, -1 ); } else { gchar *descr = _utf8str( _effect_get_description( effect_id )); sample_slot_t *s = info->selected_slot; int on = s->ec->effects[entry]->enabled; GdkPixbuf *toggle = update_pixmap_entry( gui->uc.entry_tokens[ENTRY_FXSTATUS] ); GdkPixbuf *kf_toggle = update_pixmap_kf( on ); gtk_list_store_set( GTK_LIST_STORE(model),iter, FXC_ID, entry, FXC_FXID, descr, FXC_FXSTATUS, toggle, FXC_KF, kf_toggle, -1 ); g_free(descr); g_object_unref( kf_toggle ); g_object_unref( toggle ); } } return FALSE; } static void update_status_accessibility(int pm) { int i; if( pm != info->prev_mode ) { /* If mode changed, enable/disable widgets etc first */ if( info->status_tokens[PLAY_MODE] != info->prev_mode ) { if( pm == MODE_STREAM ) { enable_widget("frame_streamproperties"); enable_widget("frame_streamrecord"); disable_widget("frame_samplerecord"); disable_widget("frame_sampleproperties"); for(i=0; videowidgets[i].name != NULL; i++) disable_widget( videowidgets[i].name); //disable_widget_by_pointer(info->audio_knob); disable_widget( "speed_slider" ); } else { for(i=0; videowidgets[i].name != NULL; i++) enable_widget( videowidgets[i].name); //enable_widget_by_pointer(info->speed_knob); enable_widget( "speed_slider" ); } if( pm == MODE_SAMPLE ) { enable_widget("frame132"); enable_widget("frame_samplerecord"); enable_widget("frame_sampleproperties"); disable_widget("frame_streamproperties"); disable_widget("frame_streamrecord"); enable_widget( "samplerand" ); enable_widget( "freestyle" ); } else { disable_widget( "frame132"); disable_widget( "samplerand" ); disable_widget( "freestyle" ); } if( pm == MODE_PLAIN) { enable_widget( "button_samplestart" ); enable_widget( "button_sampleend" ); } else { disable_widget( "button_samplestart"); disable_widget( "button_sampleend" ); } if( pm == MODE_PLAIN) for( i = 0; plainwidgets[i].name != NULL ;i++ ) disable_widget( plainwidgets[i].name ); else for( i = 0; plainwidgets[i].name != NULL ; i ++ ) enable_widget( plainwidgets[i].name ); } } } /* Cut from global_info() This function updates the sample/stream editor if the current playing stream/sample matches with the selected sample slot */ static void update_record_tab(int pm) { if(pm == MODE_STREAM) { update_spin_value( "spin_streamduration" , 1 ); gint n_frames = get_nums( "spin_streamduration" ); gchar *time = format_time(n_frames); update_label_str( "label_streamrecord_duration", time ); g_free(time); } if(pm == MODE_SAMPLE) { update_spin_value( "spin_sampleduration", 1 ); // combo_samplecodec gint n_frames = sample_calctime(); gchar *time = format_time( n_frames ); update_label_str( "label_samplerecord_duration", time ); g_free(time); } } static void update_current_slot(int pm) { // gchar *time = format_time( (pm == MODE_STREAM ? info->status_frame : info->status_tokens[FRAME_NUM]) ); int *history = info->history_tokens[pm]; // update_label_str( "label_sampleposition", time); // g_free(time); gint update = 0; /* Mode changed or ID changed, Reload FX Chain, Reload current entry and disable widgets based on stream type */ if( pm != info->prev_mode || info->status_tokens[PLAY_MODE] != history[PLAY_MODE] || info->status_tokens[CURRENT_ID] != history[CURRENT_ID] ) { int k; info->uc.reload_hint[HINT_ENTRY] = 1; info->uc.reload_hint[HINT_CHAIN] = 1; info->uc.reload_hint[HINT_KF] = 1; update = 1; update_record_tab( pm ); if( info->status_tokens[STREAM_TYPE] == STREAM_WHITE ) { enable_widget( "colorselection" ); } else { disable_widget( "colorselection" ); } if( info->status_tokens[STREAM_TYPE] == STREAM_VIDEO4LINUX ) { info->uc.reload_hint[HINT_V4L] = 1; for(k = 0; k < 5; k ++ ) enable_widget( capt_card_set[k].name ); v4l_expander_toggle(1); } else { /* not v4l, disable capt card */ for(k = 0; k < 5; k ++ ) disable_widget( capt_card_set[k].name ); v4l_expander_toggle(0); } } if( info->status_tokens[CURRENT_ENTRY] != history[CURRENT_ENTRY] || info->uc.reload_hint[HINT_ENTRY] == 1 ) { info->uc.selected_chain_entry = info->status_tokens[CURRENT_ENTRY]; info->uc.reload_hint[HINT_ENTRY] = 1; load_parameter_info(); info->uc.reload_hint[HINT_KF] = 1; } /* Actions for stream */ if( pm == MODE_STREAM ) { // pop up stream notepad /* Is a solid color stream */ if( info->status_tokens[STREAM_TYPE] == STREAM_WHITE ) { if( ( history[STREAM_COL_R] != info->status_tokens[STREAM_COL_R] ) || ( history[STREAM_COL_G] != info->status_tokens[STREAM_COL_G] ) || ( history[STREAM_COL_B] != info->status_tokens[STREAM_COL_B] ) ) { info->uc.reload_hint[HINT_RGBSOLID] = 1; } } update_label_str( "label_currentsource", "Stream" ); gchar *time = format_time( info->status_frame ); update_label_str( "label_curtime", time ); g_free(time); } int marker_go = 0; /* Actions for sample */ if(pm == MODE_SAMPLE ) { /* Total frame change, update start,end and */ // if( history[TOTAL_FRAMES] != info->status_tokens[TOTAL_FRAMES]) // { //HERE //printf("Start / end changed: %d - %d\n", 0 , info->el.num_frames ); //printf("Current = %d - %d\n", info->status_tokens[SAMPLE_START], info->status_tokens[SAMPLE_END]); // } /* Update label and video slider*/ update_label_i( "label_sampleposition", info->status_tokens[FRAME_NUM] - info->status_tokens[SAMPLE_START] , 1); int tf = info->status_tokens[TOTAL_FRAMES]; int marker_go = 0; /* Update marker bounds */ if( (history[SAMPLE_MARKER_START] != info->status_tokens[SAMPLE_MARKER_START]) ) { gint nm = info->status_tokens[SAMPLE_MARKER_START]; if(nm >= 0) { gdouble in = (1.0 / (gdouble)info->status_tokens[TOTAL_FRAMES]) * nm; timeline_set_in_point( info->tl, in ); marker_go = 1; } else { if(pm == MODE_SAMPLE) { timeline_set_in_point( info->tl, 0.0 ); marker_go = 1; } } gchar *dur = format_time( info->status_tokens[SAMPLE_MARKER_END] - info->status_tokens[SAMPLE_MARKER_START] ); update_label_str( "label_markerduration", dur ); g_free(dur); } if( (history[SAMPLE_MARKER_END] != info->status_tokens[SAMPLE_MARKER_END]) ) { gint nm = info->status_tokens[SAMPLE_MARKER_END]; if(nm > 0 ) { gdouble out = (1.0/ (gdouble)info->status_tokens[TOTAL_FRAMES]) * nm; timeline_set_out_point( info->tl, out ); marker_go = 1; } else { if(pm == MODE_SAMPLE) { timeline_set_out_point(info->tl, 1.0 ); marker_go = 1; } } } if( (history[SAMPLE_START] != info->status_tokens[SAMPLE_START] )) { update_spin_value( "spin_samplestart", info->status_tokens[SAMPLE_START] ); update = 1; } if( (history[SAMPLE_END] != info->status_tokens[SAMPLE_END] )) { update_spin_value( "spin_sampleend", info->status_tokens[SAMPLE_END]); update = 1; } if( marker_go ) { info->uc.reload_hint[HINT_MARKER] = 1; } if( history[SAMPLE_LOOP] != info->status_tokens[SAMPLE_LOOP]) { switch( info->status_tokens[SAMPLE_LOOP] ) { case 0: set_toggle_button( "loop_none", 1 ); break; case 1: set_toggle_button( "loop_normal", 1 ); break; case 2: set_toggle_button("loop_pingpong", 1 ); break; } } gint speed = 0; if( history[SAMPLE_SPEED] != info->status_tokens[SAMPLE_SPEED] && !update) { speed = info->status_tokens[SAMPLE_SPEED]; update_slider_value( "speed_slider", speed, 0 ); update_label_i( "speed_label", speed,0 ); if( speed < 0 ) info->play_direction = -1; else info->play_direction = 1; if( speed < 0 ) speed *= -1; update_spin_value( "spin_samplespeed", speed); // update_knob_value(info->speed_knob, speed, 0); } if(update) { speed = info->status_tokens[SAMPLE_SPEED]; if(speed < 0 ) info->play_direction = -1; else info->play_direction = 1; gint len = info->status_tokens[SAMPLE_END] - info->status_tokens[SAMPLE_START]; int speed = info->status_tokens[SAMPLE_SPEED]; if(speed < 0 ) info->play_direction = -1; else info->play_direction = 1; if(speed < 0 ) speed *= -1; update_spin_range( "spin_samplespeed", 0, len, speed ); gchar *time = format_selection_time( 0, len ); // update_label_str( "label_samplelength", time ); g_free(time); update_label_str( "label_currentsource", "Sample"); update_spin_value( "spin_samplestart", info->status_tokens[SAMPLE_START]); update_spin_value( "spin_sampleend", info->status_tokens[SAMPLE_END]); info->uc.reload_hint[HINT_HISTORY] = 1; gint n_frames = sample_calctime(); time = format_time( n_frames ); } } } static void update_globalinfo() { int pm = info->status_tokens[PLAY_MODE]; int *history = info->history_tokens[pm]; int stream_changed = 0; gint i; info->uc.playmode = pm; if(info->prev_mode != pm ) memset( history , 0 , sizeof(int) * STATUS_TOKENS ); update_status_accessibility(pm); if( info->status_tokens[CURRENT_ID] != history[CURRENT_ID] || info->status_tokens[PLAY_MODE] != history[PLAY_MODE] ) { if( pm == MODE_SAMPLE || pm == MODE_STREAM ) { info->uc.reload_hint[HINT_ENTRY] = 1; info->uc.reload_hint[HINT_CHAIN] = 1; } if( pm != MODE_STREAM ) info->uc.reload_hint[HINT_EL] = 1; if( pm != MODE_PLAIN ) info->uc.reload_hint[HINT_KF] = 1; if( pm == MODE_SAMPLE ) timeline_set_selection( info->tl, TRUE ); else timeline_set_selection( info->tl, FALSE ); on_samplepage_clicked(NULL,NULL); } if( info->status_tokens[TOTAL_SLOTS] != history[TOTAL_SLOTS] || info->status_tokens[TOTAL_SLOTS] != info->uc.expected_slots ) { info->uc.reload_hint[HINT_SLIST] = 1; } gint total_frames_ = (pm == MODE_STREAM ? info->status_tokens[SAMPLE_MARKER_END] : info->status_tokens[TOTAL_FRAMES] ); gint history_frames_ = (pm == MODE_STREAM ? history[SAMPLE_MARKER_END] : history[TOTAL_FRAMES] ); gint current_frame_ = (pm == MODE_STREAM ? info->status_frame : info->status_tokens[FRAME_NUM] ); if( total_frames_ != history_frames_ ) { gchar *time = format_time( total_frames_ ); if( pm == MODE_STREAM ) { update_spin_value( "stream_length", info->status_tokens[SAMPLE_MARKER_END] ); update_label_str( "stream_length_label", time ); } update_spin_range("button_fadedur", 0, total_frames_, 0 ); update_label_i( "label_totframes", total_frames_, 1 ); if( pm == MODE_PLAIN ) { for( i = 0; i < 3; i ++) if(info->selection[i] > total_frames_ ) info->selection[i] = total_frames_; update_spin_range( "button_el_selstart", 0, total_frames_, info->selection[0]); update_spin_range( "button_el_selend", 0, total_frames_, info->selection[1]); update_spin_range( "button_el_selpaste", 0, total_frames_, info->selection[2]); } update_label_i( "label_totframes", total_frames_, 1 ); update_label_str( "label_totaltime", time ); if(pm == MODE_SAMPLE) update_label_str( "label_samplelength", time ); else update_label_str( "label_samplelength", "0:00:00:00" ); timeline_set_length( info->tl, (gdouble) total_frames_ , current_frame_); vj_kf_select_parameter( info->uc.selected_parameter_id ); g_free(time); } if( pm == MODE_STREAM ) { info->status_frame ++; if(info->status_frame > info->status_tokens[ SAMPLE_MARKER_END ]) info->status_frame = 0; } else info->status_frame = info->status_tokens[FRAME_NUM]; timeline_set_pos( info->tl, (gdouble) info->status_frame ); gchar *current_time_ = format_time( info->status_frame ); update_label_i( "label_curframe", info->status_frame ,1 ); update_label_str( "label_curtime", current_time_ ); g_free(current_time_); if( pm == MODE_SAMPLE ) update_label_i( "label_samplepos", info->status_frame , 1); else update_label_i( "label_samplepos" , 0 , 1 ); if( history[CURRENT_ID] != info->status_tokens[CURRENT_ID] ) { if(pm == MODE_SAMPLE || pm == MODE_STREAM) update_label_i( "label_currentid", info->status_tokens[CURRENT_ID] ,0); } if( history[STREAM_RECORDING] != info->status_tokens[STREAM_RECORDING] ) { if(pm == MODE_SAMPLE || pm == MODE_STREAM) { if( history[CURRENT_ID] == info->status_tokens[CURRENT_ID] ) info->uc.reload_hint[HINT_RECORDING] = 1; if( info->status_tokens[STREAM_RECORDING]) vj_msg(VEEJAY_MSG_INFO, "Veejay is recording"); else vj_msg(VEEJAY_MSG_INFO, "Recording has stopped"); } } if( pm == MODE_PLAIN ) { if( history[SAMPLE_SPEED] != info->status_tokens[SAMPLE_SPEED] ) { int plainspeed = info->status_tokens[SAMPLE_SPEED]; update_slider_value( "speed_slider", plainspeed, 0); // update_knob_value( info->speed_knob, plainspeed, 0 ); update_label_i( "speed_label", plainspeed, 0 ); if( plainspeed < 0 ) info->play_direction = -1; else info->play_direction = 1; if( plainspeed < 0 ) plainspeed *= -1; } } /* if( (pm == MODE_SAMPLE || pm == MODE_STREAM ) ) { int upd = 0; if(info->selected_slot) { if( info->selected_slot->sample_id != info->status_tokens[CURRENT_ID] || info->selected_slot->sample_type != pm ) { set_activation_of_slot_in_samplebank(false); info->selected_slot = NULL; } } if(!info->selected_slot ) upd = 1; else if( info->selected_slot->sample_id != info->status_tokens[CURRENT_ID] || info->selected_slot->sample_type != pm ) { set_activation_of_slot_in_samplebank(false); } if(!info->selected_slot) } */ /* Update current playing sample in dialog window */ update_current_slot(pm); } static void process_reload_hints(void) { int pm = info->status_tokens[PLAY_MODE]; int *history = info->history_tokens[pm]; int *entry_tokens = &(info->uc.entry_tokens[0]); if(info->uc.reload_hint[HINT_V4L] == 1 && pm == MODE_STREAM) { load_v4l_info(); } if( info->uc.reload_hint[HINT_RGBSOLID] == 1 && pm == MODE_STREAM ) update_colorselection(); if( info->uc.reload_hint[HINT_EL] == 1 ) { load_editlist_info(); reload_editlist_contents(); update_spin_range( "spin_samplestart", 0, info->el.num_frames, info->status_tokens[SAMPLE_START] ); update_spin_range( "spin_sampleend", 0, info->el.num_frames , info->status_tokens[SAMPLE_END] ); } if( info->uc.reload_hint[HINT_SLIST] == 1 ) { load_samplelist_info(true); info->uc.expected_slots = info->status_tokens[TOTAL_SLOTS]; } if( info->uc.reload_hint[HINT_RECORDING] == 1 && pm != MODE_PLAIN) { if(info->status_tokens[STREAM_RECORDING]) { if(!info->uc.recording[pm]) init_recorder( info->status_tokens[STREAM_DURATION], pm ); } } if(info->uc.reload_hint[HINT_BUNDLES] == 1 ) reload_bundles(); if( info->selected_slot && info->selected_slot->sample_id == info->status_tokens[CURRENT_ID] && info->selected_slot->sample_type == 0 && pm == MODE_PLAIN) { if( history[SAMPLE_FX] != info->status_tokens[SAMPLE_FX]) { //also for stream (index is equivalent) if(pm == MODE_SAMPLE) set_toggle_button( "check_samplefx", info->status_tokens[SAMPLE_FX]); if(pm == MODE_STREAM) set_toggle_button( "check_streamfx", info->status_tokens[SAMPLE_FX]); } } if( info->uc.reload_hint[HINT_CHAIN] == 1 && pm != MODE_PLAIN) { load_effectchain_info(); } if(info->uc.reload_hint[HINT_ENTRY] == 1 && pm != MODE_PLAIN) { char slider_name[10]; char button_name[10]; gint np = 0; gint i; /* update effect description */ info->uc.reload_hint[HINT_KF] = 1; if( entry_tokens[ENTRY_FXID] == 0) { put_text( "entry_effectname" ,"" ); disable_widget( "FXframe" ); } else { put_text( "entry_effectname", _effect_get_description( entry_tokens[ENTRY_FXID] )); enable_widget( "FXframe"); set_toggle_button( "button_entry_toggle", entry_tokens[ENTRY_FXSTATUS] ); np = _effect_get_np( entry_tokens[ENTRY_FXID] ); for( i = 0; i < np ; i ++ ) { sprintf(slider_name, "slider_p%d",i); enable_widget( slider_name ); sprintf(button_name, "inc_p%d", i); enable_widget( button_name ); sprintf(button_name, "dec_p%d", i ); enable_widget( button_name ); gint min,max,value; value = entry_tokens[3 + i]; if( _effect_get_minmax( entry_tokens[ENTRY_FXID], &min,&max, i )) { update_slider_range( slider_name,min,max, value, 0); } sprintf(button_name, "kf_p%d", i ); enable_widget( button_name ); } } update_spin_value( "button_fx_entry", info->uc.selected_chain_entry); for( i = np; i < 8 ; i ++ ) { sprintf(slider_name, "slider_p%d",i); gint min = 0, max = 1, value = 0; update_slider_range( slider_name, min,max, value, 0 ); disable_widget( slider_name ); sprintf( button_name, "inc_p%d", i); disable_widget( button_name ); sprintf( button_name, "dec_p%d", i); disable_widget( button_name ); sprintf( button_name, "kf_p%d", i ); disable_widget( button_name ); } GtkTreeModel *model = gtk_tree_view_get_model( GTK_TREE_VIEW(glade_xml_get_widget_( info->main_window, "tree_chain") )); gtk_tree_model_foreach( model, chain_update_row, (gpointer*) info ); } /* Curve needs update (start/end changed, effect id changed */ if ( info->uc.reload_hint[HINT_KF] ) vj_kf_select_parameter( info->uc.selected_parameter_id ); memset( info->uc.reload_hint, 0, sizeof(info->uc.reload_hint )); } static void reset_tree(const char *name) { GtkWidget *tree_widget = glade_xml_get_widget_( info->main_window,name ); GtkTreeModel *tree_model = gtk_tree_view_get_model( GTK_TREE_VIEW(tree_widget) ); // get a GList of all TreeViewColumns /* GList *columns =gtk_tree_view_get_columns(GTK_TREE_VIEW( tree_widget ) ); while( columns != NULL ) { GList *renderers; // get single column column = GTK_TREE_VIEW_COLUMN( columns->data ); */ /* renderers = gtk_tree_view_column_get_cell_renderers( GTK_TREE_VIEW_COLUMN(column) ); while( renderers != NULL) { GtkCellRenderer *cell = GTK_CELL_RENDERER( renderers->data ); gtk_tree_view_column_clear_attributes( GTK_TREE_VIEW_COLUMN(column ), GTK_CELL_RENDERER( cell ) ); renderers = renderers->next; } g_list_free(renderers); */ /* gtk_tree_view_column_clear( column ); columns = columns->next; } g_list_free(columns); */ gtk_list_store_clear( GTK_LIST_STORE( tree_model ) ); // gtk_tree_view_set_model( GTK_TREE_VIEW(tree_widget), GTK_TREE_MODEL(tree_model)); } // load effect controls gboolean view_entry_selection_func (GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath *path, gboolean path_currently_selected, gpointer userdata) { GtkTreeIter iter; if (gtk_tree_model_get_iter(model, &iter, path)) { gint name = 0; gtk_tree_model_get(model, &iter, FXC_ID, &name, -1); if (!path_currently_selected && name != info->uc.selected_chain_entry) { multi_vims( VIMS_CHAIN_SET_ENTRY, "%d", name ); } } return TRUE; /* allow selection state to change */ } gboolean view_sources_selection_func (GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath *path, gboolean path_currently_selected, gpointer userdata) { GtkTreeIter iter; if (gtk_tree_model_get_iter(model, &iter, path)) { gchar *name = NULL; gtk_tree_model_get(model, &iter, FXC_ID, &name, -1); if (!path_currently_selected) { gint id = 0; sscanf(name+1, "%d", &id); if(name[0] == 'S') { info->uc.selected_mix_sample_id = id; info->uc.selected_mix_stream_id = 0; } else { info->uc.selected_mix_sample_id = 0; info->uc.selected_mix_stream_id = id; } } if(name) g_free(name); } return TRUE; /* allow selection state to change */ } static void cell_data_func_dev (GtkTreeViewColumn *col, GtkCellRenderer *cell, GtkTreeModel *model, GtkTreeIter *iter, gpointer data) { gchar buf[32]; GValue val = {0, }; gint id = 0; gtk_tree_model_get_value(model, iter, V4L_SPINBOX, &val); gtk_tree_model_get(model, iter, V4L_NUM, &id,-1 ); info->uc.strtmpl[0].channel = (gint) g_value_get_float(&val); info->uc.strtmpl[0].dev = id; g_snprintf(buf, sizeof(buf), "%.0f",g_value_get_float(&val)); g_object_set(cell, "text", buf, NULL); } static void on_dev_edited (GtkCellRendererText *celltext, const gchar *string_path, const gchar *new_text, gpointer data) { GtkTreeModel *model = GTK_TREE_MODEL(data); GtkTreeIter iter; gfloat oldval = 0.0; gfloat newval = 0.0; gtk_tree_model_get_iter_from_string(model, &iter, string_path); gtk_tree_model_get(model, &iter, V4L_SPINBOX, &oldval, -1); if (sscanf(new_text, "%f", &newval) != 1) g_warning("in %s: problem converting string '%s' into float.\n", __FUNCTION__, new_text); gtk_list_store_set(GTK_LIST_STORE(model), &iter, V4L_SPINBOX, newval, -1); } static void setup_tree_spin_column( const char *tree_name, int type, const char *title) { GtkWidget *tree = glade_xml_get_widget_( info->main_window, tree_name ); GtkCellRenderer *renderer; GtkTreeViewColumn *column; renderer = gui_cell_renderer_spin_new(0.0, 3.0 , 1.0, 1.0, 1.0, 1.0, 0.0); column = gtk_tree_view_column_new(); gtk_tree_view_column_set_title(column, title ); gtk_tree_view_column_pack_start(column, renderer, TRUE); gtk_tree_view_column_set_cell_data_func( column, renderer, cell_data_func_dev, NULL,NULL ); gtk_tree_view_append_column( GTK_TREE_VIEW(tree), column); g_object_set(renderer, "editable", TRUE, NULL); GtkTreeModel *model = gtk_tree_view_get_model( GTK_TREE_VIEW(tree )); g_signal_connect(renderer, "edited", G_CALLBACK(on_dev_edited), model ); } static void setup_tree_texteditable_column( const char *tree_name, int type, const char *title, void (*callbackfunction)() ) { GtkWidget *tree = glade_xml_get_widget_( info->main_window, tree_name ); GtkCellRenderer *renderer; GtkTreeViewColumn *column; renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes( title, renderer, "text", type, NULL ); gtk_tree_view_append_column( GTK_TREE_VIEW( tree ), column ); g_object_set(renderer, "editable", TRUE, NULL ); GtkTreeModel *model = gtk_tree_view_get_model( GTK_TREE_VIEW(tree )); g_signal_connect( renderer, "edited", G_CALLBACK( callbackfunction ), model ); } static void setup_tree_text_column( const char *tree_name, int type, const char *title ) { GtkWidget *tree = glade_xml_get_widget_( info->main_window, tree_name ); GtkCellRenderer *renderer; GtkTreeViewColumn *column; renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes( title, renderer, "text", type, NULL ); gtk_tree_view_append_column( GTK_TREE_VIEW( tree ), column ); } static void setup_tree_pixmap_column( const char *tree_name, int type, const char *title ) { GtkWidget *tree = glade_xml_get_widget_( info->main_window, tree_name ); GtkCellRenderer *renderer; GtkTreeViewColumn *column; renderer = gtk_cell_renderer_pixbuf_new(); column = gtk_tree_view_column_new_with_attributes( title, renderer, "pixbuf", type, NULL ); gtk_tree_view_append_column( GTK_TREE_VIEW( tree ), column ); } static void setup_effectchain_info( void ) { GtkWidget *tree = glade_xml_get_widget_( info->main_window, "tree_chain"); GtkListStore *store = gtk_list_store_new( 4, G_TYPE_INT, G_TYPE_STRING, GDK_TYPE_PIXBUF,GDK_TYPE_PIXBUF ); gtk_tree_view_set_model( GTK_TREE_VIEW(tree), GTK_TREE_MODEL(store)); g_object_unref( G_OBJECT( store )); setup_tree_text_column( "tree_chain", FXC_ID, "Entry" ); setup_tree_text_column( "tree_chain", FXC_FXID, "Effect" ); setup_tree_pixmap_column( "tree_chain", FXC_FXSTATUS, "Status"); // todo: could be checkbox!! setup_tree_pixmap_column( "tree_chain", FXC_KF , "KF" ); // parameter interpolation on/off per entry GtkTreeSelection *selection; tree = glade_xml_get_widget_( info->main_window, "tree_chain"); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree)); gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE); gtk_tree_selection_set_select_function(selection, view_entry_selection_func, NULL, NULL); } static void load_v4l_info() { int values[5]; int len = 0; multi_vims( VIMS_STREAM_GET_V4L, "%d", (info->selected_slot == NULL ? 0 : info->selected_slot->sample_id )); gchar *answer = recv_vims(3, &len); if(len > 0 ) { int res = sscanf( answer, "%05d%05d%05d%05d%05d", &values[0],&values[1],&values[2],&values[3],&values[4]); if(res == 5) { int i; for(i = 0; i < 5; i ++ ) { update_slider_gvalue( capt_card_set[i].name, (gdouble)values[i]/65535.0 ); } } g_free(answer); } } static gint load_parameter_info() { int *st = &(info->uc.entry_tokens[0]); int len = 0; int p[16]; int i; multi_vims( VIMS_CHAIN_GET_ENTRY, "%d %d", 0, info->uc.selected_chain_entry ); gchar *answer = recv_vims(3,&len); if(len <= 0 || answer == NULL ) { if(answer) g_free(answer); for( i = 0; i < 16; i ++ ) st[i] = 0; if(info->uc.selected_rgbkey && skin__ == 0) disable_widget("rgbkey"); return 0; } int res = sscanf( answer, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d", p+0,p+1,p+2,p+3,p+4,p+5,p+6,p+7,p+8,p+9,p+10, p+11,p+12,p+13,p+14,p+15); if( res <= 0 ) { for( i = 0; i < 16; i ++ ) st[i] = 0; return 0; } if( skin__ == 0 ) { info->uc.selected_rgbkey = _effect_get_rgb( p[0] ); if(info->uc.selected_rgbkey) { enable_widget( "rgbkey"); update_rgbkey(); } else { disable_widget( "rgbkey"); info->uc.selected_rgbkey = 0; } } g_free(answer); for( i = 0; i < 16; i ++ ) st[i] = p[i]; return 1; } // load effect chain static void load_effectchain_info() { GtkWidget *tree = glade_xml_get_widget_( info->main_window, "tree_chain"); GtkListStore *store; GtkTreeIter iter; gint offset=0; gint fxlen = 0; multi_vims( VIMS_CHAIN_LIST,"%d",0 ); gchar *fxtext = recv_vims(3,&fxlen); reset_tree( "tree_chain" ); GtkTreeModel *model = gtk_tree_view_get_model( GTK_TREE_VIEW(tree )); store = GTK_LIST_STORE(model); if(fxlen <= 0 ) { int i; for( i = 0; i < 20; i ++ ) { gtk_list_store_append(store,&iter); gtk_list_store_set(store,&iter, FXC_ID, i ,-1); gtk_tree_view_set_model( GTK_TREE_VIEW(tree), GTK_TREE_MODEL(store)); } return; } if(fxlen == 5 ) offset = fxlen; gint last_index =0; while( offset < fxlen ) { gchar toggle[4]; gchar kf_toggle[4]; guint arr[6]; bzero(toggle,4); bzero(kf_toggle,4); memset(arr,0,sizeof(arr)); char line[12]; bzero(line,12); strncpy( line, fxtext + offset, 8 ); sscanf( line, "%02d%03d%1d%1d%1d", &arr[0],&arr[1],&arr[2],&arr[3],&arr[4]); char *name = _effect_get_description( arr[1] ); sprintf(toggle,"%s", arr[3] == 1 ? "on" : "off" ); while( last_index < arr[0] ) { gtk_list_store_append( store, &iter ); gtk_list_store_set( store, &iter, FXC_ID, last_index,-1); last_index ++; } if( last_index == arr[0]) { gchar *utf8_name = _utf8str( name ); sample_slot_t *s = info->selected_slot; int on = 0; if(s) on = s->ec->effects[last_index]->enabled; gtk_list_store_append( store, &iter ); /* gtk_list_store_set( store, &iter, FXC_ID, arr[0], FXC_FXID, utf8_name, FXC_FXSTATUS, utf8_toggle, FXC_KF, utf8_kf, -1 );*/ GdkPixbuf *toggle = update_pixmap_entry( arr[3] ); GdkPixbuf *kf_toggle = update_pixmap_kf( on ); gtk_list_store_set( store, &iter, FXC_ID, arr[0], FXC_FXID, utf8_name, FXC_FXSTATUS, toggle, FXC_KF, kf_toggle, -1 ); last_index ++; g_free(utf8_name); g_object_unref( toggle ); g_object_unref( kf_toggle ); } offset += 8; } while( last_index < 20 ) { gtk_list_store_append( store, &iter ); gtk_list_store_set( store, &iter, FXC_ID, last_index , -1 ); last_index ++; } gtk_tree_view_set_model( GTK_TREE_VIEW(tree), GTK_TREE_MODEL(store)); g_free(fxtext); } enum { FX_ID = 0, FX_STRING = 1, FX_NUM, }; gboolean view_fx_selection_func (GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath *path, gboolean path_currently_selected, gpointer userdata) { GtkTreeIter iter; if (gtk_tree_model_get_iter(model, &iter, path)) { gint name; gtk_tree_model_get(model, &iter, FX_ID, &name, -1); if (!path_currently_selected) { info->uc.selected_effect_id = name; } } return TRUE; /* allow selection state to change */ } void on_effectmixlist_row_activated(GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *col, gpointer user_data) { GtkTreeModel *model; GtkTreeIter iter; model = gtk_tree_view_get_model(treeview); if(gtk_tree_model_get_iter(model,&iter,path)) { gint gid =0; gtk_tree_model_get(model,&iter, FX_ID, &gid, -1); if(gid) { multi_vims(VIMS_CHAIN_ENTRY_SET_EFFECT, "%d %d %d", 0, info->uc.selected_chain_entry,gid ); // info->uc.reload_hint[HINT_CHAIN] = 1; info->uc.reload_hint[HINT_ENTRY] = 1; } } } void on_effectlist_row_activated(GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *col, gpointer user_data) { GtkTreeModel *model; GtkTreeIter iter; model = gtk_tree_view_get_model(treeview); if(gtk_tree_model_get_iter(model,&iter,path)) { gint gid =0; gtk_tree_model_get(model,&iter, FX_ID, &gid, -1); if(gid) { multi_vims(VIMS_CHAIN_ENTRY_SET_EFFECT, "%d %d %d", 0, info->uc.selected_chain_entry,gid ); if(info->status_tokens[PLAY_MODE] != MODE_PLAIN) vj_kf_delete_parameter(info->uc.selected_chain_entry); info->uc.reload_hint[HINT_ENTRY] = 1; } } } gint sort_iter_compare_func( GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer userdata) { gint sortcol = GPOINTER_TO_INT(userdata); gint ret = 0; if(sortcol == FX_STRING) { gchar *name1=NULL; gchar *name2=NULL; gtk_tree_model_get(model,a, FX_STRING, &name1, -1 ); gtk_tree_model_get(model,b, FX_STRING, &name2, -1 ); if( name1 == NULL || name2 == NULL ) { if( name1==NULL && name2==NULL) { return 0; } ret = (name1 == NULL) ? -1 : 1; } else { ret = g_utf8_collate(name1,name2); } if(name1) g_free(name1); if(name2) g_free(name2); } return ret; } gint sort_vims_func( GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer userdata) { gint sortcol = GPOINTER_TO_INT(userdata); gint ret = 0; if(sortcol == VIMS_ID) { gchar *name1 = NULL; gchar *name2 = NULL; gtk_tree_model_get(model,a, VIMS_ID, &name1, -1 ); gtk_tree_model_get(model,b, VIMS_ID, &name2, -1 ); if( name1 == NULL || name2 == NULL ) { if( name1==NULL && name2== NULL) { return 0; } ret = (name1==NULL) ? -1 : 1; } else { ret = g_utf8_collate(name1,name2); } if(name1) g_free(name1); if(name2) g_free(name2); } return ret; } // load effectlist from veejay void setup_effectlist_info() { int i; GtkWidget *trees[2]; trees[0] = glade_xml_get_widget_( info->main_window, "tree_effectlist"); trees[1] = glade_xml_get_widget_( info->main_window, "tree_effectmixlist"); GtkListStore *stores[2]; stores[0] = gtk_list_store_new( 2, G_TYPE_INT, G_TYPE_STRING ); stores[1] = gtk_list_store_new( 2, G_TYPE_INT, G_TYPE_STRING ); for(i = 0; i < 2; i ++ ) { GtkTreeSortable *sortable = GTK_TREE_SORTABLE(stores[i]); gtk_tree_sortable_set_sort_func( sortable, FX_STRING, sort_iter_compare_func, GINT_TO_POINTER(FX_STRING),NULL); gtk_tree_sortable_set_sort_column_id( sortable, FX_STRING, GTK_SORT_ASCENDING); gtk_tree_view_set_model( GTK_TREE_VIEW(trees[i]), GTK_TREE_MODEL(stores[i])); g_object_unref( G_OBJECT( stores[i] )); } setup_tree_text_column( "tree_effectlist", FX_ID, "id" ); setup_tree_text_column( "tree_effectlist", FX_STRING, "effect" ); setup_tree_text_column( "tree_effectmixlist", FX_ID, "id" ); setup_tree_text_column( "tree_effectmixlist", FX_STRING, "effect" ); g_signal_connect( trees[0], "row-activated", (GCallback) on_effectlist_row_activated, NULL ); g_signal_connect( trees[1] ,"row-activated", (GCallback) on_effectmixlist_row_activated, NULL ); GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(trees[0])); gtk_tree_selection_set_select_function(selection, view_fx_selection_func, NULL, NULL); gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE); selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(trees[1] )); gtk_tree_selection_set_select_function( selection, view_fx_selection_func, NULL,NULL ); gtk_tree_selection_set_mode( selection, GTK_SELECTION_SINGLE ); } void on_effectlist_sources_row_activated(GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *col, gpointer user_data) { GtkTreeModel *model; GtkTreeIter iter; model = gtk_tree_view_get_model(treeview); gchar *what = (gchar*) user_data; if(gtk_tree_model_get_iter(model,&iter,path)) { gchar *idstr = NULL; gtk_tree_model_get(model,&iter, SL_ID, &idstr, -1); gint id = 0; if( sscanf( idstr+1, "%d", &id ) ) { // set source / channel multi_vims( VIMS_CHAIN_ENTRY_SET_SOURCE_CHANNEL, "%d %d %d %d", 0, info->uc.selected_chain_entry, ( idstr[0] == 'T' ? 1 : 0 ), id ); vj_msg(VEEJAY_MSG_INFO, "Set source channel to %d, %d", info->uc.selected_chain_entry,id ); } if(idstr) g_free(idstr); } } /* void on_samplelist_edited(GtkCellRendererText *cell, gchar *path_string, gchar *new_text, gpointer user_data) { // welke sample id is klikked? GtkWidget *tree = glade_xml_get_widget_(info->main_window, "tree_samples"); GtkTreeIter iter; gchar *id = NULL; int n; GtkTreeModel *model = gtk_tree_view_get_model( GTK_TREE_VIEW(tree )); n = gtk_tree_model_get_iter_from_string( model, &iter, path_string); gtk_tree_model_get( model, &iter, SL_ID, &id, -1 ); int br=0; int bw=0; gchar *sysid = g_locale_from_utf8( id, -1, &br, &bw,NULL); unsigned int sample_id = (unsigned int )atoi(sysid+1); if(sample_id > 0) { char digits[2] = { 48, 57 }; char alphauc[2] = { 65,90 }; char alphalw[2] = { 97,122}; char specials[3] = { 95,46,45 }; // convert spaces,tabs to .. gint bytes_read = 0; gint bytes_written = 0; GError *error = NULL; gchar *sysstr = g_locale_from_utf8( new_text, -1, &bytes_read, &bytes_written,&error); if(error) { vj_msg_detail(VEEJAY_MSG_ERROR,"Invalid string: %s", error->message ); if(sysstr) g_free(sysstr); if(sysid) g_free(sysid); if(id) g_free(id); return; } int i; char descr[150]; bzero(descr,150); char *res = &descr[0]; for( i = 0; i < bytes_written; i ++ ) { char c = sysstr[i]; int j; if(c >= digits[0] && c <= digits[1]) *(res)++ = c; if(c >= alphauc[0] && c <= alphauc[1]) *(res)++ = c; if(c >= alphalw[0] && c <= alphalw[1]) *(res)++ = c; if( c == 32) *(res)++ = '_'; for( j = 0; j < 3; j ++ ) if( specials[j] == c ) *(res)++ = c; } if( id[0] == 'S' ) multi_vims( VIMS_SAMPLE_SET_DESCRIPTION, "%d %s", sample_id, descr ); else multi_vims( VIMS_STREAM_SET_DESCRIPTION, "%d %s", sample_id, descr ); if(info->selected_slot->sample_id == sample_id ) { if(info->selected_slot->title ) free(info->selected_slot->title ); info->selected_slot->title = strdup( descr ); gtk_label_set_text( GTK_LABEL( info->selected_gui_slot->title ), info->selected_slot->title ); } if(sysstr) g_free( sysstr ); } if(sysid) g_free(sysid); if(id) g_free(id); } */ /* Return a bank page and slot number to place sample in */ void verify_bank_capacity(int *bank_page_, int *slot_, int sample_id, int sample_type ) { int poke_slot = 0; int bank_page = find_bank_by_sample( sample_id, sample_type, &poke_slot ); if(bank_page == -1) fprintf(stderr, "BANKS + SLOTS FULL\n"); if( !bank_exists(bank_page)) add_bank( bank_page ); if(!info->sample_banks[bank_page]) fprintf(stderr, "BANK IS NULL\n"); *bank_page_ = bank_page; *slot_ = poke_slot; } void setup_samplelist_info() { effect_sources_tree = glade_xml_get_widget_( info->main_window, "tree_sources"); effect_sources_store = gtk_list_store_new( 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING ); gtk_tree_view_set_model( GTK_TREE_VIEW(effect_sources_tree), GTK_TREE_MODEL(effect_sources_store)); g_object_unref( G_OBJECT( effect_sources_store )); effect_sources_model = gtk_tree_view_get_model( GTK_TREE_VIEW(effect_sources_tree )); effect_sources_store = GTK_LIST_STORE(effect_sources_model); setup_tree_text_column( "tree_sources", SL_ID, "Id" ); // setup_tree_texteditable_column( "tree_sources", SL_DESCR , "Title" ,G_CALLBACK(on_samplelist_edited)); setup_tree_text_column( "tree_sources", SL_TIMECODE, "Length" ); GtkTreeSelection *selection; selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(effect_sources_tree)); gtk_tree_selection_set_select_function(selection, view_sources_selection_func, NULL, NULL); gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE); // g_signal_connect( effect_sources_tree, "edited", // (GCallback) on_samplelist_edited, (gpointer*) "tree_sources" ); g_signal_connect( effect_sources_tree, "row-activated", (GCallback) on_effectlist_sources_row_activated, (gpointer*)"tree_sources"); } void load_effectlist_info() { GtkWidget *tree = glade_xml_get_widget_( info->main_window, "tree_effectlist"); GtkWidget *tree2 = glade_xml_get_widget_( info->main_window, "tree_effectmixlist"); GtkListStore *store,*store2; GtkTreeIter iter; gint i,offset=0; gint fxlen = 0; single_vims( VIMS_EFFECT_LIST ); gchar *fxtext = recv_vims(5,&fxlen); _effect_reset(); reset_tree( "tree_effectlist"); // store = gtk_list_store_new( 3, G_TYPE_INT,GDK_TYPE_PIXBUF , G_TYPE_STRING ); GtkTreeModel *model = gtk_tree_view_get_model( GTK_TREE_VIEW(tree )); store = GTK_LIST_STORE(model); GtkTreeModel *model2 = gtk_tree_view_get_model( GTK_TREE_VIEW(tree2)); store2 = GTK_LIST_STORE(model2); while( offset < fxlen ) { char tmp_len[4]; bzero(tmp_len, 4); strncpy(tmp_len, fxtext + offset, 3 ); int len = atoi(tmp_len); offset += 3; if(len > 0) { effect_constr *ec; char line[255]; bzero( line, 255 ); strncpy( line, fxtext + offset, len ); ec = _effect_new(line); if(ec) info->effect_info = g_list_append( info->effect_info, ec ); } offset += len; } fxlen = g_list_length( info->effect_info ); for( i = 0; i < fxlen; i ++) { effect_constr *ec = g_list_nth_data( info->effect_info, i ); gchar *name = _utf8str( _effect_get_description( ec->id ) ); if( name != NULL) { if( _effect_get_mix(ec->id) > 0 ) { gtk_list_store_append( store2, &iter ); gtk_list_store_set( store2, &iter, FX_ID,(guint) ec->id, FX_STRING, name, -1 ); } else { gtk_list_store_append( store, &iter ); gtk_list_store_set( store, &iter, FX_ID,(guint) ec->id, FX_STRING, name, -1 ); } } g_free(name); } gtk_tree_view_set_model( GTK_TREE_VIEW(tree), GTK_TREE_MODEL(store)); // g_object_unref( G_OBJECT( store ) ); gtk_tree_view_set_model( GTK_TREE_VIEW(tree2), GTK_TREE_MODEL(store2)); g_free(fxtext); } static void select_slot(int pm) { int *history = info->history_tokens[ pm ]; if( pm != MODE_PLAIN ) { if(info->status_tokens[CURRENT_ID] != history[CURRENT_ID] || pm != history[PLAY_MODE] ) { if(info->selected_slot) { set_activation_of_slot_in_samplebank(false); info->selected_slot= NULL; info->selected_gui_slot=NULL; } } if(info->selected_slot == NULL || info->selected_slot->sample_id != info->status_tokens[CURRENT_ID] || pm != info->selected_slot->sample_type) { int b = 0; int p = 0; /* falsify activation */ no_preview_ = 2; if(info->status_tokens[CURRENT_ID] > 0) { verify_bank_capacity( &b, &p, info->status_tokens[CURRENT_ID], info->status_tokens[PLAY_MODE] ); info->selected_slot = info->sample_banks[b]->slot[p]; info->selected_gui_slot = info->sample_banks[b]->gui_slot[p]; set_activation_of_slot_in_samplebank(true); } } } else { if(info->selected_slot) set_activation_of_slot_in_samplebank(false); info->selected_slot = NULL; info->selected_gui_slot = NULL; } } /* execute after sample/stream/mixing sources list update * same for load_mixlist_info(), only different widget !! * with_reset_slotselection should be true when the reset * of the samplebanks that is used here should also reset the * current selection of a slot */ static void load_samplelist_info(gboolean with_reset_slotselection) { gint offset=0; int has_samples = 0; int has_streams = 0; int page = 0; int n_slots = 0; reset_tree( "tree_sources" ); multi_vims( VIMS_SAMPLE_LIST,"%d", 0 ); gint fxlen = 0; gchar *fxtext = recv_vims(5,&fxlen); if(fxlen > 0 && fxtext != NULL) { has_samples = 1; while( offset < fxlen ) { char tmp_len[4]; bzero(tmp_len, 4); strncpy(tmp_len, fxtext + offset, 3 ); int len = atoi(tmp_len); offset += 3; if(len > 0) { char line[300]; char descr[255]; gchar id[10]; bzero( line, 300 ); bzero( descr, 255 ); strncpy( line, fxtext + offset, len ); int values[4]; sscanf( line, "%05d%09d%09d%03d%s", &values[0], &values[1], &values[2], &values[3], descr ); gchar *title = _utf8str( descr ); gchar *timecode = format_selection_time( 0,(values[2]-values[1]) ); int int_id = values[0]; /* If sample is not already loaded/present in sample bank, skip bank update. GVeejay cannot know about external sample list updates; If new samples are created or exiting ones deleted from external, Loading the entire list will be necessary to scan for updated slots. The sample itself is updated automatically on edit() or play() */ int poke_slot= 0; int bank_page = 0; verify_bank_capacity( &bank_page , &poke_slot, int_id, 0); if(bank_page >= 0 ) { if( info->sample_banks[bank_page]->slot[poke_slot]->sample_id <= 0 ) { sample_slot_t *tmp_slot = create_temporary_slot(poke_slot,int_id,0, title,timecode ); add_sample_to_sample_banks(bank_page, tmp_slot ); free_slot(tmp_slot); n_slots ++; } else { update_sample_slot_data( bank_page, poke_slot, int_id,0,title,timecode); } } g_free(timecode); g_free(title); } offset += len; } offset = 0; } if( fxtext ) g_free(fxtext); fxlen = 0; multi_vims( VIMS_STREAM_LIST,"%d",0 ); fxtext = recv_vims(5, &fxlen); if( fxlen > 0 && fxtext != NULL) { has_streams = 1; while( offset < fxlen ) { char tmp_len[4]; bzero(tmp_len, 4); strncpy(tmp_len, fxtext + offset, 3 ); int len = atoi(tmp_len); offset += 3; if(len > 0) { char line[300]; char source[255]; char descr[255]; bzero( line, 300 ); bzero( descr, 255 ); bzero( source, 255 ); strncpy( line, fxtext + offset, len ); int values[4]; sscanf( line, "%05d%02d%03d%03d%03d%03d%03d%03d", &values[0], &values[1], &values[2], &values[3], &values[4], &values[5], &values[6], &values[7] ); strncpy( descr, line + 22, values[6] ); switch( values[1] ) { case STREAM_VIDEO4LINUX :sprintf(source,"Video4Linux stream");break; case STREAM_WHITE :sprintf(source,"Solid stream"); sprintf(descr,"infinite"); break; case STREAM_MCAST :sprintf(source,"Multicast stream");break; case STREAM_NETWORK :sprintf(source,"Unicast stream");break; case STREAM_YUV4MPEG :sprintf(source,"Yuv4Mpeg file stream");break; case STREAM_AVFORMAT :sprintf(source,"libavformat stream");break; case STREAM_DV1394 :sprintf(source,"DV1394 Camera stream");break; case STREAM_PICTURE :sprintf(source,"Image stream");break; default: sprintf(source,"Streaming from unknown"); } gchar *gsource = _utf8str( descr ); gchar *gtype = _utf8str( source ); // add to effect-sources-lists tree // add_sample_to_effect_sources_list(values[0], values[1], gtype, gsource); // add to sample_banks // add_sample_to_sample_banks(values[0], values[1], gtype, gsource); int bank_page = 0; int poke_slot = 0; verify_bank_capacity( &bank_page , &poke_slot, values[0], 1); if(bank_page >= 0 ) { if( info->sample_banks[bank_page]->slot[poke_slot] <= 0 ) { sample_slot_t *tmp_slot = create_temporary_slot(poke_slot,values[0],1, gtype,gsource ); add_sample_to_sample_banks(bank_page, tmp_slot ); n_slots ++; free_slot(tmp_slot); } else { update_sample_slot_data( bank_page, poke_slot, values[0],1,gsource,gtype); } } g_free(gsource); g_free(gtype); } offset += len; } } if(fxtext) g_free(fxtext); } gboolean view_el_selection_func (GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath *path, gboolean path_currently_selected, gpointer userdata) { GtkTreeIter iter; if (gtk_tree_model_get_iter(model, &iter, path)) { gint num = 0; gtk_tree_model_get(model, &iter, COLUMN_INT, &num, -1); if (!path_currently_selected) { info->uc.selected_el_entry = num; gint frame_num =0; frame_num = _el_ref_start_frame( num ); update_spin_value( "button_el_selstart", frame_num); update_spin_value( "button_el_selend", _el_ref_end_frame( num ) ); } } return TRUE; /* allow selection state to change */ } void on_vims_row_activated(GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *col, gpointer user_data) { GtkTreeModel *model; GtkTreeIter iter; model = gtk_tree_view_get_model(treeview); if(gtk_tree_model_get_iter(model,&iter,path)) { gchar *vimsid = NULL; gint event_id =0; gtk_tree_model_get(model,&iter, VIMS_ID, &vimsid, -1); if(sscanf( vimsid, "%d", &event_id )) { if(event_id >= VIMS_BUNDLE_START && event_id < VIMS_BUNDLE_END) { multi_vims( VIMS_BUNDLE, "%d", event_id ); info->uc.reload_hint[HINT_CHAIN] = 1; } else { gchar *args = NULL; gchar *format = NULL; gtk_tree_model_get(model,&iter, VIMS_FORMAT, &format, -1); gtk_tree_model_get(model,&iter, VIMS_CONTENTS, &args, -1 ); if( event_id == VIMS_QUIT ) { if( prompt_dialog("Stop Veejay", "Are you sure ? (All unsaved work will be lost)" ) == GTK_RESPONSE_REJECT ) return; } if( (format == NULL||args==NULL) || (strlen(format) <= 0) ) single_vims( event_id ); else { if( args == NULL || strlen(args) <= 0 ) vj_msg_detail(VEEJAY_MSG_ERROR,"VIMS %d requires arguments!", event_id); else multi_vims( event_id, format, args ); } } } if( vimsid ) g_free( vimsid ); } } void on_vimslist_row_activated(GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *col, gpointer user_data) { GtkTreeModel *model; GtkTreeIter iter; model = gtk_tree_view_get_model(treeview); if(gtk_tree_model_get_iter(model,&iter,path)) { gchar *vimsid = NULL; gint event_id = 0; gtk_tree_model_get(model,&iter, VIMS_ID, &vimsid, -1); if(!sscanf(vimsid, "%d", &event_id)) { return; } info->uc.selected_vims_entry = event_id; info->uc.selected_key_mod = 0; info->uc.selected_key_sym = 0; if(sscanf( vimsid, "%d", &event_id ) && event_id > 0) { char msg[100]; sprintf(msg, "Press a key for VIMS %03d", event_id); // prompt for key! int n = prompt_keydialog("Attach key to VIMS event", msg); if( n == GTK_RESPONSE_ACCEPT ) { int key_val = gdk2sdl_key( info->uc.pressed_key ); int key_mod = gdk2sdl_mod( info->uc.pressed_mod ); multi_vims( VIMS_BUNDLE_ATTACH_KEY, "%d %d %d", // 4th = string arguments event_id, key_val, key_mod ); info->uc.reload_hint[HINT_BUNDLES] = 1; } } if( vimsid ) g_free(vimsid); } } gboolean view_vimslist_selection_func (GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath *path, gboolean path_currently_selected, gpointer userdata) { GtkTreeIter iter; if (gtk_tree_model_get_iter(model, &iter, path)) { gchar *vimsid = NULL; gint event_id = 0; gtk_tree_model_get(model, &iter, VIMS_ID, &vimsid, -1); if(sscanf( vimsid, "%d", &event_id )) { info->uc.selected_vims_id = event_id; } if(vimsid) g_free(vimsid); } return TRUE; /* allow selection state to change */ } gboolean view_vims_selection_func (GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath *path, gboolean path_currently_selected, gpointer userdata) { GtkTreeIter iter; if (gtk_tree_model_get_iter(model, &iter, path)) { gchar *vimsid = NULL; gint event_id = 0; gchar *text = NULL; gtk_tree_model_get(model, &iter, VIMS_ID, &vimsid, -1); gtk_tree_model_get(model, &iter, VIMS_CONTENTS, &text, -1 ); int k=0; int m=0; gchar *key = NULL; gchar *mod = NULL; gtk_tree_model_get(model,&iter, VIMS_KEY, &key, -1); gtk_tree_model_get(model,&iter, VIMS_MOD, &mod, -1); if(sscanf( vimsid, "%d", &event_id )) { k = sdlkey_by_name( key ); m = sdlmod_by_name( mod ); if( event_id > 500 && event_id < 600 ) set_textview_buffer( "vimsview", text ); if( info->uc.selected_arg_buf != NULL ) free(info->uc.selected_arg_buf ); info->uc.selected_arg_buf = NULL; if( vj_event_list[event_id].params > 0 ) info->uc.selected_arg_buf = (text == NULL ? NULL: strdup( text )); info->uc.selected_vims_entry = event_id; if(k > 0) { info->uc.selected_key_mod = m; info->uc.selected_key_sym = k; } } if(vimsid) g_free( vimsid ); if(text) g_free( text ); if(key) g_free( key ); if(mod) g_free( mod ); } return TRUE; /* allow selection state to change */ } void on_editlist_row_activated(GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *col, gpointer user_data) { GtkTreeModel *model; GtkTreeIter iter; model = gtk_tree_view_get_model(treeview); if(gtk_tree_model_get_iter(model,&iter,path)) { gint num = 0; gtk_tree_model_get(model,&iter, COLUMN_INT, &num, -1); gint frame_num = _el_ref_start_frame( num ); multi_vims( VIMS_VIDEO_SET_FRAME, "%d", (int) frame_num ); } } void on_stream_color_changed(GtkColorSelection *colorsel, gpointer user_data) { if(!info->status_lock && info->selected_slot) { GdkColor current_color; GtkWidget *colorsel = glade_xml_get_widget_(info->main_window, "colorselection" ); gtk_color_selection_get_current_color( GTK_COLOR_SELECTION( colorsel ), ¤t_color ); // scale to 0 - 255 gint red = current_color.red / 256.0; gint green = current_color.green / 256.0; gint blue = current_color.blue / 256.0; multi_vims( VIMS_STREAM_COLOR, "%d %d %d %d", info->selected_slot->sample_id, red, green, blue ); } } static void setup_colorselection() { GtkWidget *sel = glade_xml_get_widget_(info->main_window, "colorselection"); g_signal_connect( sel, "color-changed", (GCallback) on_stream_color_changed, NULL ); } void on_rgbkey_color_changed(GtkColorSelection *colorsel, gpointer user_data) { if(!info->entry_lock) { GdkColor current_color; GtkWidget *colorsel = glade_xml_get_widget_(info->main_window, "rgbkey" ); gtk_color_selection_get_current_color( GTK_COLOR_SELECTION( colorsel ), ¤t_color ); // scale to 0 - 255 gint red = current_color.red / 256.0; gint green = current_color.green / 256.0; gint blue = current_color.blue / 256.0; // send p1,p2,p3 to veejay // (if effect currently on entry has rgb, this will be enabled but not here) multi_vims( VIMS_CHAIN_ENTRY_SET_ARG_VAL, "%d %d %d %d", 0, info->uc.selected_chain_entry, 1, red ); multi_vims( VIMS_CHAIN_ENTRY_SET_ARG_VAL, "%d %d %d %d", 0, info->uc.selected_chain_entry, 2, green ); multi_vims( VIMS_CHAIN_ENTRY_SET_ARG_VAL, "%d %d %d %d", 0, info->uc.selected_chain_entry, 3, blue ); info->parameter_lock = 1; update_slider_value( "slider_p1", red, 0 ); update_slider_value( "slider_p2", green, 0 ); update_slider_value( "slider_p3", blue, 0 ); info->parameter_lock = 0; } } static void setup_rgbkey() { if( skin__ == 0 ) { GtkWidget *sel = glade_xml_get_widget_(info->main_window, "rgbkey"); g_signal_connect( sel, "color-changed", (GCallback) on_rgbkey_color_changed, NULL ); } } static void setup_vimslist() { GtkWidget *tree = glade_xml_get_widget_( info->main_window, "tree_vims"); GtkListStore *store = gtk_list_store_new( 2,G_TYPE_STRING, G_TYPE_STRING); gtk_tree_view_set_model( GTK_TREE_VIEW(tree), GTK_TREE_MODEL(store)); g_object_unref( G_OBJECT( store )); setup_tree_text_column( "tree_vims", VIMS_ID, "VIMS ID"); setup_tree_text_column( "tree_vims", VIMS_DESCR, "Description" ); GtkTreeSortable *sortable = GTK_TREE_SORTABLE(store); gtk_tree_sortable_set_sort_func( sortable, VIMS_ID, sort_vims_func, GINT_TO_POINTER(VIMS_ID),NULL); gtk_tree_sortable_set_sort_column_id( sortable, VIMS_ID, GTK_SORT_ASCENDING); g_signal_connect( tree, "row-activated", (GCallback) on_vimslist_row_activated, NULL ); GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree)); gtk_tree_selection_set_select_function(selection, view_vimslist_selection_func, NULL, NULL); gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE); } void on_vimslist_edited(GtkCellRendererText *cell, gchar *path_string, gchar *new_text, gpointer user_data ) { // welke sample id is klikked? GtkWidget *tree = glade_xml_get_widget_(info->main_window, "tree_bundles"); GtkTreeIter iter; gchar *id = NULL; gchar *contents = NULL; gchar *format = NULL; gchar *key_sym = NULL; gchar *key_mod = NULL; gint event_id = 0; int n; GtkTreeModel *model = gtk_tree_view_get_model( GTK_TREE_VIEW(tree )); n = gtk_tree_model_get_iter_from_string( model, &iter, path_string); // error !! gtk_tree_model_get( model, &iter, VIMS_ID, &id, -1); gtk_tree_model_get( model, &iter, VIMS_FORMAT, &format, -1); gtk_tree_model_get( model, &iter, VIMS_CONTENTS, &contents -1 ); gtk_tree_model_get( model, &iter, VIMS_KEY, &key_sym, -1); gtk_tree_model_get( model, &iter, VIMS_MOD, &key_mod -1 ); sscanf( id, "%d", &event_id ); gint bytes_read = 0; gint bytes_written = 0; GError *error = NULL; gchar *sysstr = g_locale_from_utf8( new_text, -1, &bytes_read, &bytes_written,&error); if(sysstr == NULL || error != NULL) { goto vimslist_error; } if( event_id < VIMS_BUNDLE_START || event_id > VIMS_BUNDLE_END ) { int np = vj_event_list[ event_id ].params; char *c = format+1; int i; int tmp_val = 0; int k = sdlkey_by_name( key_sym ); int m = sdlmod_by_name( key_mod ); for( i =0 ; i < np; i ++ ) { if(*(c) == 'd') if( sscanf( sysstr, "%d", &tmp_val ) != 1 ) goto vimslist_error; c+=2; } multi_vims( VIMS_BUNDLE_ATTACH_KEY, "%d %d %d %s", event_id, k, m, sysstr ); info->uc.reload_hint[HINT_BUNDLES]=1; } vimslist_error: if(sysstr) g_free(sysstr); if(id) g_free(id); if(contents) g_free(contents); if(key_sym) g_free(key_sym); if(key_mod) g_free(key_mod); if(format) g_free(format); } static void setup_bundles() { GtkWidget *tree = glade_xml_get_widget_( info->main_window, "tree_bundles"); GtkListStore *store = gtk_list_store_new( 7,G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING ,G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING); gtk_widget_set_size_request( tree, 300, -1 ); gtk_tree_view_set_model( GTK_TREE_VIEW(tree), GTK_TREE_MODEL(store)); GtkTreeSortable *sortable = GTK_TREE_SORTABLE(store); gtk_tree_sortable_set_sort_func( sortable, VIMS_ID, sort_vims_func, GINT_TO_POINTER(VIMS_ID),NULL); gtk_tree_sortable_set_sort_column_id( sortable, VIMS_ID, GTK_SORT_ASCENDING); g_object_unref( G_OBJECT( store )); setup_tree_text_column( "tree_bundles", VIMS_ID, "VIMS"); setup_tree_text_column( "tree_bundles", VIMS_DESCR, "Description" ); setup_tree_text_column( "tree_bundles", VIMS_KEY, "Key"); setup_tree_text_column( "tree_bundles", VIMS_MOD, "Mod"); setup_tree_text_column( "tree_bundles", VIMS_PARAMS, "Max args"); setup_tree_text_column( "tree_bundles", VIMS_FORMAT, "Format" ); setup_tree_texteditable_column( "tree_bundles", VIMS_CONTENTS, "Content", G_CALLBACK(on_vimslist_edited) ); g_signal_connect( tree, "row-activated", (GCallback) on_vims_row_activated, NULL ); GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree)); gtk_tree_selection_set_select_function(selection, view_vims_selection_func, NULL, NULL); gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE); GtkWidget *tv = glade_xml_get_widget_( info->main_window, "vimsview" ); gtk_text_view_set_wrap_mode( GTK_TEXT_VIEW(tv), GTK_WRAP_WORD_CHAR ); } static void setup_editlist_info() { editlist_tree = glade_xml_get_widget_( info->main_window, "editlisttree"); editlist_store = gtk_list_store_new( 5,G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING ,G_TYPE_STRING); gtk_tree_view_set_model( GTK_TREE_VIEW(editlist_tree), GTK_TREE_MODEL(editlist_store)); g_object_unref( G_OBJECT( editlist_store )); editlist_model = gtk_tree_view_get_model( GTK_TREE_VIEW(editlist_tree )); editlist_store = GTK_LIST_STORE(editlist_model); setup_tree_text_column( "editlisttree", COLUMN_INT, "Nr"); setup_tree_text_column( "editlisttree", COLUMN_STRING0, "Timecode" ); setup_tree_text_column( "editlisttree", COLUMN_STRINGA, "Filename"); setup_tree_text_column( "editlisttree", COLUMN_STRINGB, "Duration"); setup_tree_text_column( "editlisttree", COLUMN_STRINGC, "FOURCC"); g_signal_connect( editlist_tree, "row-activated", (GCallback) on_editlist_row_activated, NULL ); GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(editlist_tree)); gtk_tree_selection_set_select_function(selection, view_el_selection_func, NULL, NULL); gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE); } /* el format [4] : number of rows [16],[16],[16],[3],[filename] [16] */ static void reload_bundles() { GtkWidget *tree = glade_xml_get_widget_( info->main_window, "tree_bundles"); GtkListStore *store; GtkTreeIter iter; gint len = 0; single_vims( VIMS_BUNDLE_LIST ); gchar *eltext = recv_vims(5,&len); // msg len gint offset = 0; reset_tree("tree_bundles"); if(len == 0 || eltext == NULL ) { return; } GtkTreeModel *model = gtk_tree_view_get_model( GTK_TREE_VIEW(tree )); store = GTK_LIST_STORE(model); int k; for( k = 0; k < sizeof(vims_keys_t); k ++ ) if( vims_keys_list[k].args ) g_free( vims_keys_list[k].args ); memset( &vims_keys_list, 0, sizeof(vims_keys_t)); while( offset < len ) { char *message = NULL; char *line = strndup( eltext + offset, 14 ); int val[4]; int n = sscanf( line, "%04d%03d%03d%04d", &val[0],&val[1],&val[2],&val[3]); if(n < 4) { exit(0); } offset += 14; if(val[3] > 0) { message = strndup( eltext + offset , val[3] ); offset += val[3]; } if( val[0] < 400 || val[0] >= VIMS_BUNDLE_START ) { // query VIMS ! (ignore in userlist) gchar *content = (message == NULL ? NULL : _utf8str( message )); gchar *keyname = sdlkey_by_id( val[1] ); gchar *keymod = sdlmod_by_id( val[2] ); gchar *descr = NULL; gchar *format = NULL; char vimsid[5]; bzero(vimsid,5); sprintf(vimsid, "%03d", val[0]); if( val[0] >= VIMS_BUNDLE_START && val[0] < VIMS_BUNDLE_END ) { if( vj_event_list[ val[0] ].event_id != val[0] && vj_event_list[val[0]].event_id != 0) { if( vj_event_list[ val[0] ].format ) g_free( vj_event_list[ val[0] ].format ); if( vj_event_list[ val[0] ].descr ) g_free( vj_event_list[ val[0] ].descr ); } vj_event_list[ val[0] ].params = 0; vj_event_list[ val[0] ].format = NULL; vj_event_list[ val[0] ].descr = _utf8str( "custom event (fixme: set bundle title)" ); vj_event_list[ val[0] ].event_id = val[0]; }/* else { if( vj_event_list[ val[0] ].event_id != 0 ) descr = vj_event_list[ val[0] ].descr; if( vj_event_list[ val[0] ].event_id != 0 ) format = vj_event_list[ val[0] ].format; }*/ vims_keys_list[ (val[2] * MOD_OFFSET) + val[1] ].keyval = val[1]; vims_keys_list[ (val[2] * MOD_OFFSET) + val[1] ].state = val[2]; vims_keys_list[ (val[2] * MOD_OFFSET) + val[1] ].args = (content == NULL ? NULL :strdup(message)); vims_keys_list[ (val[2] * MOD_OFFSET) + val[1] ].event_id = val[0]; gtk_list_store_append( store, &iter ); gtk_list_store_set(store, &iter, VIMS_ID, vimsid, VIMS_DESCR, descr, VIMS_KEY, keyname, VIMS_MOD, keymod, VIMS_PARAMS, vj_event_list[ val[0] ].params, VIMS_FORMAT, format, VIMS_CONTENTS, content, -1 ); if(content) g_free(content); if(message) free(message); } free( line ); } /* entry, start frame, end frame */ gtk_tree_view_set_model( GTK_TREE_VIEW(tree), GTK_TREE_MODEL(store)); g_free( eltext ); } static void reload_vimslist() { GtkWidget *tree = glade_xml_get_widget_( info->main_window, "tree_vims"); GtkListStore *store; GtkTreeIter iter; gint len = 0; single_vims( VIMS_VIMS_LIST ); gchar *eltext = recv_vims(5,&len); // msg len gint offset = 0; reset_tree("tree_vims"); if(len == 0 || eltext == NULL ) { return; } GtkTreeModel *model = gtk_tree_view_get_model( GTK_TREE_VIEW(tree )); store = GTK_LIST_STORE(model); while( offset < len ) { char *format = NULL; char *descr = NULL; char *line = strndup( eltext + offset, 14 ); int val[4]; sscanf( line, "%04d%02d%03d%03d", &val[0],&val[1],&val[2],&val[3]); char vimsid[5]; offset += 12; if(val[2] > 0) { format = strndup( eltext + offset, val[2] ); offset += val[2]; } if(val[3] > 0 ) { descr = strndup( eltext + offset, val[3] ); offset += val[3]; } gchar *g_format = (format == NULL ? NULL :_utf8str( format )); gchar *g_descr = (descr == NULL ? NULL :_utf8str( descr )); gtk_list_store_append( store, &iter ); vj_event_list[ val[0] ].event_id = val[0]; vj_event_list[ val[0] ].params = val[1]; vj_event_list[ val[0] ].format = (format == NULL ? NULL :_utf8str( format )); vj_event_list[ val[0] ].descr = (descr == NULL ? NULL : _utf8str( descr )); sprintf(vimsid, "%03d", val[0] ); gtk_list_store_set( store, &iter, VIMS_ID, vimsid, VIMS_DESCR, g_descr,-1 ); if(g_format) g_free(g_format); if(g_descr) g_free(g_descr); if(format) free(format); if(descr) free(descr); free( line ); } /* entry, start frame, end frame */ gtk_tree_view_set_model( GTK_TREE_VIEW(tree), GTK_TREE_MODEL(store)); g_free( eltext ); } static void reload_editlist_contents() { GtkWidget *tree = glade_xml_get_widget_( info->main_window, "editlisttree"); GtkListStore *store; GtkTreeIter iter; gint i; gint len = 0; single_vims( VIMS_EDITLIST_LIST ); gchar *eltext = recv_vims(6,&len); // msg len gint offset = 0; gint num_files=0; reset_tree("editlisttree"); _el_ref_reset(); _el_entry_reset(); if( eltext == NULL || len < 0 ) return; char str_nf[4]; strncpy( str_nf, eltext , sizeof(str_nf)); sscanf( str_nf, "%04d", &num_files ); offset += 4; int n = 0; el_constr *el; for( i = 0; i < num_files ; i ++ ) { int itmp =0; char *tmp1 = (char*) strndup( eltext+offset, 4 ); int line_len = 0; char fourcc[4]; bzero(fourcc,4); n = sscanf( tmp1, "%04d", &line_len ); // line len if(line_len>0) { offset += 4; char *line = (char*)strndup( eltext + offset, line_len ); offset += line_len; char *tmp = (char*) strndup( line, 3 ); sscanf(tmp, "%03d",&itmp ); char *file = strndup( line + 3, itmp ); free(tmp); tmp = (char*) strndup( line + 3 + itmp, 16 ); int a,b,c; int n = sscanf(tmp, "%04d%010d%02d", &a,&b,&c); free(tmp); strncpy(fourcc, line + 3 + itmp + 16, c ); el = _el_entry_new( i, file, b, fourcc ); info->editlist = g_list_append( info->editlist, el ); free(line); free(file); } free(tmp1); } GtkTreeModel *model = gtk_tree_view_get_model( GTK_TREE_VIEW(tree )); store = GTK_LIST_STORE(model); int total_frames = 0; // running total of frames int row_num = 0; while( offset < len ) { char *tmp = (char*)strndup( eltext + offset, (3*16) ); offset += (3*16); long nl=0, n1=0,n2=0; sscanf( tmp, "%016ld%016ld%016ld", &nl,&n1,&n2 ); if(nl < 0 || nl >= num_files) { printf("exceed max files\n"); return; } int file_len = _el_get_nframes( nl ); if(file_len <= 0) { row_num++; continue; } if(n1 < 0 ) n1 = 0; if(n2 >= file_len) n2 = file_len; if(n2 <= n1 ) { row_num++; continue; } info->elref = g_list_append( info->elref, _el_ref_new( row_num,(int) nl,n1,n2,total_frames ) ) ; char *tmpname = _el_get_filename(nl); gchar *fname = get_relative_path(tmpname); gchar *timecode = format_selection_time( n1,n2 ); gchar *gfourcc = _utf8str( _el_get_fourcc(nl) ); gchar *timeline = format_selection_time( 0, total_frames ); // insert values to editlist //add_sample_to_editlist((guint)row_num,timeline,fname,timecode,gfourcc); gtk_list_store_append( store, &iter ); gtk_list_store_set( store, &iter, COLUMN_INT, (guint) row_num, COLUMN_STRING0, timeline, COLUMN_STRINGA, fname, COLUMN_STRINGB, timecode, COLUMN_STRINGC, gfourcc,-1 ); g_free(timecode); g_free(gfourcc); g_free(fname); g_free(timeline); free(tmp); total_frames = total_frames + (n2-n1) + 1; row_num ++; } info->el.num_frames = total_frames; gtk_tree_view_set_model( GTK_TREE_VIEW(tree), GTK_TREE_MODEL(store)); g_free( eltext ); } // execute after el change: static void load_editlist_info() { char norm; float fps; int values[10]; long rate = 0; long dum[2]; memset(values, 0, sizeof(values)); single_vims( VIMS_VIDEO_INFORMATION ); int len = 0; gchar *res = recv_vims(3,&len); if( len <= 0 || res==NULL) { fprintf(stderr, "cannot read VIDEO INFORMATION\n"); return; } int n = sscanf( res, "%d %d %d %c %f %d %d %ld %d %ld %ld", &values[0], &values[1], &values[2], &norm,&fps, &values[4], &values[5], &rate, &values[7], &dum[0], &dum[1]); char tmp[15]; snprintf( tmp, sizeof(tmp)-1, "%dx%d", values[0],values[1]); info->el.width = values[0]; info->el.height = values[1]; /* gint w = values[0]; gint h = values[1]; update_spin_value( "priout_width", w ); update_spin_value( "priout_height", h ); if( w > 352 ) w = 352; if( h > 288 ) h = 288; update_spin_range( "preview_width", 16, w, (info->run_state == RUN_STATE_REMOTE ? (w/2) : w ) ); update_spin_range( "preview_height", 16, h, (info->run_state == RUN_STATE_REMOTE ? (h/2) : h ) ); update_spin_incr( "preview_width", 16, 0 ); update_spin_incr( "preview_height", 16, 0 ); update_spin_incr( "priout_width", 16,0 ); update_spin_incr( "priout_height", 16, 0 ); */ update_label_str( "label_el_wh", tmp ); snprintf( tmp, sizeof(tmp)-1, "%s", (norm == 'p' ? "PAL" : "NTSC" ) ); update_label_str( "label_el_norm", tmp); update_label_f( "label_el_fps", fps ); update_spin_value( "screenshot_width", info->el.width ); update_spin_value( "screenshot_height", info->el.height ); info->el.fps = fps; info->el.num_files = dum[0]; snprintf( tmp, sizeof(tmp)-1, "%s", ( values[2] == 0 ? "progressive" : (values[2] == 1 ? "top first" : "bottom first" ) ) ); update_label_str( "label_el_inter", tmp ); update_label_i( "label_el_arate", (int)rate, 0); update_label_i( "label_el_achans", values[7], 0); update_label_i( "label_el_abits", values[5], 0); if( rate == 0 ) { disable_widget( "button_5_4"); disable_widget_by_pointer(info->audiovolume_knob); disable_widget( "audio_knobframe"); } else { enable_widget( "button_5_4"); enable_widget_by_pointer(info->audiovolume_knob); enable_widget( "audio_knobframe"); } g_free(res); } void vj_gui_set_preview_window( int w , int h ) { if( w < 0 || w > 1568 || h < 0 || h > 1024 ) { fprintf(stderr, "Please use a sane range for width X height\n"); return; } info->preview_size_w = w; info->preview_size_h = h; } static void disable_widget(const char *name) { GtkWidget *w = glade_xml_get_widget_(info->main_window,name); if(w) { gtk_widget_set_sensitive( GTK_WIDGET(w), FALSE ); } } static void disable_widget_by_pointer(GtkWidget *w) { gtk_widget_set_sensitive( GTK_WIDGET(w), FALSE ); } static void enable_widget_by_pointer(GtkWidget *w) { gtk_widget_set_sensitive( GTK_WIDGET(w), TRUE ); } static void enable_widget(const char *name) { GtkWidget *w = glade_xml_get_widget_(info->main_window,name); if(w) { gtk_widget_set_sensitive( GTK_WIDGET(w), TRUE ); } } static gchar *format_time(int pos) { MPEG_timecode_t tc; if(pos==0) memset(&tc, 0, sizeof(tc)); else mpeg_timecode( &tc, pos, mpeg_framerate_code( mpeg_conform_framerate( info->el.fps )), info->el.fps ); gchar *tmp = g_new( gchar, 20); snprintf(tmp, 20, "%2d:%2.2d:%2.2d:%2.2d", tc.h, tc.m, tc.s, tc.f ); return tmp; } static gchar *format_selection_time(int start, int end) { MPEG_timecode_t tc; memset( &tc, 0,sizeof(tc)); if( (end-start) <= 0) memset( &tc, 0, sizeof(tc)); else mpeg_timecode( &tc, (end-start), mpeg_framerate_code( mpeg_conform_framerate( info->el.fps ) ), info->el.fps ); gchar *tmp = g_new( gchar, 20); snprintf( tmp, 20, "%2d:%2.2d:%2.2d:%2.2d", tc.h, tc.m, tc.s, tc.f ); return tmp; } static void set_color_fg(const char *name, GdkColor *col) { GtkWidget *w = glade_xml_get_widget_( info->main_window,name ); if(w) { GtkStyle *style; style = gtk_style_copy(gtk_widget_get_style(w)); style->fg[GTK_STATE_NORMAL].pixel = col->pixel; style->fg[GTK_STATE_NORMAL].red = col->red; style->fg[GTK_STATE_NORMAL].green = col->green; style->fg[GTK_STATE_NORMAL].blue = col->blue; gtk_widget_set_style(w, style); } } static gboolean update_cpumeter_timeout( gpointer data ) { GtkWidget *w = glade_xml_get_widget_( info->main_window, "cpumeter"); gdouble ms = (gdouble)info->status_tokens[ELAPSED_TIME]; gdouble max = ((1.0/info->el.fps)*1000); gdouble frac = 1.0 / max; gdouble invert = 0.0; invert = 1.0 - (frac * (ms > max ? max : ms)); if(invert < 0.0) invert = 0.0; if(ms > max) { frac = 1.0; // set progres bar red GdkColor color; color.red = 0xffff; color.green = 0x0000; color.blue = 0x0000; // if(gdk_colormap_alloc_color(info->color_map, // &color, TRUE, TRUE )) set_color_fg( "cpumeter", &color ); } else { GdkColor color; color.red = 0x0000; color.green = 0xffff; color.blue = 0x0000; // if(gdk_colormap_alloc_color(info->color_map, // &color, TRUE, TRUE)) set_color_fg( "cpumeter", &color); // progress bar green } gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR(w), invert ); return TRUE; } static gboolean refresh_image_horror(gpointer data) { if(info->status_lock) return TRUE; if(info->status_tokens[PLAY_MODE] == MODE_PLAIN ) return TRUE; if(no_preview_!=0) { no_preview_ --; return TRUE; } if(selected_is_playing()) { if(info->selected_slot->pixbuf) gdk_pixbuf_unref( info->selected_slot->pixbuf ); info->selected_slot->pixbuf = NULL; if(info->sequence_view->w == 0 || info->sequence_view->h == 0 ) return TRUE; no_draw_ = 1; int i; for( i = 0; i < info->sequence_view->envelope_size; i ++ ) { sequence_gui_slot_t *g = info->sequence_view->gui_slot[i]; if(g->pixbuf_ref && g->sample_id == info->selected_slot->sample_id && g->sample_type == info->selected_slot->sample_type) { gdk_pixbuf_unref(g->pixbuf_ref); g->pixbuf_ref = NULL; } } } return TRUE; } static gboolean update_imageA( gpointer data ) { //while (gtk_events_pending ()) //gtk_main_iteration (); if(info->status_lock) { return TRUE; } if( info->state == STATE_PLAYING ) // && info->status_passed >= get_nums("preview_delay") ) { GdkPixbuf *new_pixbuf = NULL; if( no_preview_ ) { no_preview_ --; return TRUE; } if(info->status_tokens[PLAY_MODE] == MODE_PLAIN ) { if( is_button_toggled( "previewtoggle" )) { gveejay_update_image2( glade_xml_get_widget_(info->main_window, "imageA"), get_nums("preview_width"),get_nums("preview_height") ); } if( no_preview_ )return TRUE; } else if(info->selected_slot) { if(info->selected_slot->sample_id == info->status_tokens[CURRENT_ID] && info->selected_slot->sample_type == info->status_tokens[PLAY_MODE] && selected_is_playing()) { if( is_button_toggled( "previewtoggle" )) { new_pixbuf = gveejay_update_image2( glade_xml_get_widget_(info->main_window, "imageA"), get_nums("preview_width"),get_nums("preview_height") ); if(!new_pixbuf) return TRUE; //if( info->selected_slot->pixbuf) // gdk_pixbuf_unref(info->selected_slot->pixbuf ); /* if(!info->selected_slot->pixbuf) { info->selected_slot->pixbuf = gdk_pixbuf_scale_simple( new_pixbuf, info->image_dimensions[0], info->image_dimensions[1], GDK_INTERP_BILINEAR ); gveejay_update_image( info->selected_slot,info->selected_gui_slot, info->image_dimensions[0], info->image_dimensions[1] ); update_cached_slots(); } */ // if(info->selected_slot->pixbuf) // { /* critical, which slot is really selected in notepad !? */ /* critical, are we sure ? */ // gdk_pixbuf_unref( info->selected_slot->pixbuf ); // info->selected_slot->pixbuf = NULL; // } if(!info->selected_slot->pixbuf && is_button_toggled("previewtoggle")) { info->selected_slot->pixbuf = gdk_pixbuf_scale_simple( new_pixbuf, info->image_dimensions[0], info->image_dimensions[1], GDK_INTERP_BILINEAR ); gveejay_update_image( info->selected_slot,info->selected_gui_slot, info->image_dimensions[0], info->image_dimensions[1] ); update_cached_slots(); } } } } } return TRUE; } static gboolean update_sample_record_timeout(gpointer data) { if( info->uc.playmode == MODE_SAMPLE ) { GtkWidget *w = glade_xml_get_widget_( info->main_window, "samplerecord_progress" ); gdouble tf = info->status_tokens[STREAM_DURATION]; gdouble cf = info->status_tokens[STREAM_RECORDED]; gdouble fraction = cf / tf; if(!info->status_tokens[STREAM_RECORDING] ) { gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR(w), 0.0); info->samplerecording = 0; info->uc.recording[MODE_SAMPLE] = 0; if(info->uc.render_record) { info->uc.reload_hint[HINT_HISTORY]=1; info->uc.render_record = 0; // render list has private edl } else { info->uc.reload_hint[HINT_EL] = 1; } return FALSE; } else { gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR(w), fraction ); } } return TRUE; } static gboolean update_stream_record_timeout(gpointer data) { GtkWidget *w = glade_xml_get_widget_( info->main_window, "streamrecord_progress" ); if( info->uc.playmode == MODE_STREAM ) { gdouble tf = info->status_tokens[STREAM_DURATION]; gdouble cf = info->status_tokens[STREAM_RECORDED]; gdouble fraction = cf / tf; if(!info->status_tokens[STREAM_RECORDING] ) { gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR(w), 0.0); info->streamrecording = 0; info->uc.recording[MODE_STREAM] = 0; info->uc.reload_hint[HINT_EL] = 1; // recording finished, reload edl return FALSE; } else gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR(w), fraction ); } return TRUE; } static gboolean update_progress_timeout(gpointer data) { GtkWidget *w = glade_xml_get_widget_( info->main_window, "connecting"); gtk_progress_bar_pulse (GTK_PROGRESS_BAR (w)); return TRUE; } static void init_progress() { //GtkWidget *w = glade_xml_get_widget_( info->main_window, "connecting"); info->connecting = g_timeout_add( 300 , update_progress_timeout, (gpointer*) info ); } static void init_recorder(int total_frames, gint mode) { if(mode == MODE_STREAM) { info->streamrecording = g_timeout_add(300, update_stream_record_timeout, (gpointer*) info ); } if(mode == MODE_SAMPLE) { info->samplerecording = g_timeout_add(300, update_sample_record_timeout, (gpointer*) info ); } info->uc.recording[mode] = 1; } static void init_cpumeter() { info->cpumeter = g_timeout_add(300,update_cpumeter_timeout, (gpointer*) info ); int ms = (int) ( 1.0 / info->el.fps * 1000 ); if(preview_priority_) info->imageA = g_timeout_add(G_PRIORITY_HIGH_IDLE,update_imageA, (gpointer*)info); else info->imageA = gtk_idle_add( update_imageA, (gpointer*) info); g_timeout_add(600, refresh_image_horror, (gpointer*) info); } static void update_gui() { int pm = info->status_tokens[PLAY_MODE]; if( pm == MODE_SAMPLE && info->uc.randplayer ) { info->uc.randplayer = 0; set_toggle_button( "samplerand", 0 ); } if( pm == MODE_PATTERN ) { if(!info->uc.randplayer ) { info->uc.randplayer = 1; enable_widget( "freestyle" ); enable_widget( "samplerand" ); set_toggle_button( "samplerand", 1 ); } info->status_tokens[PLAY_MODE] = MODE_SAMPLE; pm = MODE_SAMPLE; } if(pm < 0 || pm > 2) { fprintf(stderr, "Cannot deal with veejay\n"); exit(0); } select_slot(pm); update_globalinfo(); process_reload_hints(); if( pm != MODE_PLAIN) interpolate_parameters(); } static void get_gd(char *buf, char *suf, const char *filename) { if(filename !=NULL && suf != NULL) sprintf(buf, "%s/%s/%s", GVEEJAY_DATADIR,suf, filename ); if(filename !=NULL && suf==NULL) sprintf(buf, "%s/%s", GVEEJAY_DATADIR, filename); if(filename == NULL && suf != NULL) sprintf(buf, "%s/%s/" , GVEEJAY_DATADIR, suf); } static void veejay_untick(gpointer data) { vj_msg(VEEJAY_MSG_INFO, "Ending veejay session"); if(info->state == STATE_PLAYING) { info->state = STATE_STOPPED; } } static gboolean veejay_tick( GIOChannel *source, GIOCondition condition, gpointer data) { vj_gui_t *gui = (vj_gui_t*) data; if( (condition&G_IO_ERR) ) { return FALSE; } if( (condition&G_IO_HUP) ) { return FALSE; } if( (condition&G_IO_NVAL) ) { return FALSE; } if(gui->state==STATE_PLAYING && (condition & G_IO_IN) ) { //vj_client_poll( gui->client, V_STATUS )) //vj_client_poll( gui->client, V_STATUS )) gui->status_lock = 1; int nb = 0; char sta_len[6]; bzero(sta_len,6); nb = vj_client_read( gui->client, V_STATUS, sta_len, 5 ); if(sta_len[0] != 'V' ) return FALSE; int n_bytes = 0; sscanf( sta_len+1, "%03d", &n_bytes ); if( n_bytes == 0 || n_bytes >= STATUS_BYTES ) { return FALSE; } bzero( gui->status_msg, STATUS_BYTES ); nb = vj_client_read( gui->client, V_STATUS, gui->status_msg, n_bytes ); while(vj_client_poll( gui->client, V_STATUS )) { // is there a more recent message ? char tmp[6]; bzero(tmp,6); nb = vj_client_read( gui->client,V_STATUS,tmp, 5); int bb = 0; sscanf( tmp+1, "%03d", &bb ); if(bb>0) nb = vj_client_read(gui->client, V_STATUS, gui->status_msg, bb ); } gui->status_lock = 1; if(nb > 0) { int n = sscanf( gui->status_msg, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d", gui->status_tokens + 0, gui->status_tokens + 1, gui->status_tokens + 2, gui->status_tokens + 3, gui->status_tokens + 4, gui->status_tokens + 5, gui->status_tokens + 6, gui->status_tokens + 7, gui->status_tokens + 8, gui->status_tokens + 9, gui->status_tokens + 10, gui->status_tokens + 11, gui->status_tokens + 12, gui->status_tokens + 13, gui->status_tokens + 14, gui->status_tokens + 15, gui->status_tokens + 16 ); if( n != 17 ) { // restore status (to prevent gui from going bezerk) int *history = info->history_tokens[ info->uc.playmode ]; int i; for(i = 0; i < STATUS_TOKENS; i ++ ) { gui->status_tokens[i] = history[i]; } fprintf(stderr, "Warning: using outdated status tokens %d\n",n); exit(0); } update_gui(); } gui->status_lock = 0; int pm = info->status_tokens[PLAY_MODE]; int *history = info->history_tokens[pm]; int i; for( i = 0; i < STATUS_TOKENS; i ++ ) history[i] = info->status_tokens[i]; info->prev_mode = pm; // on_samplepage_clicked(NULL,NULL); if(nb <= 0) { return FALSE; } // flush rest char tmp[5]; while(vj_client_poll( gui->client, V_STATUS )) nb = vj_client_read( gui->client,V_STATUS,tmp, 1); } return TRUE; } void vj_gui_stop_launch() { switch( info->state ) { case STATE_IDLE: break; case STATE_RECONNECT: info->state = STATE_IDLE; memset( &(info->timer), 0, sizeof(struct timeval)); memset( &(info->alarm), 0, sizeof(struct timeval)); if(info->connecting) { gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR (glade_xml_get_widget_(info->main_window, "connecting")),0.0); g_source_remove( info->connecting ); info->connecting = 0; } break; case STATE_PLAYING: if( info->run_state == RUN_STATE_LOCAL ) { if( prompt_dialog("Quit Veejay ?" , "Are you sure?" ) != GTK_RESPONSE_REJECT ) { single_vims( VIMS_QUIT ); vj_gui_disconnect(); } } if( info->run_state == RUN_STATE_REMOTE ) { vj_gui_disconnect(); } break; default: break; // stop timer } } void vj_fork_or_connect_veejay(char *configfile) { char *remote = get_text( "entry_hostname" ); char *files = get_text( "entry_filename" ); int port = get_nums( "button_portnum" ); gchar **args; int n_args = 0; char port_str[15]; char config[512]; char tmp[20]; int i = 0; int arglen = vims_verbosity ? 15 :14 ; arglen += (info->config.deinter); arglen += (info->config.osc); arglen += (info->config.vims); args = g_new ( gchar *, arglen ); args[0] = g_strdup("veejay"); sprintf(port_str, "-p%d", port); args[1] = g_strdup( port_str ); if(configfile) sprintf(config, "-l%s", configfile); if( config_file_status == 0 ) { if(files == NULL || strlen(files)<= 0) args[2] = g_strdup("-d"); else args[2] = g_strdup(files); } else { printf("FIXME: Cant guess port num / hostname yet !\n"); args[2] = g_strdup( config ); } args[3] = g_strdup( "-O5" ); sprintf(tmp, "-W%d", info->config.w ); args[4] = g_strdup( tmp ); sprintf(tmp, "-H%d", info->config.h ); args[5] = g_strdup( tmp ); sprintf(tmp, "-R%g", info->config.fps ); args[6] = g_strdup( tmp ); sprintf(tmp, "-N%d", info->config.norm ); args[7] = g_strdup( tmp ); sprintf(tmp, "-Y%d", info->config.pixel_format ); args[8] = g_strdup( tmp ); sprintf(tmp, "-m%d", info->config.sampling ); args[9] = g_strdup( tmp ); sprintf(tmp, "-c%d", info->config.sync ); args[10] = g_strdup( tmp ); sprintf(tmp, "-t%d", info->config.timer == 0 ? 0 : 2); args[11] = g_strdup( tmp ); sprintf(tmp, "-r%d", info->config.audio_rate ); args[12] = g_strdup( tmp ); args[13] = NULL; int k=13; while( k <= (arglen-1)) args[k++] = NULL; if( vims_verbosity ) args[13] = g_strdup( "-v" ); if( info->config.deinter ) { if(args[13]==NULL) args[13] = g_strdup( "-I"); else args[14] = g_strdup( "-I" ); } if( info->config.osc) { gchar osc_token[20]; sprintf(osc_token , "-M %s", info->config.mcast_osc ); int f = 13; while(args[f] != NULL ) f ++; args[f] = g_strdup( osc_token ); } if( info->config.vims) { gchar vims_token[20]; sprintf(vims_token, "-V %s", info->config.mcast_vims ); int f = 13; while(args[f] != NULL) f++; args[f] = g_strdup( vims_token ); } // for(k = 0 ; k < arglen; k ++ ) // fprintf(stderr, "%s arg %d = '%s'\n", __FUNCTION__, k, args[k] ); if( info->state == STATE_IDLE || info->state == STATE_STOPPED) { // start local veejay if(strncasecmp(remote, "localhost", strlen(remote)) == 0 || strncasecmp(remote, "127.0.0.1", strlen(remote))==0) { // another veejay may be locally running at host:port if(!vj_gui_reconnect( remote, NULL, port )) { GError *error = NULL; int pid; init_progress(); gettimeofday( &(info->timer) , NULL ); memcpy( &(info->alarm), &(info->timer), sizeof(struct timeval)); gboolean ret = g_spawn_async_with_pipes( NULL, args, NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_STDOUT_TO_DEV_NULL, NULL, NULL, &pid, NULL, NULL, NULL, //&(iot.stderr_pipe), &error ); g_strfreev( args ); if(error) { vj_msg_detail(VEEJAY_MSG_ERROR, "There was an error: [%s]\n", error->message ); ret = FALSE; g_error_free(error); } if( ret == FALSE ) { info->state = STATE_IDLE; vj_msg(VEEJAY_MSG_ERROR, "Failed to start veejay"); } else { info->run_state = RUN_STATE_LOCAL; info->state = STATE_RECONNECT; vj_launch_toggle(FALSE); } } else { info->run_state = RUN_STATE_REMOTE; if(is_button_toggled("previewtoggle")) { /* Keep a watch not to choke the bandwith */ set_toggle_button( "previewtoggle", 0 ); } } } else { if(!vj_gui_reconnect(remote,NULL,port )) { vj_msg(VEEJAY_MSG_ERROR, "Cannot establish connection with %s : %d", remote, port ); } } } /* else { if( info->state == STATE_PLAYING ) { vj_gui_disconnect( ); vj_msg(VEEJAY_MSG_ERROR, "Disconnected."); info->state = STATE_RECONNECT; } }*/ for( i = 0; i < n_args; i ++) { g_free(args[i]); } } void vj_gui_free() { if(info) { int i; //vj_gui_disconnect(); for( i = 0; i < 3 ; i ++ ) { if(info->history_tokens[i]) free(info->history_tokens[i]); } free(info); } info = NULL; gtk_main_quit(); } static void vj_init_style( const char *name, const char *font ) { GtkWidget *window = glade_xml_get_widget_(info->main_window, "gveejay_window"); GtkWidget *widget = glade_xml_get_widget_(info->main_window, name ); gtk_text_view_set_wrap_mode( GTK_TEXT_VIEW(widget), GTK_WRAP_WORD_CHAR ); GtkStyle *style = gtk_style_copy( gtk_widget_get_style(GTK_WIDGET(window))); PangoFontDescription *desc = pango_font_description_from_string( font ); pango_font_description_set_style( desc, PANGO_STYLE_NORMAL ); style->font_desc = desc; gtk_widget_set_style( widget, style ); gtk_style_ref(style); } void vj_gui_style_setup() { if(!info) return; info->color_map = gdk_colormap_get_system(); vj_init_style( "veejaytext", "Monospace, 8" ); } void vj_gui_theme_setup() { char path[MAX_PATH_LEN]; bzero(path,MAX_PATH_LEN); get_gd(path,NULL, "gveejay.rc"); gtk_rc_parse(path); } gint gui_client_event_signal(GtkWidget *widget, GdkEventClient *event, void *data) { static GdkAtom atom_rcfiles = GDK_NONE; if(!atom_rcfiles) atom_rcfiles = gdk_atom_intern("_GTK_READ_RCFILES", FALSE); if(event->message_type == atom_rcfiles) { char path[MAX_PATH_LEN]; get_gd(path,NULL, "gveejay.rc"); gtk_rc_parse(path); return TRUE; } return FALSE; } void vj_gui_set_debug_level(int level, int preview_p ) { veejay_set_debug_level( level ); vims_verbosity = level; if(level) veejay_msg(VEEJAY_MSG_INFO, "Be verbose"); preview_priority_ = preview_p; } void set_skin(int skin) { skin__ = skin; } void vj_gui_init(char *glade_file) { char path[MAX_PATH_LEN]; int i; vj_mem_init(); glade_init(); vj_gui_t *gui = (vj_gui_t*)vj_malloc(sizeof(vj_gui_t)); if(!gui) { return; } memset( gui, 0, sizeof(vj_gui_t)); memset( gui->status_tokens, 0, STATUS_TOKENS ); memset( gui->sample, 0, 2 ); memset( gui->selection, 0, 3 ); memset( &(gui->uc), 0, sizeof(veejay_user_ctrl_t)); gui->prev_mode = -1; memset( &(gui->el), 0, sizeof(veejay_el_t)); // FIXME: Set to max samples / SAMPLES_PER_PAGE , 50 pages for now gui->sample_banks = (sample_bank_t**) vj_malloc(sizeof(sample_bank_t*) * NUM_BANKS ); memset( gui->sample_banks, 0 , sizeof(sample_bank_t*) * NUM_BANKS ); for( i = 0 ; i < 3 ; i ++ ) { gui->history_tokens[i] = (int*) vj_malloc(sizeof(int) * STATUS_TOKENS); memset( gui->history_tokens[i], 0xffff, sizeof(int) *STATUS_TOKENS); } gui->uc.reload_force_avoid = false; /* if(info || ) { vj_gui_free(); } */ memset( vj_event_list, 0, sizeof(vj_event_list)); get_gd( path, NULL, glade_file); gui->client = NULL; gui->main_window = glade_xml_new(path,NULL,NULL); gui->state = STATE_STOPPED; if(!gui->main_window) { free(gui); } info = gui; glade_xml_signal_autoconnect( gui->main_window ); GtkWidget *frame = glade_xml_get_widget_( info->main_window, "markerframe" ); info->tl = timeline_new(); gtk_widget_set_size_request(frame, 200,14 ); g_signal_connect( info->tl, "pos_changed", (GCallback) on_timeline_value_changed, NULL ); g_signal_connect( info->tl, "in_point_changed", (GCallback) on_timeline_in_point_changed, NULL ); g_signal_connect( info->tl, "out_point_changed", (GCallback) on_timeline_out_point_changed, NULL ); g_signal_connect( info->tl, "bind_toggled", (GCallback) on_timeline_bind_toggled, NULL ); g_signal_connect( info->tl, "cleared", (GCallback) on_timeline_cleared, NULL ); gtk_widget_show(frame); gtk_container_add( GTK_CONTAINER(frame), info->tl ); gtk_widget_show(info->tl); gui->config.w = 352; gui->config.h = 288; gui->config.fps = 25.0; gui->config.sampling = 1; gui->config.pixel_format = 1; gui->config.sync = 1; gui->config.timer = 1; gui->config.deinter = 1; gui->config.norm = 0; gui->config.audio_rate = 0; gui->config.osc = 0; gui->config.vims = 0; gui->config.mcast_osc = g_strdup( "224.0.0.32" ); gui->config.mcast_vims = g_strdup( "224.0.0.33" ); g_timeout_add_full( G_PRIORITY_DEFAULT_IDLE, 200, is_alive, (gpointer*) info,NULL); GtkWidget *mainw = glade_xml_get_widget_(info->main_window,"gveejay_window" ); /* Make this run after any internal handling of the client event happened * to make sure that all changes implicated by it are already in place and * we thus can make our own adjustments. */ if( !skin__ ) gtk_label_set_text( glade_xml_get_widget_(info->main_window, "build_revision"), VEEJAY_CODENAME ); g_signal_connect_after( GTK_OBJECT(mainw), "client_event", GTK_SIGNAL_FUNC( G_CALLBACK(gui_client_event_signal) ), NULL ); g_signal_connect( GTK_OBJECT(mainw), "destroy", G_CALLBACK( gtk_main_quit ), NULL ); g_signal_connect( GTK_OBJECT(mainw), "delete-event", G_CALLBACK( gveejay_quit ), NULL ); ; GtkWidget *box = glade_xml_get_widget_( info->main_window, "sample_bank_hbox" ); info->sample_bank_pad = gtk_notebook_new(); gtk_notebook_set_tab_pos( GTK_NOTEBOOK(info->sample_bank_pad), GTK_POS_BOTTOM ); gtk_box_pack_start (GTK_BOX (box), GTK_WIDGET(info->sample_bank_pad), TRUE, TRUE, 0); gtk_widget_show( info->sample_bank_pad ); setup_samplebank( NUM_SAMPLES_PER_COL, NUM_SAMPLES_PER_ROW ); create_ref_slots(12); setup_knobs(); setup_vimslist(); setup_effectchain_info(); setup_effectlist_info(); setup_editlist_info(); setup_samplelist_info(); setup_v4l_devices(); setup_colorselection(); setup_rgbkey(); setup_bundles(); set_toggle_button( "button_252", vims_verbosity ); vj_gui_disable(); } static gboolean update_log(gpointer data) { if(info->state != STATE_PLAYING) return TRUE; gint len = 0; single_vims( VIMS_LOG ); gchar *buf = recv_log_vims(6, &len ); if(len > 0 ) { GtkWidget *view = glade_xml_get_widget_( info->main_window, "veejaytext"); GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view)); GtkTextIter iter,enditer; if(line_count > 100) { clear_textview_buffer( "veejaytext" ); line_count = 1; } gtk_text_buffer_get_end_iter(buffer, &iter); int nr,nw; gchar *text = g_locale_to_utf8( buf, -1, &nr, &nw, NULL); gtk_text_buffer_insert( buffer, &iter, text, nw ); line_count ++; gtk_text_buffer_get_end_iter(buffer, &enditer); gtk_text_view_scroll_to_iter( GTK_TEXT_VIEW(view), &enditer, 0.0, FALSE, 0.0, 0.0 ); g_free( text ); } return TRUE; } gboolean enter_videobook(GtkWidget *w, gpointer user_data) { fprintf(stderr, "enter\n"); return FALSE; } gboolean leave_videobook(GtkWidget *w, gpointer user_data) { fprintf(stderr, "leave\n"); return FALSE; } void vj_gui_preview(void) { if(info->preview_ready) return; gint w = info->el.width; gint h = info->el.height; if(info->preview_size_w != 0) w = info->preview_size_w; if(info->preview_size_h != 0) h = info->preview_size_h; update_spin_value( "priout_width", w ); update_spin_value( "priout_height", h ); if( w > 352 ) w = 352; if( h > 288 ) h = 288; update_spin_range( "preview_width", 16, w, (info->run_state == RUN_STATE_REMOTE ? ((info->preview_size_w==0 ? w/2: info->preview_size_w)) : w ) ); update_spin_range( "preview_height", 16, h, (info->run_state == RUN_STATE_REMOTE ? ((info->preview_size_h == 0 ? h/2 : info->preview_size_h)) : h ) ); update_spin_incr( "preview_width", 16, 0 ); update_spin_incr( "preview_height", 16, 0 ); update_spin_incr( "priout_width", 16,0 ); update_spin_incr( "priout_height", 16, 0 ); info->preview_ready = 1; } int vj_gui_reconnect(char *hostname,char *group_name, int port_num) { info->client = vj_client_alloc(0,0,0); if(!vj_client_connect( info->client, hostname, group_name, port_num ) ) { if(info->client) vj_client_free(info->client); info->client = NULL; info->run_state = 0; return 0; } vj_msg(VEEJAY_MSG_INFO, "New connection with Veejay running on %s port %d", (group_name == NULL ? hostname : group_name), port_num ); int k = 0; for( k = 0; k < 3; k ++ ) memset( info->history_tokens[k] , 0, (sizeof(int) * STATUS_TOKENS) ); info->channel = g_io_channel_unix_new( vj_client_get_status_fd( info->client, V_STATUS)); info->state = STATE_PLAYING; g_io_add_watch_full( info->channel, G_PRIORITY_DEFAULT, G_IO_IN| G_IO_ERR | G_IO_NVAL | G_IO_HUP, veejay_tick, (gpointer*) info, veejay_untick ); info->logging = g_timeout_add( 600, update_log,(gpointer*) info ); load_editlist_info(); init_cpumeter(); /* Now setup preview image size */ if(info->rawdata) free(info->rawdata); info->rawdata = (guchar*) vj_malloc(sizeof(guchar) * info->el.width * info->el.height * 3); memset(info->rawdata,0,sizeof(guchar) * info->el.width * info->el.height * 3 ); memset( &vims_keys_list, 0, sizeof(vims_keys_t)); load_effectlist_info(); reload_vimslist(); reload_editlist_contents(); reload_bundles(); // load_samplelist_info(true); // if( skin__ == 0 ) // { GtkWidget *w = glade_xml_get_widget_(info->main_window, "gveejay_window" ); // GtkWidget *w2 = glade_xml_get_widget_(info->main_window, "veejay_connection"); gtk_widget_show( w ); // gtk_widget_hide( w2); //} info->uc.reload_hint[HINT_SLIST] = 1; info->uc.reload_hint[HINT_CHAIN] = 1; info->uc.reload_hint[HINT_ENTRY] = 1; int speed = info->status_tokens[SAMPLE_SPEED]; if( speed < 0 ) info->play_direction = -1; else info->play_direction=1; if( speed < 0 ) speed *= -1; //update_slider_range( "speedslider",0,68, speed, 0); update_spin_range( "spin_framedelay", 0, 9, 0); update_slider_range( "speed_slider", -25,25,speed,0); update_label_i( "speed_label", speed,0); // update_knob_range(info->speed_knob, 1,25, speed, 0); if( info->run_state == RUN_STATE_LOCAL) set_toggle_button( "previewtoggle", 1 ); update_label_str( "label_hostnamex", (hostname == NULL ? group_name: hostname ) ); update_label_i( "label_portx",port_num,0); info->key_id = gtk_key_snooper_install( key_handler , NULL); info->preview_ready = 0; return 1; } static void veejay_stop_connecting(vj_gui_t *gui) { GtkWidget *veejay_conncection_window; if(!gui->sensitive) vj_gui_enable(); vj_launch_toggle(TRUE); /*gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR (glade_xml_get_widget_(info->main_window, "connecting")),0.0); g_source_remove( info->connecting ); info->connecting = 0;*/ veejay_conncection_window = glade_xml_get_widget(info->main_window, "veejay_connection"); gtk_widget_hide(veejay_conncection_window); } gboolean is_alive(gpointer data) { vj_gui_t *gui = (vj_gui_t*) data; if(gui->state == STATE_IDLE || gui->state == STATE_STOPPED ) { if(gui->sensitive) vj_gui_disable(); if(!gui->launch_sensitive) vj_launch_toggle(TRUE); } if( gui->state == STATE_RECONNECT ) { struct timeval timenow; gettimeofday(&timenow, NULL); /* at least 2 seconds before trying to connect !*/ if( (timenow.tv_sec - info->alarm.tv_sec) < TIMEOUT_SECONDS ) { if( (timenow.tv_usec - info->timer.tv_usec) > 1.0) { char *remote = get_text( "entry_hostname" ); int port = get_nums( "button_portnum" ); if(!vj_gui_reconnect( remote, NULL, port )) { gui->state = STATE_RECONNECT; memcpy(&(info->timer),&timenow,sizeof(timenow)); } } } else { vj_gui_stop_launch(); if(info->run_state == RUN_STATE_LOCAL) { message_dialog( "Run Error", "Failed to start local Veejay - check configuration"); } else { gchar hello_world[100]; sprintf(hello_world, "Failed to make a connection with %s : %d",get_text("entry_hostname"), get_nums("button_portnum") ); message_dialog( "Failed connection", hello_world ); } } } if( gui->state == STATE_PLAYING ) { vj_gui_preview(); if(!gui->sensitive) { vj_gui_enable(); veejay_stop_connecting(gui); } } return TRUE; } void vj_gui_disconnect() { info->state = STATE_IDLE; if(info->client) { g_io_channel_shutdown(info->channel, FALSE, NULL); g_io_channel_unref(info->channel); g_source_remove( info->logging ); vj_client_close(info->client); vj_client_free(info->client); info->client = NULL; info->run_state = 0; gtk_key_snooper_remove( info->key_id ); vj_msg(VEEJAY_MSG_INFO, "Disconnected - Use Launcher"); } /* reset all trees */ reset_tree("tree_effectlist"); reset_tree("tree_effectmixlist"); reset_tree("tree_chain"); reset_tree("tree_sources"); reset_tree("editlisttree"); /* clear console text */ clear_textview_buffer("veejaytext"); free_samplebank(); info->preview_ready = 0; // if( skin__ == 0 ) // { // GtkWidget *w = glade_xml_get_widget_( info->main_window, "gveejay_window"); // gtk_widget_hide( w ); // } } void vj_launch_toggle(gboolean value) { GtkWidget *w = glade_xml_get_widget_(info->main_window, "button_veejay" ); gtk_widget_set_sensitive( GTK_WIDGET(w), value ); info->launch_sensitive = ( value == TRUE ? 1 : 0); } void vj_gui_disable() { int i = 0; while( gwidgets[i].name != NULL ) { disable_widget( gwidgets[i].name ); i++; } disable_widget_by_pointer(info->audiovolume_knob); // disable_widget_by_pointer(info->speed_knob); // gtk_widget_set_sensitive( GTK_WIDGET( // glade_xml_get_widget_(info->main_window, "button_loadconfigfile") ), TRUE ); info->sensitive = 0; set_toggle_button( "previewtoggle", 0 ); enable_widget ("vs_box" ); } void vj_gui_enable() { int i =0; while( gwidgets[i].name != NULL) { enable_widget( gwidgets[i].name ); i++; } enable_widget_by_pointer(info->audiovolume_knob); // enable_widget_by_pointer(info->speed_knob); enable_widget( "speed_slider"); // disable loadconfigfile // gtk_widget_set_sensitive( GTK_WIDGET( // glade_xml_get_widget_(info->main_window, "button_loadconfigfile") ), FALSE ); info->sensitive = 1; disable_widget( "vs_box" ); } /* void vj_gui_put_image(void) { GtkWidget *pixbuf_widget = glade_xml_get_widget_( info->main_window, "imageA" ); GdkPixbuf *pixbuf = NULL; gint w = 100; gint h = 100; gint row_strides = 3 * w; gint bw = 0; // veejay sends current frame as image in RGB, 8 bytes per sample // send 'get image' message multi_vims( VIMS_RGB24_IMAGE, "%d %d", w ,h ); // read image from socket, store length of image in bw gchar *rawdata = recv_vims( 5, &bw ); if(bw<=0 ) { if (rawdata) free(rawdata); return ; } GdkPixbuf *old_image = gtk_image_get_pixbuf( pixbuf_widget ); // create a new picture from memory pixbuf = gdk_pixbuf_new_from_data( rawdata,GDK_COLORSPACE_RGB, false,8,w,h,row_strides,NULL,NULL ); // set picture gtk_image_set_from_pixbuf(pixbuf_widget,pixbuf); // free ? //@ gdk_pixbuf_unref(pixbuf); g_free(rawdata); } */ /* -------------------------------------------------------------------------------------------------------------------------- * Returns infos to a given sample/stream... use as follows * which_one decides what sample/stream do you mean: 0 = current playing, -1 = last created, > 0 = sample number * mode decides if you gather informations of a sample (== VJ_PLAYBACK_MODE_SAMPLE) or a stream (== VJ_PLAYBACK_MODE_TAG) to see, why this is made see comments in veejay/vj-event.c in void vj_event_send_sample_info(..) * s_type, descr and timecode are pointers to return the loaded values of the selected sample/stream * This function loads the SAMPLE_INFO to a new temporary sample_slot you should free after use -------------------------------------------------------------------------------------------------------------------------- */ sample_slot_t *vj_gui_get_sample_info(gint which_one, gint mode ) { sample_slot_t *tmp_slot = (sample_slot_t*) vj_malloc(sizeof(sample_slot_t)); memset( tmp_slot, 0, sizeof(sample_slot_t)); multi_vims( VIMS_SAMPLE_INFO, "%d %d", which_one, mode ); gint sample_info_len = 0; gchar *sample_info = recv_vims( 5, &sample_info_len); gchar *ptr = sample_info; // gint descr_len = 0; gchar *p = sample_info; if(sample_info_len <= 0 ) { if(sample_info) g_free(sample_info); if(tmp_slot) free(tmp_slot); return NULL; } sscanf(sample_info, "%d",&descr_len ); sample_info += 3; tmp_slot->title = g_strndup( sample_info, descr_len ); sample_info += descr_len; gint timecode_len = 0; sscanf( sample_info,"%d", &timecode_len ); sample_info += 3; tmp_slot->timecode = g_strndup( sample_info, timecode_len ); sample_info += timecode_len; tmp_slot->sample_id = which_one; tmp_slot->sample_type = mode; if(p) g_free(p); return tmp_slot; } static void widget_get_rect_in_screen (GtkWidget *widget, GdkRectangle *r) { gint x,y,w,h; GdkRectangle extents; GdkWindow *window; window = gtk_widget_get_parent_window(widget); /* getting parent window */ gdk_window_get_root_origin(window, &x,&y); /* parent's left-top screen coordinates */ gdk_drawable_get_size(window, &w,&h); /* parent's width and height */ gdk_window_get_frame_extents(window, &extents); /* parent's extents (including decorations) */ r->x = x + (extents.width-w)/2 + widget->allocation.x; /* calculating x (assuming: left border size == right border size) */ r->y = y + (extents.height-h)-(extents.width-w)/2 + widget->allocation.y; /* calculating y (assuming: left border size == right border size == bottom border size) */ r->width = widget->allocation.width; r->height = widget->allocation.height; } /* -------------------------------------------------------------------------------------------------------------------------- * Function that creates the sample-bank initially, just add the widget to the GUI and create references for the * sample_banks-structure so that the widgets are easiely accessable * The GUI componenets are in sample_bank[i]->gui_slot[j] * -------------------------------------------------------------------------------------------------------------------------- */ int power_of_2(int x) { int p = 1; while( p < x ) p <<= 1; return p; } /* Add a page to the notebook and initialize slots */ static int add_bank( gint bank_num ) { gchar str_label[5]; gchar frame_label[20]; sprintf(str_label, "%d", bank_num ); sprintf(frame_label, "Samples %d to %d", (bank_num * NUM_SAMPLES_PER_PAGE), (bank_num * NUM_SAMPLES_PER_PAGE) + NUM_SAMPLES_PER_PAGE ); /* Check image dimensions */ if( info->image_dimensions[0] == 0 && info->image_dimensions[1] == 0 ) setup_samplebank( NUM_SAMPLES_PER_COL, NUM_SAMPLES_PER_ROW ); /* Add requested bank num */ if(info->sample_banks[bank_num] ) { exit(0); } info->sample_banks[bank_num] = (sample_bank_t*) vj_malloc(sizeof(sample_bank_t)); memset(info->sample_banks[bank_num],0,sizeof(sample_bank_t)); info->sample_banks[bank_num]->bank_number = bank_num; sample_slot_t **slot = (sample_slot_t**) vj_malloc(sizeof(sample_slot_t*) * NUM_SAMPLES_PER_PAGE); sample_gui_slot_t **gui_slot = (sample_gui_slot_t**) vj_malloc(sizeof(sample_gui_slot_t*) * NUM_SAMPLES_PER_PAGE ); int j; for(j = 0;j < NUM_SAMPLES_PER_PAGE; j ++ ) { slot[j] = (sample_slot_t*) vj_malloc(sizeof(sample_slot_t) ); gui_slot[j] = (sample_gui_slot_t*) vj_malloc(sizeof(sample_gui_slot_t)); memset(slot[j], 0 , sizeof(sample_slot_t) ); memset(gui_slot[j], 0, sizeof(sample_gui_slot_t)); slot[j]->rawdata = (guchar*) vj_malloc(sizeof(guchar) * 3 * 256 * 256 ); slot[j]->slot_number = j; slot[j]->sample_id = -1; slot[j]->sample_type = -1; } info->sample_banks[bank_num]->slot = slot; info->sample_banks[bank_num]->gui_slot = gui_slot; GtkWidget *sb = info->sample_bank_pad; GtkFrame *frame = gtk_frame_new(frame_label); GtkWidget *label = gtk_label_new( str_label ); gtk_widget_set_size_request(frame, 200,200 ); gtk_widget_show(frame); info->sample_banks[bank_num]->page_num = gtk_notebook_append_page(GTK_NOTEBOOK(info->sample_bank_pad), frame, label); GtkWidget *table = gtk_table_new( NUM_SAMPLES_PER_COL, NUM_SAMPLES_PER_ROW, true ); gtk_container_add( GTK_CONTAINER(frame), table ); gtk_widget_show(table); gtk_widget_show(sb ); gint col, row; for( col = 0; col < NUM_SAMPLES_PER_COL; col ++ ) { for( row = 0; row < NUM_SAMPLES_PER_ROW; row ++ ) { int slot_nr = col * NUM_SAMPLES_PER_ROW + row; if(slot_nr < NUM_SAMPLES_PER_PAGE) { create_slot( bank_num, slot_nr ,info->image_dimensions[0], info->image_dimensions[1]); sample_gui_slot_t *gui_slot = info->sample_banks[bank_num]->gui_slot[slot_nr]; gtk_table_attach_defaults ( table, gui_slot->event_box, row, row+1, col, col+1); } } } if(!info->fg_) { info->fg_ = widget_get_fg( info->sample_banks[bank_num]->gui_slot[0]->frame ); } return bank_num; } void free_samplebank(void) { int i,j; while( gtk_notebook_get_n_pages(GTK_NOTEBOOK(info->sample_bank_pad) ) > 0 ) gtk_notebook_remove_page( GTK_NOTEBOOK(info->sample_bank_pad), -1 ); info->selection_slot = NULL; info->selection_gui_slot = NULL; info->selected_slot = NULL; info->selected_gui_slot = NULL; for( i = 0; i < NUM_BANKS; i ++ ) { if(info->sample_banks[i]) { /* free memory in use */ for(j = 0; j < NUM_SAMPLES_PER_PAGE ; j ++ ) { sample_slot_t *slot = info->sample_banks[i]->slot[j]; sample_gui_slot_t *gslot = info->sample_banks[i]->gui_slot[j]; if(slot->title) free(slot->title); if(slot->timecode) free(slot->timecode); if(slot->pixbuf) gdk_pixbuf_unref(slot->pixbuf); if(slot->rawdata) free(slot->rawdata); if(slot->ec) del_chain( slot->ec ); free(slot); // if(gslot->title) g_object_unref( gslot->title ); // if(gslot->timecode) g_object_unref(gslot->title); // if(gslot->image) g_object_unref( gslot->image ); // if(gslot->event_box) g_object_unref( gslot->event_box ); // if(gslot->main_vbox) g_object_unref( gslot->main_vbox ); // if(gslot->upper_vbox) g_object_unref( gslot->upper_vbox ); // if(gslot->upper_hbox) g_object_unref( gslot->upper_hbox ); // if(gslot->frame ) g_object_unref( gslot->frame ); if(gslot) free(gslot); } free(info->sample_banks[i]); } } memset( info->sample_banks, 0, sizeof(sample_bank_t*) * NUM_BANKS ); GtkWidget *imgA = glade_xml_get_widget_ (info->main_window, "imageA" ); if(imgA) { char path[MAX_PATH_LEN]; bzero(path,MAX_PATH_LEN); get_gd(path,NULL, "veejay-logo.png"); GdkPixbuf *buf = gdk_pixbuf_new_from_file( path,NULL ); gtk_image_set_from_pixbuf( imgA, buf ); gdk_pixbuf_unref( buf ); } g_source_remove( info->imageA ); } void setup_samplebank(gint num_cols, gint num_rows) { sample_bank_t **sample_banks = info->sample_banks; // print width of notebook samples GdkRectangle result; widget_get_rect_in_screen( info->sample_bank_pad, &result ); // gint image_width = 44; // gint image_height = 36; gint image_width = result.width / num_cols; gint image_height = result.height / num_rows; // info->image_dimensions[0] = 44; // info->image_dimensions[1] = 36; info->image_dimensions[0] = image_width * 0.7; info->image_dimensions[1] = image_height * 0.7; } /* -------------------------------------------------------------------------------------------------------------------------- * Function that resets the visualized sample-informations of the samplebanks, it does this by going through all * slots that allready used and resets them (which means cleaning the shown infos as well as set them free for further use) * with_selection should be TRUE when the actual selection of a sample-bank-slot should also be reseted * (what is for instance necessary when vj reconnected) -------------------------------------------------------------------------------------------------------------------------- */ static int bank_exists( int bank_page, int slot_num ) { if(!info->sample_banks[bank_page]) return 0; return 1; } static int find_bank_by_sample(int sample_id, int sample_type, int *slot ) { int i; /* See if ID is somewhere in the samplebank */ for( i = 0; i < NUM_BANKS; i ++ ) { int j; if(info->sample_banks[i]) for( j = 0; j < NUM_SAMPLES_PER_PAGE; j ++ ) { if(info->sample_banks[i]->slot[j]->sample_id == sample_id && info->sample_banks[i]->slot[j]->sample_type == sample_type ) { *slot = j; return i; } } } /* Fall back to suggest a bank number to add the new id */ for( i = 0; i < NUM_BANKS; i ++ ) { if(!info->sample_banks[i]) /* First slot in bank */ { *slot = 0; return i; } else { int j; /* Scan for available slots in this bank page */ for( j = 0; j < NUM_SAMPLES_PER_PAGE; j ++ ) { if( info->sample_banks[i]->slot[j]->sample_id <= 0 ) { *slot = j; return i; } } } } /* Everything is full ?? TODO: Error checking/handling*/ *slot = -1; return -1; } static int find_bank(int page_nr) { int i = 0; for ( i = 0 ; i < NUM_BANKS; i ++ ) if( info->sample_banks[i] && info->sample_banks[i]->page_num == page_nr ) { return info->sample_banks[i]->bank_number; } return -1; }/* static int find_free_bank_slot(void) { int i = 0; for( i = 0; i < NUM_BANKS; i++ ) if(info->sample_banks[i]) { int j; for(j = 0; j < NUM_SAMPLES_PER_PAGE; j ++ ) if(info->sample_banks[i]->slot[j]->sample_id == 0 ) return i; } } */ static int find_free_bank(void) { int i = 0; for ( i = 0 ; i < NUM_BANKS; i ++ ) if(!info->sample_banks[i]) return i; return -1; } /* -------------------------------------------------------------------------------------------------------------------------- * Function that creates one sample-bank-slot and also builds up the sample_banks-structure -------------------------------------------------------------------------------------------------------------------------- static gboolean image_configure_event (GtkWidget *widget, GdkEventConfigure *event, gpointer data) { GtkWidget *notepad = glade_xml_get_widget(info->main_window, "sample_bank"); gint slot = (gint*) data; gint page = gtk_notebook_get_current_page( GTK_NOTEBOOK(notepad)); GdkPixbuf *old_pixbuf = (GdkPixbuf*) g_object_get_data( G_OBJECT(widget), "pixbuf" ); GdkPixbuf *pixbuf = info->sample_banks[page]->slot[slot]->pixbuf; g_object_set_data( G_OBJECT(widget), "pixbuf", pixbuf ); g_object_unref( old_pixbuf ); return FALSE; } */ static int compare_pixbuf(GdkPixbuf *a, GdkPixbuf *b) { guchar *A = gdk_pixbuf_get_pixels( a ); guchar *B = gdk_pixbuf_get_pixels( b ); gint aN = gdk_pixbuf_get_width(a ) * gdk_pixbuf_get_height(a); gint bN = gdk_pixbuf_get_width(b ) * gdk_pixbuf_get_height(b); gint i; gint kN = (aN < bN ? aN : bN ); for( i = 0; i < kN; i ++ ) { if(A[i] != B[i]) return 0; } return 1; } /* Redraw the screen from the backing pixmapap */ static gboolean image_expose_event (GtkWidget *widget, GdkEventExpose *event, gpointer data) { guchar *pixels; int rowstride; // ha ha redraw whole page ! GtkWidget *notepad = info->sample_bank_pad; gint bank_nr = find_bank( gtk_notebook_get_current_page( GTK_NOTEBOOK(notepad)) ); if(no_draw_) return FALSE; if(bank_nr < 0 ) return FALSE; if ( info->sample_banks[bank_nr] == NULL ) { exit(0); } int i = (gint*) data; sample_slot_t *slot = info->sample_banks[bank_nr]->slot[i]; if(!slot->pixbuf || slot->sample_id <= 0 ) return FALSE; sample_gui_slot_t *guislot = info->sample_banks[bank_nr]->gui_slot[i]; if(slot->pixbuf != NULL && slot->sample_id > 0 && is_button_toggled("previewtoggle")) { rowstride = gdk_pixbuf_get_rowstride( slot->pixbuf ); g_assert( slot->pixbuf ); guchar *pixels = gdk_pixbuf_get_pixels( slot->pixbuf ) + rowstride * event->area.y + event->area.x * 3; if(pixels && rowstride > 0) gdk_draw_rgb_image_dithalign( widget->window, widget->style->black_gc, // event->area.x, event->area.y, 0,0,info->image_dimensions[0],info->image_dimensions[1], // event->area.width, event->area.height, GDK_RGB_DITHER_NORMAL, pixels, rowstride, event->area.x , event->area.y ); } return FALSE; } // TODO: merge with image_expose event ? static gboolean image_expose_seq_event (GtkWidget *widget, GdkEventExpose *event, gpointer data) { guchar *pixels; int rowstride; int j = (gint*) data; // sequence slot number /* sample_slot_t *slot = info->sample_banks[bank_nr]->slot[i]; if(!slot->pixbuf || slot->sample_id <= 0 ) return FALSE; sample_gui_slot_t *guislot = info->sample_banks[bank_nr]->gui_slot[i]; if(slot->pixbuf && slot->sample_id > 0) { rowstride = gdk_pixbuf_get_rowstride( slot->pixbuf ); guchar *pixels = gdk_pixbuf_get_pixels( slot->pixbuf ) + rowstride * event->area.y + event->area.x * 3; if(pixels) gdk_draw_rgb_image_dithalign( widget->window, widget->style->black_gc, // event->area.x, event->area.y, 0,0,info->image_dimensions[0],info->image_dimensions[1], // event->area.width, event->area.height, GDK_RGB_DITHER_NORMAL, pixels, rowstride, event->area.x , event->area.y ); }*/ if(info->sequence_view->w == 0 || info->sequence_view->h == 0 ) { sequence_gui_slot_t *g = info->sequence_view->gui_slot[j]; GdkRectangle result; widget_get_rect_in_screen( g->frame, &result ); info->sequence_view->w = result.width; info->sequence_view->h = result.height; return FALSE; } if(no_draw_) return FALSE; if( info->sequence_view->gui_slot[j]->pixbuf_ref && is_button_toggled("previewtoggle")) { sequence_gui_slot_t *g = info->sequence_view->gui_slot[j]; if(!g->sample_id) return FALSE; if(!g->pixbuf_ref ) return FALSE; g_assert( g->pixbuf_ref ); rowstride = gdk_pixbuf_get_rowstride( g->pixbuf_ref ); guchar *pixels = gdk_pixbuf_get_pixels( g->pixbuf_ref ) + rowstride * event->area.y + event->area.x * 3; if(pixels) gdk_draw_rgb_image_dithalign( widget->window, widget->style->black_gc, 0,0,info->sequence_view->w, info->sequence_view->h, GDK_RGB_DITHER_NORMAL, pixels, rowstride, event->area.x , event->area.y ); } return FALSE; } static void set_activation_of_cache_slot_in_samplebank( sequence_gui_slot_t *gui_slot, gboolean activate) { if (activate) { gtk_frame_set_shadow_type(gui_slot->frame,GTK_SHADOW_IN); } else gtk_frame_set_shadow_type(gui_slot->frame,GTK_SHADOW_ETCHED_IN); } static void update_cached_slots(void) { int i; if(info->sequence_view->w == 0 || info->sequence_view->h == 0 ) return; for( i = 0; i < info->sequence_view->envelope_size; i ++ ) { sequence_gui_slot_t *g = info->sequence_view->gui_slot[i]; sample_slot_t *s = info->selected_slot; if(g->sample_id == info->selected_slot->sample_id && g->sample_type == info->selected_slot->sample_type && s->pixbuf) { if(!g->pixbuf_ref && is_button_toggled("previewtoggle")) { g->pixbuf_ref = gdk_pixbuf_scale_simple( s->pixbuf, info->sequence_view->w, info->sequence_view->h, GDK_INTERP_BILINEAR ); } } } gtk_widget_queue_draw( info->quick_select ); } static gboolean on_cacheslot_activated_by_mouse (GtkWidget *widget, GdkEventButton *event, gpointer user_data) { gint bank_nr = -1; gint slot_nr = -1; if(info->status_tokens[PLAY_MODE] == MODE_PLAIN ) return FALSE; slot_nr = (gint *)user_data; set_activation_of_cache_slot_in_samplebank( info->sequence_view->gui_slot[slot_nr], false ); if( event->type == GDK_BUTTON_PRESS && (event->state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK ) { info->current_sequence_slot = slot_nr; sample_slot_t *s = info->selected_slot; sequence_gui_slot_t *g = info->sequence_view->gui_slot[slot_nr]; /* if(!s->pixbuf) { fprintf(stderr, "Slot with id %d is empty?\n", s->sample_id ); return FALSE;} if(g->pixbuf_ref) gdk_pixbuf_unref( g->pixbuf_ref ); g->pixbuf_ref = gdk_pixbuf_scale_simple( s->pixbuf, info->sequence_view->w, info->sequence_view->h, GDK_INTERP_BILINEAR ); */ g->sample_id = s->sample_id; g->sample_type = s->sample_type; vj_msg(VEEJAY_MSG_INFO, "Placed %s %d in Memory slot %d", (g->sample_type == 0 ? "Sample" : "Stream" ), g->sample_id, slot_nr ); } else if(event->type == GDK_BUTTON_PRESS) { sequence_gui_slot_t *g = info->sequence_view->gui_slot[slot_nr]; if(g->sample_id <= 0) { vj_msg(VEEJAY_MSG_ERROR, "Memory slot %d empty, put with SHIFT + mouse button1",slot_nr); return FALSE; } multi_vims(VIMS_SET_MODE_AND_GO, "%d %d", g->sample_type, g->sample_id ); } return FALSE; } static void create_ref_slots(int envelope_size) { gchar frame_label[50]; GtkWidget *vbox = glade_xml_get_widget_ (info->main_window, "quickselect"); info->quick_select = gtk_frame_new(NULL); gtk_widget_set_size_request(info->quick_select, 400,40 ); gtk_box_pack_start( GTK_BOX( vbox ), GTK_WIDGET(info->quick_select), TRUE, TRUE, 0); gtk_widget_show(info->quick_select); /* Allocate */ info->sequence_view = (sequence_envelope*) vj_malloc(sizeof(sequence_envelope) ); memset( info->sequence_view, 0, sizeof( sequence_envelope ) ); info->sequence_view->gui_slot = (sequence_gui_slot_t**) vj_malloc(sizeof(sequence_gui_slot_t*) * envelope_size ); memset( info->sequence_view->gui_slot, 0, sizeof( sequence_gui_slot_t*) * envelope_size ); /* Setup table for slots */ sprintf(frame_label, "Last played" ); GtkWidget *table = gtk_table_new( 1, envelope_size, true ); gtk_container_add( GTK_CONTAINER(info->quick_select), table ); gtk_widget_show(table); gint col=0; gint row=0; for( row = 0; row < envelope_size; row ++ ) { sequence_gui_slot_t *gui_slot = (sequence_gui_slot_t*)vj_malloc(sizeof(sequence_gui_slot_t)); memset(gui_slot, 0, sizeof(sequence_gui_slot_t)); info->sequence_view->gui_slot[row] = gui_slot; gui_slot->event_box = gtk_event_box_new(); gtk_event_box_set_visible_window(gui_slot->event_box, TRUE); GTK_WIDGET_SET_FLAGS(gui_slot->event_box,GTK_CAN_FOCUS); /* Right mouse button is popup menu, click = play */ g_signal_connect( G_OBJECT(gui_slot->event_box), "button_press_event", G_CALLBACK(on_cacheslot_activated_by_mouse), (gpointer)row ); gtk_widget_show(GTK_WIDGET(gui_slot->event_box)); /* the surrounding frame for each slot */ gui_slot->frame = gtk_frame_new(NULL); gtk_container_set_border_width (GTK_CONTAINER(gui_slot->frame),1); gtk_widget_show(GTK_WIDGET(gui_slot->frame)); gtk_container_add (GTK_CONTAINER (gui_slot->event_box), gui_slot->frame); /* the slot main container */ gui_slot->main_vbox = gtk_vbox_new(false,0); gtk_container_add (GTK_CONTAINER (gui_slot->frame), gui_slot->main_vbox); gtk_widget_show( GTK_WIDGET(gui_slot->main_vbox) ); /* The sample's image */ gui_slot->image = gtk_drawing_area_new(); gtk_box_pack_start (GTK_BOX (gui_slot->main_vbox), GTK_WIDGET(gui_slot->image), TRUE, TRUE, 0); gtk_widget_set_size_request( gui_slot->image, info->sequence_view->w,info->sequence_view->h ); g_signal_connect( gui_slot->image, "expose_event", G_CALLBACK(image_expose_seq_event), (gpointer) row ); gtk_widget_show( GTK_WIDGET(gui_slot->image)); gtk_table_attach_defaults ( table, gui_slot->event_box, row, row+1, col, col+1); } info->sequence_view->w = 0; info->sequence_view->h = 0; info->sequence_view->envelope_size = envelope_size; } static void create_slot(gint bank_nr, gint slot_nr, gint w, gint h) { gchar hotkey[3]; gchar descr[50]; char debug[15]; sample_bank_t **sample_banks = info->sample_banks; sample_gui_slot_t *gui_slot = sample_banks[bank_nr]->gui_slot[slot_nr]; // sprintf( descr, "%s %d", (sample_banks[bank_nr]->slot[slot_nr]->sample_type == 0 ? "Sample" : "Stream" ), // sample_banks[bank_nr]->slot[slot_nr]->sample_id ); if(gui_slot->event_box != NULL ) { fprintf(stderr, "Already created ! %p\n", gui_slot->event_box ); exit(0); } if( slot_nr < 0 || slot_nr > NUM_SAMPLES_PER_PAGE) exit(0); // to reach clicks on the following GUI-Elements of one slot, they are packed into an event_box gui_slot->event_box = gtk_event_box_new(); gtk_event_box_set_visible_window(gui_slot->event_box, TRUE); GTK_WIDGET_SET_FLAGS(gui_slot->event_box,GTK_CAN_FOCUS); g_signal_connect( G_OBJECT(gui_slot->event_box), "button_press_event", G_CALLBACK(on_slot_activated_by_mouse), (gpointer)slot_nr ); g_signal_connect( G_OBJECT(gui_slot->event_box), "key_press_event", G_CALLBACK(on_slot_activated_by_key), (gpointer)slot_nr ); gtk_widget_show(GTK_WIDGET(gui_slot->event_box)); /* the surrounding frame for each slot */ gui_slot->frame = gtk_frame_new(NULL); gtk_container_set_border_width (GTK_CONTAINER(gui_slot->frame),1); gtk_widget_show(GTK_WIDGET(gui_slot->frame)); gtk_container_add (GTK_CONTAINER (gui_slot->event_box), gui_slot->frame); /* the slot main container */ gui_slot->main_vbox = gtk_vbox_new(false,0); gtk_container_add (GTK_CONTAINER (gui_slot->frame), gui_slot->main_vbox); gtk_widget_show( GTK_WIDGET(gui_slot->main_vbox) ); // gui_slot->image = gtk_image_new(); gui_slot->image = gtk_drawing_area_new(); gtk_box_pack_start (GTK_BOX (gui_slot->main_vbox), GTK_WIDGET(gui_slot->image), TRUE, TRUE, 0); // gtk_widget_show(GTK_WIDGET(gui_slot->image)); gtk_widget_set_size_request( gui_slot->image, info->image_dimensions[0],info->image_dimensions[1] ); g_signal_connect( gui_slot->image, "expose_event", G_CALLBACK(image_expose_event), (gpointer) info->sample_banks[bank_nr]->slot[slot_nr]->slot_number ); gtk_widget_show( GTK_WIDGET(gui_slot->image)); /* the upper container for all slot-informations */ gui_slot->upper_hbox = gtk_hbox_new(false,0); gtk_box_pack_start (GTK_BOX (gui_slot->main_vbox), gui_slot->upper_hbox, FALSE, TRUE, 0); gtk_widget_show(GTK_WIDGET(gui_slot->upper_hbox)); if( sample_banks[bank_nr]->slot[slot_nr]->sample_type >= 0 ) { /* the hotkey that is assigned to this slot */ sprintf(hotkey, "F-%d", (slot_nr+1)); gui_slot->hotkey = GTK_LABEL(gtk_label_new(hotkey)); } else { gui_slot->hotkey = GTK_LABEL(gtk_label_new("")); } gtk_misc_set_alignment(GTK_MISC(gui_slot->hotkey), 0.0, 0.0); gtk_misc_set_padding (GTK_MISC(gui_slot->hotkey), 0, 0); gtk_box_pack_start (GTK_BOX (gui_slot->upper_hbox), GTK_WIDGET(gui_slot->hotkey), FALSE, FALSE, 0); gtk_widget_show(GTK_WIDGET(gui_slot->hotkey)); gui_slot->upper_vbox = gtk_vbox_new(false,0); gtk_box_pack_start (GTK_BOX (gui_slot->upper_hbox), gui_slot->upper_vbox, TRUE, TRUE, 0); gtk_widget_show(GTK_WIDGET(gui_slot->upper_vbox)); gui_slot->title = GTK_LABEL(gtk_label_new("")); gtk_misc_set_alignment(GTK_MISC(gui_slot->title), 0.00, 0.00); gtk_misc_set_padding (GTK_MISC(gui_slot->title), 0, 0); gtk_box_pack_start (GTK_BOX (gui_slot->upper_vbox), GTK_WIDGET(gui_slot->title), FALSE, FALSE, 0); gtk_widget_show(GTK_WIDGET(gui_slot->title)); gui_slot->timecode = GTK_LABEL(gtk_label_new("")); gtk_misc_set_alignment(GTK_MISC(gui_slot->timecode), 0.0, 0.0); gtk_misc_set_padding (GTK_MISC(gui_slot->timecode), 0,0 ); gtk_box_pack_start (GTK_BOX (gui_slot->upper_vbox), GTK_WIDGET(gui_slot->timecode), FALSE, FALSE, 0); gtk_widget_show(GTK_WIDGET(gui_slot->timecode)); } /* -------------------------------------------------------------------------------------------------------------------------- * Handler of mouse clicks on the GUI-elements of one slot * single-click activates the slot and the loaded sample (if there is one) * double-click or tripple-click activates it and plays it immediatelly -------------------------------------------------------------------------------------------------------------------------- */ static gboolean on_slot_activated_by_mouse (GtkWidget *widget, GdkEventButton *event, gpointer user_data) { gint bank_nr = -1; gint slot_nr = -1; bank_nr = find_bank( gtk_notebook_get_current_page(GTK_NOTEBOOK(info->sample_bank_pad))); if(bank_nr < 0 ) return FALSE; slot_nr = (gint *)user_data; sample_bank_t **sample_banks = info->sample_banks; /* Dont select slot if nothing is there */ if( info->sample_banks[ bank_nr ]->slot[ slot_nr ]->sample_id <= 0 ) return FALSE; // if(info->selected_gui_slot != NULL || info->selected_slot != NULL ) // set_activation_of_slot_in_samplebank( false ); if( event->type == GDK_2BUTTON_PRESS ) { sample_slot_t *s = sample_banks[bank_nr]->slot[slot_nr]; // info->selected_slot = sample_banks[bank_nr]->slot[slot_nr]; // info->selected_gui_slot = sample_banks[bank_nr]->gui_slot[slot_nr]; // fprintf(stderr, "New slot = %p\n",info->selected_slot); // set_activation_of_slot_in_samplebank(false); multi_vims( VIMS_SET_MODE_AND_GO, "%d %d", s->sample_type, s->sample_id); // gtk_widget_grab_focus(widget); } else if(event->type == GDK_BUTTON_PRESS ) { if(info->selection_slot) set_selection_of_slot_in_samplebank(false); info->selection_slot = sample_banks[bank_nr]->slot[slot_nr]; info->selection_gui_slot = sample_banks[bank_nr]->gui_slot[slot_nr]; set_selection_of_slot_in_samplebank(true ); } return FALSE; } /* -------------------------------------------------------------------------------------------------------------------------- * Handler of key presses on the GUI-elements of one slot -------------------------------------------------------------------------------------------------------------------------- */ static gboolean on_slot_activated_by_key (GtkWidget *widget, GdkEventKey *event, gpointer user_data) { // test printf("%s\n","press"); return FALSE; } /* -------------------------------------------------------------------------------------------------------------------------- * Function that handles to select/activate a special slot in the samplebank -------------------------------------------------------------------------------------------------------------------------- */ static void set_activation_of_slot_in_samplebank( gboolean activate) { if(!info->selected_gui_slot || !info->selected_slot ) return; GdkColor color; color.red = info->fg_->red; color.green = info->fg_->green; color.blue = info->fg_->blue; if(info->selected_slot->sample_id <= 0 ) { gtk_frame_set_shadow_type( info->selected_gui_slot->frame, GTK_SHADOW_ETCHED_IN ); } else { if (activate) { color.green = 0xffff; color.red = 0; color.blue =0; gtk_frame_set_shadow_type(info->selected_gui_slot->frame,GTK_SHADOW_IN); gtk_widget_grab_focus(info->selected_gui_slot->frame); } else { gtk_frame_set_shadow_type(info->selected_gui_slot->frame,GTK_SHADOW_ETCHED_IN); } } gtk_widget_modify_fg ( info->selected_gui_slot->title, GTK_STATE_NORMAL, &color ); gtk_widget_modify_fg ( info->selected_gui_slot->timecode, GTK_STATE_NORMAL, &color ); // gtk_widget_modify_fg ( gtk_frame_get_label_widget( info->selected_gui_slot->frame ), // GTK_STATE_NORMAL, &color ); } static void set_selection_of_slot_in_samplebank(gboolean active) { if(!info->selection_slot) return; if(info->selection_slot->sample_id <= 0 ) return; GdkColor color; color.red = info->fg_->red; color.green = info->fg_->green; color.blue = info->fg_->blue; if(active) { color.blue = 0xffff; color.green = 0; color.red =0; } if(info->selected_slot == info->selection_slot) { color.green = 0xffff; color.red = 0; color.blue = 0; } gtk_widget_modify_fg ( info->selection_gui_slot->title, GTK_STATE_NORMAL, &color ); gtk_widget_modify_fg ( info->selection_gui_slot->timecode, GTK_STATE_NORMAL, &color ); gtk_widget_modify_fg ( gtk_frame_get_label_widget( info->selection_gui_slot->frame ), GTK_STATE_NORMAL, &color ); } static int add_sample_to_sample_banks(int bank_page,sample_slot_t *slot) { /* Add the temporary sample */ // FIXME : slot loading int bp = 0; int s = 0; verify_bank_capacity( &bp, &s, slot->sample_id, slot->sample_type ); update_sample_slot_data( bp, s, slot->sample_id,slot->sample_type,slot->title,slot->timecode); return 1; } /* -------------------------------------------------------------------------------------------------------------------------- * Removes a selected sample from the specific sample-bank-slot and update the free_slots-GList as well as -------------------------------------------------------------------------------------------------------------------------- */ static void remove_sample_from_slot() { gint bank_nr = -1; gint slot_nr = -1; bank_nr = find_bank( gtk_notebook_get_current_page( GTK_NOTEBOOK( info->sample_bank_pad ) ) ); if(bank_nr < 0 ) return; if(!info->selection_slot) return; slot_nr = info->selection_slot->slot_number; if( info->selection_slot->sample_id == info->status_tokens[CURRENT_ID] && info->selection_slot->sample_type == info->status_tokens[PLAY_MODE] ) { gchar error_msg[100]; sprintf(error_msg, "Cannot delete %s %d while playing", (info->selection_slot->sample_type == MODE_SAMPLE ? "Sample" : "Stream" ), info->selection_slot->sample_id ); message_dialog( "Error while deleting", error_msg ); return; } multi_vims( (info->selection_slot->sample_type == 0 ? VIMS_SAMPLE_DEL : VIMS_STREAM_DELETE ), "%d", info->selection_slot->sample_id ); gint id_len = 0; gint deleted_sample = 0; gchar *deleted_id = recv_vims( 3, &id_len ); sscanf( deleted_id, "%d", &deleted_sample ); if( deleted_sample ) { // decrement history of delete type int *his = info->history_tokens[ (info->status_tokens[PLAY_MODE]) ]; his[TOTAL_SLOTS] = his[TOTAL_SLOTS] - 1; update_sample_slot_data( bank_nr, slot_nr, 0, -1, NULL, NULL); set_selection_of_slot_in_samplebank( false ); info->selection_gui_slot = NULL; info->selection_slot = NULL; } } /* -------------------------------------------------------------------------------------------------------------------------- * Callback function that is needed for inserting free-slots/banks in the appropriate GLists at the correct postion, * by just comparing their index-values ---------------------------------------------------------------------------------------------------------------------- static gint compare_index(gint *index_1, gint *index_2 ) { return (index_1 - index_2); } */ /* -------------------------------------------------------------------------------------------------------------------------- * Function adds the given infos to the list of effect-sources -------------------------------------------------------------------------------------------------------------------------- */ static void add_sample_to_effect_sources_list(gint id, gint type, gchar *title, gchar *timecode) { gchar id_string[10]; GtkTreeIter iter; if (type == STREAM_NO_STREAM) sprintf( id_string, "S%04d", id); else sprintf( id_string, "T%04d", id); gtk_list_store_append( effect_sources_store, &iter ); gtk_list_store_set( effect_sources_store, &iter, SL_ID, id_string, SL_DESCR, title, SL_TIMECODE , timecode,-1 ); } /* -------------------------------------------------------------------------------------------------------------------------- * Function adds the given infos to Editlist -------------------------------------------------------------------------------------------------------------------------- static void add_sample_to_editlist(guint row_number, gchar *timeline, gchar *fname, gchar *timecode, gchar *gfourcc) { GtkTreeIter iter; gtk_list_store_append( editlist_store, &iter ); gtk_list_store_set( editlist_store, &iter, COLUMN_INT, row_number, // <- start timecode?! (timecode of offset) COLUMN_STRING0, timeline, COLUMN_STRINGA, fname, COLUMN_STRINGB, timecode, COLUMN_STRINGC, gfourcc,-1 ); } */ /* Update a slot, either set from function arguments or clear it */ static void update_sample_slot_data(int page_num, int slot_num, int sample_id, gint sample_type, gchar *title, gchar *timecode) { /* See if we must add a new Page */ if( info->sample_banks[page_num ] == NULL ) { fprintf(stderr, "Bank page null\n"); exit(0); } sample_slot_t *slot = info->sample_banks[page_num]->slot[slot_num]; sample_gui_slot_t *gui_slot = info->sample_banks[page_num]->gui_slot[slot_num]; if(slot->timecode) free(slot->timecode); if(slot->title) free(slot->title); slot->sample_id = sample_id; slot->sample_type = sample_type; slot->timecode = timecode == NULL ? strdup("") : strdup( timecode ); slot->title = title == NULL ? strdup("") : strdup( title ); if( sample_id > 0 && sample_type >= 0 ) { if(!slot->ec ) slot->ec = new_chain(); } if(gui_slot) { if(gui_slot->title) gtk_label_set_text( GTK_LABEL( gui_slot->title ), slot->title ); if(gui_slot->timecode) gtk_label_set_text( GTK_LABEL( gui_slot->timecode ), slot->timecode ); if(sample_id > 0 ) { gchar frame_title[20]; sprintf(frame_title, "%s-%d", (sample_type == 0 ? "Sample" : "Stream" ), sample_id); gtk_frame_set_label( gui_slot->frame, frame_title ); } else { gtk_frame_set_label(gui_slot->frame, NULL ); } } if( sample_id == 0 ) { if(slot->pixbuf) { gdk_pixbuf_unref( slot->pixbuf ); slot->pixbuf = NULL; if( gui_slot ) gtk_widget_queue_draw( gui_slot->image ); } } // add sample/stream to sources add_sample_to_effect_sources_list(sample_id, sample_type, title, timecode); } /* Adding a video clip as sample; the VIMS command editlist add sample returns a new ID, which we read by gveejay_new_slot() then, we create a temporary sample and use this object to update the bank. */ static void vj_gui_add_sample(gchar *filename, gint mode) { multi_vims( VIMS_EDITLIST_ADD_SAMPLE, "%s", filename); gveejay_new_slot(MODE_SAMPLE); } /* -------------------------------------------------------------------------------------------------------------------------- * Function that is used for the VJ-GUI to show the options-dailog for a selected sample/stream * and decides if the selected slot contains an video-sample or an stream * -------------------------------------------------------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------------------------------------------------------- * Function that is used to show in the options dialog the values of the selected sample... This function decides wether to * take these values from the current loaded sample or by using a different way if the selected sample is not the currently * loaded on. The gboolean-Flag determines if the options-dialog is filled with actual data even if the selected sample * isn't currently played ... this is useful to avoid constantly reloading of unchanged values if the dialog currently * shows data of a non-played sample -------------------------------------------------------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------------------------------------------------------- * Function that is used for the VJ-GUI to apply all changes that are made within the sample/stream-options dialog * to the sample/stream that is shown within this dialog (which is the selected slot of the sample bank) * -------------------------------------------------------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------------------------------------------------------- * * Function initialize the knobs to regulate the global speed and the audio volume * --------------------------------------------------------------------------------------------------------------------------*/ void setup_knobs() { GtkAdjustment *speed_adj; char path[MAX_PATH_LEN]; bzero(path,MAX_PATH_LEN); get_gd( path, NULL, "knob.png" ); // audio volume GtkAdjustment *adj = GTK_ADJUSTMENT(gtk_adjustment_new( 100.0,0.0,100.0,0.1,1.0,0.0 )); info->audiovolume_knob = (GtkKnob *) gtk_knob_new(adj, path); gtk_widget_show(GTK_WIDGET(info->audiovolume_knob)); gtk_widget_set_sensitive( GTK_WIDGET(info->audiovolume_knob), TRUE); gtk_container_add (GTK_CONTAINER (glade_xml_get_widget_( info->main_window, "audio_knobframe")), GTK_WIDGET(info->audiovolume_knob)); g_signal_connect( adj, "value_changed", (GCallback) on_audiovolume_knob_value_changed, NULL ); update_label_i( "volume_label", 100,0); // speed /* info->speed_knob = (GtkKnob *) gtk_knob_new(NULL,path); gtk_widget_show(GTK_WIDGET(info->speed_knob)); gtk_widget_set_sensitive( GTK_WIDGET(info->speed_knob), TRUE); gtk_container_add (GTK_CONTAINER (glade_xml_get_widget_( info->main_window, "speed_knobframe")), GTK_WIDGET(info->speed_knob)); speed_adj = gtk_knob_get_adjustment(info->speed_knob); speed_adj->lower = 0; speed_adj->upper = 12; speed_adj->step_increment = 1; speed_adj->page_size = 0; speed_adj->page_increment = 1; g_signal_connect( speed_adj, "value_changed", (GCallback) on_speed_knob_value_changed, NULL ); */ }