/* Gveejay Reloaded - graphical interface for VeeJay * (C) 2002-2004 Niels Elburg * with contributions by Thomas Rheinhold (2005) * (initial sampledeck representation in GTK) * with contributions by Jerome Blanchi (2016-2018) * (Gtk3 Migration and other stuff) * * 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 #include #include #include #include #include #include #ifdef HAVE_SDL #include #endif #include #include #include #include #include #include #include #include #include #include #ifdef STRICT_CHECKING #include #endif #define RUP8(num)(((num)+8)&~8) #ifdef ARCH_X86_64 static gpointer castIntToGpointer( int val ) { int64_t g_int64_val = (int64_t) val; return (gpointer) g_int64_val; } #else static gpointer castIntToGpointer( int val) { return (gpointer) val; } #endif #define MAX_SLOW 25 #define QUICKSELECT_SLOTS 10 #define MAX_WIDGET_CACHE 512 static int beta__ = 0; static int use_vims_mcast = 0; static int samplebank_ready_ = 0; static int faster_ui_ = 0; static GtkWidget *widget_cache[MAX_WIDGET_CACHE]; enum { WIDGET_IMAGEA = 0, WIDGET_NOTEBOOK18 = 1, WIDGET_LABEL_CURFRAME = 2, WIDGET_LABEL_MOUSEAT = 3, WIDGET_LABEL_CURTIME = 4, WIDGET_LABEL_SAMPLEPOSITION = 5, WIDGET_PANELS = 6, WIDGET_VIMS_MESSENGER_PLAY = 7, WIDGET_STATUSBAR = 8, WIDGET_LOOP_NONE = 9, WIDGET_LOOP_NORMAL = 10, WIDGET_LOOP_PINGPONG = 11, WIDGET_LOOP_RANDOM = 12, WIDGET_LOOP_ONCENOP = 13, WIDGET_LABEL_MARKEREND = 14, WIDGET_TOGGLE_SUBRENDER = 15, WIDGET_TOGGLE_FADEMETHOD = 16, WIDGET_SPIN_SAMPLESPEED = 17, WIDGET_SPIN_SAMPLESTART = 18, WIDGET_SPIN_SAMPLEEND = 19, WIDGET_PLAYHINT = 20, WIDGET_LABEL_MARKERDURATION = 21, WIDGET_LABEL_MARKERSTART = 22, WIDGET_SPEED_SLIDER = 23, WIDGET_SLOW_SLIDER = 24, WIDGET_SPIN_TEXT_START = 25, WIDGET_SPIN_TEXT_END = 26, WIDGET_MANUALOPACITY = 27, WIDGET_SAMPLERAND = 28, WIDGET_STREAM_LENGTH = 29, WIDGET_STREAM_LENGTH_LABEL = 30, WIDGET_BUTTON_FADEDUR = 31, WIDGET_LABEL_TOTFRAMES = 32, WIDGET_LABEL_SAMPLELENGTH = 33, WIDGET_LABEL_TOTALTIME = 34, WIDGET_LABEL_SAMPLEPOS = 35, WIDGET_FEEDBACKBUTTON = 36, WIDGET_MACRORECORD = 37, WIDGET_MACROPLAY = 38, WIDGET_MACROSTOP = 39, WIDGET_BUTTON_EL_SELSTART = 40, WIDGET_BUTTON_EL_SELEND = 41, WIDGET_LABEL_LOOP_STAT_STOP = 42, WIDGET_SAMPLE_LOOPSTOP = 43, WIDGET_STREAM_LOOPSTOP = 44, WIDGET_LABEL_LOOP_STATS = 45, WIDGET_SEQACTIVE = 46, WIDGET_LABEL_CURRENTID = 47, WIDGET_CALI_TAKE_BUTTON = 48, WIDGET_CURRENT_STEP_LABEL = 49, WIDGET_LABEL_EFFECTNAME = 50, WIDGET_LABEL_EFFECTANIM_NAME = 51, WIDGET_VALUE_FRIENDLYNAME = 52, WIDGET_BUTTON_ENTRY_TOGGLE = 53, WIDGET_SUBRENDER_ENTRY_TOGGLE = 54, WIDGET_TRANSITION_LOOP = 55, WIDGET_TRANSITION_ENABLED = 56, WIDGET_COMBO_CURVE_FX_PARAM = 57, WIDGET_FX_M1 = 58, WIDGET_FX_M2 = 59, WIDGET_FX_M3 = 60, WIDGET_FX_M4 = 61, WIDGET_CHECK_SAMPLEFX = 62, WIDGET_CHECK_STREAMFX = 63, WIDGET_SLIDER_P0 = 64, WIDGET_SLIDER_P1 = 65, WIDGET_SLIDER_P2 = 66, WIDGET_SLIDER_P3 = 67, WIDGET_SLIDER_P4 = 68, WIDGET_SLIDER_P5 = 69, WIDGET_SLIDER_P6 = 70, WIDGET_SLIDER_P7 = 71, WIDGET_SLIDER_P8 = 72, WIDGET_SLIDER_P9 = 73, WIDGET_SLIDER_P10 = 74, WIDGET_SLIDER_P11 = 75, WIDGET_SLIDER_P12 = 76, WIDGET_SLIDER_P13 = 77, WIDGET_SLIDER_P14 = 78, WIDGET_SLIDER_P15 = 79, WIDGET_RGBKEY = 80, WIDGET_FRAME_P0 = 81, WIDGET_FRAME_P1 = 82, WIDGET_FRAME_P2 = 83, WIDGET_FRAME_P3 = 84, WIDGET_FRAME_P4 = 85, WIDGET_FRAME_P5 = 86, WIDGET_FRAME_P6 = 87, WIDGET_FRAME_P7 = 88, WIDGET_FRAME_P8 = 89, WIDGET_FRAME_P9 = 90, WIDGET_FRAME_P10 = 91, WIDGET_FRAME_P11 = 92, WIDGET_FRAME_P12 = 93, WIDGET_FRAME_P13 = 94, WIDGET_FRAME_P14 = 95, WIDGET_FRAME_P15 = 96, WIDGET_SLIDER_BOX_P0 = 97, WIDGET_SLIDER_BOX_P1 = 98, WIDGET_SLIDER_BOX_P2 = 99, WIDGET_SLIDER_BOX_P3 = 100, WIDGET_SLIDER_BOX_P4 = 101, WIDGET_SLIDER_BOX_P5 = 102, WIDGET_SLIDER_BOX_P6 = 103, WIDGET_SLIDER_BOX_P7 = 104, WIDGET_SLIDER_BOX_P8 = 105, WIDGET_SLIDER_BOX_P9 = 106, WIDGET_SLIDER_BOX_P10 = 107, WIDGET_SLIDER_BOX_P11 = 108, WIDGET_SLIDER_BOX_P12 = 109, WIDGET_SLIDER_BOX_P13 = 110, WIDGET_SLIDER_BOX_P14 = 111, WIDGET_SLIDER_BOX_P15 = 112, WIDGET_LABEL_P0 = 113, WIDGET_LABEL_P1 = 114, WIDGET_LABEL_P2 = 115, WIDGET_LABEL_P3 = 116, WIDGET_LABEL_P4 = 117, WIDGET_LABEL_P5 = 118, WIDGET_LABEL_P6 = 119, WIDGET_LABEL_P7 = 120, WIDGET_LABEL_P8 = 121, WIDGET_LABEL_P9 = 122, WIDGET_LABEL_P10 = 123, WIDGET_LABEL_P11 = 124, WIDGET_LABEL_P12 = 125, WIDGET_LABEL_P13 = 126, WIDGET_LABEL_P14 = 127, WIDGET_LABEL_P15 = 128, WIDGET_INC_P0 = 129, WIDGET_INC_P1 = 130, WIDGET_INC_P2 = 131, WIDGET_INC_P3 = 132, WIDGET_INC_P4 = 133, WIDGET_INC_P5 = 134, WIDGET_INC_P6 = 135, WIDGET_INC_P7 = 136, WIDGET_INC_P8 = 137, WIDGET_INC_P9 = 138, WIDGET_INC_P10 = 139, WIDGET_INC_P11 = 140, WIDGET_INC_P12 = 141, WIDGET_INC_P13 = 142, WIDGET_INC_P14 = 143, WIDGET_INC_P15 = 144, WIDGET_DEC_P0 = 145, WIDGET_DEC_P1 = 146, WIDGET_DEC_P2 = 147, WIDGET_DEC_P3 = 148, WIDGET_DEC_P4 = 149, WIDGET_DEC_P5 = 150, WIDGET_DEC_P6 = 151, WIDGET_DEC_P7 = 152, WIDGET_DEC_P8 = 153, WIDGET_DEC_P9 = 154, WIDGET_DEC_P10 = 155, WIDGET_DEC_P11 = 156, WIDGET_DEC_P12 = 157, WIDGET_DEC_P13 = 158, WIDGET_DEC_P14 = 159, WIDGET_DEC_P15 = 160, WIDGET_FRAME_FXTREE2 = 161, WIDGET_CURVE_TOGGLEENTRY_PARAM = 163, WIDGET_CURVE_SPINSTART = 164, WIDGET_CURVE_SPINEND = 165, WIDGET_CURVE_CHAIN_TOGGLEENTRY = 166, WIDGET_FRAME_FXTREE3 = 167, WIDGET_CURVE_TYPESPLINE = 168, WIDGET_CURVE_TYPEFREEHAND = 169, WIDGET_CURVE_TYPELINEAR = 170, WIDGET_SAMPLE_LENGTH_LABEL = 171, WIDGET_BUTTON_FX_ENTRY = 172, WIDGET_NOTEBOOK15 = 173, WIDGET_SAMPLE_LOOP_BOX = 174, WIDGET_BUTTON_084 = 175, WIDGET_VIDEO_NAVIGATION_BUTTONS = 176, WIDGET_BUTTON_SAMPLESTART = 177, WIDGET_BUTTON_SAMPLEEND = 178, WIDGET_BUTTON_200 = 181, WIDGET_FRAME_FXTREE = 182, WIDGET_VJFRAMERATE = 183, WIDGET_SCROLLEDWINDOW49 = 184, WIDGET_SAMPLEGRID_FRAME = 185, WIDGET_MARKERFRAME = 186, WIDGET_FXPANEL = 187, WIDGET_BUTTON_083 = 188, WIDGET_FXANIMCONTROLS = 189, WIDGET_CURVECONTAINER = 190, WIDGET_SRTFRAME = 192, WIDGET_FRAME_FXTREE1 = 193, WIDGET_BUTTON_5_4 = 194, WIDGET_TOGGLE_MULTICAST = 195, WIDGET_CALI_SAVE_BUTTON = 196, WIDGET_VBOX633 = 197, WIDGET_HBOX910 = 198, WIDGET_HBOX27 = 199, WIDGET_SAMPLE_BANK_HBOX = 200, WIDGET_BUTTON_SAMPLEBANK_PREV = 201, WIDGET_BUTTON_SAMPLEBANK_NEXT = 202, WIDGET_SPIN_SAMPLEBANK_SELECT = 203, WIDGET_HBOX709 = 204, WIDGET_SAMPLE_PANEL = 205, WIDGET_VBOX623 = 206, WIDGET_SLIDER_BOX_G0 = 207, WIDGET_SLIDER_BOX_G1 = 208, WIDGET_SLIDER_BOX_G2 = 209, WIDGET_SLIDER_BOX_G3 = 210, WIDGET_SLIDER_BOX_G4 = 211, WIDGET_SLIDER_BOX_G5 = 212, WIDGET_SLIDER_BOX_G6 = 213, WIDGET_SLIDER_BOX_G7 = 214, WIDGET_SLIDER_BOX_G8 = 215, WIDGET_SLIDER_BOX_G9 = 216, WIDGET_SLIDER_BOX_G10 = 217, WIDGET_VEEJAY_BOX = 230, WIDGET_CURVE_CHAIN_TOGGLECHAIN = 231, WIDGET_FX_MNONE = 232, WIDGET_SPIN_MACRODELAY = 233, WIDGET_MACRORECORD1 = 234, WIDGET_MACROPLAY1 = 235, WIDGET_MACROSTOP1 = 236, WIDGET_SPIN_SAMPLEDURATION = 237, }; enum { SAMPLE_WIDGET_SAMPLE_LOOP_BOX = 0, SAMPLE_WIDGET_BUTTON_084, SAMPLE_WIDGET_VIDEO_NAVIGATION_BUTTONS, SAMPLE_WIDGET_BUTTON_SAMPLESTART, SAMPLE_WIDGET_BUTTON_SAMPLEEND, SAMPLE_WIDGET_SPEED_SLIDER, SAMPLE_WIDGET_SLOW_SLIDER, SAMPLE_WIDGET_BUTTON_200, SAMPLE_WIDGET_FRAME_FXTREE, SAMPLE_WIDGET_VJFRAMERATE, SAMPLE_WIDGET_SCROLLEDWINDOW49, SAMPLE_WIDGET_SAMPLEGRID_FRAME, SAMPLE_WIDGET_MARKERFRAME, SAMPLE_WIDGET_FXPANEL, SAMPLE_WIDGET_BUTTON_083, SAMPLE_WIDGET_PANEL, SAMPLE_WIDGET_NONE // must be last }; enum { PLAIN_WIDGET_VIDEO_NAVIGATION_BUTTONS = 0, PLAIN_WIDGET_BUTTON_084, PLAIN_WIDGET_BUTTON_083, PLAIN_WIDGET_BUTTON_SAMPLESTART, PLAIN_WIDGET_BUTTON_SAMPLEEND, PLAIN_WIDGET_SPEED_SLIDER, PLAIN_WIDGET_SLOW_SLIDER, PLAIN_WIDGET_VJFRAMERATE, PLAIN_WIDGET_MARKERFRAME, PLAIN_WIDGET_NONE, }; enum { STREAM_WIDGET_BUTTON_200 = 0, STREAM_WIDGET_FRAME_FXTREE, STREAM_WIDGET_FRAME_FXTREE3, STREAM_WIDGET_FXPANEL, STREAM_WIDGET_PANEL, STREAM_WIDGET_SCROLLEDWINDOW49, STREAM_WIDGET_SAMPLEGRID_FRAME, STREAM_WIDGET_NONE, }; enum { FB_WIDGET_MARKERFRAME = 0, FB_WIDGET_VBOX633, FB_WIDGET_HBOX910, FB_WIDGET_HBOX27, FB_WIDGET_SAMPLE_BANK_HBOX, FB_WIDGET_BUTTON_SAMPLEBANK_PREV, FB_WIDGET_BUTTON_SAMPLEBANK_NEXT, FB_WIDGET_SPIN_SAMPLEBANK_SELECT, FB_WIDGET_HBOX709, FB_WIDGET_SAMPLE_PANEL, FB_WIDGET_NOTEBOOK15, FB_WIDGET_VBOX623, FB_WIDGET_SAMPLEGRID_FRAME, FB_WIDGET_PANELS, FB_WIDGET_NONE }; static struct { const int fb_widget_id; const int widget_id; } fb_widget_map[] = { { FB_WIDGET_MARKERFRAME, WIDGET_MARKERFRAME }, { FB_WIDGET_VBOX633, WIDGET_VBOX633 }, { FB_WIDGET_HBOX910, WIDGET_HBOX910 }, { FB_WIDGET_HBOX27, WIDGET_HBOX27 }, { FB_WIDGET_SAMPLE_BANK_HBOX, WIDGET_SAMPLE_BANK_HBOX }, { FB_WIDGET_BUTTON_SAMPLEBANK_PREV, WIDGET_BUTTON_SAMPLEBANK_PREV }, { FB_WIDGET_BUTTON_SAMPLEBANK_NEXT, WIDGET_BUTTON_SAMPLEBANK_NEXT }, { FB_WIDGET_SPIN_SAMPLEBANK_SELECT, WIDGET_SPIN_SAMPLEBANK_SELECT }, { FB_WIDGET_HBOX709,WIDGET_HBOX709 }, { FB_WIDGET_SAMPLE_PANEL, WIDGET_SAMPLE_PANEL }, { FB_WIDGET_NOTEBOOK15, WIDGET_NOTEBOOK15 }, { FB_WIDGET_VBOX623, WIDGET_VBOX623 }, { FB_WIDGET_SAMPLEGRID_FRAME,FB_WIDGET_SAMPLEGRID_FRAME }, { FB_WIDGET_PANELS, WIDGET_PANELS }, }; static struct { const int stream_widget_id; const int widget_id; } stream_widget_map[] = { { STREAM_WIDGET_BUTTON_200, WIDGET_BUTTON_200 }, { STREAM_WIDGET_FRAME_FXTREE, WIDGET_FRAME_FXTREE }, { STREAM_WIDGET_FRAME_FXTREE3, WIDGET_FRAME_FXTREE3 }, { STREAM_WIDGET_FXPANEL, WIDGET_FXPANEL }, { STREAM_WIDGET_PANEL, WIDGET_PANELS }, { STREAM_WIDGET_SCROLLEDWINDOW49, WIDGET_SCROLLEDWINDOW49 }, { STREAM_WIDGET_SAMPLEGRID_FRAME, WIDGET_SAMPLEGRID_FRAME }, { STREAM_WIDGET_NONE, -1 }, }; static struct { const int sample_widget_id; const int widget_id; } sample_widget_map[] = { { SAMPLE_WIDGET_SAMPLE_LOOP_BOX, WIDGET_SAMPLE_LOOP_BOX }, { SAMPLE_WIDGET_BUTTON_084, WIDGET_BUTTON_084 }, { SAMPLE_WIDGET_VIDEO_NAVIGATION_BUTTONS, WIDGET_VIDEO_NAVIGATION_BUTTONS }, { SAMPLE_WIDGET_BUTTON_SAMPLESTART, WIDGET_BUTTON_SAMPLESTART }, { SAMPLE_WIDGET_BUTTON_SAMPLEEND, WIDGET_BUTTON_SAMPLEEND }, { SAMPLE_WIDGET_SPEED_SLIDER, WIDGET_SPEED_SLIDER }, { SAMPLE_WIDGET_SLOW_SLIDER, WIDGET_SLOW_SLIDER }, { SAMPLE_WIDGET_BUTTON_200, WIDGET_BUTTON_200 }, { SAMPLE_WIDGET_FRAME_FXTREE, WIDGET_FRAME_FXTREE }, { SAMPLE_WIDGET_VJFRAMERATE, WIDGET_VJFRAMERATE }, { SAMPLE_WIDGET_SCROLLEDWINDOW49, WIDGET_SCROLLEDWINDOW49 }, { SAMPLE_WIDGET_SAMPLEGRID_FRAME, WIDGET_SAMPLEGRID_FRAME }, { SAMPLE_WIDGET_MARKERFRAME, WIDGET_MARKERFRAME }, { SAMPLE_WIDGET_FXPANEL, WIDGET_FXPANEL }, { SAMPLE_WIDGET_BUTTON_083, WIDGET_BUTTON_083 }, { SAMPLE_WIDGET_PANEL, WIDGET_PANELS }, { SAMPLE_WIDGET_NONE, -1 }, }; static struct { const int plain_widget_id; const int widget_id; } plain_widget_map[] = { { PLAIN_WIDGET_VIDEO_NAVIGATION_BUTTONS, WIDGET_VIDEO_NAVIGATION_BUTTONS }, { PLAIN_WIDGET_BUTTON_084, WIDGET_BUTTON_084 }, { PLAIN_WIDGET_BUTTON_083, WIDGET_BUTTON_083 }, { PLAIN_WIDGET_BUTTON_SAMPLESTART, WIDGET_BUTTON_SAMPLESTART }, { PLAIN_WIDGET_BUTTON_SAMPLEEND, WIDGET_BUTTON_SAMPLEEND }, { PLAIN_WIDGET_SPEED_SLIDER, WIDGET_SPEED_SLIDER }, { PLAIN_WIDGET_SLOW_SLIDER, WIDGET_SLOW_SLIDER }, { PLAIN_WIDGET_VJFRAMERATE, WIDGET_VJFRAMERATE }, { PLAIN_WIDGET_MARKERFRAME, WIDGET_MARKERFRAME }, { PLAIN_WIDGET_NONE, -1 }, }; static struct { const char *name; const int id; } widget_map[] = { { "imageA", WIDGET_IMAGEA }, { "notebook18", WIDGET_NOTEBOOK18 }, { "panels", WIDGET_PANELS }, { "notebook15", WIDGET_NOTEBOOK15 }, { "label_curframe", WIDGET_LABEL_CURFRAME }, { "label_mouseat", WIDGET_LABEL_MOUSEAT }, { "label_curtime", WIDGET_LABEL_CURTIME }, { "label_sampleposition", WIDGET_LABEL_SAMPLEPOSITION }, { "vims_messenger_play", WIDGET_VIMS_MESSENGER_PLAY }, { "statusbar", WIDGET_STATUSBAR }, { "loop_none", WIDGET_LOOP_NONE }, { "loop_normal", WIDGET_LOOP_NORMAL }, { "loop_pingpong", WIDGET_LOOP_PINGPONG }, { "loop_random", WIDGET_LOOP_RANDOM }, { "loop_oncenop", WIDGET_LOOP_ONCENOP }, { "label_markerend", WIDGET_LABEL_MARKEREND }, { "toggle_subrender", WIDGET_TOGGLE_SUBRENDER }, { "toggle_fademethod", WIDGET_TOGGLE_FADEMETHOD }, { "spin_samplespeed", WIDGET_SPIN_SAMPLESPEED }, { "spin_samplestart", WIDGET_SPIN_SAMPLESTART }, { "spin_sampleend", WIDGET_SPIN_SAMPLEEND }, { "playhint", WIDGET_PLAYHINT }, { "label_markerduration", WIDGET_LABEL_MARKERDURATION }, { "label_markerstart", WIDGET_LABEL_MARKERSTART }, { "speed_slider", WIDGET_SPEED_SLIDER }, { "slow_slider", WIDGET_SLOW_SLIDER }, { "spin_text_start", WIDGET_SPIN_TEXT_START }, { "spin_text_end", WIDGET_SPIN_TEXT_END }, { "manualopacity", WIDGET_MANUALOPACITY }, { "samplerand", WIDGET_SAMPLERAND }, { "stream_length", WIDGET_STREAM_LENGTH }, { "stream_length_label", WIDGET_STREAM_LENGTH_LABEL }, { "button_fadedur", WIDGET_BUTTON_FADEDUR }, { "label_totframes", WIDGET_LABEL_TOTFRAMES }, { "label_samplelength", WIDGET_LABEL_SAMPLELENGTH }, { "label_totaltime", WIDGET_LABEL_TOTALTIME }, { "sample_length_label", WIDGET_SAMPLE_LENGTH_LABEL }, { "label_samplepos", WIDGET_LABEL_SAMPLEPOS }, { "feedbackbutton", WIDGET_FEEDBACKBUTTON }, { "macrorecord", WIDGET_MACRORECORD }, { "macroplay", WIDGET_MACROPLAY }, { "macrostop", WIDGET_MACROSTOP }, { "button_el_selstart", WIDGET_BUTTON_EL_SELSTART }, { "button_el_selend", WIDGET_BUTTON_EL_SELEND }, { "label_loop_stat_stop", WIDGET_LABEL_LOOP_STAT_STOP }, { "sample_loopstop", WIDGET_SAMPLE_LOOPSTOP }, { "stream_loopstop", WIDGET_STREAM_LOOPSTOP }, { "label_loop_stats", WIDGET_LABEL_LOOP_STATS }, { "seqactive", WIDGET_SEQACTIVE }, { "label_currentid", WIDGET_LABEL_CURRENTID }, { "cali_take_button", WIDGET_CALI_TAKE_BUTTON }, { "current_step_label", WIDGET_CURRENT_STEP_LABEL }, { "check_samplefx", WIDGET_CHECK_SAMPLEFX }, { "check_streamfx", WIDGET_CHECK_STREAMFX }, { "slider_p0", WIDGET_SLIDER_P0 }, { "slider_p1", WIDGET_SLIDER_P1 }, { "slider_p2", WIDGET_SLIDER_P2 }, { "slider_p3", WIDGET_SLIDER_P3 }, { "slider_p4", WIDGET_SLIDER_P4 }, { "slider_p5", WIDGET_SLIDER_P5 }, { "slider_p6", WIDGET_SLIDER_P6 }, { "slider_p7", WIDGET_SLIDER_P7 }, { "slider_p8", WIDGET_SLIDER_P8 }, { "slider_p9", WIDGET_SLIDER_P9 }, { "slider_p10", WIDGET_SLIDER_P10 }, { "slider_p11", WIDGET_SLIDER_P11 }, { "slider_p12", WIDGET_SLIDER_P12 }, { "slider_p13", WIDGET_SLIDER_P13 }, { "slider_p14", WIDGET_SLIDER_P14 }, { "slider_p15", WIDGET_SLIDER_P15 }, { "frame_p0", WIDGET_FRAME_P0 }, { "frame_p1", WIDGET_FRAME_P1 }, { "frame_p2", WIDGET_FRAME_P2 }, { "frame_p3", WIDGET_FRAME_P3 }, { "frame_p4", WIDGET_FRAME_P4 }, { "frame_p5", WIDGET_FRAME_P5 }, { "frame_p6", WIDGET_FRAME_P6 }, { "frame_p7", WIDGET_FRAME_P7 }, { "frame_p8", WIDGET_FRAME_P8 }, { "frame_p9", WIDGET_FRAME_P9 }, { "frame_p10", WIDGET_FRAME_P10 }, { "frame_p11", WIDGET_FRAME_P11 }, { "frame_p12", WIDGET_FRAME_P12 }, { "frame_p13", WIDGET_FRAME_P13 }, { "frame_p14", WIDGET_FRAME_P14 }, { "frame_p15", WIDGET_FRAME_P15 }, { "slider_box_p0", WIDGET_SLIDER_BOX_P0 }, { "slider_box_p1", WIDGET_SLIDER_BOX_P1 }, { "slider_box_p2", WIDGET_SLIDER_BOX_P2 }, { "slider_box_p3", WIDGET_SLIDER_BOX_P3 }, { "slider_box_p4", WIDGET_SLIDER_BOX_P4 }, { "slider_box_p5", WIDGET_SLIDER_BOX_P5 }, { "slider_box_p6", WIDGET_SLIDER_BOX_P6 }, { "slider_box_p7", WIDGET_SLIDER_BOX_P7 }, { "slider_box_p8", WIDGET_SLIDER_BOX_P8 }, { "slider_box_p9", WIDGET_SLIDER_BOX_P9 }, { "slider_box_p10", WIDGET_SLIDER_BOX_P10 }, { "slider_box_p11", WIDGET_SLIDER_BOX_P11 }, { "slider_box_p12", WIDGET_SLIDER_BOX_P12 }, { "slider_box_p13", WIDGET_SLIDER_BOX_P13 }, { "slider_box_p14", WIDGET_SLIDER_BOX_P14 }, { "slider_box_p15", WIDGET_SLIDER_BOX_P15 }, { "label_p0", WIDGET_LABEL_P0 }, { "label_p1", WIDGET_LABEL_P1 }, { "label_p2", WIDGET_LABEL_P2 }, { "label_p3", WIDGET_LABEL_P3 }, { "label_p4", WIDGET_LABEL_P4 }, { "label_p5", WIDGET_LABEL_P5 }, { "label_p6", WIDGET_LABEL_P6 }, { "label_p7", WIDGET_LABEL_P7 }, { "label_p8", WIDGET_LABEL_P8 }, { "label_p9", WIDGET_LABEL_P9 }, { "label_p10", WIDGET_LABEL_P10 }, { "label_p11", WIDGET_LABEL_P11 }, { "label_p12", WIDGET_LABEL_P12 }, { "label_p13", WIDGET_LABEL_P13 }, { "label_p14", WIDGET_LABEL_P14 }, { "label_p15", WIDGET_LABEL_P15 }, { "inc_p0", WIDGET_INC_P0 }, { "inc_p1", WIDGET_INC_P1 }, { "inc_p2", WIDGET_INC_P2 }, { "inc_p3", WIDGET_INC_P3 }, { "inc_p4", WIDGET_INC_P4 }, { "inc_p5", WIDGET_INC_P5 }, { "inc_p6", WIDGET_INC_P6 }, { "inc_p7", WIDGET_INC_P7 }, { "inc_p8", WIDGET_INC_P8 }, { "inc_p9", WIDGET_INC_P9 }, { "inc_p10", WIDGET_INC_P10 }, { "inc_p11", WIDGET_INC_P11 }, { "inc_p12", WIDGET_INC_P12 }, { "inc_p13", WIDGET_INC_P13 }, { "inc_p14", WIDGET_INC_P14 }, { "inc_p15", WIDGET_INC_P15 }, { "dec_p0", WIDGET_DEC_P0 }, { "dec_p1", WIDGET_DEC_P1 }, { "dec_p2", WIDGET_DEC_P2 }, { "dec_p3", WIDGET_DEC_P3 }, { "dec_p4", WIDGET_DEC_P4 }, { "dec_p5", WIDGET_DEC_P5 }, { "dec_p6", WIDGET_DEC_P6 }, { "dec_p7", WIDGET_DEC_P7 }, { "dec_p8", WIDGET_DEC_P8 }, { "dec_p9", WIDGET_DEC_P9 }, { "dec_p10", WIDGET_DEC_P10 }, { "dec_p11", WIDGET_DEC_P11 }, { "dec_p12", WIDGET_DEC_P12 }, { "dec_p13", WIDGET_DEC_P13 }, { "dec_p14", WIDGET_DEC_P14 }, { "dec_p15", WIDGET_DEC_P15 }, { "rgbkey", WIDGET_RGBKEY }, { "frame_fxtree2", WIDGET_FRAME_FXTREE2 }, { "curve_toggleentry_param",WIDGET_CURVE_TOGGLEENTRY_PARAM }, { "curve_spinstart", WIDGET_CURVE_SPINSTART }, { "curve_spinend", WIDGET_CURVE_SPINEND }, { "curve_chain_toggleentry",WIDGET_CURVE_CHAIN_TOGGLEENTRY }, { "frame_fxtree3", WIDGET_FRAME_FXTREE3 }, { "curve_typespline", WIDGET_CURVE_TYPESPLINE }, { "curve_typefreehand", WIDGET_CURVE_TYPEFREEHAND }, { "curve_typelinear", WIDGET_CURVE_TYPELINEAR }, { "button_fx_entry", WIDGET_BUTTON_FX_ENTRY }, { "subrender_entry_toggle", WIDGET_SUBRENDER_ENTRY_TOGGLE }, { "label_effectname", WIDGET_LABEL_EFFECTNAME }, { "label_effectanim_name", WIDGET_LABEL_EFFECTANIM_NAME }, { "value_friendlyname", WIDGET_VALUE_FRIENDLYNAME }, { "button_entry_toggle", WIDGET_BUTTON_ENTRY_TOGGLE }, { "transition_loop", WIDGET_TRANSITION_LOOP }, { "transition_enabled", WIDGET_TRANSITION_ENABLED }, { "combo_curve_fx_param", WIDGET_COMBO_CURVE_FX_PARAM }, { "fx_m1", WIDGET_FX_M1 }, { "fx_m2", WIDGET_FX_M2 }, { "fx_m3", WIDGET_FX_M3 }, { "fx_m4", WIDGET_FX_M4 }, { "fx_mnone", WIDGET_FX_MNONE }, {"sample_loop_box", WIDGET_SAMPLE_LOOP_BOX }, {"button_084", WIDGET_BUTTON_084 }, {"button_083", WIDGET_BUTTON_083 }, {"video_navigation_buttons", WIDGET_VIDEO_NAVIGATION_BUTTONS}, {"button_samplestart", WIDGET_BUTTON_SAMPLESTART}, {"button_sampleend", WIDGET_BUTTON_SAMPLEEND}, {"speed_slider", WIDGET_SPEED_SLIDER}, {"slow_slider", WIDGET_SLOW_SLIDER}, {"button_200", WIDGET_BUTTON_200}, // mask button {"frame_fxtree", WIDGET_FRAME_FXTREE}, {"fxpanel", WIDGET_FXPANEL}, {"vjframerate", WIDGET_VJFRAMERATE }, {"scrolledwindow49", WIDGET_SCROLLEDWINDOW49 }, {"samplegrid_frame", WIDGET_SAMPLEGRID_FRAME }, {"markerframe", WIDGET_MARKERFRAME }, {"fxanimcontrols", WIDGET_FXANIMCONTROLS }, {"curve_container", WIDGET_CURVECONTAINER }, {"SRTframe", WIDGET_SRTFRAME }, {"frame_fxtree1", WIDGET_FRAME_FXTREE1 }, {"button_5_4", WIDGET_BUTTON_5_4 }, {"toggle_multicast", WIDGET_TOGGLE_MULTICAST }, {"cali_save_button", WIDGET_CALI_SAVE_BUTTON }, {"veejay_box", WIDGET_VEEJAY_BOX }, { "vbox633", WIDGET_VBOX633 }, { "hbox910", WIDGET_HBOX910 }, { "hbox27", WIDGET_HBOX27 }, { "sample_bank_hbox", WIDGET_SAMPLE_BANK_HBOX }, { "button_samplebank_prev", WIDGET_BUTTON_SAMPLEBANK_PREV }, { "button_samplebank_next", WIDGET_BUTTON_SAMPLEBANK_NEXT }, { "spin_samplebank_select", WIDGET_SPIN_SAMPLEBANK_SELECT }, { "hbox709", WIDGET_HBOX709 }, { "sample_panel", WIDGET_SAMPLE_PANEL }, { "vbox623", WIDGET_VBOX623 }, { "slider_box_p0", WIDGET_SLIDER_BOX_G0 }, { "slider_box_p1", WIDGET_SLIDER_BOX_G1 }, { "slider_box_p2", WIDGET_SLIDER_BOX_G2 }, { "slider_box_p3", WIDGET_SLIDER_BOX_G3 }, { "slider_box_p4", WIDGET_SLIDER_BOX_G4 }, { "slider_box_p5", WIDGET_SLIDER_BOX_G5 }, { "slider_box_p6", WIDGET_SLIDER_BOX_G6 }, { "slider_box_p7", WIDGET_SLIDER_BOX_G7 }, { "slider_box_p8", WIDGET_SLIDER_BOX_G8 }, { "slider_box_p9", WIDGET_SLIDER_BOX_G9 }, { "slider_box_p10", WIDGET_SLIDER_BOX_G10 }, { "curve_chain_togglechain", WIDGET_CURVE_CHAIN_TOGGLECHAIN }, { "spin_macrodelay", WIDGET_SPIN_MACRODELAY }, { "macrorecord1", WIDGET_MACRORECORD1 }, { "macroplay1", WIDGET_MACROPLAY1 }, { "macrostop1", WIDGET_MACROSTOP1 }, { "spin_sampleduration", WIDGET_SPIN_SAMPLEDURATION }, { NULL, -1 }, }; static struct { const char *text; } tooltips[] = { {"Mouse left: Set in point,\nMouse right: Set out point,\nDouble click: Clear selection,\nMouse middle: Drag selection"}, {"Mouse left/right: Play slot,\nShift + Mouse left: Put sample in slot.\nYou can also put selected samples."}, {"Mouse left: Select slot (sample in slot),\nMouse double click: Play sample in slot,\nShift + Mouse left: Set slot as mixing current mixing channel"}, {"Select a SRT sequence to edit"}, {"Double click: add effect to current entry in chain list,\n [+] Shift L: add disabled,\n [+] Ctrl L: add to selected sample"}, {"Filter the effects list by any string"}, {"Shift + Mouse left : Toogle selected fx,\nControl + Mouse left : Toogle selected fx anim"}, {NULL}, }; enum { TOOLTIP_TIMELINE = 0, TOOLTIP_QUICKSELECT = 1, TOOLTIP_SAMPLESLOT = 2, TOOLTIP_SRTSELECT = 3, TOOLTIP_FXSELECT = 4, TOOLTIP_FXFILTER = 5, TOOLTIP_FXCHAINTREE = 6 }; #define FX_PARAMETER_DEFAULT_NAME "" #define FX_PARAMETER_VALUE_DEFAULT_HINT "" enum { STREAM_NO_STREAM = 0, STREAM_RED = 9, STREAM_GREEN = 8, STREAM_GENERATOR = 7, STREAM_CALI = 6, STREAM_WHITE = 4, STREAM_VIDEO4LINUX = 2, STREAM_DV1394 = 17, STREAM_NETWORK = 13, STREAM_MCAST = 14, STREAM_YUV4MPEG = 1, STREAM_AVFORMAT = 12, STREAM_CLONE = 15, STREAM_VLOOP = 3, 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_KF_STATUS = 3, ENTRY_KF_TYPE = 4, ENTRY_TRANSITION_ENABLED = 5, ENTRY_TRANSITION_LOOP = 6, ENTRY_SOURCE = 7, ENTRY_CHANNEL = 8, ENTRY_VIDEO_ENABLED = 9, ENTRY_SUBRENDER_ENTRY = 10, ENTRY_P0 = 11, ENTRY_P1 = 12, ENTRY_P2 = 13, ENTRY_P3 = 14, ENTRY_P4 = 15, ENTRY_P5 = 16, ENTRY_P6 = 17, ENTRY_P8 = 18, ENTRY_P9 = 19, ENTRY_P10 = 20, ENTRY_P11 = 21, ENTRY_P12 = 22, ENTRY_P13 = 23, ENTRY_P14 = 24, ENTRY_P15 = 25, ENTRY_LAST = 26 /* ENTRY_P1 = 16, ENTRY_P2 = 21, ENTRY_P3 = 26, ENTRY_P4 = 31, ENTRY_P5 = 36, ENTRY_P6 = 41, ENTRY_P8 = 46, ENTRY_P9 = 51, ENTRY_P10 = 56, ENTRY_P11 = 61, ENTRY_P12 = 66, ENTRY_P13 = 71, ENTRY_P14 = 76, ENTRY_P15 = 81, ENTRY_LAST = 86 */ }; #define ENTRY_PARAMSET ENTRY_P0 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, HINT_SEQ_ACT = 14, HINT_SEQ_CUR = 15, HINT_GENERATOR =16, HINT_MACRO=17, HINT_KEYS = 18, HINT_MACRODELAY = 19, NUM_HINTS = 20, }; 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 enum { FILE_FILTER_DEFAULT =0, FILE_FILTER_SL, FILE_FILTER_XML, FILE_FILTER_YUV, FILE_FILTER_CFG, FILE_FILTER_NONE, } file_filter_t; // NUM_HINTS_MAX must be larger than NUM_HINTS and divisable by 8 #define NUM_HINTS_MAX 32 typedef struct { int reload_hint[NUM_HINTS_MAX]; int reload_hint_checksums[NUM_HINTS_MAX]; int selected_vims_accel[2]; int entry_tokens[ENTRY_LAST]; int streams[4096]; int recording[2]; int selected_chain_entry; int selected_el_entry; int selected_vims_entry; int render_record; int iterator; int selected_effect_id; gboolean reload_force_avoid; int playmode; int sample_rec_duration; 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; stream_templ_t strtmpl[2]; // v4l, dv1394 int selected_parameter_id; // current kf int selected_vims_type; char *selected_vims_args; int cali_duration; int cali_stage; int expected_num_samples; int expected_num_streams; int real_num_samples; int real_num_streams; } veejay_user_ctrl_t; typedef struct { float fps; float ratio; 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; gchar *args; } vims_t; typedef struct { gint keyval; gint state; gchar *args; gchar *vims; gint event_id; } vims_keys_t; static int user_preview = 0; static int NUM_BANKS = 50; static int NUM_SAMPLES_PER_PAGE = 12; static int SAMPLEBANK_COLUMNS = 6; static int SAMPLEBANK_ROWS = 2; static int use_key_snoop = 0; #define G_MOD_OFFSET 200 #define SEQUENCE_LENGTH 1024 #define MEM_SLOT_SIZE 32 static vims_t vj_event_list[VIMS_MAX]; static vims_keys_t vims_keys_list[VIMS_MAX]; static int vims_verbosity = 0; #define livido_port_t vevo_port_t static int cali_stream_id = 0; static int cali_onoff = 0; static int geo_pos_[2] = { -1,-1 }; static vevo_port_t *fx_list_ = NULL; typedef struct { GtkWidget *title; GtkWidget *timecode; GtkWidget *image; GtkWidget *frame; GtkWidget *event_box; GtkWidget *upper_hbox; GtkWidget *hotkey; } sample_gui_slot_t; typedef struct { GtkWidget *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; } 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 { char *hostname; int port_num; int state; // IDLE, PLAYING struct timeval p_time; int w_state; // watchdog state int w_delay; } watchdog_t; typedef struct { char **description; } value_hint; #define SAMPLE_MAX_PARAMETERS 32 typedef struct { int defaults[SAMPLE_MAX_PARAMETERS]; int min[SAMPLE_MAX_PARAMETERS]; int max[SAMPLE_MAX_PARAMETERS]; char description[150]; char *param_description[SAMPLE_MAX_PARAMETERS]; value_hint *hints[SAMPLE_MAX_PARAMETERS]; int id; int is_video; int num_arg; int has_rgb; int is_gen; } effect_constr; #define EFFECT_LIST_SIZE 4096 typedef struct { GtkBuilder *main_window; vj_client *client; int status_tokens[STATUS_TOKENS]; /* current status tokens */ int *history_tokens[4]; /* 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 sensitive; int launch_sensitive; struct timeval alarm; struct timeval timer; // GIOChannel *channel; GdkVisual *color_map; gint connecting; // gint logging; gint streamrecording; gint samplerecording; // gint cpumeter; gint cachemeter; gint image_w; gint image_h; veejay_el_t el; veejay_user_ctrl_t uc; effect_constr **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; GtkWidget *sample_sequencer; 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; sequence_envelope *sequencer_view; int sequencer_col; int sequencer_row; int sequence_playing; gint current_sequence_slot; // GtkKnob *audiovolume_knob; // GtkKnob *speed_knob; int image_dimensions[2]; // guchar *rawdata; int prev_mode; GtkWidget *tl; GtkWidget *curve; int status_frame; int key_id; GdkRGBA *normal; gboolean key_now; void *mt; watchdog_t watch; int vims_line; void *midi; struct timeval time_last; uint8_t *cali_buffer; } vj_gui_t; enum { STATE_STOPPED = 0, STATE_RECONNECT = 1, STATE_PLAYING = 2, STATE_CONNECT = 3, STATE_DISCONNECT = 4, STATE_BUSY = 5, STATE_LOADING = 6, STATE_WAIT_FOR_USER = 7, STATE_QUIT = 8, }; enum { FXC_ID = 0, FXC_FXID = 1, FXC_FXSTATUS = 2, FXC_KF = 3, FXC_MIXING = 4, FXC_SUBRENDER = 5, FXC_KF_STATUS = 6, FXC_N_COLS = 7, }; enum { MACRO_FRAME = 0, MACRO_DUP = 1, MACRO_LOOP = 2, MACRO_MSG_SEQ = 3, MACRO_VIMS = 4, MACRO_VIMS_DESCR = 5, }; enum { V4L_NUM=0, V4L_NAME=1, V4L_SPINBOX=2, V4L_LOCATION=3, }; enum { VIMS_ID=0, VIMS_KEY=1, VIMS_MOD=2, VIMS_DESCR=3, VIMS_PARAMS=4, VIMS_FORMAT=5, VIMS_CONTENTS=6, }; enum { VIMS_LIST_ITEM_ID=0, VIMS_LIST_ITEM_DESCR=1 }; typedef struct { const char *text; } widget_name_t; typedef struct { GtkListStore *list; GtkTreeModelSort *sorted; GtkTreeModelFilter *filtered; } effectlist_models; typedef struct { effectlist_models stores[3]; gchar *filter_string; } effectlist_data; static widget_name_t *slider_box_names_ = NULL; static widget_name_t *slider_names_ = NULL; static widget_name_t *param_frame_ = NULL; static widget_name_t *param_names_ = NULL; static widget_name_t *param_incs_ = NULL; static widget_name_t *param_decs_ = NULL; static widget_name_t *gen_names_ = NULL; static widget_name_t *gen_incs_ = NULL; static widget_name_t *gen_decs_ = NULL; static effectlist_data fxlist_data; #define MAX_PATH_LEN 1024 #define VEEJAY_MSG_OUTPUT 4 #define GENERATOR_PARAMS 11 #define SEQUENCER_COL 10 #define SEQUENCER_ROW 10 static guint macro_line[4] = { 0,0,0,0 }; static vj_gui_t *info = NULL; void *get_ui_info() { return (void*) info; } void reloaded_schedule_restart(); /* global pointer to the sample-bank */ /* global pointer to the effects-source-list */ static GtkWidget *effect_sources_tree = NULL; static GtkListStore *effect_sources_store = NULL; static GtkTreeModel *effect_sources_model = NULL; static GtkWidget *cali_sourcetree = NULL; static GtkListStore *cali_sourcestore = NULL; static GtkTreeModel *cali_sourcemodel = NULL; /* global pointer to the editlist-tree */ static GtkWidget *editlist_tree = NULL; static GtkListStore *editlist_store = NULL; static GtkTreeModel *editlist_model = NULL; //void gtk_configure_window_cb( GtkWidget *w, GdkEventConfigure *ev, gpointer data ); static int get_slider_val(const char *name); static int get_slider_val2(GtkWidget *w); void vj_msg(int type, const char format[], ...); //static void vj_msg_detail(int type, const char format[], ...); 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 int get_nums(const char *name); static gchar *get_text(const char *name); static void put_text(const char *name, char *text); static void set_toggle_button(const char *name, int status); static void update_slider_gvalue(const char *name, gdouble value ); static void update_slider_value2(GtkWidget *w, gint value, gint scale); static void update_slider_range2(GtkWidget *w, gint min, gint max, gint value, gint scaled); 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_range2(GtkWidget *w, gint min, gint max, gint val); 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_i2(GtkWidget *label, int num, int prefix); 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(int *his, int p, int k); static gint load_parameter_info(); static void load_v4l_info(); static void reload_editlist_contents(); static void load_effectchain_info(); static void set_feedback_status(); static void load_effectlist_info(); static void load_sequence_list(); static void load_generator_info(); static void load_samplelist_info(gboolean with_reset_slotselection); static void load_editlist_info(); static void set_pm_page_label(int sample_id, int type); static void notebook_set_page(const char *name, int page); static void hide_widget(const char *name); static void show_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, int expand ); static void setup_tree_pixmap_column( const char *tree_name, int type, const char *title ); gchar *_utf8str( const char *c_str ); static gchar *recv_vims(int len, int *bytes_written); static gchar *recv_vims_args(int slen, int *bytes_written, int *arg0, int *arg1, int *arg2); static GdkPixbuf *update_pixmap_entry( int status ); static gboolean chain_update_row(GtkTreeModel * model, GtkTreePath * path, GtkTreeIter * iter,gpointer data); int resize_primary_ratio_y(); int resize_primary_ratio_x(); 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(); 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, GtkAllocation *allocation, gint *image_w, gint *image_h); 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 gboolean on_slot_activated_by_mouse (GtkWidget *widget, GdkEventButton *event, gpointer user_data); static void add_sample_to_effect_sources_list(gint id, gint type, gchar *title, gchar *timecode); static void set_activation_of_slot_in_samplebank(gboolean activate); static int bank_exists( int bank_page, int slot_num ); static int find_bank_by_sample(int sample_id, int sample_type, int *slot ); static int add_bank( gint bank_num ); static void set_selection_of_slot_in_samplebank(gboolean active); static void remove_sample_from_slot(); static void create_ref_slots(int envelope_size); static void create_sequencer_slots(int x, int y); void clear_samplebank_pages(); void free_samplebank(void); void reset_samplebank(void); int verify_bank_capacity(int *bank_page_, int *slot_, int sample_id, int sample_type ); static void widget_get_rect_in_screen (GtkWidget *widget, GdkRectangle *r); static void update_curve_widget( GtkWidget *curve ); /* not used */ /* static void update_curve_accessibility(const char *name); */ static void reset_tree(const char *name); static void reload_srt(); static void reload_fontlist(); static void indicate_sequence( gboolean active, sequence_gui_slot_t *slot ); static void set_textview_buffer(const char *name, gchar *utf8text); void interrupt_cb(); int get_and_draw_frame(int type, char *wid_name); GdkPixbuf *vj_gdk_pixbuf_scale_simple( GdkPixbuf *src, int dw, int dh, GdkInterpType inter_type ); static void vj_kf_select_parameter(int id); static void vj_kf_refresh(gboolean force); static void vj_kf_reset(); static void veejay_stop_connecting(vj_gui_t *gui); void reload_macros(); void reportbug(); void select_chain_entry(int entry); GtkWidget *glade_xml_get_widget_( GtkBuilder *m, const char *name ); gboolean gveejay_idle(gpointer data) { if(gveejay_running()) { int sync = 0; if( is_alive(&sync) == FALSE ) { return FALSE; } if( sync ) { if( gveejay_time_to_sync( get_ui_info() ) ) { veejay_update_multitrack( get_ui_info() ); } vj_midi_handle_events( info->midi ); } } return TRUE; } static void init_widget_cache() { // TODO: add more mappings to reduce the number of times we need to call glade_xml_get_widget_ from update_gui() memset(widget_cache, 0, sizeof(widget_cache)); for( int i = 0; widget_map[i].name != NULL; i ++ ) { widget_cache[ widget_map[i].id ] = glade_xml_get_widget_( info->main_window, widget_map[i].name ); if( widget_cache[ widget_map[i].id ] == NULL ){ veejay_msg(VEEJAY_MSG_ERROR, "Widget '%s' does not exist", widget_map[i].name ); } } } /* NOT USED static void identify_widget(GtkWidget *w) { for( int i = 0; widget_map[i].name != NULL; i ++ ) { if( widget_cache[ widget_map[i].id ] == w ) { veejay_msg(VEEJAY_MSG_DEBUG, "Widget %p is %s", w, widget_map[i].name ); return; } } veejay_msg(VEEJAY_MSG_DEBUG, "Widget %p is not in widget_cache"); } */ static gboolean is_edl_displayed() { int panel_page = gtk_notebook_get_current_page( GTK_NOTEBOOK( widget_cache[ WIDGET_NOTEBOOK18 ] )); int sample_page = gtk_notebook_get_current_page( GTK_NOTEBOOK( widget_cache[ WIDGET_NOTEBOOK15] )); if( panel_page == 5 && sample_page == 2 ) return TRUE; return FALSE; } static gboolean is_fxanim_displayed() { int fxanim_page = gtk_notebook_get_current_page( GTK_NOTEBOOK( widget_cache[ WIDGET_NOTEBOOK18 ] )); if( fxanim_page == 1) return TRUE; return FALSE; } gboolean periodic_pull(gpointer data) { int deckpage = gtk_notebook_get_current_page( GTK_NOTEBOOK( widget_cache[ WIDGET_NOTEBOOK18 ] )); int pm = info->status_tokens[PLAY_MODE]; if( pm == MODE_STREAM && deckpage == 5 && info->status_tokens[STREAM_TYPE] == STREAM_GENERATOR) { info->uc.reload_hint[HINT_GENERATOR] = 1; } if( pm != MODE_PLAIN ) { info->uc.reload_hint[HINT_ENTRY] = 1; info->uc.reload_hint[HINT_CHAIN] = 1; } return TRUE; } static int data_checksum(char *data,size_t len) { int i; int checksum = 0; for( i = 0; i < len; i ++ ) { checksum = (checksum >> 1) + ((checksum & 1) << 15 ); checksum += (int) data[i]; checksum &= 0xffff; } return checksum; } void reset_cali_images( int type, char *wid_name ); gboolean disable_sample_image = FALSE; void set_disable_sample_image(gboolean status) { disable_sample_image = status; } void add_class(GtkWidget *widget, const char *name) { GtkStyleContext *ctx = gtk_widget_get_style_context(widget); gtk_style_context_add_class(ctx, name); } void remove_class(GtkWidget *widget, const char *name) { GtkStyleContext *ctx = gtk_widget_get_style_context(widget); gtk_style_context_remove_class(ctx, name); } static gchar* strduplastn(gchar *title) { gchar *reversed = g_strreverse(title); gchar *part = g_strndup(reversed,12); gchar *reverse = g_strreverse(part); gchar *result = g_strdup(reverse); g_free(part); return result; } GtkWidget *glade_xml_get_widget_( GtkBuilder *m, const char *name ) { GtkWidget *widget = GTK_WIDGET (gtk_builder_get_object( m , name )); if(!widget) { return NULL; } #ifdef STRICT_CHECKING assert( widget != NULL ); #endif return widget; } static void add_class_by_name(const char *widget_name, const char *name) { GtkWidget *widget = glade_xml_get_widget_(info->main_window,widget_name); add_class(widget, name); } void gtk_notebook_set_current_page__( GtkWidget *w, gint num, const char *f, int line ) { gtk_notebook_set_current_page( GTK_NOTEBOOK(w), num ); } void gtk_widget_set_size_request__( GtkWidget *w, gint iw, gint h, const char *f, int line ) { gtk_widget_set_size_request(w, iw, h ); } #ifndef STRICT_CHECKING #define gtk_widget_set_size_request_(a,b,c) gtk_widget_set_size_request(a,b,c) #define gtk_notebook_set_current_page_(a,b) gtk_notebook_set_current_page(a,b) #else #define gtk_widget_set_size_request_(a,b,c) gtk_widget_set_size_request__(a,b,c,__FUNCTION__,__LINE__) #define gtk_notebook_set_current_page_(a,b) gtk_notebook_set_current_page__(a,b,__FUNCTION__,__LINE__) #endif static struct { gchar *text; } text_msg_[] = { { "Running realtime" }, { NULL }, }; enum { TEXT_REALTIME = 0 }; static struct { const char *name; } capt_label_set[] = { { "label333" }, //brightness { "label334" }, //contrast { "label336" }, //hue { "label777" }, //saturation { "label29" }, //temperature { "label337"}, //gamma { "label25" }, //sharpness { "label20" }, //gain { "label21" }, //red balance { "label22" }, //blue balance { "label23" }, //green balance { "label20" }, //gain { "label26" }, //bl_compensate { "label34" }, //whiteness { "label33" }, //blacklevel { "label31" }, //exposure { "label24" }, //autowhitebalance { "label27" }, //autogain { "label28" }, //autohue { "label30" }, //fliph { "label32" }, //flipv { NULL }, }; static struct { const char *name; } capt_card_set[] = { { "v4l_brightness" }, { "v4l_contrast" }, { "v4l_hue" }, { "v4l_saturation" }, { "v4l_temperature"}, { "v4l_gamma" }, { "v4l_sharpness" }, { "v4l_gain" }, { "v4l_redbalance" }, { "v4l_bluebalance" }, { "v4l_greenbalance" }, { "v4l_gain" }, { "v4l_backlightcompensation"}, { "v4l_whiteness"}, { "v4l_black_level" }, { "v4l_exposure" }, { "check_autowhitebalance"}, { "check_autogain" }, { "check_autohue" }, { "check_flip" }, { "check_flipv"}, { NULL }, }; #define CAPT_CARD_SLIDERS 16 #define CAPT_CARD_BOOLS 5 static int preview_box_w_ = MAX_PREVIEW_WIDTH; static int preview_box_h_ = MAX_PREVIEW_HEIGHT; static void *bankport_ = NULL; int vj_get_preview_box_w() { return preview_box_w_; } int vj_get_preview_box_h() { return preview_box_h_; } #ifdef STRICT_CHECKING static void gtk_image_set_from_pixbuf__( GtkImage *w, GdkPixbuf *p, const char *f, int l ) { assert( GTK_IS_IMAGE(w) ); gtk_image_set_from_pixbuf(w, p); } static void gtk_widget_set_sensitive___( GtkWidget *w, gboolean state, const char *f, int l ) { assert( GTK_IS_WIDGET(w) ); gtk_widget_set_sensitive(w, state ); } #endif static void select_slot(int pm); #ifdef STRICT_CHECKING #define gtk_widget_set_sensitive_( w,p ) gtk_widget_set_sensitive___( w,p,__FUNCTION__,__LINE__ ) #define gtk_image_set_from_pixbuf_(w,p) gtk_image_set_from_pixbuf__( w,p, __FUNCTION__,__LINE__ ) #else #define gtk_widget_set_sensitive_( w,p ) gtk_widget_set_sensitive( w,p ) #define gtk_image_set_from_pixbuf_(w,p) gtk_image_set_from_pixbuf( w,p ) #endif 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 }; static sample_slot_t *find_slot_by_sample( int sample_id , int sample_type ); static sample_gui_slot_t *find_gui_slot_by_sample( int sample_id , int sample_type ); gchar *_utf8str(const char *c_str) { gsize bytes_read = 0; gsize bytes_written = 0; GError *error = NULL; if(!c_str) return NULL; char *result = (char*) g_locale_to_utf8( c_str, -1, &bytes_read, &bytes_written, &error ); if(error) { g_free(error); if( result ) g_free(result); result = NULL; } return result; } /*! \brief Return the widget current state foreground color. * * \param w A pointer of calling widget * \return A pointer to GdkRGBA */ GdkRGBA *widget_get_fg(GtkWidget *w ) { if(!w) return NULL; GtkStyleContext *sc = gtk_widget_get_style_context(w); GdkRGBA *color = (GdkRGBA*)vj_calloc(sizeof(GdkRGBA)); gtk_style_context_get_color ( sc, gtk_style_context_get_state (sc), color ); return color; } static void scan_devices( const char *name) { GtkWidget *tree = glade_xml_get_widget_(info->main_window,name); GtkListStore *store; GtkTreeIter iter; reset_tree(name); gint len = 0; single_vims( VIMS_DEVICE_LIST ); gchar *text = recv_vims(6,&len); if(len <= 0|| !text ) { veejay_msg(VEEJAY_MSG_WARNING, "No capture devices found on veejay server"); return; } GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW(tree)); store = GTK_LIST_STORE(model); gint offset =0; gint i = 0; gchar *ptr = text + offset; while( offset < len ) { char tmp[4]; gchar *name = NULL; gdouble gchannel = 1.0; gchar *loca = NULL; gint name_len=0; gint loc_len=0; strncpy(tmp,ptr+offset,3); tmp[3] = '\0'; offset += 3; name_len = atoi( tmp ); if(name_len <= 0 ) { veejay_msg(VEEJAY_MSG_ERROR, "Reading name of capture device: '%s'",ptr+offset ); return; } name = strndup( ptr + offset, name_len ); offset += name_len; strncpy( tmp, ptr + offset, 3 ); tmp[3] = '\0'; offset += 3; loc_len = atoi( tmp ); if( loc_len <= 0 ) { veejay_msg(VEEJAY_MSG_ERROR, "Reading location of capture device"); return; } loca = strndup( ptr + offset, loc_len ); offset += loc_len; gchar *thename = _utf8str( name ); gchar *theloca = _utf8str( loca ); gtk_list_store_append( store, &iter); gtk_list_store_set(store, &iter, V4L_NUM, i, V4L_NAME, thename, V4L_SPINBOX, gchannel, V4L_LOCATION, theloca, -1); g_free(thename); g_free(theloca); free(loca); free(name); i ++; } free(text); gtk_tree_view_set_model(GTK_TREE_VIEW(tree), model ); } static void scan_generators( const char *name) { GtkWidget *tree = glade_xml_get_widget_(info->main_window,name); GtkListStore *store; GtkTreeIter iter; reset_tree(name); gint len = 0; single_vims( VIMS_GET_GENERATORS ); gchar *text = recv_vims(5,&len); if(len <= 0|| !text ) { veejay_msg(VEEJAY_MSG_WARNING, "No generators found on veejay server"); return; } GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW(tree)); store = GTK_LIST_STORE(model); gint offset =0; gint i = 0; gchar *ptr = text + offset; while( offset < len ) { char tmp[4]; gchar *name = NULL; gint name_len=0; strncpy(tmp,ptr+offset,3); tmp[3] = '\0'; offset += 3; name_len = atoi( tmp ); if(name_len <= 0 ) { veejay_msg(VEEJAY_MSG_ERROR, "Reading name of generator: '%s'",ptr+offset ); return; } name = strndup( ptr + offset, name_len ); offset += name_len; gchar *thename = _utf8str( name ); gtk_list_store_append( store, &iter); gtk_list_store_set(store, &iter,0,thename,-1); g_free(thename); free(name); i ++; } free(text); gtk_tree_view_set_model(GTK_TREE_VIEW(tree), model ); } static void set_tooltip_by_widget(GtkWidget *w, const char *text) { gtk_widget_set_tooltip_text( w,text ); } static void set_tooltip(const char *name, const char *text) { GtkWidget *w = glade_xml_get_widget_(info->main_window,name); if(!w) { #ifdef STRICT_CHECKING veejay_msg(VEEJAY_MSG_ERROR, "Widget '%s' not found",name); #endif return; } gtk_widget_set_tooltip_text( w,text ); } 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 channel = info->uc.strtmpl[0].channel; gint num = info->uc.strtmpl[0].dev; multi_vims( VIMS_STREAM_NEW_V4L,"%d %d", num, channel ); } } gboolean device_selection_func( GtkTreeSelection *sel, GtkTreeModel *model, GtkTreePath *path, gboolean path_currently_selected, gpointer userdata ) { GtkTreeIter iter; GValue val = { 0, }; if( gtk_tree_model_get_iter( model, &iter, path ) ) { gint num = 0; //gtk_tree_model_get(model, &iter, V4L_NUM,&num, -1 ); gchar *file = NULL; gtk_tree_model_get( model, &iter, V4L_LOCATION, &file, -1 ); sscanf( file, "/dev/video%d", &num ); if(! path_currently_selected ) { gtk_tree_model_get_value(model, &iter, V4L_SPINBOX, &val); info->uc.strtmpl[0].dev = num; info->uc.strtmpl[0].channel = (int) g_value_get_float(&val); } g_free(file); } return TRUE; } static void setup_v4l_devices() { GtkWidget *tree = glade_xml_get_widget_( info->main_window, "tree_v4ldevices"); GtkListStore *store = gtk_list_store_new( 4, G_TYPE_INT, G_TYPE_STRING, G_TYPE_FLOAT, G_TYPE_STRING ); gtk_tree_view_set_model( GTK_TREE_VIEW(tree), GTK_TREE_MODEL(store)); GtkTreeSelection *sel = gtk_tree_view_get_selection( GTK_TREE_VIEW( tree ) ); gtk_tree_selection_set_mode( sel, GTK_SELECTION_SINGLE ); gtk_tree_selection_set_select_function( sel, device_selection_func, NULL,NULL ); // gtk_tree_view_set_fixed_height_mode( GTK_TREE_VIEW(tree), TRUE ); g_object_unref( G_OBJECT( store )); setup_tree_text_column( "tree_v4ldevices", V4L_NUM, "#",0 ); setup_tree_text_column( "tree_v4ldevices", V4L_NAME, "Device Name",0); setup_tree_spin_column( "tree_v4ldevices", V4L_SPINBOX, "Channel"); setup_tree_text_column( "tree_v4ldevices", V4L_LOCATION, "Location",0); g_signal_connect( tree, "row-activated", (GCallback) on_devicelist_row_activated, NULL ); //scan_devices( "tree_v4ldevices" ); } gboolean vims_macro_selection_func( GtkTreeSelection *sel, GtkTreeModel *model, GtkTreePath *path, gboolean path_currently_selected, gpointer data) { GtkTreeIter iter; if( gtk_tree_model_get_iter( model, &iter, path) ) { guint frame_num = 0, dup_num = 0, loop_num = 0, seq_no = 0; gchar *message = NULL; gtk_tree_model_get( model, &iter, MACRO_FRAME, &frame_num, -1); gtk_tree_model_get( model, &iter, MACRO_DUP, &dup_num, -1); gtk_tree_model_get( model, &iter, MACRO_MSG_SEQ, &seq_no, -1); gtk_tree_model_get( model, &iter, MACRO_LOOP, &loop_num, -1); gtk_tree_model_get( model, &iter, MACRO_VIMS, &message, -1 ); macro_line[0] = frame_num; macro_line[1] = dup_num; macro_line[2] = loop_num; macro_line[3] = seq_no; update_spin_value( "macro_frame_position", frame_num ); update_spin_value( "macro_dup_position", dup_num ); update_spin_value( "macro_loop_position", loop_num ); put_text( "macro_vims_message", message ); g_free(message); } return TRUE; } static void setup_macros() { GtkWidget *tree = glade_xml_get_widget_( info->main_window, "macro_macros" ); GtkListStore *store = gtk_list_store_new( 6, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING ); gtk_tree_view_set_model( GTK_TREE_VIEW(tree), GTK_TREE_MODEL(store) ); GtkTreeSelection *sel = gtk_tree_view_get_selection( GTK_TREE_VIEW(tree) ); gtk_tree_selection_set_mode( sel, GTK_SELECTION_SINGLE ); gtk_tree_selection_set_select_function( sel, vims_macro_selection_func, NULL,NULL ); g_object_unref( G_OBJECT(store) ); setup_tree_text_column( "macro_macros", MACRO_FRAME, "Frame",0 ); setup_tree_text_column( "macro_macros", MACRO_DUP, "Dup",0); setup_tree_text_column( "macro_macros", MACRO_LOOP, "Loop",0); setup_tree_text_column( "macro_macros", MACRO_MSG_SEQ, "#",0); setup_tree_text_column( "macro_macros", MACRO_VIMS, "VIMS Message",0); setup_tree_text_column( "macro_macros", MACRO_VIMS_DESCR, "Description",0); } 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; int _effect_is_gen(int effect_id) { effect_constr *ec = info->effect_info[effect_id]; if(ec != NULL) return ec->is_gen; return 0; } int _effect_get_mix(int effect_id) { effect_constr *ec = info->effect_info[effect_id]; if(ec != NULL) return ec->is_video; return 0; } int _effect_get_rgb(int effect_id) { effect_constr *ec = info->effect_info[effect_id]; if(ec != NULL) return ec->has_rgb; return 0; } /* * Return the number of parameters from an effect identifier * * FIXME return too much parameter for some generator */ int _effect_get_np(int effect_id) { effect_constr *ec = info->effect_info[effect_id]; if(ec != NULL) return ec->num_arg; return 0; } int _effect_get_minmax( int effect_id, int *min, int *max, int index ) { effect_constr *ec = info->effect_info[effect_id]; if(ec != NULL && index < ec->num_arg) { *min = ec->min[index]; *max = ec->max[index]; return 1; } return 0; } char *_effect_get_param_description(int effect_id, int param) { effect_constr *ec = info->effect_info[effect_id]; if(ec != NULL) return ec->param_description[param]; return FX_PARAMETER_DEFAULT_NAME; } char *_effect_get_description(int effect_id) { effect_constr *ec = info->effect_info[effect_id]; if(ec != NULL) return ec->description; return FX_PARAMETER_DEFAULT_NAME; } char *_effect_get_hint(int effect_id, int p, int v) { effect_constr *ec = info->effect_info[effect_id]; if(ec != NULL) { if( ec->hints[p] == NULL) return FX_PARAMETER_VALUE_DEFAULT_HINT; return ec->hints[p]->description[v]; } return FX_PARAMETER_VALUE_DEFAULT_HINT; } 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 = vj_malloc(sizeof(el_ref)); 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 n = g_list_length( info->elref ); int i; for(i = 0; i < n; i ++ ) { el_ref *edl = g_list_nth_data(info->elref, i ); if(edl) free(edl); } 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,q; char len[4]; int offset = 0; veejay_memset(len,0,sizeof(len)); if(!effect_line) return NULL; strncpy(len, effect_line, 3); sscanf(len, "%03d", &descr_len); if(descr_len <= 0) return NULL; ec = vj_calloc( sizeof(effect_constr)); strncpy( ec->description, effect_line+3, descr_len ); if(sscanf(effect_line+(descr_len+3), "%03d%1d%1d%1d%02d", &(ec->id),&(ec->is_video),&(ec->has_rgb),&(ec->is_gen), &(ec->num_arg)) != 5 ) { veejay_msg(VEEJAY_MSG_ERROR, "Error parsing FX"); free(ec); return NULL; } offset = descr_len + 11; for(p=0; p < ec->num_arg; p++) { int len = 0; int n = sscanf(effect_line+offset,"%06d%06d%06d%03d", &(ec->min[p]), &(ec->max[p]),&(ec->defaults[p]),&len ); if( n != 4 ) { veejay_msg(VEEJAY_MSG_ERROR,"Parse error in FX '%s' arguments", ec->description); free(ec); return NULL; } ec->param_description[p] = (char*) vj_calloc(sizeof(char) * (len+1) ); strncpy( ec->param_description[p], effect_line + offset + 6 + 6 + 6 + 3, len ); offset += 3; offset += len; offset+=18; } for(p=0; p < ec->num_arg; p++) { int hint_len = 0; int n = sscanf( effect_line + offset, "%06d", &hint_len ); if( n != 1 ) { veejay_msg(VEEJAY_MSG_ERROR,"Parse error in FX '%s' list hints", ec->description); free(ec); return NULL; } offset += 6; if(hint_len == 0) continue; ec->hints[p] = (value_hint*) vj_calloc(sizeof(value_hint)); ec->hints[p]->description = (char**) vj_calloc(sizeof(char*) * (ec->max[p]+2) ); for(q = 0; q <= ec->max[p]; q ++ ) { int value_hint = 0; n = sscanf( effect_line + offset, "%03d", &value_hint ); if( n != 1) { veejay_msg(VEEJAY_MSG_ERROR,"Parse error in FX list value hint"); free(ec); return NULL; } offset += 3; ec->hints[p]->description[q] = (char*) vj_calloc(sizeof(char) * value_hint + 1 ); strncpy( ec->hints[p]->description[q], effect_line + offset, value_hint ); offset += value_hint; } } return ec; } void _effect_free( effect_constr *effect ) { if(effect) { int p; for( p = 0; p < effect->num_arg; p ++ ) { free( effect->param_description[p] ); } if( effect->hints ) { for( p = 0; p < effect->num_arg; p ++ ) { if( effect->hints[p] == NULL ) continue; int q; for( q = 0; effect->hints[p]->description[q] != NULL; q ++ ) { free( effect->hints[p]->description[q] ); } free( effect->hints[p]->description ); free( effect->hints[p] ); } } free(effect); } } void _effect_reset(void) { int i; for( i = 0; i < EFFECT_LIST_SIZE; i ++ ) { _effect_free( info->effect_info[i] ); info->effect_info[i] = NULL; } } static gchar *get_relative_path(char *path) { return _utf8str( basename( path )); } gchar *dialog_save_file(const char *title, const char *current_name) { GtkWidget *parent_window = glade_xml_get_widget_(info->main_window, "gveejay_window" ); GtkWidget *dialog = gtk_file_chooser_dialog_new(title, GTK_WINDOW(parent_window), GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL); add_class(dialog, "reloaded" ); gtk_file_chooser_set_current_name( GTK_FILE_CHOOSER(dialog), current_name ); 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, file_filter_t type ) { GtkFileFilter *filter = NULL; switch(type) { case FILE_FILTER_DEFAULT: for(int 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 ); } break; case FILE_FILTER_SL: 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); break; case FILE_FILTER_XML: 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); break; case FILE_FILTER_YUV: filter = gtk_file_filter_new(); gtk_file_filter_set_name( filter, "YUV4MPEG files (*.yuv)"); gtk_file_filter_add_pattern( filter, "*.yuv" ); gtk_file_chooser_add_filter( GTK_FILE_CHOOSER(dialog), filter); break; case FILE_FILTER_CFG: filter = gtk_file_filter_new(); gtk_file_filter_set_name( filter, "MIDI config files (*.cfg)"); gtk_file_filter_add_pattern( filter, "*.cfg" ); gtk_file_chooser_add_filter( GTK_FILE_CHOOSER(dialog), filter); break; default: break; } 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, file_filter_t 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, GTK_WINDOW(parent_window), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); add_class( dialog, "reloaded" ); 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); _file_path = NULL; } 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; } static char *produce_os_str() { char os_str[512]; char cpu_type[32]; char *simd = vj_calloc( 128 ); #ifdef ARCH_X86 sprintf(cpu_type,"x86"); #endif #ifdef ARCH_X86_64 sprintf(cpu_type, "x86-64"); #endif #ifdef ARCH_PPC sprintf(cpu_type, "ppc"); #endif #ifdef ARCH_MIPS sprintf(cpu_type, "mips"); #endif #ifdef HAVE_ASM_MMX strcat( simd, "MMX "); #endif #ifdef HAVE_ASM_MMX2 strcat( simd, "MMX2 "); #endif #ifdef HAVE_ASM_SSE strcat( simd, "SSE " ); #endif #ifdef HAVE_ASM_SSE2 strcat( simd, "SSE2" ); #endif #ifdef HAVE_ASM_CMOV strcat( simd, "cmov" ); #endif #ifdef HAVE_ASM_3DNOW strcat( simd, "3DNow"); #endif #ifdef ARCH_PPC #ifdef HAVE_ALTIVEC strcat( simd, "altivec"); #else strcat( simd, "no optimizations"); #endif #endif #ifdef ARCH_MIPS strcat( simd, "no optimizations"); #endif sprintf(os_str,"Arch: %s with %s", cpu_type, simd ); return strdup( os_str ); } void about_dialog() { const gchar *artists[] = { "Matthijs v. Henten (glade, pixmaps) ", "Dursun Koca (V-logo)", NULL }; const gchar *authors[] = { "Developed by:", "Matthijs v. Henten ", "Dursun Koca", "Niels Elburg ", "\n", "Contributions by:", "Thomas Reinhold ", "Toni ", "d/j/a/y (GTK3 port)", NULL }; const gchar *web = { "http://www.veejayhq.net" }; char blob[1024]; char *os_str = produce_os_str(); const gchar *donate = { "You can donate cryptocoins!\n"\ "Bitcoin: 1PUNRsv8vDt1upTx9tTpY5sH8mHW1DTrKJ\n" "or via PayPal: veejayhq@gmail.com\n" }; sprintf(blob, "Veejay - A visual instrument and realtime video sampler for GNU/Linux\n%s\n%s", os_str, donate ); free(os_str); 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" }; char path[MAX_PATH_LEN]; veejay_memset( path,0, sizeof(path)); 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, "program_name", "reloaded", "name", VEEJAY_CODENAME, "version", VERSION, "copyright", "(C) 2004 - 2019 N. Elburg et all.", "comments", "The graphical interface for Veejay", "website", web, "authors", authors, "artists", artists, "comments", blob, "license", license, "logo", pixbuf, NULL ); add_class(about,"reloaded"); g_object_unref(pixbuf); g_signal_connect( about , "response", G_CALLBACK( gtk_widget_destroy),NULL); GtkWidget *mainw = glade_xml_get_widget_(info->main_window,"gveejay_window" ); gtk_window_set_transient_for(GTK_WINDOW(about),GTK_WINDOW (mainw)); gtk_window_set_keep_above(GTK_WINDOW(about), TRUE); gtk_window_present(GTK_WINDOW(about)); } gboolean dialogkey_snooper( GtkWidget *w, GdkEventKey *event, gpointer user_data) { GtkWidget *entry = (GtkWidget*) user_data; if( !gtk_widget_is_focus( entry ) ) { return FALSE; } #ifdef HAVE_SDL if(event->type == GDK_KEY_PRESS) { gchar tmp[100]; info->uc.pressed_key = gdk2sdl_key( event->keyval ); info->uc.pressed_mod = gdk2sdl_mod( event->state ); gchar *text = gdkkey_by_id( event->keyval ); gchar *mod = gdkmod_by_id( event->state ); if( text ) { if(!mod || strncmp(mod, " ", 1 ) == 0 ) snprintf(tmp, sizeof(tmp),"%s", text ); else snprintf(tmp, sizeof(tmp), "%s + %s", mod,text); gchar *utf8_text = _utf8str( tmp ); gtk_entry_set_text( GTK_ENTRY(entry), utf8_text); g_free(utf8_text); } } #endif return FALSE; } #ifdef HAVE_SDL static gboolean key_handler( GtkWidget *w, GdkEventKey *event, gpointer user_data) { if(event->type != GDK_KEY_PRESS) return FALSE; int gdk_keyval = gdk2sdl_key( event->keyval ); int gdk_state = gdk2sdl_mod( event->state ); if( gdk_keyval >= 0 && gdk_state >= 0 ) { char *message = vims_keys_list[(gdk_state * G_MOD_OFFSET)+gdk_keyval].vims; if(message) msg_vims(message); } return FALSE; } #endif static int check_format_string( char *args, char *format ) { if(!format || !args ) return 0; char dirty[128]; int n = sscanf( args, format, &dirty,&dirty, &dirty,&dirty, &dirty,&dirty, &dirty,&dirty, &dirty,&dirty ); return n; } int prompt_keydialog(const char *title, char *msg) { if(!info->uc.selected_vims_entry ) return 0; info->uc.pressed_mod = 0; info->uc.pressed_key = 0; char pixmap[1024]; veejay_memset(pixmap,0,sizeof(pixmap)); get_gd( pixmap, NULL, "icon_keybind.png"); 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_CANCEL, GTK_RESPONSE_REJECT, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL); add_class(dialog, "reloaded" ); GtkWidget *keyentry = gtk_entry_new(); gtk_entry_set_text( GTK_ENTRY(keyentry), ""); gtk_editable_set_editable( GTK_EDITABLE(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_box_new( GTK_ORIENTATION_HORIZONTAL, 12 ); gtk_container_set_border_width( GTK_CONTAINER( hbox1 ), 6 ); GtkWidget *hbox2 = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, 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 ); GtkWidget *pentry = NULL; if(vj_event_list[ info->uc.selected_vims_entry ].params) { //@ put in default args char *arg_str = vj_event_list[ info->uc.selected_vims_entry ].args; pentry = gtk_entry_new(); GtkWidget *arglabel = gtk_label_new("Arguments:"); if(arg_str) gtk_entry_set_text( GTK_ENTRY(pentry), arg_str ); gtk_editable_set_editable( GTK_EDITABLE(pentry), TRUE ); gtk_container_add( GTK_CONTAINER(hbox1), arglabel ); gtk_container_add( GTK_CONTAINER(hbox1), pentry ); } #ifdef HAVE_SDL if( info->uc.selected_vims_entry ) { char tmp[100]; char *str_mod = sdlmod_by_id( info->uc.pressed_mod ); char *str_key = sdlkey_by_id( info->uc.pressed_key ); int key_combo_ok = 0; if(str_mod && str_key ) { snprintf(tmp,100,"VIMS %d : %s + %s", info->uc.selected_vims_entry, str_mod, str_key ); key_combo_ok = 1; }else if ( str_key ) { snprintf(tmp, 100,"VIMS %d: %s", info->uc.selected_vims_entry,str_key); key_combo_ok = 1; } if( key_combo_ok ) { gtk_entry_set_text( GTK_ENTRY(keyentry), tmp ); } } #endif GtkWidget* content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); gtk_container_add( GTK_CONTAINER(content_area), hbox1 ); gtk_container_add( GTK_CONTAINER(content_area), hbox2 ); gtk_widget_show_all( dialog ); int id = gtk_key_snooper_install( dialogkey_snooper, keyentry); int n = gtk_dialog_run(GTK_DIALOG(dialog)); gtk_key_snooper_remove( id ); if(pentry) { gchar *args = (gchar*) gtk_entry_get_text( GTK_ENTRY(pentry)); int np = check_format_string( args, vj_event_list[ info->uc.selected_vims_entry ].format ); if( np == vj_event_list[ info->uc.selected_vims_entry ].params ) { if(info->uc.selected_vims_args ) free(info->uc.selected_vims_args ); info->uc.selected_vims_args = strdup( args ); } } 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); add_class(dialog, "reloaded" ); GtkWidget *label = gtk_label_new( msg ); g_signal_connect_swapped(dialog, "response", G_CALLBACK(gtk_widget_destroy),dialog); GtkWidget* content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); gtk_container_add(GTK_CONTAINER(content_area), 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); add_class( dialog, "reloaded" ); 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_box_new( GTK_ORIENTATION_HORIZONTAL, 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_get_content_area (GTK_DIALOG (dialog))), hbox1 ); gtk_widget_show_all( dialog ); int n = gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); return n; } int error_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_OK, NULL); add_class(dialog, "reloaded" ); gtk_dialog_set_default_response( GTK_DIALOG(dialog), GTK_RESPONSE_OK ); 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_box_new( GTK_ORIENTATION_HORIZONTAL, 12 ); gtk_container_set_border_width( GTK_CONTAINER( hbox1 ), 6 ); GtkWidget *icon = gtk_image_new_from_stock(GTK_STOCK_DIALOG_ERROR, 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_get_content_area (GTK_DIALOG (dialog))), 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 ); // 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 ); clear_progress_bar( "seq_rec_progress",0.0); exit(0); } static int running_g_ = 1; static int restart_ = 0; int gveejay_restart() { return restart_; } gboolean gveejay_running() { if(!running_g_) return FALSE; return TRUE; } gboolean gveejay_relaunch() { return (info->watch.state == STATE_QUIT ? FALSE: TRUE); } gboolean gveejay_quit( GtkWidget *widget, gpointer user_data) { if( info->watch.state == STATE_PLAYING) { if(prompt_dialog("Quit Reloaded", "Are you sure?") != GTK_RESPONSE_ACCEPT) return TRUE; } info->watch.state = STATE_QUIT; 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); free(slot); } slot = NULL; } /* 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_calloc(sizeof(sample_slot_t)); if(id>0) { slot->sample_id = id; slot->sample_type = type; slot->timecode = strduplastn(timecode); //slot->title = strduplastn(title); slot->title = strdup(title); slot->slot_number = slot_id; } return slot; } int is_current_track(char *host, int port ) { char *remote = get_text( "entry_hostname" ); int num = get_nums( "button_portnum" ); if( strncasecmp( remote, host, strlen(host)) == 0 && port == num ) return 1; return 0; } void gveejay_popup_err( const char *type, char *msg ) { message_dialog( type, msg ); } void donatenow(); void update_gui(); int veejay_get_sample_image(int id, int type, int wid, int hei) { multi_vims( VIMS_GET_SAMPLE_IMAGE, "%d %d %d %d", id, type, wid, hei ); uint8_t *data_buffer = (uint8_t*) vj_malloc( sizeof(uint8_t) * RUP8(wid * hei * 3)); int sample_id = 0; int sample_type =0; int full_range = 0; gint bw = 0; gchar *data = recv_vims_args( 13, &bw, &sample_id, &sample_type,&full_range ); if( data == NULL || bw <= 0 ) { if( data_buffer ) free(data_buffer); if( data ) free(data); return 0; } int expected_len = (wid * hei); expected_len += (wid*hei/4); expected_len += (wid*hei/4); if( bw != expected_len ) { if(data_buffer) free(data_buffer); if( data ) free(data); return 0; } uint8_t *in = (uint8_t*)data; uint8_t *out = data_buffer; VJFrame *src1 = yuv_yuv_template( in, in + (wid * hei), in + (wid * hei) + (wid*hei)/4,wid,hei,(full_range ? PIX_FMT_YUVJ420P : PIX_FMT_YUV420P) ); VJFrame *dst1 = yuv_rgb_template( out, wid,hei,PIX_FMT_BGR24 ); yuv_convert_any_ac( src1, dst1 ); GdkPixbuf *img = gdk_pixbuf_new_from_data(out, GDK_COLORSPACE_RGB, FALSE, 8, wid, hei, wid*3, NULL, NULL ); if( img == NULL ) return 0; /* int poke_slot= 0; int bank_page = 0; verify_bank_capacity( &bank_page , &poke_slot, sample_id, sample_type); 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,sample_id,sample_type, "PREVIEW","00:00:00" ); add_sample_to_sample_banks(bank_page, tmp_slot ); free_slot(tmp_slot); } } */ sample_slot_t *slot = find_slot_by_sample( sample_id, sample_type ); sample_gui_slot_t *gui_slot = find_gui_slot_by_sample( sample_id, sample_type ); if( slot && gui_slot ) { slot->pixbuf = vj_gdk_pixbuf_scale_simple(img,wid,hei, GDK_INTERP_NEAREST); if( slot->pixbuf) { gtk_image_set_from_pixbuf_( GTK_IMAGE( gui_slot->image ), slot->pixbuf ); g_object_unref( slot->pixbuf ); slot->pixbuf = NULL; } } free(data_buffer); free(data); g_object_unref(img); free(src1); free(dst1); return bw; } void gveejay_new_slot(int mode) { if(!samplebank_ready_) { samplebank_ready_ = 1; } if( mode == MODE_STREAM ) { info->uc.expected_num_streams = info->uc.real_num_streams + 1; } else { info->uc.expected_num_samples = info->uc.real_num_samples + 1; } } #include "callback.c" enum { COLOR_RED=0, COLOR_BLUE=1, COLOR_GREEN=2, COLOR_BLACK=3, COLOR_NUM }; 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; 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; default: sprintf(prefix,"Debug:"); break; } snprintf(buf, sizeof(buf), "%s %s\n",prefix,tmp ); gsize nr,nw; gchar *text = g_locale_to_utf8( buf, -1, &nr, &nw, NULL); text[strlen(text)-1] = '\0'; gtk_statusbar_push( GTK_STATUSBAR( widget_cache[ WIDGET_STATUSBAR] ),0, text ); g_free( text ); va_end(args); } void msg_vims(char *message) { if(!info->client) return; int n = vj_client_send(info->client, V_CMD, (unsigned char*)message); if( n <= 0 ) reloaded_schedule_restart(); } int get_loop_value() { if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( widget_cache[WIDGET_LOOP_NONE]) ) ) return 0; if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( widget_cache[WIDGET_LOOP_NORMAL]) ) ) return 1; if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( widget_cache[WIDGET_LOOP_PINGPONG]) ) ) return 2; if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( widget_cache[WIDGET_LOOP_RANDOM]) ) ) return 3; if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( widget_cache[WIDGET_LOOP_ONCENOP]) ) ) return 4; return 1; // loop normal } static void multi_vims(int id, const char format[],...) { char block[1032]; char tmp[1024]; va_list args; if(!info->client) return; va_start(args, format); vsnprintf(tmp, sizeof(tmp), format, args ); snprintf(block, sizeof(block), "%03d:%s;",id,tmp); va_end(args); if(vj_client_send( info->client, V_CMD, (unsigned char*) block)<=0 ) reloaded_schedule_restart(); } static void single_vims(int id) { char block[8]; if(!info->client) return; snprintf(block,sizeof(block), "%03d:;",id); if(vj_client_send( info->client, V_CMD, (unsigned char*) block)<=0 ) reloaded_schedule_restart(); } static gchar *recv_vims_args(int slen, int *bytes_written, int *arg0, int *arg1, int *arg2) { int tmp_len = slen+1; unsigned char tmp[tmp_len]; veejay_memset(tmp,0,sizeof(tmp)); int ret = vj_client_read( info->client, V_CMD, tmp, slen ); if( ret == -1 ) reloaded_schedule_restart(); int len = 0; if( sscanf( (char*)tmp, "%06d", &len ) != 1 ) return NULL; if( sscanf( (char*)tmp + 6, "%04d", arg0 ) != 1 ) return NULL; if( sscanf( (char*)tmp + 10, "%02d", arg1) != 1 ) return NULL; if( sscanf( (char*)tmp + 12, "%1d", arg2) != 1 ) return NULL; unsigned char *result = NULL; if( ret <= 0 || len <= 0 || slen <= 0) return (gchar*)result; result = (unsigned char*) vj_calloc(sizeof(unsigned char) * RUP8(len + 1 + 16) ); *bytes_written = vj_client_read( info->client, V_CMD, result, len ); if( *bytes_written == -1 ) reloaded_schedule_restart(); return (gchar*) result; } static gchar *recv_vims(int slen, int *bytes_written) { int tmp_len = slen+1; unsigned char tmp[tmp_len]; veejay_memset(tmp,0,sizeof(tmp)); int ret = vj_client_read( info->client, V_CMD, tmp, slen ); if( ret == -1 ) reloaded_schedule_restart(); int len = 0; if( sscanf( (char*)tmp, "%d", &len ) != 1 ) return NULL; unsigned char *result = NULL; if( ret <= 0 || len <= 0 || slen <= 0) return (gchar*)result; result = (unsigned char*) vj_calloc(sizeof(unsigned char) * (len + 1) ); *bytes_written = vj_client_read( info->client, V_CMD, result, len ); if( *bytes_written == -1 ) reloaded_schedule_restart(); return (gchar*) result; } 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_val2(GtkWidget *w) { GtkAdjustment *a = gtk_range_get_adjustment( GTK_RANGE( w )); return (int) gtk_adjustment_get_value (a); } static int get_slider_val(const char *name) { GtkWidget *w = glade_xml_get_widget_( info->main_window, name ); if(!w) return 0; GtkAdjustment *a = gtk_range_get_adjustment( GTK_RANGE( w )); return (int) gtk_adjustment_get_value (a); } static void vj_kf_reset() { int osl = info->status_lock; info->status_lock = 1; reset_curve( info->curve ); if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget_cache[WIDGET_CURVE_TOGGLEENTRY_PARAM]))) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(widget_cache[WIDGET_CURVE_TOGGLEENTRY_PARAM]), FALSE ); } /* update the time bounds accordingly the sample marker*/ int total_frames = (info->status_tokens[PLAY_MODE] == MODE_STREAM ? info->status_tokens[SAMPLE_MARKER_END] : ( info->status_tokens[PLAY_MODE] == MODE_SAMPLE ? info->status_tokens[TOTAL_FRAMES]: 0) ); int lo = (info->selection[0] == info->selection[1] ? 0 : info->selection[0]); int hi = (info->selection[1] > info->selection[0] ? info->selection[1] : total_frames ); if( lo == hi ) { lo = 0; hi = total_frames; } update_spin_range2( widget_cache[WIDGET_CURVE_SPINSTART], 0, total_frames, lo ); update_spin_range2( widget_cache[WIDGET_CURVE_SPINEND], 0, total_frames, hi ); GtkWidget* curveparam = widget_cache[WIDGET_COMBO_CURVE_FX_PARAM]; //block "changed" signal to prevent propagation guint signal_id=g_signal_lookup("changed", GTK_TYPE_COMBO_BOX); gulong handler_id=handler_id=g_signal_handler_find( (gpointer)curveparam, G_SIGNAL_MATCH_ID, signal_id, 0, NULL, NULL, NULL ); if (handler_id) g_signal_handler_block((gpointer)curveparam, handler_id); gtk_combo_box_set_active (GTK_COMBO_BOX(curveparam),0); if (handler_id) g_signal_handler_unblock((gpointer)curveparam, handler_id); info->status_lock = osl; } static void vj_kf_refresh(gboolean force) { if(!force && !is_fxanim_displayed()) return; int *entry_tokens = &(info->uc.entry_tokens[0]); if( entry_tokens[ENTRY_FXID] > 0 && _effect_get_np( entry_tokens[ENTRY_FXID] )) { gtk_widget_set_sensitive_( widget_cache[WIDGET_FRAME_FXTREE3] , TRUE ); GtkWidget* curveparam = widget_cache[WIDGET_COMBO_CURVE_FX_PARAM]; //block "changed" signal to prevent propagation guint signal_id=g_signal_lookup("changed", GTK_TYPE_COMBO_BOX); gulong handler_id=handler_id=g_signal_handler_find( (gpointer)curveparam, G_SIGNAL_MATCH_ID, signal_id, 0, NULL, NULL, NULL ); if (handler_id) g_signal_handler_block((gpointer)curveparam, handler_id); gtk_combo_box_set_active (GTK_COMBO_BOX(curveparam),0); if (handler_id) g_signal_handler_unblock((gpointer)curveparam, handler_id); vj_kf_select_parameter(0); } else { vj_kf_reset(); gtk_widget_set_sensitive_( widget_cache[WIDGET_FRAME_FXTREE3], FALSE ); } } /*! \brief Reset the current curve and update using the selected effect parameter * * \sa reset_curve * \sa update_curve_widget * * \param num the selected effect parameter */ static void vj_kf_select_parameter(int num) { sample_slot_t *s = info->selected_slot; if(!s) { gtk_combo_box_set_active (GTK_COMBO_BOX(widget_cache[WIDGET_COMBO_CURVE_FX_PARAM]),FALSE); return; } info->uc.selected_parameter_id = num; reset_curve( info->curve ); update_curve_widget( info->curve ); } /*! \brief Ask server KF of current fx param and and set them. If none set initial value * * \sa set_points_in_curve_ext * \sa set_initial_curve * * \param num the selected effect parameter */ static void update_curve_widget(GtkWidget *curve) { int i = info->uc.selected_chain_entry; /* chain entry */ int id = info->uc.entry_tokens[ENTRY_FXID]; int blen = 0; int lo = 0, hi = 0, curve_type=0; int p = -1; int status = 0; multi_vims( VIMS_SAMPLE_KF_GET, "%d %d",i,info->uc.selected_parameter_id ); unsigned char *blob = (unsigned char*) recv_vims( 8, &blen ); int checksum = data_checksum( (char*) blob, blen ) + i + info->uc.selected_parameter_id; if( info->uc.reload_hint_checksums[HINT_KF] == checksum ) { if( blob ) free(blob); return; } info->uc.reload_hint_checksums[HINT_KF] = checksum; /* update the time bounds accordingly the sample marker*/ if( lo == hi && hi == 0 ) { if( info->status_tokens[PLAY_MODE] == MODE_SAMPLE ) { lo = info->status_tokens[SAMPLE_START]; hi = info->status_tokens[SAMPLE_END]; } else { lo = 0; hi = info->status_tokens[SAMPLE_MARKER_END]; } } int total_frames = (info->status_tokens[PLAY_MODE] == MODE_STREAM ? info->status_tokens[SAMPLE_MARKER_END] : ( info->status_tokens[PLAY_MODE] == MODE_SAMPLE ? info->status_tokens[TOTAL_FRAMES]: 0) ); update_spin_range2( widget_cache[WIDGET_CURVE_SPINSTART],0, total_frames, lo ); update_spin_range2( widget_cache[WIDGET_CURVE_SPINEND], 0, total_frames, hi ); /* If parameter have KF set the points or set the initial curve */ if( blob && blen > 0 ) { p = set_points_in_curve_ext( curve, blob,id,i, &lo,&hi, &curve_type,&status ); if( p >= 0 ) { info->uc.selected_parameter_id = p; switch( curve_type ) { case GTK3_CURVE_TYPE_SPLINE: gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(widget_cache[WIDGET_CURVE_TYPESPLINE]), TRUE ); break; case GTK3_CURVE_TYPE_FREE: gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(widget_cache[WIDGET_CURVE_TYPEFREEHAND]), TRUE); break; default: gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(widget_cache[WIDGET_CURVE_TYPELINEAR]), TRUE ); break; } if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(widget_cache[WIDGET_CURVE_TOGGLEENTRY_PARAM])) != status ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(widget_cache[WIDGET_CURVE_TOGGLEENTRY_PARAM]), status ); } } } else { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(widget_cache[WIDGET_CURVE_TOGGLEENTRY_PARAM]), FALSE ); set_initial_curve( curve, info->uc.entry_tokens[ENTRY_FXID], info->uc.selected_parameter_id, lo, hi , info->uc.entry_tokens[ ENTRY_P0 + info->uc.selected_parameter_id ] ); } if(blob) free(blob); return; } static int get_nums(const char *name) { GtkWidget *w = glade_xml_get_widget_( info->main_window, name); if(!w) { veejay_msg(VEEJAY_MSG_ERROR, "No such widget (spin): '%s'",name); 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) { veejay_msg(VEEJAY_MSG_ERROR, "No such widget (textview): '%s'",name); return; } 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) { veejay_msg(VEEJAY_MSG_ERROR, "No such widget (textview): '%s'",name); return NULL; } 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) { veejay_msg(VEEJAY_MSG_ERROR, "No such widget (textview): '%s'",name); return; } 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) { veejay_msg(VEEJAY_MSG_ERROR, "No such widget (text): '%s'",name); 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) { veejay_msg(VEEJAY_MSG_ERROR, "No such widget (text): '%s'",name); return; } if(w) { gchar *utf8_text = _utf8str( text ); gtk_entry_set_text( GTK_ENTRY(w), utf8_text ); g_free(utf8_text); } } int is_button_toggled(const char *name) { GtkWidget *w = glade_xml_get_widget_( info->main_window, name); if(!w) { veejay_msg(VEEJAY_MSG_ERROR, "No such widget (togglebutton): '%s'",name); 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) { veejay_msg(VEEJAY_MSG_ERROR, "No such widget (togglebutton): '%s'",name); return; } 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) { veejay_msg(VEEJAY_MSG_ERROR, "No such widget (slider): '%s'",name); return; } GtkAdjustment *a = gtk_range_get_adjustment( GTK_RANGE( w )); gtk_adjustment_set_value( a, value ); } static void update_slider_value2(GtkWidget *w, gint value, gint scale) { gdouble gvalue; if(scale) gvalue = (gdouble) value / (gdouble) scale; else gvalue = (gdouble) value; GtkAdjustment *a = gtk_range_get_adjustment( GTK_RANGE( w )); gtk_adjustment_set_value( a, gvalue ); } static void update_slider_value(const char *name, gint value, gint scale) { GtkWidget *w = glade_xml_get_widget_( info->main_window, name ); if(!w) { veejay_msg(VEEJAY_MSG_ERROR, "No such widget (slider): '%s'",name); return; } gdouble gvalue; if(scale) gvalue = (gdouble) value / (gdouble) scale; else gvalue = (gdouble) value; GtkAdjustment *a = gtk_range_get_adjustment( GTK_RANGE( w )); gtk_adjustment_set_value( a, gvalue ); } static void update_spin_incr( const char *name, gdouble step, gdouble page ) { GtkWidget *w = glade_xml_get_widget_( info->main_window, name ); if(!w) { veejay_msg(VEEJAY_MSG_ERROR, "No such widget (spin): '%s'",name); return; } gtk_spin_button_set_increments(GTK_SPIN_BUTTON(w),step,page ); } static void update_spin_range2(GtkWidget *w, gint min, gint max, gint val) { 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 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) { veejay_msg(VEEJAY_MSG_ERROR, "No such widget (spin): '%s'",name); 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) { veejay_msg(VEEJAY_MSG_ERROR, "No such widget (spin): '%s'",name); return; } gtk_spin_button_set_value( GTK_SPIN_BUTTON(w), (gdouble) value ); } static void update_slider_range2(GtkWidget *w, gint min, gint max, gint value, gint scaled) { if(min == max) { return; } GtkRange *range = GTK_RANGE(w); 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 ); } GtkAdjustment *a = gtk_range_get_adjustment( GTK_RANGE( w )); gtk_range_set_adjustment(range, a ); } 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 ); if(!w) { veejay_msg(VEEJAY_MSG_ERROR, "No such widget (slider): '%s'",name); return; } if(min == max) { return; } GtkRange *range = GTK_RANGE(w); 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 ); } GtkAdjustment *a = gtk_range_get_adjustment( GTK_RANGE( w )); gtk_range_set_adjustment(range, a ); } static void update_label_i2(GtkWidget *label, int num, int prefix) { char str[20]; if(prefix) g_snprintf( str,sizeof(str), "%09d", num ); else g_snprintf( str,sizeof(str), "%d", num ); gtk_label_set_text( GTK_LABEL(label), str); } static void update_label_i(const char *name, int num, int prefix) { GtkWidget *label = glade_xml_get_widget_( info->main_window, name); if(!label) { veejay_msg(VEEJAY_MSG_ERROR, "No such widget (label): '%s'",name); return; } char str[20]; if(prefix) g_snprintf( str,sizeof(str), "%09d", num ); else g_snprintf( str,sizeof(str), "%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) { veejay_msg(VEEJAY_MSG_ERROR, "No such widget (label): '%s'",name); 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); #ifdef STRICT_CHECKING if(!label) veejay_msg(VEEJAY_MSG_ERROR, "No such widget (label): '%s'",name); assert( label != NULL ); #else if(!label ||!text) return; #endif gchar *utf8_text = _utf8str( text ); if(!utf8_text) return; gtk_label_set_text( GTK_LABEL(label), utf8_text); g_free(utf8_text); } static void label_set_markup(const char *name, gchar *str) { GtkWidget *label = glade_xml_get_widget_( info->main_window, name); if(!label) return; gtk_label_set_markup( GTK_LABEL(label), str ); } 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 = widget_cache[ WIDGET_RGBKEY ]; GdkColor color; /* update from entry tokens (delivered by GET_CHAIN_ENTRY */ int *p = &(info->uc.entry_tokens[0]); color.red = 255 * p[ENTRY_P1]; color.green = 255 * p[ENTRY_P2]; color.blue = 255 * p[ENTRY_P3]; 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 = widget_cache[ WIDGET_RGBKEY ]; info->entry_lock = 1; GdkColor color; color.red = 255 * ( get_slider_val2( widget_cache[WIDGET_SLIDER_P1]) ); color.green = 255 * ( get_slider_val2( widget_cache[WIDGET_SLIDER_P2]) ); color.blue = 255 * ( get_slider_val2( widget_cache[WIDGET_SLIDER_P3]) ); gtk_color_selection_set_current_color(GTK_COLOR_SELECTION( colorsel ), &color ); info->entry_lock = 0; } } static GdkPixbuf *update_pixmap_entry( int status ) { char path[MAX_PATH_LEN]; char filename[MAX_PATH_LEN]; snprintf(filename,sizeof(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; if(!gui->selected_slot) return FALSE; int entry = info->uc.selected_chain_entry; 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 )); char tmp[128]; if( _effect_get_mix( effect_id ) ) { snprintf(tmp,sizeof(tmp),"%s %d", (gui->uc.entry_tokens[ENTRY_SOURCE] == 0 ? "Sample " : "T " ), gui->uc.entry_tokens[ENTRY_CHANNEL]); } else { snprintf(tmp,sizeof(tmp),"%s"," "); } gchar *mixing = _utf8str(tmp); int kf_status = gui->uc.entry_tokens[ENTRY_KF_STATUS]; GdkPixbuf *toggle = update_pixmap_entry( gui->uc.entry_tokens[ENTRY_VIDEO_ENABLED] ); GdkPixbuf *kf_toggle = update_pixmap_entry( kf_status ); GdkPixbuf *subrender_toggle = update_pixmap_entry( gui->uc.entry_tokens[ENTRY_SUBRENDER_ENTRY]); gtk_list_store_set( GTK_LIST_STORE(model),iter, FXC_ID, entry, FXC_FXID, descr, FXC_FXSTATUS, toggle, FXC_KF, kf_toggle, FXC_MIXING, mixing, FXC_SUBRENDER, subrender_toggle, FXC_KF_STATUS, kf_status, -1 ); g_free(descr); g_free(mixing); g_object_unref( kf_toggle ); g_object_unref( toggle ); g_object_unref( subrender_toggle ); } } return FALSE; } /* 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" ); char *time = format_time(n_frames, (double) info->el.fps); update_label_str( "label_streamrecord_duration", time ); free(time); } if(pm == MODE_SAMPLE) { on_spin_sampleduration_value_changed(NULL,NULL); } } static void update_current_slot(int *history, int pm, int last_pm) { gint update = 0; if( pm != last_pm || info->status_tokens[CURRENT_ID] != history[CURRENT_ID] ) { int k; update = 1; update_record_tab( pm ); if( info->status_tokens[STREAM_TYPE] == STREAM_VIDEO4LINUX ) { info->uc.reload_hint[HINT_V4L] = 1; for(k = 0; capt_card_set[k].name != NULL; k ++ ) { show_widget( capt_card_set[k].name ); show_widget( capt_label_set[k].name ); } } else { for(k = 0; capt_card_set[k].name != NULL ; k ++ ) { hide_widget( capt_card_set[k].name ); hide_widget( capt_label_set[k].name ); } } switch(info->status_tokens[STREAM_TYPE]) { case STREAM_GENERATOR: if(!gtk_widget_is_sensitive( GTK_WIDGET( widget_cache[WIDGET_FRAME_FXTREE1] ) ) ) { gtk_widget_set_sensitive( GTK_WIDGET( widget_cache[WIDGET_FRAME_FXTREE1] ), TRUE ); } show_widget("frame_fxtree1"); hide_widget("notebook16"); break; case STREAM_WHITE: hide_widget("frame_fxtree1"); if(gtk_widget_is_sensitive( GTK_WIDGET( widget_cache[WIDGET_FRAME_FXTREE1] ) ) ) { gtk_widget_set_sensitive( GTK_WIDGET( widget_cache[WIDGET_FRAME_FXTREE1] ), FALSE ); } show_widget("notebook16"); notebook_set_page("notebook16",1 ); break; case STREAM_VIDEO4LINUX: hide_widget("frame_fxtree1"); if(gtk_widget_is_sensitive( GTK_WIDGET( widget_cache[WIDGET_FRAME_FXTREE1] ) ) ) { gtk_widget_set_sensitive( GTK_WIDGET( widget_cache[WIDGET_FRAME_FXTREE1] ), FALSE ); } show_widget("notebook16"); notebook_set_page("notebook16",0 ); break; default: hide_widget( "frame_fxtree1"); if(gtk_widget_is_sensitive( GTK_WIDGET( widget_cache[WIDGET_FRAME_FXTREE1] ) ) ) { gtk_widget_set_sensitive( GTK_WIDGET( widget_cache[WIDGET_FRAME_FXTREE1] ), FALSE ); } hide_widget( "notebook16"); break; } info->uc.reload_hint[HINT_HISTORY] = 1; info->uc.reload_hint[HINT_CHAIN] = 1; info->uc.reload_hint[HINT_ENTRY] = 1; info->uc.reload_hint[HINT_KF] = 1; put_text( "entry_samplename", "" ); set_pm_page_label( info->status_tokens[CURRENT_ID], pm ); } /* Actions for stream */ if( ( info->status_tokens[CURRENT_ID] != history[CURRENT_ID] || pm != last_pm ) && pm == MODE_STREAM ) { /* 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; } } if( info->status_tokens[STREAM_TYPE] == STREAM_GENERATOR ) { info->uc.reload_hint[HINT_GENERATOR] = 1; } /*char *time = format_time( info->status_frame,(double)info->el.fps ); update_label_str( "label_curtime", time ); free(time);*/ update_label_str( "playhint", "Streaming"); info->uc.reload_hint[HINT_KF] = 1; } /* Actions for sample */ if( pm == MODE_SAMPLE ) { int marker_go = 0; /* Update marker bounds */ if( (history[SAMPLE_MARKER_START] != info->status_tokens[SAMPLE_MARKER_START]) ) { update = 1; 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; } } char *dur = format_time( info->status_tokens[SAMPLE_MARKER_END] - info->status_tokens[SAMPLE_MARKER_START], (double)info->el.fps ); char *start = format_time( info->status_tokens[SAMPLE_MARKER_START] , (double)info->el.fps); update_label_str( "label_markerduration", dur ); update_label_str( "label_markerstart", start ); free(dur); free(start); } 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; } } char *end = format_time( info->status_tokens[SAMPLE_MARKER_END], (double)info->el.fps ); gtk_label_set_text( GTK_LABEL(widget_cache[WIDGET_LABEL_MARKEREND]), end); free(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: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget_cache[WIDGET_LOOP_NONE]), TRUE); break; case 1: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget_cache[WIDGET_LOOP_NORMAL]), TRUE); break; case 2: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget_cache[WIDGET_LOOP_PINGPONG]), TRUE); break; case 3: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget_cache[WIDGET_LOOP_RANDOM]), TRUE); break; case 4: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget_cache[WIDGET_LOOP_ONCENOP]), TRUE); break; } } gint speed = info->status_tokens[SAMPLE_SPEED]; if( history[SAMPLE_SPEED] != info->status_tokens[SAMPLE_SPEED] ) { speed = info->status_tokens[SAMPLE_SPEED]; update_slider_value( "speed_slider", speed, 0 ); if( speed < 0 ) info->play_direction = -1; else info->play_direction = 1; if( speed < 0 ) speed *= -1; gtk_spin_button_set_value( GTK_SPIN_BUTTON(widget_cache[WIDGET_SPIN_SAMPLESPEED]), (gdouble) speed ); if( pm == MODE_SAMPLE ) { if( speed == 0 ) update_label_str( "playhint", "Paused" ); else update_label_str( "playhint", "Playing"); } } if( history[FRAME_DUP] != info->status_tokens[FRAME_DUP] ) { update_spin_value( "spin_framedelay", info->status_tokens[FRAME_DUP]); update_slider_value("slow_slider", info->status_tokens[FRAME_DUP],0); } /* veejay keeps sample limits , dont use update_spin_range for spin_samplestart and spin_sampleend */ if( (history[SAMPLE_START] != info->status_tokens[SAMPLE_START] || get_nums("spin_samplestart") != info->status_tokens[SAMPLE_START])) { update = 1; } if( (history[SAMPLE_END] != info->status_tokens[SAMPLE_END] || get_nums("spin_sampleend") != info->status_tokens[SAMPLE_END]) ) { update = 1; } if( (history[SUBRENDER] != info->status_tokens[SUBRENDER] || gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(widget_cache[ WIDGET_TOGGLE_SUBRENDER ]) ) != info->status_tokens[SUBRENDER]) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( widget_cache[ WIDGET_TOGGLE_SUBRENDER ] ) , TRUE ); } if( history[FADE_ALPHA] != info->status_tokens[FADE_ALPHA] || info->status_tokens[FADE_ALPHA] != gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( widget_cache[ WIDGET_TOGGLE_FADEMETHOD ] )) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( widget_cache[ WIDGET_TOGGLE_FADEMETHOD ] ), TRUE ); } if( history[FADE_METHOD] != info->status_tokens[FADE_METHOD] ) { switch(info->status_tokens[FADE_METHOD]) { case -1: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget_cache[WIDGET_FX_MNONE]), TRUE ); break; case 1: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget_cache[WIDGET_FX_M1]), TRUE ); break; case 2: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget_cache[WIDGET_FX_M2]), TRUE ); break; case 3: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget_cache[WIDGET_FX_M3]), TRUE ); break; case 4: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget_cache[WIDGET_FX_M4]), TRUE ); break; default: break; } } 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_range2( widget_cache[ WIDGET_SPIN_SAMPLESPEED ], -1 * len, len, speed ); gtk_spin_button_set_value( GTK_SPIN_BUTTON(widget_cache[WIDGET_SPIN_SAMPLESTART]), (gdouble) info->status_tokens[SAMPLE_START] ); gtk_spin_button_set_value( GTK_SPIN_BUTTON(widget_cache[WIDGET_SPIN_SAMPLEEND]), (gdouble) info->status_tokens[SAMPLE_END]); timeline_set_length( info->tl, (gdouble) info->status_tokens[SAMPLE_END], info->status_tokens[FRAME_NUM] ); // update_spin_range( "spin_text_start", 0, n_frames ,0); // update_spin_range( "spin_text_end", 0, n_frames,n_frames ); } } if( pm == MODE_SAMPLE|| pm == MODE_STREAM ) if( history[CHAIN_FADE] != info->status_tokens[CHAIN_FADE] ) { double val = (double) info->status_tokens[CHAIN_FADE]; update_slider_value( "manualopacity", val,0 ); } } static void on_vims_messenger (void) { if( !gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( widget_cache[WIDGET_VIMS_MESSENGER_PLAY] )) ) return; GtkTextIter start, end; GtkTextBuffer* buffer; gchar *str = NULL; static int wait = 0; GtkTextView *t = GTK_TEXT_VIEW(GTK_WIDGET(glade_xml_get_widget_ (info->main_window,"vims_messenger_textview"))); buffer = gtk_text_view_get_buffer(t); if(info->vims_line >= gtk_text_buffer_get_line_count(buffer)) { info->vims_line = 0; } if(wait) { wait--; } else { gtk_text_buffer_get_iter_at_line(buffer, &start, info->vims_line); end = start; gtk_text_iter_forward_sentence_end(&end); str = gtk_text_buffer_get_text (buffer, &start, &end, TRUE); if(strlen(str) <= 0) { vj_msg(VEEJAY_MSG_INFO, "Nothing to do at line %d", info->vims_line); info->vims_line++; return; } if(str[0] == '+') { str[0] = ' '; g_strstrip(str); wait = atoi(str); vj_msg(VEEJAY_MSG_INFO, "Next VIMS message in %d frames", wait); } else { msg_vims( str ); vj_msg(VEEJAY_MSG_INFO, "Sent VIMS message '%s' (line %d)",str, info->vims_line ); } info->vims_line++; } } static int total_frames_ = 0; int get_total_frames() { return total_frames_; } /* static char *bugbuffer_ = NULL; static int bugoffset_ = 0; gboolean capture_data (GIOChannel *source, GIOCondition condition, gpointer data ) { int fd = g_io_channel_unix_get_fd( source ); GIOStatus ret; GError *err = NULL; gchar *msg; gsize len; if (condition & G_IO_HUP) g_error ("Read end of pipe died!\n"); ret = g_io_channel_read_line (source, &msg, &len, NULL, &err); if (ret == G_IO_STATUS_ERROR) g_error ("Error reading: %s\n", err->message); memcpy( bugbuffer_ + (sizeof(char) * bugoffset_) , msg , len ); bugoffset_ += len; g_free (msg); return TRUE; } */ void reportbug () { char l[3] = { 'e','n', '\0'}; char *lang = getenv("LANG"); char URL[1024]; if(lang) { l[0] = lang[0]; l[1] = lang[1]; } /* char veejay_homedir[1024]; char body[1024]; char subj[100]; gchar **argv = (gchar**) malloc ( sizeof(gchar*) * 5 ); int i; argv[0] = malloc( sizeof(char) * 100 ); memset( argv[0], 0, sizeof(char) * 100 ); argv[2] = NULL; // snprintf(subj,sizeof(subj),"reloaded %s has a problem", VERSION); snprintf(veejay_homedir, sizeof(veejay_homedir),"%s/.veejay/", home ); sprintf(argv[0], "%s/report_problem.sh" ,veejay_homedir); argv[1] = strdup( veejay_homedir ); if( bugoffset_ > 0 ) { free(bugbuffer_); bugoffset_= 0; bugbuffer_ = NULL; } // GError error = NULL; gint stdout_pipe = 0; gint pid =0; gboolean ret = g_spawn_async_with_pipes( NULL, argv, NULL, G_SPAWN_LEAVE_DESCRIPTORS_OPEN & G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, &pid, NULL, &stdout_pipe, NULL, NULL ); if( !ret ) { veejay_msg(VEEJAY_MSG_ERROR, "Error executing bug report tool"); return; } GIOChannel *chan = g_io_channel_unix_new( stdout_pipe ); bugbuffer_ = (char*) malloc(sizeof(char) * 32000 ); memset(bugbuffer_, 0, sizeof(char) * 32000); guint retb = g_io_add_watch( chan, G_IO_IN, capture_data, NULL ); */ // if( prompt_dialog("Report a problem", "" ) // == GTK_RESPONSE_ACCEPT ) snprintf(URL , sizeof(URL), "firefox \"http://groups.google.com/group/veejay-discussion/post?hl=%s\" &",l ); puts(URL); if( system(URL) <= 0 ) { veejay_msg(VEEJAY_MSG_ERROR, "Unable to open browser to veejay homepage"); } } void donatenow() { char URL[512]; snprintf(URL , sizeof(URL), "firefox \"http://www.veejayhq.net/contributing\" &" ); if( system(URL) <= 0 ) { veejay_msg(VEEJAY_MSG_ERROR, "Unable to open browser to veejay homepage"); } } static void reset_fxtree() { int i; for(i = 0; i < 3; i ++ ) { gtk_list_store_clear(fxlist_data.stores[i].list); } } 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) ); if(GTK_IS_TREE_MODEL_SORT(tree_model)) { GtkTreeModel *child_model = gtk_tree_model_sort_get_model( GTK_TREE_MODEL_SORT(tree_model) ); gtk_list_store_clear( GTK_LIST_STORE( child_model ) ); } else { if( GTK_IS_LIST_STORE(tree_model) ) { /*! * invalidate selection callback to prevent undesirable calls, clear the list * and finally restore selection callback. */ GtkTreeSelection *selection; GtkTreeSelectionFunc selection_func; selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_widget)); selection_func = gtk_tree_selection_get_select_function(selection); gtk_tree_selection_set_select_function(selection, NULL, NULL, NULL); gtk_list_store_clear(GTK_LIST_STORE(tree_model)); gtk_tree_selection_set_select_function(selection, selection_func, NULL, NULL); } } } void select_chain_entry(int entry) { GtkWidget *tree = glade_xml_get_widget_( info->main_window, "tree_chain"); GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree)); GtkTreePath *path = gtk_tree_path_new_from_indices( entry, -1 ); gtk_tree_selection_select_path(sel, path); gtk_tree_path_free(path); } // 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 ); int sl = info->status_lock; info->status_lock = 1; if(!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget_cache[WIDGET_FX_MNONE]))) { multi_vims( VIMS_CHAIN_FADE_ENTRY,"%d %d",0, name ); } else { multi_vims( VIMS_CHAIN_FADE_ENTRY,"%d %d",0,-1); } info->status_lock = sl; update_label_i( "label_fxentry", name, 0 ); vj_midi_learning_vims_msg( info->midi, NULL, VIMS_CHAIN_SET_ENTRY,name ); if( get_nums("button_fx_entry") != name ) { info->status_lock = 1; update_spin_value( "button_fx_entry", name ); //FIXME info->uc.reload_hint[HINT_KF] = 1; info->uc.reload_hint[HINT_ENTRY] = 1; info->status_lock = 0; } return TRUE; /*the state of the node may be toggled*/ } return TRUE; } return FALSE; /* the state of the node should be left unchanged */ } gboolean cali_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; if( info->uc.cali_stage != 0 ) { veejay_msg(VEEJAY_MSG_ERROR, "%d", info->uc.cali_stage); return TRUE; } 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') { cali_stream_id = id; update_label_str("current_step_label","Please take an image with the cap on the lens."); GtkWidget *nb = glade_xml_get_widget_(info->main_window, "cali_notebook"); gtk_notebook_next_page( GTK_NOTEBOOK(nb)); } if(name) g_free(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, }; gtk_tree_model_get_value(model, iter, V4L_SPINBOX, &val); 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_text_column( const char *tree_name, int type, const char *title,int len ) { 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 ); if(len) { veejay_msg(VEEJAY_MSG_DEBUG, "Tree %s ,Title %s, width=%d", tree_name,title, len ); gtk_tree_view_column_set_min_width( column, len); } } 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 ); } void server_files_selection_func (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 *name = NULL; gtk_tree_model_get(model, &iter, 0, &name, -1); multi_vims(VIMS_EDITLIST_ADD_SAMPLE, "0 %s" , name ); vj_msg(VEEJAY_MSG_INFO, "Tried to open %s",name); g_free(name); } } void generators_selection_func(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 *name = NULL; gtk_tree_model_get(model, &iter, 0, &name, -1); multi_vims(VIMS_STREAM_NEW_GENERATOR, "0 %s" , name ); vj_msg(VEEJAY_MSG_INFO, "Tried to open %s",name); g_free(name); gveejay_new_slot(MODE_STREAM); gtk_widget_hide( glade_xml_get_widget_(info->main_window, "generator_window") ); } } static void setup_generators() { GtkWidget *tree = glade_xml_get_widget_( info->main_window, "generators"); GtkListStore *store = gtk_list_store_new( 1, 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( "generators", 0, "Filename",0 ); g_signal_connect( tree, "row-activated", (GCallback) generators_selection_func, NULL); } static void setup_server_files(void) { GtkWidget *tree = glade_xml_get_widget_( info->main_window, "server_files"); GtkListStore *store = gtk_list_store_new( 1, 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( "server_files", 0, "Filename",0 ); g_signal_connect( tree, "row-activated", (GCallback) server_files_selection_func, NULL); } static void load_v4l_info() { int values[21]; int len = 0; veejay_memset(values,-1,sizeof(values)); 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 && answer ) { int res = sscanf(answer, "%05d%05d%05d%05d%05d%05d%05d%05d%05d%05d%05d%05d%05d%05d%05d%05d%05d%05d%05d%05d%05d", &values[0],&values[1],&values[2],&values[3],&values[4],&values[5], &values[6],&values[7],&values[8],&values[9],&values[10],&values[11], &values[12],&values[13],&values[14],&values[15],&values[16],&values[17],&values[18],&values[19],&values[20]); if(res < 21 ) { free(answer); return; } int i; int n = CAPT_CARD_SLIDERS; for(i = 0; i < n; i ++ ) { if( values[i] < 0 ) { hide_widget( capt_card_set[i].name ); hide_widget( capt_label_set[i].name ); } else { show_widget( capt_card_set[i].name ); show_widget( capt_label_set[i].name); update_slider_gvalue( capt_card_set[i].name, (gdouble)values[i]/65535.0 ); } } n += CAPT_CARD_BOOLS; for( ; i < n; i ++ ) { if( values[i] < 0 ) { hide_widget( capt_card_set[i].name ); hide_widget( capt_label_set[i].name ); } else { show_widget( capt_card_set[i].name ); show_widget( capt_label_set[i].name); set_toggle_button( capt_card_set[i].name, values[i] ); } } free(answer); } } static gint load_parameter_info() { int *p = &(info->uc.entry_tokens[0]); int len = 0; int i = 0; multi_vims( VIMS_CHAIN_GET_ENTRY, "%d %d", 0, info->uc.selected_chain_entry ); gchar *answer = recv_vims(3,&len); int checksum = data_checksum(answer,len); if( info->uc.reload_hint_checksums[HINT_ENTRY] == checksum ) { if(answer) free(answer); return -1; } info->uc.reload_hint_checksums[HINT_ENTRY] = checksum; veejay_memset( p, 0, sizeof(info->uc.entry_tokens)); if(len <= 0 || answer == NULL ) { if(answer) free(answer); if(info->uc.selected_rgbkey ) gtk_widget_set_sensitive_( widget_cache[WIDGET_RGBKEY], FALSE ); return 0; } char *ptr; char *token = strtok_r( answer," ", &ptr ); if(!token) { veejay_msg(VEEJAY_MSG_ERROR,"Invalid reply from %d", VIMS_CHAIN_GET_ENTRY ); free(answer); return 0; } p[i] = atoi(token); while( (token = strtok_r( NULL, " ", &ptr ) ) != NULL ) { i++; p[i] = atoi( token ); } info->uc.selected_rgbkey = _effect_get_rgb( p[0] ); if(info->uc.selected_rgbkey) { gtk_widget_set_sensitive_( widget_cache[WIDGET_RGBKEY], TRUE ); update_rgbkey(); } else { gtk_widget_set_sensitive_( widget_cache[WIDGET_RGBKEY], FALSE ); info->uc.selected_rgbkey = 0; } if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget_cache[WIDGET_CURVE_CHAIN_TOGGLEENTRY])) != p[ENTRY_KF_STATUS]){ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget_cache[WIDGET_CURVE_CHAIN_TOGGLEENTRY]), p[ENTRY_KF_STATUS]); } switch( p[ENTRY_KF_TYPE] ) { case GTK3_CURVE_TYPE_SPLINE: if(!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget_cache[WIDGET_CURVE_TYPESPLINE]))) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget_cache[WIDGET_CURVE_TYPESPLINE]), TRUE ); } break; case GTK3_CURVE_TYPE_FREE: if(!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget_cache[WIDGET_CURVE_TYPEFREEHAND]))) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget_cache[WIDGET_CURVE_TYPEFREEHAND]), TRUE ); } break; case GTK3_CURVE_TYPE_LINEAR: if(!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget_cache[WIDGET_CURVE_TYPELINEAR]))) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget_cache[WIDGET_CURVE_TYPELINEAR]), TRUE ); } break; default: break; } if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget_cache[WIDGET_SUBRENDER_ENTRY_TOGGLE])) != p[ENTRY_SUBRENDER_ENTRY]) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget_cache[WIDGET_SUBRENDER_ENTRY_TOGGLE]), p[ENTRY_SUBRENDER_ENTRY]); } free(answer); return 1; } static void load_generator_info() { int args[GENERATOR_PARAMS+1]; gint fxlen = 0; multi_vims( VIMS_GET_STREAM_ARGS,"%d",0 ); gchar *fxtext = recv_vims(3,&fxlen); int checksum = data_checksum(fxtext,fxlen); if( info->uc.reload_hint_checksums[HINT_GENERATOR] == checksum ) { if(fxtext) free(fxtext); return; } info->uc.reload_hint_checksums[HINT_GENERATOR] = checksum; if(fxtext == NULL) return; veejay_memset(args,0,sizeof(args)); generator_to_arr(fxtext, args); int np = _effect_get_np( args[0] ); int i; for( i = 0; i < np ; i ++ ) { if(!gtk_widget_is_sensitive( GTK_WIDGET(widget_cache[WIDGET_SLIDER_BOX_G0 + i] ))) { gtk_widget_set_sensitive( GTK_WIDGET(widget_cache[WIDGET_SLIDER_BOX_G0 + i] ), TRUE ); } gchar *tt1 = _utf8str(_effect_get_param_description( args[0],i)); set_tooltip( gen_names_[i].text, tt1 ); gint min=0,max=0,value = 0; value = args[1 + i]; if( _effect_get_minmax( args[0], &min,&max, i )) { update_slider_range( gen_names_[i].text,min,max, value, 0); } g_free(tt1); } for( i = np; i < GENERATOR_PARAMS; i ++ ) { gint min = 0, max = 1, value = 0; update_slider_range( gen_names_[i].text, min,max, value, 0 ); if(gtk_widget_is_sensitive( GTK_WIDGET(widget_cache[WIDGET_SLIDER_BOX_G0 + i] ))) { gtk_widget_set_sensitive( GTK_WIDGET(widget_cache[WIDGET_SLIDER_BOX_G0 + i] ), FALSE ); } set_tooltip( gen_names_[i].text, "" ); } free(fxtext); } /****************************************************** * * EFFECT CHAIN * ******************************************************/ /****************************************************** * setup_effectchain_info() * setup tree effect chain model and selection mode * ******************************************************/ static void setup_effectchain_info( void ) { GtkWidget *tree = glade_xml_get_widget_( info->main_window, "tree_chain"); GtkListStore *store = gtk_list_store_new( FXC_N_COLS, G_TYPE_INT, G_TYPE_STRING, GDK_TYPE_PIXBUF,GDK_TYPE_PIXBUF,G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_INT); 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, "#",0 ); setup_tree_text_column( "tree_chain", FXC_FXID, "Effect",0 ); //FIXME setup_tree_pixmap_column( "tree_chain", FXC_FXSTATUS, "Run"); setup_tree_pixmap_column( "tree_chain", FXC_KF , "Anim" ); // TODO parameter interpolation on/off per entry setup_tree_text_column( "tree_chain", FXC_MIXING, "Channel",0); setup_tree_pixmap_column( "tree_chain", FXC_SUBRENDER, "Subrender"); GtkTreeSelection *selection; // selection stuff 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); // signal stuff (button press) g_signal_connect(GTK_TREE_VIEW(tree), "button-press-event", (GCallback) on_effectchain_button_pressed, NULL); } /****************************************************** * load_effectchain_info() * load effect chain from server (VIMS transmition) * to the fx chain tree view * ******************************************************/ static void load_effectchain_info() { GtkWidget *tree = glade_xml_get_widget_( info->main_window, "tree_chain"); gint fxlen = 0; multi_vims( VIMS_CHAIN_LIST,"%d",0 ); gchar *fxtext = recv_vims(3,&fxlen); int checksum = data_checksum(fxtext,fxlen); if( info->uc.reload_hint_checksums[HINT_CHAIN] == checksum ) { if(fxtext) free(fxtext); return; } info->uc.reload_hint_checksums[HINT_CHAIN] = checksum; GtkListStore *store; gchar toggle[4]; guint arr[VIMS_CHAIN_LIST_ENTRY_VALUES]; GtkTreeIter iter; gint offset=0; set_tooltip_by_widget (tree, tooltips[TOOLTIP_FXCHAINTREE].text); reset_tree( "tree_chain" ); GtkTreeModel *model = gtk_tree_view_get_model( GTK_TREE_VIEW(tree )); store = GTK_LIST_STORE(model); //update chain fx status gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(widget_cache[WIDGET_CURVE_CHAIN_TOGGLECHAIN]), info->status_tokens[SAMPLE_FX] ); //also for stream (index is equivalent) if(info->status_tokens[PLAY_MODE] == MODE_SAMPLE){ gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(widget_cache[WIDGET_CHECK_SAMPLEFX]), info->status_tokens[SAMPLE_FX] ); } else { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(widget_cache[WIDGET_CHECK_STREAMFX]), info->status_tokens[SAMPLE_FX] ); } // no fx, clean list and return if(fxlen <= 0 ) { int i; for( i = 0; i < SAMPLE_MAX_EFFECTS; 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 ) { char line[VIMS_CHAIN_LIST_ENTRY_LENGTH+1]; veejay_memset(arr,0,sizeof(arr)); veejay_memset(line,0,sizeof(line)); strncpy( line, fxtext + offset, VIMS_CHAIN_LIST_ENTRY_LENGTH ); int n_tokens = sscanf( line, VIMS_CHAIN_LIST_ENTRY_FORMAT, &arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5],&arr[6], &arr[7], &arr[8]); if( n_tokens != VIMS_CHAIN_LIST_ENTRY_VALUES ) { veejay_msg(0,"Error parsing FX chain response"); break; } // clean list until next entry while( last_index < arr[0] ) { gtk_list_store_append( store, &iter ); gtk_list_store_set( store, &iter, FXC_ID, last_index,-1); last_index ++; } // time to fill current entry char *name = _effect_get_description( arr[1] ); snprintf(toggle,sizeof(toggle),"%s",arr[3] == 1 ? "on" : "off" ); if( last_index == arr[0]) { gchar *utf8_name = _utf8str( name ); char tmp[128]; if( _effect_get_mix( arr[1] ) ) { snprintf(tmp,sizeof(tmp),"%s %d", (arr[5] == 0 ? "Sample " : "T " ), arr[6]); } else { snprintf(tmp,sizeof(tmp),"%s"," "); } gchar *mixing = _utf8str(tmp); gtk_list_store_append( store, &iter ); int kf_status = arr[7]; GdkPixbuf *toggle = update_pixmap_entry( arr[3] ); GdkPixbuf *kf_togglepf = update_pixmap_entry( kf_status ); GdkPixbuf *subrender_toggle = update_pixmap_entry(arr[8]); gtk_list_store_set( store, &iter, FXC_ID, arr[0], FXC_FXID, utf8_name, FXC_FXSTATUS, toggle, FXC_KF, kf_togglepf, FXC_MIXING,mixing, FXC_SUBRENDER, subrender_toggle, FXC_KF_STATUS, kf_status, -1 ); last_index ++; g_free(utf8_name); g_free(mixing); g_object_unref( toggle ); g_object_unref( kf_togglepf ); g_object_unref( subrender_toggle ); } offset += VIMS_CHAIN_LIST_ENTRY_LENGTH; } // finally clean list end while( last_index < SAMPLE_MAX_EFFECTS ) { 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)); free(fxtext); } /****************************************************** * * EFFECTS LISTS * ******************************************************/ enum { // FX_ID = 0, FX_STRING = 0, 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)) { gchar *name = NULL; gtk_tree_model_get(model, &iter, FX_STRING, &name, -1); if (!path_currently_selected) { int value = 0; vevo_property_get( fx_list_, name, 0, &value ); if(value) { info->uc.selected_effect_id = value; } } g_free(name); } return TRUE; /* allow selection state to change */ } static guint effectlist_add_mask = 0; static const guint FXLIST_ADD_DISABLED = 1 << 1; static const guint FXLIST_ADD_TO_SELECTED = 1 << 2; gboolean on_effectlist_row_key_pressed (GtkWidget *widget, GdkEventKey *event, gpointer user_data) { if(event->type & GDK_KEY_PRESS){ switch(event->keyval){ case GDK_KEY_Shift_L: effectlist_add_mask |= FXLIST_ADD_DISABLED; break; case GDK_KEY_Control_L: effectlist_add_mask |= FXLIST_ADD_TO_SELECTED; break; } } return FALSE; } gboolean on_effectlist_row_key_released (GtkWidget *widget, GdkEventKey *event, gpointer user_data) { if(event->type & GDK_KEY_RELEASE){ switch(event->keyval){ case GDK_KEY_Shift_L: effectlist_add_mask &= !(FXLIST_ADD_DISABLED); break; case GDK_KEY_Control_L: effectlist_add_mask &= !(FXLIST_ADD_TO_SELECTED); break; } } return FALSE; } 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; gchar *name = NULL; gtk_tree_model_get(model,&iter, FX_STRING, &name, -1); if(vevo_property_get( fx_list_, name, 0, &gid ) == 0 ) { guint slot = 0; if((effectlist_add_mask & FXLIST_ADD_TO_SELECTED) && info->selection_slot) slot = info->selection_slot->sample_id; multi_vims(VIMS_CHAIN_ENTRY_SET_EFFECT, "%d %d %d %d", slot, info->uc.selected_chain_entry,gid, !(effectlist_add_mask & FXLIST_ADD_DISABLED) ); char trip[100]; snprintf(trip,sizeof(trip), "%03d:%d %d %d %d;", VIMS_CHAIN_ENTRY_SET_EFFECT,slot,info->uc.selected_chain_entry, gid, !(effectlist_add_mask & FXLIST_ADD_DISABLED) ); vj_midi_learning_vims( info->midi, NULL, trip, 0 ); info->uc.reload_hint[HINT_CHAIN] = 1; info->uc.reload_hint[HINT_ENTRY] = 1; info->uc.reload_hint[HINT_KF] = 1; } g_free(name); } } 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; } //EffectListData* get_effectlistdata static gboolean effect_row_visible (GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data) { effectlist_data *fxlistdata = (effectlist_data*) user_data; gboolean value=TRUE; if(fxlistdata != NULL && fxlistdata->filter_string != NULL) { if(strlen(fxlistdata->filter_string)) { value=FALSE; gchar *idstr = NULL; gtk_tree_model_get(model, iter, SL_ID, &idstr, -1); if((idstr != NULL) && strcasestr(idstr, fxlistdata->filter_string) != NULL) { value = TRUE; } g_free (idstr); } } return value; } /****************************************************** * setup_effectlist_info() * prepare the views of effects lists * * Three treeview : fxlist mixlist, alphalist * ******************************************************/ void setup_effectlist_info() { int i; GtkWidget *trees[3]; trees[0] = glade_xml_get_widget_( info->main_window, "tree_effectlist"); trees[1] = glade_xml_get_widget_( info->main_window, "tree_effectmixlist"); trees[2] = glade_xml_get_widget_( info->main_window, "tree_alphalist" ); set_tooltip_by_widget (trees[0], tooltips[TOOLTIP_FXSELECT].text); set_tooltip_by_widget (trees[1], tooltips[TOOLTIP_FXSELECT].text); set_tooltip_by_widget (trees[2], tooltips[TOOLTIP_FXSELECT].text); fx_list_ = (vevo_port_t*) vpn( 200 ); for(i = 0; i < 3; i ++ ) { fxlist_data.stores[i].list = gtk_list_store_new( 1, G_TYPE_STRING ); fxlist_data.stores[i].filtered = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (GTK_TREE_MODEL (fxlist_data.stores[i].list), NULL)); fxlist_data.stores[i].sorted = GTK_TREE_MODEL_SORT (gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (fxlist_data.stores[i].filtered))); fxlist_data.filter_string = NULL; gtk_tree_model_filter_set_visible_func (fxlist_data.stores[i].filtered, effect_row_visible, &fxlist_data, NULL); GtkTreeSortable *sortable = GTK_TREE_SORTABLE(fxlist_data.stores[i].list); 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_headers_visible( GTK_TREE_VIEW(trees[i]), FALSE ); gtk_tree_view_set_model( GTK_TREE_VIEW(trees[i]),GTK_TREE_MODEL( fxlist_data.stores[i].sorted)); g_object_unref( G_OBJECT( fxlist_data.stores[i].list )); } setup_tree_text_column( "tree_effectlist", FX_STRING, "Effect",0 ); setup_tree_text_column( "tree_effectmixlist", FX_STRING, "Effect",0 ); setup_tree_text_column( "tree_alphalist", FX_STRING, "Alpha",0); for(i = 0; i < 3; i ++ ) { g_signal_connect( trees[i],"row-activated", (GCallback) on_effectlist_row_activated, NULL ); GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(trees[i])); gtk_tree_selection_set_select_function(selection, view_fx_selection_func, NULL, NULL); gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE); g_signal_connect( G_OBJECT(trees[i]), "key_press_event", G_CALLBACK( on_effectlist_row_key_pressed ), NULL ); g_signal_connect( G_OBJECT(trees[i]), "key-release-event", G_CALLBACK( on_effectlist_row_key_released ), NULL ); } GtkWidget *entry_filterfx = glade_xml_get_widget_( info->main_window, "filter_effects"); set_tooltip_by_widget (entry_filterfx, tooltips[TOOLTIP_FXFILTER].text); g_signal_connect(G_OBJECT(entry_filterfx), "changed", G_CALLBACK( on_filter_effects_changed ), &fxlist_data ); } void set_feedback_status() { int len = 0; single_vims(VIMS_GET_FEEDBACK); gchar *answer = recv_vims(3,&len); if(answer == NULL) return; int status = atoi(answer); set_toggle_button("feedbackbutton", status); g_free(answer); } /****************************************************** * load_effectlist_info() * load the effects information from the server * (VIMS transmission) to the treeviews * ******************************************************/ 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"); GtkWidget *tree3 = glade_xml_get_widget_( info->main_window, "tree_alphalist"); GtkListStore *store,*store2,*store3; char line[4096]; GtkTreeIter iter; gint i,offset=0; gint fxlen = 0; single_vims( VIMS_EFFECT_LIST ); gchar *fxtext = recv_vims(6,&fxlen); _effect_reset(); reset_fxtree(); store = fxlist_data.stores[0].list; store2 = fxlist_data.stores[1].list; store3 = fxlist_data.stores[2].list; int ec_idx = 0; int hi_id = 0; while( offset < fxlen ) { char tmp_len[5]; veejay_memset(tmp_len,0,sizeof(tmp_len)); strncpy(tmp_len, fxtext + offset, 4 ); int len = 0; if( sscanf(tmp_len, "%4d", &len ) != 1 ) { veejay_msg(0, "FX header length error"); exit(0); } offset += 4; if(len > 0) { effect_constr *ec; veejay_memset( line,0,sizeof(line)); memcpy( line, fxtext + offset, len ); int bad_len = strlen(line); if( len != bad_len ) { veejay_msg(0, "Expected %d bytes, only got %d", len, bad_len ); exit(0); } ec = _effect_new(line); if( ec ) { info->effect_info[ec->id] = ec; ec_idx ++; if( hi_id < ec->id ) hi_id = ec->id; } } offset += len; } for( i = 0; i <= hi_id; i ++) { effect_constr *ec = info->effect_info[i]; if(ec == NULL) continue; if( ec->is_gen ) continue; gchar *name = _utf8str( ec->description ); if( name != NULL) { // tree_alphalist if( strncasecmp( "alpha:" , ec->description, 6 ) == 0 ) { gtk_list_store_append( store3, &iter ); int len = strlen( ec->description ); char *newName = vj_calloc( len ); veejay_memcpy(newName,ec->description+6, len-6 ); gtk_list_store_set( store3,&iter, FX_STRING, newName, -1 ); vevo_property_set( fx_list_, newName, VEVO_ATOM_TYPE_INT,1,&(ec->id)); free(newName); } else { // tree_effectmixlist if( ec->is_video ) { gtk_list_store_append( store2, &iter ); gtk_list_store_set( store2, &iter, FX_STRING, name, -1 ); vevo_property_set( fx_list_, name, VEVO_ATOM_TYPE_INT, 1, &(ec->id)); } else { // tree_effectlist gtk_list_store_append( store, &iter ); gtk_list_store_set( store, &iter, FX_STRING, name, -1 ); vevo_property_set( fx_list_, name, VEVO_ATOM_TYPE_INT, 1, &(ec->id)); } } } g_free(name); } gtk_tree_view_set_model( GTK_TREE_VIEW(tree), GTK_TREE_MODEL(fxlist_data.stores[0].sorted)); gtk_tree_view_set_model( GTK_TREE_VIEW(tree2), GTK_TREE_MODEL(fxlist_data.stores[1].sorted)); gtk_tree_view_set_model( GTK_TREE_VIEW(tree3), GTK_TREE_MODEL(fxlist_data.stores[2].sorted)); free(fxtext); veejay_msg(VEEJAY_MSG_DEBUG, "Loaded %d effects (highest ID is %d)", ec_idx, hi_id ); } 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); 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 ); char trip[100]; snprintf(trip, sizeof(trip), "%03d:%d %d %d %d",VIMS_CHAIN_ENTRY_SET_SOURCE_CHANNEL, 0, info->uc.selected_chain_entry, ( idstr[0] == 'T' ? 1 : 0 ), id ); vj_midi_learning_vims( info->midi, NULL, trip, 0 ); } if(idstr) g_free(idstr); } } /****************************************************** * * SAMPLES LIST * ******************************************************/ /* Return a bank page and slot number to place sample in */ int 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) { veejay_msg(VEEJAY_MSG_ERROR, "No slot found for (%d,%d)",sample_id,sample_type); return -1; } if( !bank_exists(bank_page, poke_slot)) add_bank( bank_page ); *bank_page_ = bank_page; *slot_ = poke_slot; return 1; } 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_headers_visible( GTK_TREE_VIEW(effect_sources_tree), FALSE ); 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",0 ); setup_tree_text_column( "tree_sources", SL_TIMECODE, "Length" ,0); 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, "row-activated", (GCallback) on_effectlist_sources_row_activated, (gpointer*)"tree_sources"); cali_sourcetree = glade_xml_get_widget_(info->main_window, "cali_sourcetree"); cali_sourcestore= gtk_list_store_new( 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING ); gtk_tree_view_set_headers_visible( GTK_TREE_VIEW( cali_sourcetree), FALSE ); gtk_tree_view_set_model( GTK_TREE_VIEW(cali_sourcetree), GTK_TREE_MODEL(cali_sourcestore)); g_object_unref( G_OBJECT(cali_sourcestore)); cali_sourcemodel = gtk_tree_view_get_model( GTK_TREE_VIEW(cali_sourcetree )); cali_sourcestore = GTK_LIST_STORE(cali_sourcemodel); setup_tree_text_column( "cali_sourcetree", SL_ID, "Id",0 ); setup_tree_text_column( "cali_sourcetree", SL_TIMECODE, "Length" ,0); GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(cali_sourcetree)); gtk_tree_selection_set_select_function(sel, cali_sources_selection_func, NULL, NULL); gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE); // g_signal_connect( cali_sourcetree, "row-activated", (GCallback) on_effectlist_sources_row_activated, (gpointer*)"tree_sources"); } static uint8_t *ref_trashcan[3] = { NULL,NULL,NULL }; static GdkPixbuf *pix_trashcan[3] = { NULL,NULL,NULL }; void reset_cali_images( int type, char *wid_name ) { GtkWidget *dstImage = glade_xml_get_widget_( info->main_window, wid_name ); if( pix_trashcan[type] != NULL ) { g_object_unref( pix_trashcan[type] ); pix_trashcan[type] = NULL; } if( ref_trashcan[type] != NULL ) { free( ref_trashcan[type] ); ref_trashcan[type] = NULL; } gtk_image_clear( GTK_IMAGE(dstImage) ); } int get_and_draw_frame(int type, char *wid_name) { GtkWidget *dstImage = glade_xml_get_widget_( info->main_window, wid_name ); if(dstImage == 0 ) { veejay_msg(VEEJAY_MSG_ERROR, "No widget '%s'",wid_name); return 0; } multi_vims( VIMS_CALI_IMAGE, "%d %d", cali_stream_id,type); int bw = 0; gchar *buf = recv_vims( 3, &bw ); if( bw <= 0 ) { veejay_msg(VEEJAY_MSG_ERROR, "Unable to get calibration image."); return 0; } int len = 0; int uvlen = 0; int w = 0; int h = 0; int tlen = 0; if( sscanf(buf,"%08d%06d%06d%06d%06d",&tlen, &len, &uvlen,&w,&h) != 5 ) { free(buf); veejay_msg(VEEJAY_MSG_ERROR,"Error reading calibration data header" ); return 0; } uint8_t *out = (uint8_t*) vj_malloc(sizeof(uint8_t) * (w*h*3)); uint8_t *srcbuf = (uint8_t*) vj_malloc(sizeof(uint8_t) * len ); int res = vj_client_read(info->client, V_CMD, srcbuf, tlen ); if( res <= 0 ) { free(out); free(srcbuf); free(buf); veejay_msg(VEEJAY_MSG_ERROR, "Error while receiving calibration image."); return 0; } VJFrame *src = yuv_yuv_template(srcbuf, srcbuf, srcbuf, w, h, PIX_FMT_GRAY8 ); VJFrame *dst = yuv_rgb_template( out, w,h,PIX_FMT_BGR24 ); yuv_convert_any_ac( src,dst ); GdkPixbuf *pix = gdk_pixbuf_new_from_data(out, GDK_COLORSPACE_RGB, FALSE, 8, w, h, w*3, NULL, NULL ); if( ref_trashcan[type] != NULL ) { free(ref_trashcan[type]); ref_trashcan[type]=NULL; } if( pix_trashcan[type] != NULL ) { g_object_unref( pix_trashcan[type] ); pix_trashcan[type] = NULL; } gtk_image_set_from_pixbuf_( GTK_IMAGE( dstImage ), pix ); // gdk_pixbuf_unref( pix ); free(src); free(dst); free(buf); // free(out); free(srcbuf); ref_trashcan[type] = out; pix_trashcan[type] = pix; return 1; } static void select_slot( int pm ) { if( pm == MODE_SAMPLE || pm == MODE_STREAM ) { int b = 0; int p = 0; if(info->status_tokens[CURRENT_ID] > 0) { if(verify_bank_capacity( &b, &p, info->status_tokens[CURRENT_ID], info->status_tokens[STREAM_TYPE] )) { set_activation_of_slot_in_samplebank(FALSE); 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 { set_activation_of_slot_in_samplebank(FALSE); info->selected_slot = NULL; info->selected_gui_slot = NULL; } } static void load_sequence_list() { single_vims( VIMS_SEQUENCE_LIST ); gint len = 0; gchar *text = recv_vims( 6, &len ); if( len <= 0 || text == NULL ) return; int checksum = data_checksum(text,len); if( info->uc.reload_hint_checksums[HINT_SEQ_ACT] == checksum ) { if(text) free(text); return; } info->uc.reload_hint_checksums[HINT_SEQ_ACT] = checksum; int playing=0; int size =0; int active=0; sscanf( text, "%04d%04d%4d",&playing,&size,&active ); int nlen = len - 12; int offset = 0; int id = 0; gchar *in = text + 12; while( offset < nlen ) { int sample_id = 0; int type = 0; char seqtext[32]; sscanf( in + offset, "%04d%02d", &sample_id, &type ); offset += 6; if( sample_id > 0 ) { sprintf(seqtext,"%c%d",( type == 0 ? 'S' : 'T' ), sample_id); gtk_label_set_text( GTK_LABEL(info->sequencer_view->gui_slot[id]->image), seqtext ); } else { gtk_label_set_text( GTK_LABEL(info->sequencer_view->gui_slot[id]->image), NULL ); } id ++; } free(text); } static void load_samplelist_info(gboolean with_reset_slotselection) { char line[300]; char source[255]; char descr[255]; gint offset=0; gint no_samples = 1; if( cali_onoff == 1 ) reset_tree( "cali_sourcetree"); with_reset_slotselection = FALSE; // FIXME: there is a bug if( with_reset_slotselection ) { reset_samplebank(); reset_tree( "tree_sources" ); } int load_from = info->uc.expected_num_samples; if( load_from < 0 ) load_from = 0; multi_vims( VIMS_SAMPLE_LIST,"%d", (with_reset_slotselection ? 0 : load_from) ); gint fxlen = 0; gchar *fxtext = recv_vims(8,&fxlen); if(fxlen > 0 && fxtext != NULL) { no_samples = 0; while( offset < fxlen ) { char tmp_len[8] = { 0 }; strncpy(tmp_len, fxtext + offset, 3 ); int len = atoi(tmp_len); offset += 3; if(len > 0) { veejay_memset( line,0,sizeof(line)); veejay_memset( descr,0,sizeof(descr)); strncpy( line, fxtext + offset, len ); int values[4] = { 0,0,0,0 }; sscanf( line, "%05d%09d%09d%03d",&values[0], &values[1], &values[2], &values[3]); strncpy( descr, line + 5 + 9 + 9 + 3 , values[3] ); gchar *title = _utf8str( descr ); char *timecode = format_selection_time( 0,(values[2]-values[1]) ); int int_id = values[0]; int poke_slot= 0; int bank_page = -1; verify_bank_capacity( &bank_page , &poke_slot, int_id, values[1]); 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 ); add_sample_to_effect_sources_list( int_id,0, title, timecode); free_slot(tmp_slot); if( !disable_sample_image ) { veejay_get_sample_image( int_id, 0, info->image_dimensions[0], info->image_dimensions[1] ); } } else { update_sample_slot_data( bank_page, poke_slot, int_id,0,title,timecode); } } if( info->status_tokens[CURRENT_ID] == values[0] && info->status_tokens[PLAY_MODE] == 0 ) put_text( "entry_samplename", title ); free(timecode); g_free(title); } offset += len; } offset = 0; } if( fxtext ) free(fxtext); fxlen = 0; load_from = info->uc.expected_num_streams; if( load_from < 0 ) load_from = 0; multi_vims( VIMS_STREAM_LIST,"%d",(with_reset_slotselection ? 0 : load_from) ); fxtext = recv_vims(5, &fxlen); if( fxlen > 0 && fxtext != NULL) { no_samples = 0; while( offset < fxlen ) { char tmp_len[4]; veejay_memset(tmp_len,0,sizeof(tmp_len)); strncpy(tmp_len, fxtext + offset, 3 ); int len = atoi(tmp_len); offset += 3; if(len > 0) { veejay_memset(line,0,sizeof(line)); veejay_memset(descr,0,sizeof(descr)); strncpy( line, fxtext + offset, len ); int values[10]; veejay_memset(values,0, sizeof(values)); 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_CALI: snprintf(source,sizeof(source),"calibrate %d",values[0]); break; case STREAM_VIDEO4LINUX: snprintf(source,sizeof(source),"capture %d",values[0]); break; case STREAM_WHITE: snprintf(source,sizeof(source),"solid %d",values[0]); break; case STREAM_MCAST: snprintf(source,sizeof(source),"multicast %d",values[0]); break; case STREAM_NETWORK: snprintf(source,sizeof(source),"unicast %d",values[0]); break; case STREAM_YUV4MPEG: snprintf(source,sizeof(source),"y4m %d",values[0]); break; case STREAM_DV1394: snprintf(source,sizeof(source),"dv1394 %d",values[0]); break; case STREAM_PICTURE: snprintf(source,sizeof(source),"image %d",values[0]); break; case STREAM_GENERATOR: snprintf(source,sizeof(source),"Z%d",values[0]); break; case STREAM_CLONE: snprintf(source,sizeof(source),"T%d", values[0]); break; case STREAM_VLOOP: snprintf(source,sizeof(source),"vloop %d", values[0]); break; case STREAM_AVF: snprintf(source,sizeof(source),"stream %d", values[0]); break; default: snprintf(source,sizeof(source),"??? %d", values[0]); break; } gchar *gsource = _utf8str( descr ); gchar *gtype = _utf8str( source ); int bank_page = -1; int poke_slot = 0; verify_bank_capacity( &bank_page , &poke_slot, values[0], values[1]); 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,values[0],values[1], gtype,gsource ); add_sample_to_sample_banks(bank_page, tmp_slot ); add_sample_to_effect_sources_list( values[0], values[1],gsource,gtype); free_slot(tmp_slot); } else { update_sample_slot_data( bank_page, poke_slot, values[0],values[1],gsource,gtype); } } g_free(gsource); g_free(gtype); } offset += len; } } if(fxtext) free(fxtext); select_slot( info->status_tokens[PLAY_MODE] ); if(no_samples) { samplebank_ready_ = 1; // as long as there are no samples, samplebank will not initialize } } 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 ) { char msg[100]; sprintf(msg, "%03d:%s;", event_id, args ); msg_vims(msg); } } } } if( vimsid ) g_free( vimsid ); } } 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; gint n_params = 0; gtk_tree_model_get(model, &iter, VIMS_ID, &vimsid, -1); gtk_tree_model_get(model, &iter, VIMS_CONTENTS, &text, -1 ); gtk_tree_model_get(model, &iter, VIMS_PARAMS, &n_params, -1); int k=0; int m=0; gchar *key = NULL; gchar *mod = NULL; #ifdef HAVE_SDL gtk_tree_model_get(model,&iter, VIMS_KEY, &key, -1); gtk_tree_model_get(model,&iter, VIMS_MOD, &mod, -1); #endif if(sscanf( vimsid, "%d", &event_id )) { #ifdef HAVE_SDL k = sdlkey_by_name( key ); m = sdlmod_by_name( mod ); #endif info->uc.selected_vims_entry = event_id; if( event_id >= VIMS_BUNDLE_START && event_id < VIMS_BUNDLE_END ) info->uc.selected_vims_type = 0; else info->uc.selected_vims_type = 1; if(info->uc.selected_vims_args ) free(info->uc.selected_vims_args); info->uc.selected_vims_args = NULL; if( n_params > 0 && text ) info->uc.selected_vims_args = strdup( text ); info->uc.selected_vims_accel[0] = m; info->uc.selected_vims_accel[1] = k; clear_textview_buffer( "vimsview" ); if(text) set_textview_buffer( "vimsview", text ); } 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 ); gint red = current_color.red / 255.0; gint green = current_color.green / 255.0; gint blue = current_color.blue / 255.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 / 255.0; gint green = current_color.green / 255.0; gint blue = current_color.blue / 255.0; 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_value2(widget_cache[WIDGET_SLIDER_P1], red, 0 ); update_slider_value2(widget_cache[WIDGET_SLIDER_P2], green, 0 ); update_slider_value2(widget_cache[WIDGET_SLIDER_P3], blue, 0 ); info->parameter_lock = 0; } } static void setup_rgbkey() { GtkWidget *sel = widget_cache[ WIDGET_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_LIST_ITEM_ID, "VIMS ID",0); setup_tree_text_column( "tree_vims", VIMS_LIST_ITEM_DESCR, "Description",0 ); 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); } 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, "Event ID",0); setup_tree_text_column( "tree_bundles", VIMS_KEY, "Key",0); setup_tree_text_column( "tree_bundles", VIMS_MOD, "Mod",0); setup_tree_text_column( "tree_bundles", VIMS_DESCR, "Description",0 ); setup_tree_text_column( "tree_bundles", VIMS_PARAMS, "Max args",0); setup_tree_text_column( "tree_bundles", VIMS_FORMAT, "Format",0 ); 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, "#",0); setup_tree_text_column( "editlisttree", COLUMN_STRING0, "Timecode",0 ); setup_tree_text_column( "editlisttree", COLUMN_STRINGA, "Filename",0); setup_tree_text_column( "editlisttree", COLUMN_STRINGB, "Duration",0); setup_tree_text_column( "editlisttree", COLUMN_STRINGC, "FOURCC",0); 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); } static void reload_keys() { gint len = 0; single_vims( VIMS_KEYLIST ); gchar *text = recv_vims( 6, &len ); gint offset = 0; int checksum = data_checksum(text,len); if( info->uc.reload_hint_checksums[HINT_KEYS] == checksum ) { if(text) free(text); return; } info->uc.reload_hint_checksums[HINT_KEYS] = checksum; if( len == 0 || text == NULL ) return; gint k,index; for( k = 0; k < VIMS_MAX ; k ++ ) { vims_keys_t *p = &vims_keys_list[k]; if(p->vims) free(p->vims); p->keyval = 0; p->state = 0; p->event_id = 0; p->vims = NULL; } char *ptr = text; while( offset < len ) { int val[6]; veejay_memset(val,0,sizeof(val)); int n = sscanf( ptr + offset, "%04d%03d%03d%03d", &val[0],&val[1],&val[2],&val[3]); if( n != 4 ) { free(text); return; } offset += 13; char *message = strndup( ptr + offset , val[3] ); offset += val[3]; index = (val[1] * G_MOD_OFFSET) + val[2]; if( index < 0 || index >= VIMS_MAX ) { free(message); continue; } vims_keys_list[ index ].keyval = val[2]; vims_keys_list[ index ].state = val[1]; vims_keys_list[ index ].event_id = val[0]; vims_keys_list[ index ].vims = message; } free(text); } static void reload_bundles() { reload_keys(); 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(6,&len); // msg len gint offset = 0; int checksum = data_checksum(eltext,len); if( info->uc.reload_hint_checksums[HINT_BUNDLES] == checksum ) { if( eltext) free(eltext); return; } info->uc.reload_hint_checksums[HINT_BUNDLES] = checksum; reset_tree("tree_bundles"); if(len == 0 || eltext == NULL ) { #ifdef STRICT_CHECKING assert(eltext != NULL && len > 0); #endif return; } GtkTreeModel *model = gtk_tree_view_get_model( GTK_TREE_VIEW(tree )); store = GTK_LIST_STORE(model); char *ptr = eltext; while( offset < len ) { char *message = NULL; char *format = NULL; char *args = NULL; int val[6] = { 0,0,0,0,0,0 }; if(sscanf( ptr + offset, "%04d%03d%03d%04d", &val[0],&val[1],&val[2],&val[3]) != 4 ) { veejay_msg(VEEJAY_MSG_DEBUG,"%s: Unexpected input at byte %d",__FUNCTION__, offset ); free(eltext); return; } offset += 14; message = strndup( ptr + offset , val[3] ); offset += val[3]; if( sscanf( ptr + offset, "%03d%03d", &val[4], &val[5] ) != 2 ) { veejay_msg(VEEJAY_MSG_DEBUG,"%s: Unexpected input at byte %d",__FUNCTION__, offset ); free(eltext); return; } offset += 6; if(val[4]) // format string { format = strndup( ptr + offset, val[4] ); offset += val[4]; } if(val[5]) // argument string { args = strndup( ptr + offset, val[5] ); offset += val[5]; } gchar *g_descr = NULL; gchar *g_format = NULL; gchar *g_content = NULL; #ifdef HAVE_SDL gchar *g_keyname = sdlkey_by_id( val[1] ); gchar *g_keymod = sdlmod_by_id( val[2] ); #else gchar *g_keyname = "N/A"; gchar *g_keymod = ""; #endif gchar *g_vims[5]; snprintf( (char*) g_vims,sizeof(g_vims), "%03d", val[0] ); if( val[0] >= VIMS_BUNDLE_START && val[0] < VIMS_BUNDLE_END ) { g_content = _utf8str( message ); g_descr = _utf8str("Bundle"); } else { g_descr = _utf8str( message ); if( format ) g_format = _utf8str( format ); if( args ) { g_content = _utf8str( args ); //@ set default VIMS argument: if(vj_event_list[val[0]].args ) { free(vj_event_list[val[0]].args ); vj_event_list[val[0]].args = NULL; } vj_event_list[ val[0] ].args = strdup( args ); } } gtk_list_store_append( store, &iter ); gtk_list_store_set(store, &iter, VIMS_ID, g_vims, VIMS_KEY, g_keyname, VIMS_MOD, g_keymod, VIMS_DESCR, g_descr, VIMS_PARAMS, vj_event_list[ val[0] ].params, VIMS_FORMAT, g_format, VIMS_CONTENTS, g_content, /* this is a hidden column, when the item is selected, the text is displayed in the textview widget */ -1 ); if(message) free(message); if(format) free(format); if(args) free(args); if( g_descr ) g_free(g_descr ); if( g_format ) g_free(g_format ); if( g_content) g_free(g_content ); } /* entry, start frame, end frame */ gtk_tree_view_set_model( GTK_TREE_VIEW(tree), GTK_TREE_MODEL(store)); 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 ) { #ifdef STRICT_CHECKING assert(eltext != NULL && len > 0); #endif 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, 12 ); int val[4]; if( sscanf(line, "%04d%02d%03d%03d", &val[0],&val[1],&val[2],&val[3]) != 4 ) { veejay_msg(0,"Expected exactly 4 tokens: [%s]", line); } if( val[0] < 0 || val[0] > 1024 ) { veejay_msg(0,"Invalid ID at position %d", offset ); } if( val[1] < 0 || val[1] > 99 ) { veejay_msg(0, "Invalid number of arguments at position %d", offset); } if( val[2] < 0 || val[2] > 999 ) { veejay_msg(0, "Invalid format length at position %d", offset ); } if( val[3] < 0 || val[3] > 999 ) { veejay_msg(0, "Invalid name length at position %d", offset ); } 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]; } if(vj_event_list[val[0]].format ) free(vj_event_list[val[0]].format); if(vj_event_list[val[0]].descr ) free(vj_event_list[val[0]].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; vj_event_list[ val[0] ].descr = descr; sprintf(vimsid, "%03d", val[0] ); gtk_list_store_set(store, &iter, VIMS_LIST_ITEM_ID, vimsid, VIMS_LIST_ITEM_DESCR,descr,-1 ); free( line ); } gtk_tree_view_set_model( GTK_TREE_VIEW(tree), GTK_TREE_MODEL(store)); free( eltext ); } static char *tokenize_on_space( char *q ) { int n = 0; char *r = NULL; char *p = q; while( *p != '\0' && !isblank( *p ) && *p != ' ' && *p != 20) { (*p)++; n++; } if( n <= 0 ) return NULL; r = vj_calloc( n+1 ); strncpy( r, q, n ); return r; } static int have_srt_ = 0; static void init_srt_editor() { reload_fontlist(); update_spin_range( "spin_text_x", 0, info->el.width-1 , 0 ); update_spin_range( "spin_text_y", 0, info->el.height-1, 0 ); update_spin_range( "spin_text_size", 10, 500, 40 ); update_spin_range( "spin_text_start", 0, total_frames_, 0 ); } static void reload_fontlist() { GtkWidget *box = glade_xml_get_widget_( info->main_window, "combobox_fonts"); gtk_combo_box_text_remove_all (GTK_COMBO_BOX_TEXT( box ) ); single_vims( VIMS_FONT_LIST ); gint len = 0; gchar *srts = recv_vims(6,&len ); gint i = 0; gchar *p = srts; while( i < len ) { char tmp[4]; veejay_memset(tmp,0,sizeof(tmp)); strncpy(tmp, p, 3 ); int slen = atoi(tmp); p += 3; gchar *seq_str = strndup( p, slen ); gtk_combo_box_text_append( GTK_COMBO_BOX_TEXT(box), NULL, seq_str ); p += slen; free(seq_str); i += (slen + 3); } free(srts); } static void reload_srt() { if(!have_srt_) { init_srt_editor(); have_srt_ = 1; } GtkWidget *box = glade_xml_get_widget_( info->main_window, "combobox_textsrt"); gtk_combo_box_text_remove_all (GTK_COMBO_BOX_TEXT( box ) ); clear_textview_buffer( "textview_text"); single_vims( VIMS_SRT_LIST ); gint i=0, len = 0; gchar *srts = recv_vims(6,&len ); if( srts == NULL || len <= 0 ) { // disable_widget( "SRTframe" ); return; } gchar *p = srts; gchar *token = NULL; while( i < len ) { token = tokenize_on_space( p ); if(!token) break; if(token) { gtk_combo_box_text_append( GTK_COMBO_BOX_TEXT(box), NULL, token ); i += strlen(token) + 1; free(token); } else i++; p = srts + i; } free(srts); } void _edl_reset(void) { if( info->elref != NULL) { int n = g_list_length(info->elref); int i; for( i = 0; i <=n ; i ++ ) { void *ptr = g_list_nth_data( info->elref , i ); if(ptr) free(ptr); } g_list_free( info->elref ); } } void reload_macros() { GtkWidget *tree = glade_xml_get_widget_( info->main_window, "macro_macros" ); GtkListStore *store; GtkTreeIter iter; gint consumed = 0; gint len = 0; single_vims( VIMS_GET_ALL_MACRO ); gchar *answer = recv_vims(8, &len); int checksum = data_checksum(answer,len); if( info->uc.reload_hint_checksums[HINT_MACRO] == checksum ) { if(answer) free(answer); return; } info->uc.reload_hint_checksums[HINT_MACRO] = checksum; reset_tree("macro_macros"); if( answer == NULL || len < 0 ) return; GtkTreeModel *model = gtk_tree_view_get_model( GTK_TREE_VIEW(tree )); store = GTK_LIST_STORE(model); gchar *ptr = answer; int error = 0; while(consumed < len) { long frame_num = 0; int at_dup = 0; int at_loop = 0; int at_seq = 0; int msg_len = 0; int n = sscanf( ptr, "%08ld%02d%08d%02d%03d", &frame_num, &at_dup, &at_loop, &at_seq, &msg_len ); if( n != 5) { error = 1; break; } ptr += (8 + 2 + 8 + 2 + 3); char *msg = strndup( ptr, msg_len ); int vims_id = -1; n = sscanf(msg,"%03d:", &vims_id); char *descr = NULL; if( vims_id >= 0 && vims_id < VIMS_QUIT ) descr = vj_event_list[vims_id].descr; gtk_list_store_append( store, &iter ); gtk_list_store_set(store, &iter, MACRO_FRAME, (guint) frame_num, MACRO_DUP, (guint) at_dup, MACRO_LOOP, (guint) at_loop, MACRO_MSG_SEQ, (guint) at_seq, MACRO_VIMS, msg, MACRO_VIMS_DESCR, (descr == NULL ? "Unknown": descr), -1 ); ptr += msg_len; free(msg); consumed += (8 + 2 + 8 + 2 + 3); consumed += msg_len; } if(error){ veejay_msg(0,"Unable to read all VIMS macros"); } gtk_tree_view_set_model( GTK_TREE_VIEW(tree), GTK_TREE_MODEL(store)); free(answer); info->uc.reload_hint[HINT_MACRO] = 0; } 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(); _edl_reset(); if( eltext == NULL || len < 0 ) { return; } el_constr *el; char *tmp = strndup( eltext + offset, 4 ); if( sscanf( tmp,"%d",&num_files ) != 1 ) { free(tmp); free(eltext); return; } free(tmp); offset += 4; for( i = 0; i < num_files ; i ++ ) { int name_len = 0; tmp = strndup( eltext + offset, 4 ); if( sscanf( tmp,"%d", &name_len ) != 1 ) { free(tmp); free(eltext); return; } offset += 4; free(tmp); char *file = strndup( eltext + offset, name_len ); offset += name_len; int iter = 0; tmp = strndup( eltext + offset, 4 ); if( sscanf( tmp, "%d", &iter ) != 1 ) { free(tmp); free(eltext); return; } free(tmp); offset += 4; long num_frames = 0; tmp = strndup( eltext + offset, 10 ); if( sscanf(tmp, "%ld", &num_frames ) != 1 ) { free(tmp); free(eltext); return; } free(tmp); offset += 10; int fourcc_len = 0; tmp = strndup( eltext + offset, 2 ); if( sscanf( tmp, "%d", &fourcc_len) != 1 ) { free(tmp); free(eltext); return; } offset += fourcc_len; char *fourcc = strndup( eltext + offset - 1, fourcc_len ); el = _el_entry_new( iter, file, num_frames, fourcc ); info->editlist = g_list_append( info->editlist, el ); offset += 2; free(file); free(fourcc); free(tmp); } 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 ) { 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) { free(tmp); free(eltext); return; } int file_len = _el_get_nframes( nl ); if(file_len <= 0) { free(tmp); row_num++; continue; } if(n1 < 0 ) n1 = 0; if(n2 >= file_len) n2 = file_len; if(n2 <= n1 ) { free(tmp); 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); char *timecode = format_selection_time( n1,n2 ); gchar *gfourcc = _utf8str( _el_get_fourcc(nl) ); gchar *timeline = format_selection_time( 0, total_frames ); 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 ); free(timecode); g_free(gfourcc); g_free(fname); free(timeline); free(tmp); total_frames = total_frames + (n2-n1) + 1; row_num ++; } gtk_tree_view_set_model( GTK_TREE_VIEW(tree), GTK_TREE_MODEL(store)); free( eltext ); } // execute after el change: static void load_editlist_info() { char norm; float fps; int values[10] = { 0 }; long rate = 0; long dum[2]; char tmp[16]; int len = 0; single_vims( VIMS_VIDEO_INFORMATION ); gchar *res = recv_vims(3,&len); if( len <= 0 || res==NULL) { #ifdef STRICT_CHECKING assert(len > 0 && res != NULL); #endif return; } sscanf(res, "%d %d %d %c %f %d %d %ld %d %ld %ld %d %d", &values[0], &values[1], &values[2], &norm,&fps, &values[4], &values[5], &rate, &values[7], &dum[0], &dum[1], &values[8], &use_vims_mcast); snprintf( tmp, sizeof(tmp)-1, "%dx%d", values[0],values[1]); info->el.width = values[0]; info->el.height = values[1]; info->el.num_frames = dum[1]; 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; #ifdef STRICT_CHECKING assert( info->el.fps > 0 ); #endif 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( values[4] == 0 ) { if(gtk_widget_is_sensitive( widget_cache[ WIDGET_BUTTON_5_4 ] )) gtk_widget_set_sensitive(widget_cache[ WIDGET_BUTTON_5_4 ], FALSE); } else { if(!gtk_widget_is_sensitive(widget_cache[ WIDGET_BUTTON_5_4 ] )) gtk_widget_set_sensitive(widget_cache[ WIDGET_BUTTON_5_4 ], TRUE); if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON( widget_cache[ WIDGET_BUTTON_5_4 ] )) != values[8] ) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON( widget_cache[ WIDGET_BUTTON_5_4 ] ) , values[8] ); } if( use_vims_mcast ) { if(!gtk_widget_is_sensitive(widget_cache[ WIDGET_TOGGLE_MULTICAST] )) gtk_widget_set_sensitive(widget_cache[ WIDGET_TOGGLE_MULTICAST ], TRUE); } else { if(gtk_widget_is_sensitive(widget_cache[ WIDGET_TOGGLE_MULTICAST ] )) gtk_widget_set_sensitive(widget_cache[ WIDGET_TOGGLE_MULTICAST ], FALSE); } free(res); } static void notebook_set_page(const char *name, int page) { GtkWidget *w = glade_xml_get_widget_(info->main_window,name); if(!w) { veejay_msg(VEEJAY_MSG_ERROR, "Widget '%s' not found",name); return; } gtk_notebook_set_current_page( GTK_NOTEBOOK(w), page ); } static void hide_widget(const char *name) { GtkWidget *w = glade_xml_get_widget_(info->main_window,name); if(!w) { veejay_msg(VEEJAY_MSG_ERROR, "Widget '%s' not found",name); return; } gtk_widget_hide(w); } static void show_widget(const char *name) { GtkWidget *w = glade_xml_get_widget_(info->main_window,name); if(!w) { veejay_msg(VEEJAY_MSG_ERROR, "Widget '%s' not found",name); return; } gtk_widget_show(w); } char *format_selection_time(int start, int end) { double fps = (double) info->el.fps; int pos = (end-start); return format_time( pos, fps ); } static gboolean update_cpumeter_timeout( gpointer data ) { gdouble ms = (gdouble)info->status_tokens[ELAPSED_TIME]; //gdouble fs = (gdouble)get_slider_val( "framerate" ); gdouble fs = (gdouble) info->status_tokens[18] * 0.01; gdouble lim = (1.0f/fs)*1000.0; if( ms < lim ) { update_label_str( "cpumeter", text_msg_[TEXT_REALTIME].text ); } else { char text[32]; sprintf(text, "%2.2f FPS", ( 1.0f / ms ) * 1000.0 ); update_label_str( "cpumeter", text ); } return TRUE; } static gboolean update_cachemeter_timeout( gpointer data ) { char text[32]; gint v = info->status_tokens[TOTAL_MEM]; sprintf(text,"%d MB cached",v); update_label_str( "cachemeter", text ); return TRUE; } static gboolean update_sample_record_timeout(gpointer data) { if( info->uc.playmode == MODE_SAMPLE ) { GtkWidget *w; if( is_button_toggled("seqactive" ) ) { w = glade_xml_get_widget_( info->main_window, "rec_seq_progress" ); } else { 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.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 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 char glade_path[1024]; char *get_glade_path() { return glade_path; } char *get_gveejay_dir() { return RELOADED_DATADIR; } void get_gd(char *buf, char *suf, const char *filename) { const char *dir = RELOADED_DATADIR; if(filename !=NULL && suf != NULL) sprintf(buf, "%s/%s/%s",dir,suf, filename ); if(filename !=NULL && suf==NULL) sprintf(buf, "%s/%s", dir, filename); if(filename == NULL && suf != NULL) sprintf(buf, "%s/%s/" , dir, suf); } GdkPixbuf *vj_gdk_pixbuf_scale_simple( GdkPixbuf *src, int dw, int dh, GdkInterpType inter_type ) { return gdk_pixbuf_scale_simple( src,dw,dh,inter_type ); /* GdkPixbuf *res = gdk_pixbuf_new( GDK_COLORSPACE_RGB, FALSE, 8, dw, dh ); #ifdef STRICT_CHECKING assert( GDK_IS_PIXBUF( res ) ); #endif uint8_t *res_out = gdk_pixbuf_get_pixels( res ); uint8_t *src_in = gdk_pixbuf_get_pixels( src ); uint32_t src_w = gdk_pixbuf_get_width( src ); uint32_t src_h = gdk_pixbuf_get_height( src ); int dst_w = gdk_pixbuf_get_width( res ); int dst_h = gdk_pixbuf_get_height( res ); VJFrame *src1 = yuv_rgb_template( src_in, src_w, src_h, PIX_FMT_BGR24 ); VJFrame *dst1 = yuv_rgb_template( res_out, dst_w, dst_h, PIX_FMT_BGR24 ); veejay_msg(VEEJAY_MSG_ERROR, "%s: %dx%d -> %dx%d", __FUNCTION__, src_w,src_h,dst_w,dst_h ); yuv_convert_any_ac( src1,dst1, src1->format, dst1->format ); free(src1); free(dst1); return res;*/ } void gveejay_sleep( void *u ) { struct timespec nsecsleep; nsecsleep.tv_nsec = 500000; nsecsleep.tv_sec = 0; nanosleep( &nsecsleep, NULL ); } //static int tick = 0; int gveejay_time_to_sync( void *ptr ) { vj_gui_t *ui = (vj_gui_t*) ptr; struct timeval time_now; gettimeofday( &time_now, 0 ); double diff = time_now.tv_sec - ui->time_last.tv_sec + (time_now.tv_usec - ui->time_last.tv_usec ) * 1.e-6; float fps = 0.0; int ret = 0; if ( ui->watch.state == STATE_PLAYING ) { fps = ui->el.fps; float spvf = 1.0f / fps; if( diff > spvf ) { // veejay_msg(0, "%d diff = %g, delay=%f, ela=%f, spvf=%f", tick++, diff, 0.0,ela,spvf); ret = 1; } } return ret; } int veejay_update_multitrack( void *ptr ) { sync_info *s = multitrack_sync( info->mt ); /* if( s->status_list[s->master] == NULL ) { info->watch.w_state = STATE_STOPPED; free(s->status_list); free(s->img_list ); free(s->widths); free(s->heights); free(s); gettimeofday( &(info->time_last) , 0 ); return 1; }*/ GtkWidget *maintrack = widget_cache[ WIDGET_IMAGEA ]; int i; GtkWidget *ww = widget_cache[ WIDGET_NOTEBOOK18 ]; int deckpage = gtk_notebook_get_current_page(GTK_NOTEBOOK(ww)); #ifdef STRICT_CHECKING assert( s->status_list[s->master] != NULL ); #endif int tmp = 0; if( s->status_list[s->master] != NULL ) { for ( i = 0; i < STATUS_TOKENS; i ++ ) { tmp += s->status_list[s->master][i]; info->status_tokens[i] = s->status_list[s->master][i]; } } if( tmp == 0 ) { free(s->status_list); free(s->img_list ); free(s->widths); free(s->heights); free(s); gettimeofday( &(info->time_last) , 0 ); return 0; } info->status_lock = 1; info->uc.playmode = info->status_tokens[ PLAY_MODE ]; update_gui(); info->prev_mode = info->status_tokens[ PLAY_MODE ]; int pm = info->status_tokens[PLAY_MODE]; #ifdef STRICT_CHECKING assert( pm >= 0 && pm < 4 ); #endif int *history = info->history_tokens[pm]; veejay_memcpy( history, info->status_tokens, sizeof(int) * STATUS_TOKENS ); for( i = 0; i < s->tracks ; i ++ ) { if( s->status_list[i] ) { update_multitrack_widgets( info->mt, s->status_list[i], i ); free(s->status_list[i]); } if( s->img_list[i] ) { if( i == s->master ) { #ifdef STRICT_CHECKING assert( s->widths[i] > 0 ); assert( s->heights[i] > 0 ); assert( GDK_IS_PIXBUF( s->img_list[i] ) ); #endif if( gdk_pixbuf_get_height(s->img_list[i]) == preview_box_w_ && gdk_pixbuf_get_width(s->img_list[i]) == preview_box_h_ ) gtk_image_set_from_pixbuf_( GTK_IMAGE( maintrack ), s->img_list[i] ); else { GdkPixbuf *result = vj_gdk_pixbuf_scale_simple( s->img_list[i],preview_box_w_,preview_box_h_, GDK_INTERP_NEAREST ); if(result) { gtk_image_set_from_pixbuf_( GTK_IMAGE( maintrack ), result ); g_object_unref(result); } } if( history[PLAY_MODE] == info->status_tokens[PLAY_MODE] && history[CURRENT_ID] == info->status_tokens[CURRENT_ID] ) { vj_img_cb( s->img_list[i] ); } } if(deckpage == 3) // notebook18 >>> Multitrack page multitrack_update_sequence_image( info->mt, i, s->img_list[i] ); if( s->img_list[i] ) g_object_unref( s->img_list[i] ); } } info->status_lock = 0; free(s->status_list); free(s->img_list ); free(s->widths); free(s->heights); free(s); gettimeofday( &(info->time_last) , 0 ); return 1; } static void update_status_accessibility(int old_pm, int new_pm) { int i; if( old_pm == new_pm ) return; if( new_pm == MODE_STREAM ) { for(i=0; sample_widget_map[i].sample_widget_id != SAMPLE_WIDGET_NONE; i ++ ) { if(gtk_widget_is_sensitive(GTK_WIDGET(widget_cache[ sample_widget_map[i].widget_id ] )) ) { gtk_widget_set_sensitive(GTK_WIDGET(widget_cache[ sample_widget_map[i].widget_id ] ), FALSE); } } for(i=0; plain_widget_map[i].plain_widget_id != PLAIN_WIDGET_NONE; i ++ ) { if(gtk_widget_is_sensitive(GTK_WIDGET(widget_cache[ plain_widget_map[i].widget_id ] )) ) { gtk_widget_set_sensitive(GTK_WIDGET(widget_cache[ plain_widget_map[i].widget_id ] ), FALSE); } } for(i=0; stream_widget_map[i].stream_widget_id != STREAM_WIDGET_NONE; i ++ ) { if(!gtk_widget_is_sensitive(GTK_WIDGET(widget_cache[ stream_widget_map[i].widget_id ] )) ) { gtk_widget_set_sensitive(GTK_WIDGET(widget_cache[ stream_widget_map[i].widget_id ] ), TRUE); } } } if( new_pm == MODE_SAMPLE ) { for(i=0; stream_widget_map[i].stream_widget_id != STREAM_WIDGET_NONE; i ++ ) { if(gtk_widget_is_sensitive(GTK_WIDGET(widget_cache[ stream_widget_map[i].widget_id ] )) ) { gtk_widget_set_sensitive(GTK_WIDGET(widget_cache[ stream_widget_map[i].widget_id ] ), FALSE); } } for(i=0; plain_widget_map[i].plain_widget_id != PLAIN_WIDGET_NONE; i ++ ) { if(gtk_widget_is_sensitive(GTK_WIDGET(widget_cache[ plain_widget_map[i].widget_id ] )) ) { gtk_widget_set_sensitive(GTK_WIDGET(widget_cache[ plain_widget_map[i].widget_id ] ), FALSE); } } for(i=0; sample_widget_map[i].sample_widget_id != SAMPLE_WIDGET_NONE; i ++ ) { if(!gtk_widget_is_sensitive(GTK_WIDGET(widget_cache[ sample_widget_map[i].widget_id ] )) ) { gtk_widget_set_sensitive(GTK_WIDGET(widget_cache[ sample_widget_map[i].widget_id ] ), TRUE); } } } if( new_pm == MODE_PLAIN) { for(i=0; stream_widget_map[i].stream_widget_id != STREAM_WIDGET_NONE; i ++ ) { if(gtk_widget_is_sensitive(GTK_WIDGET(widget_cache[ stream_widget_map[i].widget_id ] )) ) { gtk_widget_set_sensitive(GTK_WIDGET(widget_cache[ stream_widget_map[i].widget_id ] ), FALSE); } } for(i=0; sample_widget_map[i].sample_widget_id != SAMPLE_WIDGET_NONE; i ++ ) { if(gtk_widget_is_sensitive(GTK_WIDGET(widget_cache[ sample_widget_map[i].widget_id ] )) ) { gtk_widget_set_sensitive(GTK_WIDGET(widget_cache[ sample_widget_map[i].widget_id ] ), FALSE); } } for(i=0; plain_widget_map[i].plain_widget_id != PLAIN_WIDGET_NONE; i ++ ) { if(!gtk_widget_is_sensitive(GTK_WIDGET(widget_cache[ plain_widget_map[i].widget_id ] )) ) { gtk_widget_set_sensitive(GTK_WIDGET(widget_cache[ plain_widget_map[i].widget_id ] ), TRUE); } } } GtkWidget *n = widget_cache[ WIDGET_PANELS ]; int page_needed = 0; switch( new_pm ) { case MODE_SAMPLE: page_needed =0 ; break; case MODE_STREAM: page_needed = 1; break; case MODE_PLAIN: page_needed = 2; break; default: break; } gtk_notebook_set_current_page( GTK_NOTEBOOK(n), page_needed ); } static void set_pm_page_label(int sample_id, int type) { gchar ostitle[100]; gchar ftitle[100]; switch(type) { case 0: snprintf(ostitle, sizeof(ostitle), "Sample %d",sample_id);break; case 1: snprintf(ostitle, sizeof(ostitle), "Stream %d",sample_id);break; default: snprintf(ostitle,sizeof(ostitle), "Plain");break; } gchar *title = _utf8str(ostitle); snprintf(ftitle,sizeof(ftitle), "%s", ostitle); label_set_markup( "label_current_mode", ftitle); update_label_str( "label_currentsource", (type == 0 ? "Sample" : "Stream" ) ); g_free(title); } static void update_globalinfo(int *history, int pm, int last_pm) { int i; 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] ); if( total_frames_ != history_frames_ ) { gint current_frame_ = info->status_tokens[FRAME_NUM]; char *time = format_time( total_frames_,(double) info->el.fps ); if( pm == MODE_STREAM ) { gtk_spin_button_set_value( GTK_SPIN_BUTTON( widget_cache[WIDGET_STREAM_LENGTH] ), (gdouble) info->status_tokens[SAMPLE_MARKER_END]); gtk_label_set_text( GTK_LABEL( widget_cache[WIDGET_STREAM_LENGTH_LABEL] ), time ); } if( pm != MODE_SAMPLE) { update_spin_range2( widget_cache[WIDGET_BUTTON_FADEDUR],0, total_frames_, ( total_frames_ > 25 ? 25 : total_frames_-1 ) ); } update_label_i2( widget_cache[WIDGET_LABEL_TOTFRAMES], total_frames_, 1 ); if( pm == MODE_SAMPLE ) { gtk_label_set_text( GTK_LABEL( widget_cache[WIDGET_LABEL_SAMPLELENGTH] ), time ); } update_label_i2( widget_cache[ WIDGET_LABEL_TOTFRAMES ], total_frames_, 1 ); gtk_label_set_text( GTK_LABEL( widget_cache[WIDGET_LABEL_TOTALTIME] ), time ); if(pm == MODE_SAMPLE) gtk_label_set_text( GTK_LABEL( widget_cache[WIDGET_SAMPLE_LENGTH_LABEL] ), time ); else gtk_label_set_text( GTK_LABEL( widget_cache[WIDGET_SAMPLE_LENGTH_LABEL] ), "0:00:00:00" ); timeline_set_length( info->tl, (gdouble) total_frames_ , current_frame_); if( pm != MODE_STREAM ) info->uc.reload_hint[HINT_EL] = 1; free(time); } info->status_frame = info->status_tokens[FRAME_NUM]; timeline_set_pos( info->tl, (gdouble) info->status_frame ); char *current_time_ = format_time( info->status_frame, (double) info->el.fps ); char *mouse_at_time = format_time( timeline_get_point(TIMELINE_SELECTION(info->tl)), (double)info->el.fps); update_label_i2( widget_cache[ WIDGET_LABEL_CURFRAME ],info->status_frame ,1 ); gtk_label_set_text( GTK_LABEL( widget_cache[WIDGET_LABEL_CURTIME] ), current_time_ ); gtk_label_set_text( GTK_LABEL( widget_cache[WIDGET_LABEL_MOUSEAT] ), mouse_at_time); // WARNING: updating EDL labels when not visible on screen incurs high cost (these labels are updated every frame period) if( pm == MODE_SAMPLE && is_edl_displayed() ) { gtk_label_set_text( GTK_LABEL( widget_cache[WIDGET_LABEL_SAMPLEPOSITION] ), current_time_ ); update_label_i2( widget_cache[ WIDGET_LABEL_SAMPLEPOS ], info->status_frame, 1); } free(current_time_); free(mouse_at_time); if( last_pm != pm ) update_status_accessibility( last_pm, pm); if( info->status_tokens[FEEDBACK] != history[FEEDBACK] ) { if(info->status_tokens[FEEDBACK] == 1) { // when feedback is enabled for ( i = 0; fb_widget_map[i].fb_widget_id != FB_WIDGET_NONE; i ++ ) { if(gtk_widget_is_sensitive(GTK_WIDGET(widget_cache[fb_widget_map[i].widget_id]))) gtk_widget_set_sensitive(GTK_WIDGET(widget_cache[fb_widget_map[i].widget_id]), FALSE); } } else { for ( i = 0; fb_widget_map[i].fb_widget_id != FB_WIDGET_NONE; i ++ ) { if(!gtk_widget_is_sensitive(GTK_WIDGET(widget_cache[fb_widget_map[i].widget_id]))) gtk_widget_set_sensitive(GTK_WIDGET(widget_cache[fb_widget_map[i].widget_id]), TRUE); } } if(info->status_tokens[FEEDBACK] != gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( widget_cache[WIDGET_FEEDBACKBUTTON] ) )) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( widget_cache[WIDGET_FEEDBACKBUTTON] ), info->status_tokens[FEEDBACK] ); } } if( info->status_tokens[MACRO] != history[MACRO] ) { switch(info->status_tokens[MACRO]) { case 1: gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( widget_cache[WIDGET_MACRORECORD1] ), TRUE ); gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( widget_cache[WIDGET_MACRORECORD] ), TRUE ); break; case 2: gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( widget_cache[WIDGET_MACROPLAY1] ), TRUE ); gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( widget_cache[WIDGET_MACROPLAY] ), TRUE ); break; default: gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( widget_cache[WIDGET_MACROSTOP1] ), TRUE ); gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( widget_cache[WIDGET_MACROSTOP] ), TRUE ); break; } } if( (pm == MODE_SAMPLE || pm == MODE_STREAM ) && info->status_tokens[CURRENT_ENTRY] != history[CURRENT_ENTRY] ) { info->uc.selected_chain_entry = info->status_tokens[CURRENT_ENTRY]; select_chain_entry(info->uc.selected_chain_entry); info->uc.reload_hint[HINT_KF] = 1; info->uc.reload_hint[HINT_ENTRY] = 1; } if( info->status_tokens[CURRENT_ID] != history[CURRENT_ID] || last_pm != pm ) { info->uc.reload_hint[HINT_ENTRY] = 1; info->uc.reload_hint[HINT_CHAIN] = 1; info->uc.reload_hint[HINT_MACRO] = 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 ); timeline_clear_points( info->tl ); } if( pm == MODE_SAMPLE ) { info->selection[0] = info->status_tokens[SAMPLE_MARKER_START]; info->selection[1] = info->status_tokens[SAMPLE_MARKER_END]; gtk_spin_button_set_value( GTK_SPIN_BUTTON( widget_cache[WIDGET_BUTTON_EL_SELSTART] ), (gdouble) info->selection[0]); gtk_spin_button_set_value( GTK_SPIN_BUTTON( widget_cache[WIDGET_BUTTON_EL_SELEND ] ), (gdouble) info->selection[1]); } if( pm == MODE_STREAM ) { info->selection[0] = 0; info->selection[1] = total_frames_; } select_slot( info->status_tokens[PLAY_MODE] ); } if( info->status_tokens[TOTAL_SLOTS] != history[TOTAL_SLOTS] && samplebank_ready_) { int n_samples = 0; int n_streams = 0; if( pm == MODE_PLAIN || pm == MODE_SAMPLE ) { n_samples = info->status_tokens[SAMPLE_COUNT]; n_streams = info->status_tokens[SAMPLE_INV_COUNT]; } else { n_streams = info->status_tokens[SAMPLE_COUNT]; n_samples = info->status_tokens[SAMPLE_INV_COUNT]; } if( ( (info->uc.real_num_samples > 0 && n_samples > info->uc.real_num_samples ) || (info->uc.real_num_streams > 0 && n_streams > info->uc.real_num_streams)) ) { info->uc.reload_hint[HINT_SLIST] = 1; } else { info->uc.reload_hint[HINT_SLIST] = 2; } info->uc.real_num_samples = n_samples; info->uc.real_num_streams = n_streams; } if( info->status_tokens[SAMPLE_LOOP_STAT_STOP] != history[SAMPLE_LOOP_STAT_STOP] ) { update_label_i2( widget_cache[WIDGET_LABEL_LOOP_STAT_STOP], info->status_tokens[SAMPLE_LOOP_STAT_STOP],0); if( pm == MODE_SAMPLE ) gtk_spin_button_set_value( GTK_SPIN_BUTTON( widget_cache[ WIDGET_SAMPLE_LOOPSTOP ] ), (gdouble) info->status_tokens[SAMPLE_LOOP_STAT_STOP] ); if( pm == MODE_STREAM ) gtk_spin_button_set_value( GTK_SPIN_BUTTON( widget_cache[ WIDGET_STREAM_LOOPSTOP ] ), (gdouble) info->status_tokens[SAMPLE_LOOP_STAT_STOP] ); } if( info->status_tokens[SAMPLE_LOOP_STAT ] != history[SAMPLE_LOOP_STAT] ) { update_label_i2( widget_cache[ WIDGET_LABEL_LOOP_STATS ], info->status_tokens[SAMPLE_LOOP_STAT], 0); } if( info->status_tokens[SEQ_ACT] != history[SEQ_ACT] ) { info->uc.reload_hint[HINT_SEQ_ACT] = 1; } if( info->status_tokens[SEQ_CUR] != history[SEQ_CUR] && pm != MODE_PLAIN ) { int in = info->status_tokens[SEQ_CUR]; if( in < MAX_SEQUENCES ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(widget_cache[WIDGET_SEQACTIVE]), TRUE ); indicate_sequence( FALSE, info->sequencer_view->gui_slot[ info->sequence_playing ] ); info->sequence_playing = in; indicate_sequence( TRUE, info->sequencer_view->gui_slot[ info->sequence_playing ] ); } else { indicate_sequence( FALSE, info->sequencer_view->gui_slot[ info->sequence_playing ] ); gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(widget_cache[WIDGET_SEQACTIVE]), FALSE ); } } if( history[CURRENT_ID] != info->status_tokens[CURRENT_ID] ) { if(pm == MODE_SAMPLE || pm == MODE_STREAM) update_label_i2( widget_cache[ WIDGET_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_value2( widget_cache[WIDGET_SPEED_SLIDER], plainspeed, 0); if( plainspeed < 0 ) info->play_direction = -1; else info->play_direction = 1; if( plainspeed < 0 ) plainspeed *= -1; if( plainspeed == 0 ) { gtk_label_set_text( GTK_LABEL( widget_cache[WIDGET_PLAYHINT] ), "Paused" ); } else { gtk_label_set_text( GTK_LABEL( widget_cache[WIDGET_PLAYHINT] ), "Playing" ); } } } if( pm == MODE_STREAM ) { if( info->status_tokens[STREAM_TYPE] == STREAM_VIDEO4LINUX ) { if(info->uc.cali_duration > 0 ) { GtkWidget *tb = widget_cache[WIDGET_CALI_TAKE_BUTTON]; info->uc.cali_duration--; vj_msg(VEEJAY_MSG_INFO, "Calibrate step %d of %d", info->uc.cali_duration, info->uc.cali_stage); if(info->uc.cali_duration == 0) { info->uc.cali_stage ++; //@ cali_stage = 1, done capturing black frames switch(info->uc.cali_stage) { case 1: //@ capturing black frames gtk_label_set_text( GTK_LABEL( widget_cache[WIDGET_CURRENT_STEP_LABEL] ), "Please take an image of a uniformly lit area in placed in front of your lens."); gtk_button_set_label( GTK_BUTTON(tb), "Take White Frames"); break; case 2: case 3: gtk_label_set_text( GTK_LABEL( widget_cache[WIDGET_CURRENT_STEP_LABEL] ), "Image calibrated. You may need to adjust brightness."); if(!gtk_widget_is_sensitive(widget_cache[ WIDGET_CALI_SAVE_BUTTON ] )) gtk_widget_set_sensitive(widget_cache[ WIDGET_CALI_SAVE_BUTTON ], TRUE); break; default: gtk_label_set_text( GTK_LABEL( widget_cache[WIDGET_CURRENT_STEP_LABEL] ), "Image calibrated. You may need to adjust brightness."); gtk_button_set_label( GTK_BUTTON(tb), "Take Black Frames"); veejay_msg(VEEJAY_MSG_ERROR, "Warning, mem leak if not reset first."); break; } if(info->uc.cali_stage >= 2 ) { info->uc.cali_stage = 0; } } } } } update_current_slot(history, pm, last_pm); } static void disable_fx_entry() { int i; gint min=0,max=1,value=0; if(gtk_widget_is_sensitive( widget_cache[WIDGET_FRAME_FXTREE2 ] ) ) { gtk_widget_set_sensitive_( widget_cache[WIDGET_FRAME_FXTREE2 ] , FALSE ); } gtk_label_set_text( GTK_LABEL( widget_cache[WIDGET_LABEL_EFFECTNAME] ), ""); gtk_label_set_text( GTK_LABEL( widget_cache[WIDGET_LABEL_EFFECTANIM_NAME] ), ""); gtk_label_set_text( GTK_LABEL( widget_cache[WIDGET_VALUE_FRIENDLYNAME ] ), FX_PARAMETER_VALUE_DEFAULT_HINT ); if( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON( widget_cache[WIDGET_BUTTON_ENTRY_TOGGLE] ) )) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( widget_cache[WIDGET_BUTTON_ENTRY_TOGGLE] ), FALSE ); } if( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON( widget_cache[WIDGET_SUBRENDER_ENTRY_TOGGLE] ) )) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( widget_cache[WIDGET_SUBRENDER_ENTRY_TOGGLE] ), FALSE); } if( (int) gtk_spin_button_get_value( GTK_SPIN_BUTTON( widget_cache[WIDGET_TRANSITION_LOOP] ) ) != 0 ) { gtk_spin_button_set_value( GTK_SPIN_BUTTON( widget_cache[WIDGET_TRANSITION_LOOP] ), (gdouble) 0); } if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( widget_cache[WIDGET_TRANSITION_ENABLED] ) ) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( widget_cache[WIDGET_TRANSITION_ENABLED] ), FALSE ); } for( i = WIDGET_FX_M1; i <= WIDGET_FX_M4; i ++ ) { if( gtk_widget_is_sensitive(widget_cache[i]) ) { gtk_widget_set_sensitive_(widget_cache[i], FALSE); } } GtkWidget *kf_param = widget_cache[ WIDGET_COMBO_CURVE_FX_PARAM ]; gtk_combo_box_text_remove_all(GTK_COMBO_BOX_TEXT(kf_param)); for( i = 0; i < MAX_UI_PARAMETERS; i ++ ) { update_slider_range2( widget_cache[WIDGET_SLIDER_P0 + i], min,max, value, 0 ); gtk_widget_set_sensitive_( widget_cache[WIDGET_SLIDER_BOX_P0 + i], FALSE ); gtk_widget_set_tooltip_text( widget_cache[WIDGET_SLIDER_P0 + i], "" ); gtk_label_set_text(GTK_LABEL(widget_cache[WIDGET_LABEL_P0 +i ]), ""); if( faster_ui_ ) gtk_widget_hide( widget_cache[WIDGET_FRAME_P0 + i]); } } static void enable_fx_entry() { int *entry_tokens = &(info->uc.entry_tokens[0]); int i; if(!gtk_widget_is_sensitive( widget_cache[ WIDGET_FRAME_FXTREE2 ] )) { gtk_widget_set_sensitive( widget_cache[ WIDGET_FRAME_FXTREE2 ] ,TRUE ); } char *fx_name = _effect_get_description( entry_tokens[ENTRY_FXID] ); gtk_label_set_text( GTK_LABEL( widget_cache[WIDGET_LABEL_EFFECTNAME] ),fx_name ); gtk_label_set_text( GTK_LABEL( widget_cache[WIDGET_LABEL_EFFECTANIM_NAME] ), fx_name ); if( entry_tokens[ENTRY_VIDEO_ENABLED] != gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget_cache[WIDGET_BUTTON_ENTRY_TOGGLE])) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(widget_cache[WIDGET_BUTTON_ENTRY_TOGGLE]), entry_tokens[ENTRY_VIDEO_ENABLED]); } if( entry_tokens[ENTRY_SUBRENDER_ENTRY] != gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget_cache[WIDGET_SUBRENDER_ENTRY_TOGGLE])) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(widget_cache[WIDGET_SUBRENDER_ENTRY_TOGGLE]), entry_tokens[ENTRY_SUBRENDER_ENTRY]); } if( (int) gtk_spin_button_get_value( GTK_SPIN_BUTTON(widget_cache[WIDGET_BUTTON_FX_ENTRY])) != info->uc.selected_chain_entry ) { gtk_spin_button_set_value( GTK_SPIN_BUTTON(widget_cache[WIDGET_BUTTON_FX_ENTRY]), info->uc.selected_chain_entry ); } if( (int) gtk_spin_button_get_value( GTK_SPIN_BUTTON(widget_cache[WIDGET_TRANSITION_LOOP])) != entry_tokens[ENTRY_TRANSITION_LOOP] ) { gtk_spin_button_set_value( GTK_SPIN_BUTTON(widget_cache[WIDGET_TRANSITION_LOOP]), entry_tokens[ENTRY_TRANSITION_LOOP] ); } if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(widget_cache[WIDGET_TRANSITION_ENABLED]) ) != entry_tokens[ENTRY_TRANSITION_ENABLED]) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(widget_cache[WIDGET_TRANSITION_ENABLED]), entry_tokens[ENTRY_TRANSITION_ENABLED]); } for( i = WIDGET_FX_M1; i <= WIDGET_FX_M4; i ++ ) { if( !gtk_widget_is_sensitive(widget_cache[i]) ) { gtk_widget_set_sensitive_(widget_cache[i], TRUE); } } if( _effect_get_mix( entry_tokens[ENTRY_FXID] ) ) { if(!gtk_widget_is_sensitive(widget_cache[WIDGET_TRANSITION_ENABLED])) gtk_widget_set_sensitive_(widget_cache[WIDGET_TRANSITION_ENABLED], TRUE); if(!gtk_widget_is_sensitive(widget_cache[WIDGET_TRANSITION_LOOP])) gtk_widget_set_sensitive_(widget_cache[WIDGET_TRANSITION_LOOP], TRUE); if(!gtk_widget_is_sensitive(widget_cache[WIDGET_SUBRENDER_ENTRY_TOGGLE])) gtk_widget_set_sensitive_(widget_cache[WIDGET_SUBRENDER_ENTRY_TOGGLE], TRUE ); } else { if( gtk_widget_is_sensitive(widget_cache[WIDGET_FX_M4])) gtk_widget_set_sensitive_(widget_cache[WIDGET_FX_M4], FALSE ); if( gtk_widget_is_sensitive(widget_cache[WIDGET_FX_M3])) gtk_widget_set_sensitive_(widget_cache[WIDGET_FX_M3], FALSE ); if( gtk_widget_is_sensitive(widget_cache[WIDGET_TRANSITION_LOOP])) gtk_widget_set_sensitive_(widget_cache[WIDGET_TRANSITION_LOOP], FALSE ); if( gtk_widget_is_sensitive(widget_cache[WIDGET_TRANSITION_ENABLED])) gtk_widget_set_sensitive_(widget_cache[WIDGET_TRANSITION_ENABLED], FALSE ); if( gtk_widget_is_sensitive(widget_cache[WIDGET_SUBRENDER_ENTRY_TOGGLE])) gtk_widget_set_sensitive_(widget_cache[WIDGET_SUBRENDER_ENTRY_TOGGLE], FALSE ); } GtkWidget *kf_param = widget_cache[ WIDGET_COMBO_CURVE_FX_PARAM ]; gtk_combo_box_text_remove_all(GTK_COMBO_BOX_TEXT(kf_param)); //~ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(kf_param), FX_PARAMETER_DEFAULT_NAME); //~ gtk_combo_box_set_active (GTK_COMBO_BOX(kf_param),0); int np = _effect_get_np( entry_tokens[ENTRY_FXID] ); gint min,max,value; char kf_param_text[20]; for( i = 0; i < np ; i ++ ) { if(!gtk_widget_is_sensitive(widget_cache[WIDGET_SLIDER_BOX_P0 + i])) gtk_widget_set_sensitive_(widget_cache[WIDGET_SLIDER_BOX_P0 + i], TRUE ); if( faster_ui_ ){ gtk_widget_show(widget_cache[WIDGET_FRAME_P0 + i]); } gchar *tt1 = _effect_get_param_description(entry_tokens[ENTRY_FXID],i); gtk_widget_set_tooltip_text( widget_cache[WIDGET_SLIDER_P0 + i], tt1 ); gtk_label_set_text( GTK_LABEL( widget_cache[WIDGET_LABEL_P0 + i ] ), tt1 ); if (tt1 != NULL && tt1[0] != '\0' ) { gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(kf_param), tt1); } else { //Fall back if parameter name is missing snprintf(kf_param_text,sizeof(kf_param_text), "p%d",i); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(kf_param), kf_param_text); } /* WARNING : conditional loop break. Do not add code after this statement. */ value = entry_tokens[ENTRY_PARAMSET + i]; if( _effect_get_minmax( entry_tokens[ENTRY_FXID], &min,&max, i )) { GtkAdjustment *a = gtk_range_get_adjustment( GTK_RANGE( widget_cache[WIDGET_SLIDER_P0 + i] )); if( (gint) gtk_adjustment_get_lower(a) == min && (gint) gtk_adjustment_get_upper(a) == max && (gint) gtk_adjustment_get_value(a) == value ) continue; update_slider_range2( widget_cache[WIDGET_SLIDER_P0 + i],min,max, value, 0); } } if (np){ guint signal_id=g_signal_lookup("changed", GTK_TYPE_COMBO_BOX); gulong handler_id=handler_id=g_signal_handler_find( (gpointer)kf_param, G_SIGNAL_MATCH_ID, signal_id, 0, NULL, NULL, NULL ); if (handler_id){ g_signal_handler_block((gpointer)kf_param, handler_id); } gtk_combo_box_set_active (GTK_COMBO_BOX(kf_param),0); if (handler_id) g_signal_handler_unblock((gpointer)kf_param, handler_id); } min = 0; max = 1; value = 0; for( i = np; i < MAX_UI_PARAMETERS; i ++ ) { if( !gtk_widget_is_sensitive(widget_cache[WIDGET_SLIDER_P0 + i]) ) continue; update_slider_range2( widget_cache[WIDGET_SLIDER_P0 + i ],min,max, value, 0 ); gtk_widget_set_sensitive(widget_cache[ WIDGET_SLIDER_BOX_P0 + i ], FALSE ); if( faster_ui_ ) gtk_widget_hide( widget_cache[ WIDGET_FRAME_P0 + i ] ); gtk_widget_set_tooltip_text( widget_cache[ WIDGET_SLIDER_P0 + i ], "" ); gtk_label_set_text(GTK_LABEL (widget_cache[WIDGET_LABEL_P0 + i]), ""); } } static void process_reload_hints(int *history, int pm) { int *entry_tokens = &(info->uc.entry_tokens[0]); int md = info->uc.reload_hint[HINT_MACRODELAY]; if( md ) { md = md - 1; if( md <= 0 ) { multi_vims( VIMS_MACRO, "%d", 1 ); info->uc.reload_hint[HINT_MACRO] = 1; vj_msg(VEEJAY_MSG_INFO, "Started macro record"); } } if( pm == MODE_STREAM ) { if(info->uc.reload_hint[HINT_V4L]) load_v4l_info(); if( info->uc.reload_hint[HINT_RGBSOLID]) update_colorselection(); } if( info->uc.reload_hint[HINT_EL] ) { load_editlist_info(); reload_editlist_contents(); } if( info->uc.reload_hint[HINT_SLIST] ) { gboolean reload_sl = FALSE; if( info->uc.reload_hint[HINT_SLIST] == 2 ) { info->uc.expected_num_samples = -1; info->uc.expected_num_streams = -1; reload_sl = TRUE; } load_samplelist_info( reload_sl ); } if( info->uc.reload_hint[HINT_SEQ_ACT] == 1 ) { load_sequence_list(); } 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 ) { if( history[SAMPLE_FX] != info->status_tokens[SAMPLE_FX]) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(widget_cache[WIDGET_CURVE_CHAIN_TOGGLECHAIN]), info->status_tokens[SAMPLE_FX] ); //also for stream (index is equivalent) if(pm == MODE_SAMPLE) gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(widget_cache[WIDGET_CHECK_SAMPLEFX]), info->status_tokens[SAMPLE_FX] ); if(pm == MODE_STREAM) gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(widget_cache[WIDGET_CHECK_STREAMFX]), info->status_tokens[SAMPLE_FX] ); } } if( info->uc.reload_hint[HINT_CHAIN] == 1) { load_effectchain_info(); } info->parameter_lock = 1; if(info->uc.reload_hint[HINT_ENTRY] == 1) { int lpi = load_parameter_info(); if( lpi == 0 ) { if( entry_tokens[ENTRY_FXID] == 0 && gtk_widget_is_sensitive(widget_cache[WIDGET_FRAME_FXTREE2])) { disable_fx_entry(); info->uc.reload_hint[HINT_KF] = 1; } } else if (lpi == 1 ) { if (entry_tokens[ENTRY_FXID] != 0 ) { enable_fx_entry(); info->uc.reload_hint[HINT_KF] = 1; } } } info->parameter_lock = 0; if( info->uc.reload_hint[HINT_GENERATOR]) { load_generator_info(); } if ( info->uc.reload_hint[HINT_KF]) { info->uc.reload_hint_checksums[HINT_KF] = -1; vj_kf_refresh(FALSE); } if( beta__ && info->uc.reload_hint[HINT_HISTORY]) { reload_srt(); } if( info->uc.reload_hint[HINT_MACRO]) { reload_macros(); } memset( info->uc.reload_hint, 0, sizeof(info->uc.reload_hint )); if( md > 0 ) { info->uc.reload_hint[HINT_MACRODELAY] = md; } /*if(!samplebank_ready_) { info->uc.reload_hint[HINT_SLIST] = 2; }*/ } void update_gui() { int pm = info->status_tokens[PLAY_MODE]; int last_pm = info->prev_mode; int *history = NULL; if( last_pm < 0 ) history = info->history_tokens[0]; else history = info->history_tokens[ last_pm ]; if( info->uc.randplayer && pm != last_pm ) { info->uc.randplayer = 0; gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( widget_cache[WIDGET_SAMPLERAND] ), FALSE ); } if( pm == MODE_PATTERN && last_pm != pm) { if(!info->uc.randplayer ) { info->uc.randplayer = 1; gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( widget_cache[WIDGET_SAMPLERAND] ), TRUE ); } info->status_tokens[PLAY_MODE] = MODE_SAMPLE; pm = MODE_SAMPLE; } update_globalinfo(history, pm, last_pm); // #include // CALLGRIND_START_INSTRUMENTATION; // CALLGRIND_TOGGLE_COLLECT; process_reload_hints(history, pm); // CALLGRIND_TOGGLE_COLLECT; // CALLGRIND_STOP_INSTRUMENTATION; // CALLGRIND_DUMP_STATS; on_vims_messenger(); update_cpumeter_timeout(NULL); update_cachemeter_timeout(NULL); } void vj_gui_free() { if(info) { int i; if(info->client) vj_client_free(info->client); for( i = 0; i < 4; i ++ ) { if(info->history_tokens[i]) free(info->history_tokens[i]); } free(info); } info = NULL; vpf( fx_list_ ); vpf( bankport_ ); } void vj_gui_style_setup() { if(!info) return; info->color_map = gdk_screen_get_system_visual (gdk_screen_get_default ()); } void vj_gui_set_debug_level(int level, int n_tracks, int pw, int ph ) { veejay_set_debug_level( level ); vims_verbosity = level; if( !mt_set_max_tracks(n_tracks) ) { mt_set_max_tracks(5); } } int vj_gui_get_preview_priority(void) { return 1; } void default_bank_values(int *col, int *row ) { int nsc = SAMPLEBANK_COLUMNS; int nsy = SAMPLEBANK_ROWS; if( *col == 0 && *row == 0 ) { SAMPLEBANK_COLUMNS = nsc; SAMPLEBANK_ROWS = nsy; } else { SAMPLEBANK_ROWS = *row; SAMPLEBANK_COLUMNS = *col; } NUM_SAMPLES_PER_PAGE = SAMPLEBANK_COLUMNS * SAMPLEBANK_ROWS; NUM_BANKS = (4096 / NUM_SAMPLES_PER_PAGE ); veejay_msg(VEEJAY_MSG_INFO, "Sample bank layout is %d rows by %d columns", SAMPLEBANK_ROWS,SAMPLEBANK_COLUMNS ); } int vj_gui_sleep_time( void ) { float f = (float) info->status_tokens[ELAPSED_TIME]; float t = info->el.fps; if( t <= 0.0 || t>= 200.0 ) t = 25.0; float n = (1.0 / t) * 1000.0f; if( f < n ) return (int)( n - f ); return (int) n; } int vj_img_cb(GdkPixbuf *img ) { int i; if( !info->selected_slot || !info->selected_gui_slot || info->status_tokens[PLAY_MODE] == MODE_PLAIN) { return 0; } int sample_id = info->status_tokens[ CURRENT_ID ]; int sample_type = info->status_tokens[ PLAY_MODE ]; if( info->selected_slot->sample_type != sample_type || info->selected_slot->sample_id != sample_id ) { return 0; } if( sample_type == MODE_SAMPLE || sample_type == MODE_STREAM ) { sample_slot_t *slot = find_slot_by_sample( sample_id, sample_type ); sample_gui_slot_t *gui_slot = find_gui_slot_by_sample( sample_id, sample_type ); if( slot && gui_slot ) { slot->pixbuf = vj_gdk_pixbuf_scale_simple(img, info->image_dimensions[0],info->image_dimensions[1], GDK_INTERP_NEAREST); if(slot->pixbuf) { gtk_image_set_from_pixbuf_( GTK_IMAGE( gui_slot->image ), slot->pixbuf ); g_object_unref( slot->pixbuf ); slot->pixbuf = NULL; } } } for( i = 0; i < info->sequence_view->envelope_size; i ++ ) { sequence_gui_slot_t *g = info->sequence_view->gui_slot[i]; if(g->sample_id == info->selected_slot->sample_id && g->sample_type == info->selected_slot->sample_type) { g->pixbuf_ref = vj_gdk_pixbuf_scale_simple(img, info->sequence_view->w, info->sequence_view->h, GDK_INTERP_NEAREST ); if( g->pixbuf_ref) { gtk_image_set_from_pixbuf_( GTK_IMAGE( g->image ), g->pixbuf_ref ); g_object_unref( g->pixbuf_ref ); g->pixbuf_ref = NULL; } } } return 1; } void vj_gui_cb(int state, char *hostname, int port_num) { info->watch.state = STATE_RECONNECT; put_text( "entry_hostname", hostname ); update_spin_value( "button_portnum", port_num ); //@ clear status int i; for( i = 0; i < 4; i ++ ) { int *h = info->history_tokens[i]; veejay_memset( h, 0, sizeof(int) * STATUS_TOKENS ); } } static void reloaded_sighandler(int x) { veejay_msg(VEEJAY_MSG_WARNING, "Caught signal %x", x); if( x == SIGPIPE ) { reloaded_schedule_restart(); } else if ( x == SIGINT || x == SIGABRT ) { veejay_msg(VEEJAY_MSG_WARNING, "Stopping reloaded"); exit(0); } else if ( x == SIGSEGV ) { veejay_msg(VEEJAY_MSG_ERROR, "Found Gremlins in your system."); veejay_msg(VEEJAY_MSG_WARNING, "No fresh ale found in the fridge."); veejay_msg(VEEJAY_MSG_INFO, "Running with sub-atomic precision..."); veejay_msg(VEEJAY_MSG_ERROR, "Bugs compromised the system."); exit(0); } } static void veejay_backtrace_handler(int n , siginfo_t *si, void *ptr) { switch(n) { case SIGSEGV: veejay_msg(VEEJAY_MSG_ERROR,"Found Gremlins in your system."); //@ Suggested by Matthijs veejay_msg(VEEJAY_MSG_WARNING, "No fresh ale found in the fridge."); //@ veejay_msg(VEEJAY_MSG_INFO, "Running with sub-atomic precision..."); //@ veejay_print_backtrace(); break; default: veejay_print_backtrace(); break; } //@ Bye veejay_msg(VEEJAY_MSG_ERROR, "Bugs compromised the system."); exit(EX_SOFTWARE); } static void sigsegfault_handler(void) { struct sigaction sigst; sigst.sa_sigaction = veejay_backtrace_handler; sigemptyset(&sigst.sa_mask); sigaddset(&sigst.sa_mask, SIGSEGV ); sigst.sa_flags = SA_SIGINFO | SA_ONESHOT; if( sigaction(SIGSEGV, &sigst, NULL) == - 1 ) veejay_msg(VEEJAY_MSG_ERROR,"%s", strerror(errno)); } void register_signals() { signal( SIGINT, reloaded_sighandler ); signal( SIGPIPE, reloaded_sighandler ); signal( SIGQUIT, reloaded_sighandler ); // signal( SIGSEGV, reloaded_sighandler ); signal( SIGABRT, reloaded_sighandler ); sigsegfault_handler(); } void vj_gui_wipe() { int i; veejay_memset( info->status_tokens, 0, sizeof(int) * STATUS_TOKENS ); veejay_memset( info->uc.entry_tokens,0, sizeof(int) * ENTRY_LAST); for( i = 0 ; i < 4; i ++ ) { veejay_memset(info->history_tokens[i],0, sizeof(int) * (STATUS_TOKENS+1)); } reset_samplebank(); } GtkWidget *new_bank_pad(GtkWidget *box) { GtkWidget *pad = gtk_notebook_new(); gtk_notebook_set_tab_pos( GTK_NOTEBOOK(pad), GTK_POS_BOTTOM ); gtk_notebook_set_show_tabs( GTK_NOTEBOOK(pad ), FALSE ); gtk_box_pack_start (GTK_BOX (box), GTK_WIDGET(pad), TRUE, TRUE, 0); return pad; } gboolean slider_scroll_event( GtkWidget *widget, GdkEventScroll *ev, gpointer user_data) { gint i = GPOINTER_TO_INT(user_data); if(ev->direction == GDK_SCROLL_UP ) { PARAM_CHANGED( i, 1, slider_names_[i].text ); } else if (ev->direction == GDK_SCROLL_DOWN ) { PARAM_CHANGED( i, -1, slider_names_[i].text ); } return FALSE; } gboolean speed_scroll_event( GtkWidget *widget, GdkEventScroll *ev, gpointer user_data) { int plainspeed = info->status_tokens[SAMPLE_SPEED]; if(ev->direction == GDK_SCROLL_UP ) { plainspeed = plainspeed + 1; } else if (ev->direction == GDK_SCROLL_DOWN ) { plainspeed = plainspeed - 1; } update_slider_value( "speed_slider", plainspeed, 0 ); return FALSE; } gboolean slow_scroll_event( GtkWidget *widget, GdkEventScroll *ev, gpointer user_data) { int plainspeed = get_slider_val("slow_slider"); if(ev->direction == GDK_SCROLL_DOWN ) { plainspeed = plainspeed - 1; } else if (ev->direction == GDK_SCROLL_UP ) { plainspeed = plainspeed + 1; } if(plainspeed < 1 ) plainspeed = 1; update_slider_value("slow_slider",plainspeed,0); vj_msg(VEEJAY_MSG_INFO, "Slow video to %2.2f fps", info->el.fps / (float) plainspeed ); return FALSE; } void vj_gui_set_geom( int x, int y ) { geo_pos_[0] = x; geo_pos_[1] = y; } void vj_event_list_free() { int i; for( i = 0; i < VIMS_MAX; i ++ ) { if( vj_event_list[i].format ) free(vj_event_list[i].format); if( vj_event_list[i].descr ) free(vj_event_list[i].descr); if( vj_event_list[i].args ) free(vj_event_list[i].args); } veejay_memset( vj_event_list, 0, sizeof(vj_event_list)); } char reloaded_css_file[1024]; int use_css_file = 0; gboolean smallest_possible = FALSE; void vj_gui_set_stylesheet(const char *css_file, gboolean small_as_possible) { smallest_possible = small_as_possible; if( css_file == NULL ) { veejay_msg(VEEJAY_MSG_DEBUG,"Using system's default style"); use_css_file = 0; return; } if(strlen(css_file)==7) { if(strncasecmp(css_file, "default",7) == 0 ) { veejay_msg(VEEJAY_MSG_DEBUG, "Using reloaded's default style"); snprintf( reloaded_css_file, sizeof(reloaded_css_file), "%s/%s", RELOADED_DATADIR, "gveejay.reloaded.css"); use_css_file = 1; return; } } veejay_msg(VEEJAY_MSG_DEBUG, "Using CSS %s", reloaded_css_file); snprintf( reloaded_css_file, sizeof(reloaded_css_file), "%s", css_file); use_css_file = 1; } void vj_gui_activate_stylesheet(vj_gui_t *gui) { GtkCssProvider *css = gtk_css_provider_new(); gtk_style_context_add_provider_for_screen ( gdk_screen_get_default (),GTK_STYLE_PROVIDER (css),GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); if(use_css_file) { GError* error = NULL; veejay_msg(VEEJAY_MSG_DEBUG, "Loading stylesheet %s", reloaded_css_file); if(!gtk_css_provider_load_from_path(css, reloaded_css_file, &error)) { veejay_msg(VEEJAY_MSG_WARNING, "Could not load CSS file: %s , %s", error->message, reloaded_css_file); g_error_free (error); } GtkStyleContext *sc = gtk_widget_get_style_context( GTK_WIDGET(gui->curve) ); GdkRGBA bg,col,border; GtkStateFlags context_state = gtk_style_context_get_state(sc); vj_gtk_context_get_color(sc, "background-color", context_state, &bg); vj_gtk_context_get_color(sc, "border-color", context_state, &border); gtk_style_context_get_color(sc, context_state, &col ); gtk3_curve_set_color_background_rgba (GTK_WIDGET(gui->curve), bg.red, bg.green, bg.blue, 1.0); gtk3_curve_set_color_curve_rgba (GTK_WIDGET(gui->curve), col.red, col.green, col.blue, 1.0); gtk3_curve_set_color_grid_rgba (GTK_WIDGET(gui->curve), col.red, col.green, col.blue, 0.33); gtk3_curve_set_color_cpoint_rgba (GTK_WIDGET(gui->curve), border.red, border.green, border.blue, 1.0); } else { gtk3_curve_set_color_background_rgba (GTK_WIDGET(gui->curve), 1.0f,1.0f,1.0f, 1.0); gtk3_curve_set_color_curve_rgba (GTK_WIDGET(gui->curve), 0.0f, 0.0f, 0.0f, 1.0); gtk3_curve_set_color_grid_rgba (GTK_WIDGET(gui->curve), 0.0f, 0.0f, 0.0f, 0.33); gtk3_curve_set_color_cpoint_rgba (GTK_WIDGET(gui->curve), 0.0f, 0.0f, 0.0f, 1.0); } #if (GTK_MINOR_VERSION >= 20) gchar *css_in_mem = gtk_css_provider_to_string(css); gchar *data = NULL; if( smallest_possible ) { data = g_strconcat(css_in_mem, "\n* { font-size:98%; }\nframe,box,scale,spinbutton,button,radiobutton,checkbutton,entry, .vertical { padding-left:0px; padding-right: 0px }\nbutton,checkbutton,radiobutton,spinbutton { padding-top:1px; padding-bottom:1px;}\n", NULL ); } else { data = g_strconcat(css_in_mem, "\n* { font-size:98%; }", NULL); } gtk_css_provider_load_from_data(css, data,-1, NULL); g_clear_object(&css); g_free(css_in_mem); g_free(data); #endif } static int auto_connect_to_veejay(char *host, int port_num) { char *hostname = (host == NULL ? "localhost" : host ); int i,j; for( i = port_num; i < 9999; i += 1000 ) { //connect client at first available server if( vj_gui_reconnect( hostname, NULL, i ) ) { info->watch.state = STATE_PLAYING; veejay_msg(VEEJAY_MSG_INFO,"Trying to connect to %s:%d", hostname, i); multrack_audoadd( info->mt, hostname, i); multitrack_set_master_track( info->mt, 0 ); // set reconnect info update_spin_value( "button_portnum", i ); put_text( "entry_hostname", hostname ); // setup tracks for( j = (i+1000); j < 9999; j+= 1000 ) { veejay_msg(VEEJAY_MSG_INFO, "Trying to add %s:%d as a track", hostname, j); multrack_audoadd( info->mt, hostname, j); } multitrack_set_quality( info->mt, 1 ); i = j; return 1; } } update_spin_value( "button_portnum", port_num ); put_text( "entry_hostname", hostname ); return 0; } void vj_gui_init(const char *glade_file, int launcher, char *hostname, int port_num, int use_threads, int load_midi, char *midi_file, gboolean beta, gboolean auto_connect, gboolean fasterui) { int i; char text[100]; faster_ui_ = fasterui; vj_gui_t *gui = (vj_gui_t*)vj_calloc(sizeof(vj_gui_t)); if(!gui) { return; } snprintf( glade_path, sizeof(glade_path), "%s/%s",RELOADED_DATADIR,glade_file); veejay_msg(VEEJAY_MSG_DEBUG, "Loading glade file %s", glade_path); veejay_memset( gui->status_tokens, 0, sizeof(int) * STATUS_TOKENS ); veejay_memset( gui->sample, 0, 2 ); veejay_memset( gui->selection, 0, 3 ); veejay_memset( &(gui->uc), 0, sizeof(veejay_user_ctrl_t)); gui->uc.selected_parameter_id = -1; veejay_memset( gui->uc.entry_tokens,0, sizeof(int) * ENTRY_LAST); gui->prev_mode = -1; veejay_memset( &(gui->el), 0, sizeof(veejay_el_t)); gui->sample_banks = (sample_bank_t**) vj_calloc(sizeof(sample_bank_t*) * NUM_BANKS ); for( i = 0 ; i < 4; i ++ ) { gui->history_tokens[i] = (int*) vj_calloc(sizeof(int) * (STATUS_TOKENS+1)); } for( i = 0; i < NUM_HINTS ; i ++ ) { gui->uc.reload_hint_checksums[i] = -1; } slider_names_ = (widget_name_t*) vj_calloc(sizeof(widget_name_t) * MAX_UI_PARAMETERS ); slider_box_names_ = (widget_name_t*) vj_calloc(sizeof(widget_name_t) * MAX_UI_PARAMETERS ); param_frame_ = (widget_name_t*) vj_calloc(sizeof(widget_name_t) * MAX_UI_PARAMETERS ); param_names_ = (widget_name_t*) vj_calloc(sizeof(widget_name_t) * MAX_UI_PARAMETERS ); param_incs_ = (widget_name_t*) vj_calloc(sizeof(widget_name_t) * MAX_UI_PARAMETERS ); param_decs_ = (widget_name_t*) vj_calloc(sizeof(widget_name_t) * MAX_UI_PARAMETERS ); gen_decs_ = (widget_name_t*) vj_calloc(sizeof(widget_name_t) * GENERATOR_PARAMS ); gen_incs_ = (widget_name_t*) vj_calloc(sizeof(widget_name_t) * GENERATOR_PARAMS ); gen_names_ = (widget_name_t*) vj_calloc(sizeof(widget_name_t) * GENERATOR_PARAMS ); for( i = 0; i < MAX_UI_PARAMETERS; i ++ ) { snprintf(text,sizeof(text), "frame_p%d", i ); param_frame_[i].text = strdup( text ); snprintf(text,sizeof(text),"slider_p%d" , i ); slider_names_[i].text = strdup( text ); snprintf(text,sizeof(text),"slider_box_p%d" , i ); slider_box_names_[i].text = strdup( text ); snprintf(text,sizeof(text),"label_p%d" , i ); param_names_[i].text = strdup( text ); snprintf(text,sizeof(text),"inc_p%d", i ); param_incs_[i].text = strdup( text ); snprintf(text,sizeof(text), "dec_p%d", i ); param_decs_[i].text = strdup( text ); } for( i = 0; i < GENERATOR_PARAMS; i ++ ) { snprintf(text,sizeof(text), "slider_g%d",i); gen_names_[i].text = strdup( text ); snprintf(text,sizeof(text), "dec_g%d", i); gen_decs_[i].text = strdup(text); snprintf(text,sizeof(text), "inc_g%d", i ); gen_incs_[i].text = strdup(text); } gui->uc.reload_force_avoid = FALSE; veejay_memset( vj_event_list, 0, sizeof(vj_event_list)); gui->client = NULL; GError* error = NULL; gui->main_window = gtk_builder_new (); if (!gtk_builder_add_from_file (gui->main_window, glade_path, &error)) { free(gui); free(gui->main_window); veejay_msg(VEEJAY_MSG_ERROR, "Couldn't load builder file: %s , %s", error->message, glade_path); g_error_free (error); return; } info = gui; for( i = 0; i < MAX_UI_PARAMETERS; i ++ ) { add_class_by_name( slider_names_[i].text, "p_slider" ); } add_class_by_name( "speed_slider", "h_slider" ); add_class_by_name( "slow_slider", "h_slider" ); add_class_by_name( "framerate", "h_slider" ); GtkWidget *mainw = glade_xml_get_widget_(info->main_window,"gveejay_window" ); init_widget_cache(); //set "connection" button has default in veejay connection dialog gtk_entry_set_activates_default(GTK_ENTRY(glade_xml_get_widget_( info->main_window, "entry_hostname" )), TRUE); gtk_entry_set_activates_default(GTK_ENTRY(glade_xml_get_widget_( info->main_window, "button_portnum" )), TRUE); GtkWidget *vj_button = glade_xml_get_widget_( info->main_window, "button_veejay" ); gtk_widget_set_can_default(vj_button,TRUE); GtkWidget *connection_dial = glade_xml_get_widget_( info->main_window, "veejay_connection"); gtk_window_set_transient_for (GTK_WINDOW(connection_dial),GTK_WINDOW (mainw)); gtk_window_set_default(GTK_WINDOW(connection_dial), vj_button); gtk_builder_connect_signals( gui->main_window , NULL); GtkWidget *frame = glade_xml_get_widget_( info->main_window, "markerframe" ); info->tl = timeline_new(); add_class(info->tl, "timeline"); set_tooltip_by_widget(info->tl, tooltips[TOOLTIP_TIMELINE].text ); 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 ); bankport_ = vpn( VEVO_ANONYMOUS_PORT ); gtk_container_add( GTK_CONTAINER(frame), info->tl ); gtk_widget_show_all(frame); #ifdef STRICT_CHECKING debug_spinboxes(); #endif snprintf(text, sizeof(text), "Reloaded - version %s",VERSION); gtk_label_set_text(GTK_LABEL(glade_xml_get_widget_(info->main_window, "build_revision")), text); g_signal_connect( mainw, "destroy", G_CALLBACK( gveejay_quit ), NULL ); g_signal_connect( mainw, "delete-event", G_CALLBACK( gveejay_quit ), NULL ); GtkWidget *box = glade_xml_get_widget_( info->main_window, "sample_bank_hbox" ); info->sample_bank_pad = new_bank_pad( box ); //QuickSelect slots create_ref_slots( QUICKSELECT_SLOTS ); //SEQ create_sequencer_slots( SEQUENCER_COL, SEQUENCER_ROW ); veejay_memset( vj_event_list, 0, sizeof( vj_event_list )); veejay_memset( vims_keys_list, 0, sizeof( vims_keys_list) ); info->elref = NULL; info->effect_info = (effect_constr**) vj_calloc(sizeof(effect_constr*) * EFFECT_LIST_SIZE ); info->devlist = NULL; info->chalist = NULL; info->editlist = NULL; setup_vimslist(); setup_effectchain_info(); setup_effectlist_info(); setup_editlist_info(); setup_samplelist_info(); setup_v4l_devices(); setup_macros(); setup_colorselection(); setup_rgbkey(); setup_bundles(); setup_server_files(); setup_generators(); text_defaults(); GtkWidget *fgb = glade_xml_get_widget_(info->main_window, "boxtext" ); GtkWidget *bgb = glade_xml_get_widget_(info->main_window, "boxbg" ); GtkWidget *rb = glade_xml_get_widget_(info->main_window, "boxred" ); GtkWidget *gb = glade_xml_get_widget_(info->main_window, "boxgreen" ); GtkWidget *bb = glade_xml_get_widget_(info->main_window, "boxblue" ); GtkWidget *lnb = glade_xml_get_widget_(info->main_window,"boxln" ); g_signal_connect(G_OBJECT( bgb ), "draw", G_CALLBACK( boxbg_draw ), NULL); g_signal_connect(G_OBJECT( fgb ), "draw", G_CALLBACK( boxfg_draw ), NULL); g_signal_connect(G_OBJECT( lnb ), "draw", G_CALLBACK( boxln_draw ), NULL); g_signal_connect(G_OBJECT( rb ), "draw", G_CALLBACK( boxred_draw ), NULL); g_signal_connect(G_OBJECT( gb ), "draw", G_CALLBACK( boxgreen_draw ), NULL); g_signal_connect(G_OBJECT( bb ), "draw", G_CALLBACK( boxblue_draw ), NULL); set_toggle_button( "button_252", vims_verbosity ); int pw = MAX_PREVIEW_WIDTH; int ph = MAX_PREVIEW_HEIGHT; GtkWidget *img_wid = widget_cache[WIDGET_IMAGEA]; gui->mt = multitrack_new((void(*)(int,char*,int)) vj_gui_cb, NULL, glade_xml_get_widget_( info->main_window, "gveejay_window" ), glade_xml_get_widget_( info->main_window, "mt_box" ), glade_xml_get_widget_( info->main_window, "statusbar") , glade_xml_get_widget_( info->main_window, "previewtoggle"), pw, ph, img_wid, (void*) gui, use_threads); GtkWidget *curve_container = widget_cache[ WIDGET_CURVECONTAINER ]; gui->curve = gtk3_curve_new (); add_class(gui->curve, "curve"); gtk_container_add(GTK_CONTAINER(curve_container), gui->curve); gtk_widget_show_all(curve_container); veejay_memset( &info->watch, 0, sizeof(watchdog_t)); info->watch.state = STATE_WAIT_FOR_USER; // vj_gui_activate_stylesheet(gui); veejay_memset(&(info->watch.p_time),0,sizeof(struct timeval)); info->midi = vj_midi_new( info->main_window ); if(!beta) // srt-titling sequence stuff { GtkWidget *srtpad = gtk_notebook_get_nth_page(GTK_NOTEBOOK( widget_cache[WIDGET_NOTEBOOK18]),4); gtk_widget_hide(srtpad); } beta__ = beta; update_spin_range( "spin_framedelay", 1, MAX_SLOW, 0); update_spin_range2( widget_cache[WIDGET_SPIN_SAMPLESPEED], -25,25,1); update_slider_range( "speed_slider", -25,25,1,0); update_slider_range( "slow_slider",1,MAX_SLOW,1,0); if( load_midi ) vj_midi_load(info->midi,midi_file); for( i = 0 ; i < MAX_UI_PARAMETERS; i ++ ) { GtkWidget *slider = glade_xml_get_widget_( info->main_window, slider_names_[i].text ); g_signal_connect( slider, "scroll-event", G_CALLBACK(slider_scroll_event), (gpointer) castIntToGpointer(i) ); update_slider_range( slider_names_[i].text, 0,1,0,0); } g_signal_connect(glade_xml_get_widget_(info->main_window, "speed_slider"), "scroll-event", G_CALLBACK(speed_scroll_event), NULL ); g_signal_connect(glade_xml_get_widget_(info->main_window, "slow_slider"), "scroll-event", G_CALLBACK(slow_scroll_event), NULL ); char *have_snoop = getenv( "RELOADED_KEY_SNOOP" ); if( have_snoop == NULL ) { veejay_msg(VEEJAY_MSG_DEBUG, "Use setenv RELOADED_KEY_SNOOP=1 to mirror veejay server keyb layout" ); }else { use_key_snoop = atoi(have_snoop); if( use_key_snoop < 0 || use_key_snoop > 1 ) use_key_snoop = 0; } vj_gui_style_setup(); GtkWidget *lw = glade_xml_get_widget_( info->main_window, "veejay_connection"); if( geo_pos_[0] >= 0 && geo_pos_[1] >= 0 ) gtk_window_move( GTK_WINDOW(lw), geo_pos_[0], geo_pos_[1] ); if( auto_connect ) { if(auto_connect_to_veejay(hostname, port_num)) { veejay_stop_connecting(gui); } } if(info->watch.state != STATE_PLAYING) { if(hostname) { put_text("entry_hostname",hostname); } update_spin_value( "button_portnum", port_num ); reloaded_show_launcher (); } if( user_preview ) { set_toggle_button( "previewtoggle", 1 ); } gtk_widget_show( info->sample_bank_pad ); } void vj_gui_preview(void) { gint w = 0; gint h = 0; gint tmp_w = info->el.width; gint tmp_h = info->el.height; multitrack_get_preview_dimensions( tmp_w,tmp_h, &w, &h ); update_spin_value( "priout_width", w ); update_spin_value( "priout_height", h ); update_spin_range( "preview_width", 16, w, w); update_spin_range( "preview_height", 16, 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->image_w = w; info->image_h = h; GdkRectangle result; widget_get_rect_in_screen( glade_xml_get_widget_(info->main_window, "quickselect"), &result ); gdouble ratio = (gdouble) h / (gdouble) w; gint image_width = 32; gint image_height = 32 *ratio; info->sequence_view->w = image_width; info->sequence_view->h = image_height; for( int i = 0; i < QUICKSELECT_SLOTS; i ++ ) { gtk_widget_set_size_request_( info->sequence_view->gui_slot[i]->image, info->sequence_view->w,info->sequence_view->h ); } } void gveejay_preview( int p ) { user_preview = p; } int gveejay_user_preview() { return user_preview; } int vj_gui_reconnect(char *hostname,char *group_name, int port_num) { int k = 0; for( k = 0; k < 4; k ++ ) veejay_memset( info->history_tokens[k] , 0, (sizeof(int) * STATUS_TOKENS) ); veejay_memset( info->status_tokens, 0, sizeof(int) * STATUS_TOKENS ); if(!hostname && !group_name ) { veejay_msg(VEEJAY_MSG_ERROR,"Invalid host/group name given"); return 0; } if(info->client ) { error_dialog("Warning", "You should disconnect first"); return 0; } if(!info->client) { info->client = vj_client_alloc(0,0,0); if(!info->client) { return 0; } } if(!vj_client_connect( info->client, hostname, group_name, port_num ) ) { if(info->client) vj_client_free(info->client); info->client = NULL; return 0; } vj_msg(VEEJAY_MSG_INFO, "New connection with Veejay running on %s port %d", (group_name == NULL ? hostname : group_name), port_num ); veejay_msg(VEEJAY_MSG_INFO, "Connection established with %s:%d (Track 0)", hostname,port_num); info->status_lock = 1; info->parameter_lock = 1; info->uc.expected_num_samples = -1; info->uc.expected_num_streams = -1; info->uc.selected_chain_entry = 0; single_vims( VIMS_PROMOTION ); load_editlist_info(); update_slider_value( "framerate", info->el.fps, 0 ); veejay_memset( vims_keys_list, 0 , sizeof(vims_keys_list)); veejay_memset( vj_event_list, 0, sizeof( vj_event_list)); load_effectlist_info(); reload_vimslist(); reload_editlist_contents(); reload_bundles(); set_feedback_status(); GtkWidget *w = glade_xml_get_widget_(info->main_window, "gveejay_window" ); gtk_widget_show( w ); if( geo_pos_[0] >= 0 && geo_pos_[1] >= 0 ) gtk_window_move(GTK_WINDOW(w), geo_pos_[0], geo_pos_[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_label_str( "label_hostnamex", (hostname == NULL ? group_name: hostname ) ); update_label_i( "label_portx",port_num,0); info->status_lock = 0; info->parameter_lock = 0; multitrack_configure(info->mt, info->el.fps, info->el.width, info->el.height, &preview_box_w_, &preview_box_h_ ); vj_gui_preview(); // info->uc.reload_hint[HINT_SLIST] = 2; info->uc.reload_hint[HINT_CHAIN] = 1; info->uc.reload_hint[HINT_ENTRY] = 1; info->uc.reload_hint[HINT_SEQ_ACT] = 1; info->uc.reload_hint[HINT_HISTORY] = 1; info->uc.reload_hint[HINT_KF] = 1; // periodically pull information from veejay g_timeout_add( 1000, periodic_pull, NULL ); gettimeofday( &(info->time_last) , 0 ); //g_idle_add_full( G_PRIORITY_LOW, gveejay_idle,NULL, NULL ); return 1; } static void veejay_stop_connecting(vj_gui_t *gui) { GtkWidget *veejay_conncection_window; if(!gui->sensitive) vj_gui_enable(); info->launch_sensitive = 0; veejay_conncection_window = glade_xml_get_widget_(info->main_window, "veejay_connection"); gtk_widget_hide(veejay_conncection_window); GtkWidget *mw = glade_xml_get_widget_(info->main_window,"gveejay_window" ); gtk_widget_show( mw ); if( geo_pos_[0] >= 0 && geo_pos_[1] >= 0 ) gtk_window_move( GTK_WINDOW(mw), geo_pos_[0], geo_pos_[1] ); } void reloaded_launcher() { info->watch.state = STATE_RECONNECT; } void reloaded_show_launcher() { info->watch.state = STATE_WAIT_FOR_USER; info->launch_sensitive = TRUE; GtkWidget *veejay_connection = glade_xml_get_widget_(info->main_window,"veejay_connection" ); GtkWidget *mainw = glade_xml_get_widget_(info->main_window,"gveejay_window" ); gtk_window_set_transient_for(GTK_WINDOW(veejay_connection),GTK_WINDOW(mainw)); gtk_widget_show(veejay_connection); } void reloaded_schedule_restart() { info->watch.state = STATE_STOPPED; } void reloaded_restart() { GtkWidget *mw = glade_xml_get_widget_(info->main_window,"gveejay_window" ); // disable and hide mainwindow if(info->sensitive) vj_gui_disable(); gtk_widget_hide( mw ); vj_gui_wipe(); reloaded_show_launcher(); } gboolean is_alive( int *do_sync ) { void *data = info; vj_gui_t *gui = (vj_gui_t*) data; if( gui->watch.state == STATE_STOPPED ) { vj_gui_disconnect(TRUE); reloaded_restart(); gui->watch.state = STATE_WAIT_FOR_USER; return TRUE; } if( gui->watch.state == STATE_PLAYING ) { *do_sync = 1; return TRUE; } if( gui->watch.state == STATE_RECONNECT ) { vj_gui_disconnect(TRUE); vj_gui_wipe(); gui->watch.state = STATE_CONNECT; return TRUE; } if( gui->watch.state == STATE_QUIT ) { if(info->client) vj_gui_disconnect(FALSE); vj_gui_wipe(); return FALSE; } if( gui->watch.state == STATE_CONNECT ) { char *remote; int port; remote = get_text( "entry_hostname" ); port = get_nums( "button_portnum" ); veejay_msg(VEEJAY_MSG_INFO, "Connecting to %s: %d", remote,port ); if(!vj_gui_reconnect( remote, NULL, port )) { reloaded_schedule_restart(); } else { info->watch.state = STATE_PLAYING; if( use_key_snoop ) { #ifdef HAVE_SDL info->key_id = gtk_key_snooper_install( key_handler , NULL); #endif } multrack_audoadd( info->mt, remote, port ); multitrack_set_master_track( info->mt, 0 ); multitrack_set_quality( info->mt, 1 ); *do_sync = 1; veejay_stop_connecting(gui); } } return TRUE; } void vj_gui_disconnect(int restart_schedule) { if(info->key_id) gtk_key_snooper_remove( info->key_id ); /* reset all trees */ // reset_tree("tree_effectlist"); // reset_tree("tree_effectmixlist"); reset_fxtree(); reset_tree("tree_chain"); reset_tree("tree_sources"); reset_tree("editlisttree"); if (restart_schedule) { reloaded_schedule_restart(); clear_samplebank_pages(); free_samplebank(); } else { multitrack_close_tracks(info->mt); multitrack_disconnect(info->mt); free_samplebank(); } if(info->client) { vj_client_close(info->client); vj_client_free(info->client); info->client = NULL; } info->key_id = 0; } void vj_gui_disable() { if(gtk_widget_is_sensitive( GTK_WIDGET(widget_cache[WIDGET_VEEJAY_BOX] ))) { gtk_widget_set_sensitive( GTK_WIDGET(widget_cache[WIDGET_VEEJAY_BOX] ), FALSE ); } info->sensitive = 0; } void vj_gui_enable() { if(!gtk_widget_is_sensitive( GTK_WIDGET(widget_cache[WIDGET_VEEJAY_BOX] ))) { gtk_widget_set_sensitive( GTK_WIDGET(widget_cache[WIDGET_VEEJAY_BOX] ), TRUE ); } info->sensitive = 1; } static void widget_get_rect_in_screen (GtkWidget *widget, GdkRectangle *r) { //GdkRectangle extents; //GdkWindow *window; //window = GDK_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->x = 0; r->y = 0; GtkAllocation all; gtk_widget_get_allocation(widget, &all); r->width = all.width; r->height = all.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] * -------------------------------------------------------------------------------------------------------------------------- */ static void samplebank_size_allocate(GtkWidget *widget, GtkAllocation *allocation, void *data) { setup_samplebank( SAMPLEBANK_COLUMNS, SAMPLEBANK_ROWS, allocation, &(info->image_dimensions[0]),&(info->image_dimensions[1]) ); if(!samplebank_ready_) { samplebank_ready_ = 1; info->uc.reload_hint[HINT_SLIST] = 2; } } /* 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, "Slots %d to %d", (bank_num * NUM_SAMPLES_PER_PAGE), (bank_num * NUM_SAMPLES_PER_PAGE) + NUM_SAMPLES_PER_PAGE ); info->sample_banks[bank_num] = (sample_bank_t*) vj_calloc(sizeof(sample_bank_t)); info->sample_banks[bank_num]->bank_number = bank_num; sample_slot_t **slot = (sample_slot_t**) vj_calloc(sizeof(sample_slot_t*) * NUM_SAMPLES_PER_PAGE); sample_gui_slot_t **gui_slot = (sample_gui_slot_t**) vj_calloc(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_calloc(sizeof(sample_slot_t) ); gui_slot[j] = (sample_gui_slot_t*) vj_calloc(sizeof(sample_gui_slot_t)); 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; GtkWidget *frame = gtk_frame_new(frame_label); GtkWidget *label = gtk_label_new( str_label ); gtk_container_set_border_width( GTK_CONTAINER( frame), 1 ); gtk_widget_show(frame); info->sample_banks[bank_num]->page_num = gtk_notebook_append_page(GTK_NOTEBOOK(info->sample_bank_pad), frame, label); GtkWidget *grid = gtk_grid_new(); gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE); gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE); gtk_container_add( GTK_CONTAINER(frame), grid ); gint col, row; for( row = 0; row < SAMPLEBANK_ROWS; row ++ ) { for( col = 0; col < SAMPLEBANK_COLUMNS; col ++ ) { int slot_nr = row * SAMPLEBANK_COLUMNS + col; 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_grid_attach( GTK_GRID(grid), gui_slot->event_box, col, row, 1,1); set_tooltip_by_widget( gui_slot->frame, tooltips[TOOLTIP_SAMPLESLOT].text); } } g_signal_connect(grid,"size-allocate",G_CALLBACK(samplebank_size_allocate), NULL); gtk_widget_show(grid); gtk_widget_show(sb ); if( !info->normal ) { info->normal = widget_get_fg( GTK_WIDGET(info->sample_banks[bank_num]->gui_slot[0]->frame) ); } return bank_num; } void reset_samplebank(void) { info->selection_slot = NULL; info->selection_gui_slot = NULL; info->selected_slot = NULL; info->selected_gui_slot = NULL; int i,j; for( i = 0; i < NUM_BANKS; i ++ ) { if(info->sample_banks[i]) { for(j = 0; j < NUM_SAMPLES_PER_PAGE ; j ++ ) { update_sample_slot_data( i,j,0,0,NULL,NULL ); } } } } void clear_samplebank_pages() { while( gtk_notebook_get_n_pages(GTK_NOTEBOOK(info->sample_bank_pad) ) > 0 ) gtk_notebook_remove_page( GTK_NOTEBOOK(info->sample_bank_pad), -1 ); } void free_samplebank(void) { int i,j; 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); slot->title = NULL; } if(slot->timecode) { free(slot->timecode); slot->timecode = NULL; } if(slot->pixbuf) { g_object_unref(slot->pixbuf); slot->pixbuf = NULL; } free(slot); free(gslot); info->sample_banks[i]->slot[j] = NULL; info->sample_banks[i]->gui_slot[j] = NULL; } free(info->sample_banks[i]); info->sample_banks[i] = NULL; } } } static int dont_grow = 0; static int bank_img_w = 0; static int bank_img_h = 0; // approximate best image size for sample slot void setup_samplebank(gint num_cols, gint num_rows, GtkAllocation *allocation, int *idx, int *idy) { gint bank_wid = allocation->width; gint bank_hei = allocation->height; bank_hei -= ((12 + 12) * num_rows); // there are 2 labels on each slot if( bank_hei < 0 ) bank_hei = 1; bank_wid -= (8 * num_cols); // there is some spacing between the columns gint image_height = bank_hei / num_rows; gint image_width = bank_wid / num_cols; float ratio = (float) info->el.height / (float) info->el.width; float w,h; if( ratio <= 1.0f ) { h = ratio * image_width; w = image_width; } else { h = image_height; w = image_width / ratio; } if( image_height < h ) { w = (w / h) * image_height; h = image_height; } if( image_width < w ) { h = (h / w) * image_width; w = image_width; } if(dont_grow == 0) { bank_img_w = (int) w; bank_img_h = (int) h; *idx = bank_img_w; *idy = bank_img_h; dont_grow = 1; } else { *idx = (int) bank_img_w; *idy = (int) bank_img_h; } } /* -------------------------------------------------------------------------------------------------------------------------- * 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 sample_slot_t *find_slot_by_sample( int sample_id , int sample_type ) { char key[32]; sprintf(key, "S%04d%02d",sample_id, sample_type ); void *slot = NULL; vevo_property_get( bankport_, key, 0,&slot ); if(!slot) return NULL; return (sample_slot_t*) slot; } static sample_gui_slot_t *find_gui_slot_by_sample( int sample_id , int sample_type ) { char key[32]; sprintf(key, "G%04d%02d",sample_id, sample_type ); void *slot = NULL; vevo_property_get( bankport_, key, 0,&slot ); if(!slot) return NULL; return (sample_gui_slot_t*) slot; } static int find_bank_by_sample(int sample_id, int sample_type, int *slot ) { int i,j; for( i = 0; i < NUM_BANKS; i ++ ) { if(!info->sample_banks[i]) { continue; } 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; #ifdef STRICT_CHECKING veejay_msg(VEEJAY_MSG_DEBUG, "using existing slot (%d,%d)", sample_id,sample_type ); #endif return i; } } } for( i = 0; i < NUM_BANKS; i ++ ) { if(!info->sample_banks[i]) { *slot = 0; return i; } for( j = 0; j < NUM_SAMPLES_PER_PAGE; j ++ ) { if ( info->sample_banks[i]->slot[j]->sample_id <= 0) { *slot = j; #ifdef STRICT_CHECKING veejay_msg(VEEJAY_MSG_DEBUG, "using new slot (%d,%d)", sample_id,sample_type); #endif return i; } } } *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 void set_activation_of_cache_slot_in_samplebank(sequence_gui_slot_t *gui_slot, gboolean activate) { if (activate) { gtk_frame_set_shadow_type(GTK_FRAME(gui_slot->frame),GTK_SHADOW_IN); } else { gtk_frame_set_shadow_type(GTK_FRAME(gui_slot->frame),GTK_SHADOW_ETCHED_IN); } } static gboolean on_sequencerslot_activated_by_mouse(GtkWidget *widget, GdkEventButton *event, gpointer user_data) { gint slot_nr = GPOINTER_TO_INT(user_data); if( event->type == GDK_BUTTON_PRESS && (event->state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK ) { multi_vims( VIMS_SEQUENCE_DEL, "%d", slot_nr ); gtk_label_set_text(GTK_LABEL(info->sequencer_view->gui_slot[slot_nr]->image), NULL ); } else if(event->type == GDK_BUTTON_PRESS) { int id = info->status_tokens[CURRENT_ID]; int type=info->status_tokens[STREAM_TYPE]; if( info->selection_slot ) { id = info->selection_slot->sample_id; type=info->selection_slot->sample_type; } multi_vims( VIMS_SEQUENCE_ADD, "%d %d %d", slot_nr, id,type ); info->uc.reload_hint[HINT_SEQ_ACT] = 1; } return FALSE; } static gboolean on_cacheslot_activated_by_mouse (GtkWidget *widget, GdkEventButton *event, gpointer user_data) { gint slot_nr = -1; if(info->status_tokens[PLAY_MODE] == MODE_PLAIN ) return FALSE; slot_nr =GPOINTER_TO_INT( 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]; #ifdef STRICT_CHECKING assert( s != NULL ); assert( g != NULL ); #endif 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; } else { vj_msg(VEEJAY_MSG_INFO, "Start playing %s %d", (g->sample_type==0 ? "Sample" : "Stream" ), g->sample_id ); } multi_vims(VIMS_SET_MODE_AND_GO, "%d %d", g->sample_type, g->sample_id ); vj_midi_learning_vims_msg2( info->midi, NULL, VIMS_SET_MODE_AND_GO, g->sample_type,g->sample_id ); } return FALSE; } static void create_sequencer_slots(int nx, int ny) { GtkWidget *vbox = glade_xml_get_widget_ (info->main_window, "SampleSequencerBox"); info->sample_sequencer = gtk_frame_new(NULL); add_class(info->sample_sequencer, "sequencer"); gtk_box_pack_start( GTK_BOX( vbox ), GTK_WIDGET(info->sample_sequencer), TRUE, TRUE, 0); gtk_widget_show(info->sample_sequencer); info->sequencer_view = (sequence_envelope*) vj_calloc(sizeof(sequence_envelope) ); info->sequencer_view->gui_slot = (sequence_gui_slot_t**) vj_calloc(sizeof(sequence_gui_slot_t*) * ( nx * ny + 1 ) ); GtkWidget *table = gtk_table_new( nx, ny, TRUE ); gtk_container_add( GTK_CONTAINER(info->sample_sequencer), table ); gtk_widget_show(table); info->sequencer_col = nx; info->sequencer_row = ny; gint col=0; gint row=0; gint k = 0; for( col = 0; col < ny; col ++ ) for( row = 0; row < nx; row ++ ) { sequence_gui_slot_t *gui_slot = (sequence_gui_slot_t*)vj_calloc(sizeof(sequence_gui_slot_t)); info->sequencer_view->gui_slot[k] = gui_slot; gui_slot->event_box = gtk_event_box_new(); gtk_event_box_set_visible_window(GTK_EVENT_BOX(gui_slot->event_box), TRUE); gtk_widget_set_can_focus(gui_slot->event_box, TRUE); g_signal_connect( G_OBJECT(gui_slot->event_box), "button_press_event", G_CALLBACK(on_sequencerslot_activated_by_mouse), //@@@@ (gpointer) castIntToGpointer(k) ); gtk_widget_show(GTK_WIDGET(gui_slot->event_box)); gui_slot->frame = gtk_frame_new(NULL); gtk_container_set_border_width (GTK_CONTAINER(gui_slot->frame),0); gtk_frame_set_shadow_type(GTK_FRAME( gui_slot->frame), GTK_SHADOW_IN ); gtk_widget_show(GTK_WIDGET(gui_slot->frame)); gtk_container_add (GTK_CONTAINER (gui_slot->event_box), gui_slot->frame); add_class(gui_slot->frame, "sequencer_slot"); /* the slot main container */ gui_slot->main_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL,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_label_new(NULL); gtk_box_pack_start (GTK_BOX (gui_slot->main_vbox), GTK_WIDGET(gui_slot->image), TRUE, TRUE, 0); gtk_widget_show( gui_slot->image); gtk_table_attach_defaults ( GTK_TABLE(table), gui_slot->event_box, row, row+1, col, col+1); k++; } // gtk_widget_set_size_request_( table, 300,300); // info->sequencer_view->envelope_size = envelope_size; } static void create_ref_slots(int envelope_size) { GtkWidget *vbox = glade_xml_get_widget_ (info->main_window, "quickselect"); info->quick_select = gtk_frame_new(NULL); gtk_box_pack_start( GTK_BOX( vbox ), GTK_WIDGET(info->quick_select), TRUE, TRUE, 0); gtk_widget_show(info->quick_select); info->sequence_view = (sequence_envelope*) vj_calloc(sizeof(sequence_envelope) ); info->sequence_view->gui_slot = (sequence_gui_slot_t**) vj_calloc(sizeof(sequence_gui_slot_t*) * envelope_size ); 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_calloc(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(GTK_EVENT_BOX(gui_slot->event_box), TRUE); gtk_widget_set_can_focus(gui_slot->event_box, TRUE); /* 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) castIntToGpointer(row) ); gtk_widget_show(GTK_WIDGET(gui_slot->event_box)); /* the surrounding frame for each slot */ gui_slot->frame = gtk_frame_new(NULL); add_class(gui_slot->frame, "quickselect_slot"); set_tooltip_by_widget(gui_slot->frame, tooltips[TOOLTIP_QUICKSELECT].text ); 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_box_new(GTK_ORIENTATION_VERTICAL,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_image_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_table_attach_defaults ( GTK_TABLE(table), gui_slot->event_box, row, row+1, col, col+1); } info->sequence_view->envelope_size = envelope_size; } static void create_slot(gint bank_nr, gint slot_nr, gint w, gint h) { sample_bank_t **sample_banks = info->sample_banks; sample_gui_slot_t *gui_slot = sample_banks[bank_nr]->gui_slot[slot_nr]; // 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(GTK_EVENT_BOX(gui_slot->event_box), TRUE); gtk_widget_set_can_focus(gui_slot->event_box, TRUE); g_signal_connect( G_OBJECT(gui_slot->event_box), "button_press_event", G_CALLBACK(on_slot_activated_by_mouse), (gpointer) castIntToGpointer(slot_nr) ); gtk_widget_show(GTK_WIDGET(gui_slot->event_box)); /* the surrounding frame for each slot */ gui_slot->frame = gtk_frame_new(NULL); add_class(gui_slot->frame, "sample_slot"); gtk_container_set_border_width (GTK_CONTAINER(gui_slot->frame),0); gtk_widget_show(GTK_WIDGET(gui_slot->frame)); gtk_container_add (GTK_CONTAINER (gui_slot->event_box), GTK_WIDGET(gui_slot->frame)); /* the slot main container */ gui_slot->upper_hbox = gtk_box_new(GTK_ORIENTATION_VERTICAL,0); gtk_container_add (GTK_CONTAINER (gui_slot->frame), gui_slot->upper_hbox); gui_slot->title = gtk_label_new(""); gtk_misc_set_alignment(GTK_MISC(gui_slot->title), 0.5, 0.0); gtk_box_pack_start( GTK_BOX(gui_slot->upper_hbox), GTK_WIDGET(gui_slot->title), FALSE, FALSE, 0 ); gui_slot->image = gtk_image_new(); gtk_box_pack_start (GTK_BOX (gui_slot->upper_hbox), GTK_WIDGET(gui_slot->image), TRUE, TRUE, 0); gui_slot->hotkey = gtk_label_new(""); gtk_misc_set_alignment(GTK_MISC(gui_slot->hotkey), 0.5, 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); gui_slot->timecode = gtk_label_new(""); gtk_misc_set_alignment(GTK_MISC(gui_slot->timecode), 0.5, 0.0); gtk_misc_set_padding (GTK_MISC(gui_slot->timecode), 0,0 ); gtk_box_pack_start (GTK_BOX (gui_slot->upper_hbox), GTK_WIDGET(gui_slot->timecode), FALSE, FALSE, 0); gtk_widget_show_all(GTK_WIDGET(gui_slot->upper_hbox)); } /* ----------------------------------------------------------------------------- * Handler of mouse clicks on the GUI-elements of one slot * * - FIRST BUTTON * single-click : activates the slot and the loaded sample (if there is one) * single-click + modifier shift : select it has current channel source * 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 = GPOINTER_TO_INT(user_data); sample_bank_t **sample_banks = info->sample_banks; if( info->sample_banks[ bank_nr ]->slot[ slot_nr ]->sample_id <= 0 ) return FALSE; sample_slot_t *select_slot = sample_banks[bank_nr]->slot[slot_nr]; if( event->type == GDK_2BUTTON_PRESS ) { multi_vims( VIMS_SET_MODE_AND_GO, "%d %d", (select_slot->sample_type==MODE_SAMPLE? MODE_SAMPLE:MODE_STREAM), select_slot->sample_id); vj_midi_learning_vims_msg2( info->midi, NULL, VIMS_SET_MODE_AND_GO, select_slot->sample_type, select_slot->sample_id ); vj_msg(VEEJAY_MSG_INFO, "Start playing %s %d", (select_slot->sample_type==MODE_SAMPLE ? "Sample" : "Stream" ), select_slot->sample_id ); } else if(event->type == GDK_BUTTON_PRESS ) { switch(event->state & GDK_SHIFT_MASK){ case GDK_SHIFT_MASK : { multi_vims( VIMS_CHAIN_ENTRY_SET_SOURCE_CHANNEL, "%d %d %d %d", 0, info->uc.selected_chain_entry, select_slot->sample_type, select_slot->sample_id ); vj_msg(VEEJAY_MSG_INFO, "Set mixing channel %d to %s %d", info->uc.selected_chain_entry, (select_slot->sample_type==MODE_SAMPLE ? "Sample" : "Stream" ), select_slot->sample_id ); char trip[100]; snprintf(trip, sizeof(trip), "%03d:%d %d %d %d",VIMS_CHAIN_ENTRY_SET_SOURCE_CHANNEL, 0, info->uc.selected_chain_entry, select_slot->sample_type, select_slot->sample_id ); vj_midi_learning_vims( info->midi, NULL, trip, 0 ); } break; default : set_selection_of_slot_in_samplebank(FALSE); info->selection_slot = select_slot; info->selection_gui_slot = sample_banks[bank_nr]->gui_slot[slot_nr]; set_selection_of_slot_in_samplebank(TRUE ); break; } } return FALSE; } static void indicate_sequence( gboolean active, sequence_gui_slot_t *slot ) { if(!active) { remove_class( slot->frame, "active"); } else { add_class( slot->frame, "active"); } } static void set_activation_of_slot_in_samplebank( gboolean activate) { if(!info->selected_gui_slot || !info->selected_slot ) return; if (activate) { if( (info->status_tokens[CURRENT_ID] == info->selected_slot->sample_id && info->status_tokens[PLAY_MODE] == MODE_SAMPLE && info->selected_slot->sample_type == 0 ) || (info->status_tokens[CURRENT_ID] == info->selected_slot->sample_id && info->status_tokens[PLAY_MODE] == MODE_STREAM && info->selected_slot->sample_type != 0 ) ) { gtk_widget_grab_focus(GTK_WIDGET(info->selected_gui_slot->frame)); if( info->selection_gui_slot ) { // double click event also submitted button press event remove_class(info->selection_gui_slot->frame, "selected"); } add_class(info->selected_gui_slot->frame, "active"); } } else { remove_class(info->selected_gui_slot->frame, "active"); } } static void set_selection_of_slot_in_samplebank(gboolean active) { if(!info->selection_gui_slot || !info->selection_slot ) return; if( (info->status_tokens[CURRENT_ID] == info->selection_slot->sample_id && info->status_tokens[PLAY_MODE] == MODE_SAMPLE && info->selection_slot->sample_type == 0 ) || (info->status_tokens[CURRENT_ID] == info->selection_slot->sample_id && info->status_tokens[PLAY_MODE] == MODE_STREAM && info->selection_slot->sample_type != 0 ) ) { return; } if(active) { add_class(info->selection_gui_slot->frame, "selected"); } else { remove_class(info->selection_gui_slot->frame, "selected"); } } static int add_sample_to_sample_banks(int bank_page,sample_slot_t *slot) { int bp = 0; int s = 0; #ifdef STRICT_CHECKING int result = verify_bank_capacity( &bp, &s, slot->sample_id, slot->sample_type ); if( result ) update_sample_slot_data( bp, s, slot->sample_id,slot->sample_type,slot->title,slot->timecode); #else if(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); #endif 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[STREAM_TYPE] ) { 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 ); update_sample_slot_data( bank_nr, slot_nr, 0, -1, NULL, NULL); sample_gui_slot_t *gui_slot = info->sample_banks[bank_nr]->gui_slot[slot_nr]; if(gui_slot) gtk_image_clear( GTK_IMAGE( gui_slot->image) ); info->uc.reload_hint[HINT_SLIST] = 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[512]; GtkTreeIter iter; if (type == STREAM_NO_STREAM) snprintf( id_string,sizeof(id_string), "S[%4d] %s", id, title); else snprintf( id_string,sizeof(id_string), "T[%4d]", 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 ); GtkTreeIter iter2; if(type == STREAM_NO_STREAM) { gtk_list_store_append( cali_sourcestore,&iter2); gtk_list_store_set(cali_sourcestore,&iter2, SL_ID, id_string, SL_DESCR,title, SL_TIMECODE,timecode, -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) { 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); slot->timecode = NULL; } if(slot->title) { free(slot->title); slot->title = NULL; } slot->sample_id = sample_id; slot->sample_type = sample_type; slot->timecode = timecode == NULL ? NULL : strduplastn( timecode ); slot->title = title == NULL ? NULL : strduplastn( title ); if( sample_id > 0) { char sample_key[32]; snprintf(sample_key,sizeof(sample_key), "S%04d%02d", sample_id, sample_type ); vevo_property_set( bankport_, sample_key, VEVO_ATOM_TYPE_VOIDPTR,1, &slot ); snprintf(sample_key,sizeof(sample_key), "G%04d%02d", sample_id, sample_type ); vevo_property_set( bankport_, sample_key, VEVO_ATOM_TYPE_VOIDPTR,1,&gui_slot); } if(gui_slot) { if(sample_id > 0 ) { char hotkey[16]; if( sample_type == MODE_SAMPLE ) { snprintf(hotkey, sizeof(hotkey), "[F%d] Sample %d", (sample_id % 12), sample_id); } else{ snprintf(hotkey, sizeof(hotkey), "[F%d] Stream %d", (sample_id % 12), sample_id); } gtk_label_set_text( GTK_LABEL( gui_slot->title ), slot->title ); gtk_label_set_text( GTK_LABEL( gui_slot->hotkey ), hotkey ); gtk_label_set_text( GTK_LABEL( gui_slot->timecode ), slot->timecode ); } else { gtk_label_set_text( GTK_LABEL(gui_slot->title), "" ); gtk_label_set_text( GTK_LABEL(gui_slot->hotkey), "" ); gtk_label_set_text( GTK_LABEL(gui_slot->timecode), "" ); } } if( sample_id == 0 ) { if(slot->pixbuf) { g_object_unref( slot->pixbuf ); slot->pixbuf = NULL; } } } void veejay_release_track(int id, int release_this) { multitrack_release_track( info->mt, id, release_this ); } void veejay_bind_track( int id, int bind_this ) { multitrack_bind_track(info->mt, id, bind_this ); info->uc.reload_hint[HINT_SLIST] = 2; }