diff --git a/inc/input.h b/inc/input.h index d1c3f951880b29273d9addb86605c668801549b8..a2b3ce392d60dbd14c5ab12f3542c02780ea41c8 100644 --- a/inc/input.h +++ b/inc/input.h @@ -40,7 +40,10 @@ struct input { struct input_source* source; char* title; - struct font font; + struct font title_font; + double scale_length; + char* scale_label; + struct font scale_font; unsigned int row; unsigned int column; double frame_rate; diff --git a/inc/util.h b/inc/util.h index 4bff422b2fe1c7d4d02cdc3968578786f0ea971e..06aee535c6ba9c65c7ae376681d097fd5a1e5521 100644 --- a/inc/util.h +++ b/inc/util.h @@ -2,7 +2,7 @@ #define __TIMELAPSE_EDITOR_UTIL_H__ struct font { - const char* font_path; + char* font_name; unsigned int font_size; unsigned char font_colour[3]; }; diff --git a/src/input.c b/src/input.c index 45591519955bbc409ad2e716339d443aa0ee5743..e5c795845ef036da4135b12bb13e0f6debb99777 100644 --- a/src/input.c +++ b/src/input.c @@ -145,37 +145,60 @@ struct input_context* input_context_create( char* filter_description = strdup( "" ); - if ( '\0' != input->title[0] ) { + const char* title; + if ( 0 == strlen( input->title ) ) { + title = " "; + } else { + title = input->title; + } - char* title_text; - switch ( input->rate_unit ) { + char* title_text; + switch ( input->rate_unit ) { - case INPUT_RATE_FPS: - title_text = format_title( input->title, - input->frame_rate, 1 ); - break; + case INPUT_RATE_FPS: + title_text = format_title( title, + input->frame_rate, 1 ); + break; - case INPUT_RATE_SPF: - title_text = format_title( input->title, - 1, input->frame_rate ); - break; + case INPUT_RATE_SPF: + title_text = format_title( title, + 1, input->frame_rate ); + break; - case INPUT_RATE_MPF: - title_text = format_title( input->title, - 1, 60 * input->frame_rate ); - break; + case INPUT_RATE_MPF: + title_text = format_title( title, + 1, 60 * input->frame_rate ); + break; - } + } - filter_description = sappendf( filter_description, - "drawtext=text=%s:fontsize=%d:x=10:y=h-th-10:" - "fontcolor=#%02X%02X%02X:fontfile=%s", - title_text, input->font.font_size, - input->font.font_colour[0], input->font.font_colour[1], - input->font.font_colour[2], input->font.font_path ); + filter_description = sappendf( filter_description, + "drawtext=text=%s:fontsize=%d:x=10:y=h-th-10:" + "fontcolor=#%02X%02X%02X:font=%s", + title_text, input->title_font.font_size, + input->title_font.font_colour[0], + input->title_font.font_colour[1], + input->title_font.font_colour[2], + input->title_font.font_name ); - free( title_text ); + free( title_text ); + if ( 0 < input->scale_length ) { + filter_description = sappendf( filter_description, + ",drawbox=t=fill:c=white:x=iw-10-%lf:y=ih-13:w=%lf:h=3", + input->scale_length, input->scale_length ); + } + + if ( 0 < strlen( input->scale_label ) ) { + filter_description = sappendf( filter_description, + ",drawtext=text=%s:fontsize=%d:x=w-10-%lf/2-tw/2:y=h-th-14:" + "fontcolor=#%02X%02X%02X:font=%s", + input->scale_label, input->scale_font.font_size, + input->scale_length, + input->scale_font.font_colour[0], + input->scale_font.font_colour[1], + input->scale_font.font_colour[2], + input->scale_font.font_name ); } AVFilterInOut* outputs = avfilter_inout_alloc(); diff --git a/src/main.c b/src/main.c index 5561eeb62d6cbd971ff79c3033e59cb092c572b7..a1d0cbb44a860a262eea0342f17866c78dfed6b6 100644 --- a/src/main.c +++ b/src/main.c @@ -25,6 +25,19 @@ struct app { GListStore* input_store; struct input_source* input_sources; + GtkWidget* input_title_font; + GtkWidget* input_frame_rate_spin; + GtkWidget* input_frame_rate_mode; + GtkWidget* input_scale_label; + GtkWidget* input_scale_mu; + GtkWidget* input_scale_length; + GtkWidget* input_scale_font; + + GtkWidget* input_title_font_copy; + GtkWidget* input_frame_rate_copy; + GtkWidget* input_scale_copy; + GtkWidget* input_scale_font_copy; + GThread* render_thread; GtkWidget* progress_dialogue; GtkWidget* progress_text; @@ -45,6 +58,20 @@ static void input_class_init( InputClass* class ) { (void) class; } /* Funk! */ +static struct input* get_selected_input( struct app* app ) { + + unsigned int selected_index = gtk_single_selection_get_selected( + app->input_selection ); + Input* selected_item = INPUT_INPUT( g_list_model_get_item( + G_LIST_MODEL( app->input_store ), selected_index ) ); + if ( NULL != selected_item ) { + return selected_item->input; + } else { + return NULL; + } + +} + static void update_export_sensitivity( struct app* app ) { gtk_widget_set_sensitive( app->export_all_button, @@ -55,6 +82,61 @@ static void update_export_sensitivity( struct app* app ) { GTK_INVALID_LIST_POSITION != gtk_single_selection_get_selected( app->input_selection ) ); + struct input* input = get_selected_input( app ); + if ( NULL == input ) { + + gtk_widget_set_sensitive( app->input_title_font, false ); + gtk_widget_set_sensitive( app->input_frame_rate_spin, false ); + gtk_widget_set_sensitive( app->input_frame_rate_mode, false ); + gtk_widget_set_sensitive( app->input_scale_label, false ); + gtk_widget_set_sensitive( app->input_scale_mu, false ); + gtk_widget_set_sensitive( app->input_scale_length, false ); + gtk_widget_set_sensitive( app->input_scale_font, false ); + + gtk_widget_set_sensitive( app->input_title_font_copy, false ); + gtk_widget_set_sensitive( app->input_frame_rate_copy, false ); + gtk_widget_set_sensitive( app->input_scale_copy, false ); + gtk_widget_set_sensitive( app->input_scale_font_copy, false ); + + } else { + + gtk_widget_set_sensitive( app->input_title_font, true ); + gtk_widget_set_sensitive( app->input_frame_rate_spin, true ); + gtk_widget_set_sensitive( app->input_frame_rate_mode, true ); + gtk_widget_set_sensitive( app->input_scale_label, true ); + gtk_widget_set_sensitive( app->input_scale_mu, true ); + gtk_widget_set_sensitive( app->input_scale_length, true ); + gtk_widget_set_sensitive( app->input_scale_font, true ); + + gtk_widget_set_sensitive( app->input_title_font_copy, true ); + gtk_widget_set_sensitive( app->input_frame_rate_copy, true ); + gtk_widget_set_sensitive( app->input_scale_copy, true ); + gtk_widget_set_sensitive( app->input_scale_font_copy, true ); + + char font[1024]; + snprintf( font, 1024, "%s %d", input->title_font.font_name, + input->title_font.font_size ); + gtk_font_chooser_set_font( + GTK_FONT_CHOOSER( app->input_title_font ), font ); + gtk_spin_button_set_value( + GTK_SPIN_BUTTON( app->input_frame_rate_spin ), + input->frame_rate ); + gtk_drop_down_set_selected( + GTK_DROP_DOWN( app->input_frame_rate_mode ), + input->rate_unit ); + gtk_entry_buffer_set_text( + gtk_entry_get_buffer( GTK_ENTRY( app->input_scale_label ) ), + input->scale_label, -1 ); + gtk_spin_button_set_value( + GTK_SPIN_BUTTON( app->input_scale_length ), + input->scale_length ); + snprintf( font, 1024, "%s %d", input->scale_font.font_name, + input->scale_font.font_size ); + gtk_font_chooser_set_font( + GTK_FONT_CHOOSER( app->input_scale_font ), font ); + + } + } static int get_font( PangoFontDescription* description, @@ -66,9 +148,12 @@ static int get_font( PangoFontDescription* description, return -1; } - result->font_path = - pango_font_description_get_family( description ); - if ( NULL == result->font_path ) { + if ( NULL != result->font_name ) { + free( result->font_name ); + } + result->font_name = strdup( + pango_font_description_get_family( description ) ); + if ( NULL == result->font_name ) { *error = write_error( __FILE__, __LINE__ - 2, "Couldn't get font name" ); return -1; @@ -129,13 +214,20 @@ static void open_input_callback( NULL != input; input = input->next ) { - input->font.font_path = "/home/tom/.local/share/fonts/" - "Open Sans/OpenSans-Regular.ttf"; - input->font.font_size = 24; - input->font.font_colour[0] = 0xFF; - input->font.font_colour[1] = 0xFF; - input->font.font_colour[2] = 0xFF; + input->title_font.font_name = strdup( "Sans" ); + input->title_font.font_size = 12; + input->title_font.font_colour[0] = 0xFF; + input->title_font.font_colour[1] = 0xFF; + input->title_font.font_colour[2] = 0xFF; + + input->title = strdup( "" ); + input->scale_label = strdup( "" ); + input->scale_font.font_name = strdup( "Sans" ); + input->scale_font.font_size = 12; + input->scale_font.font_colour[0] = 0xFF; + input->scale_font.font_colour[1] = 0xFF; + input->scale_font.font_colour[2] = 0xFF; Input* new_input = INPUT_INPUT( g_object_new( INPUT_TYPE_INPUT, NULL ) ); @@ -385,7 +477,7 @@ static void export_all_file_callback( } fprintf( stderr, "Got %s as font file\n", - config->title_font.font_path ); + config->title_font.font_name ); if ( 0 == gtk_drop_down_get_selected( GTK_DROP_DOWN( app->speed_mode ) ) ) { @@ -456,11 +548,7 @@ static void export_selected_file_callback( GTK_FILE_CHOOSER( file_dialogue ) ); char* file_path = g_file_get_path( file ); - unsigned int selected_index = gtk_single_selection_get_selected( - app->input_selection ); - Input* selected_item = INPUT_INPUT( g_list_model_get_item( - G_LIST_MODEL( app->input_store ), selected_index ) ); - struct input* input = selected_item->input; + struct input* input = get_selected_input( app ); struct output_config* config = calloc( 1, sizeof (struct output_config) ); @@ -622,6 +710,18 @@ static void build_general_settings( } +static void input_selection_changed( GtkSelectionModel* selection, + unsigned int position, unsigned int n_items, void* data ) { + + (void) selection; + (void) position; + (void) n_items; + + struct app* app = (struct app*) data; + update_export_sensitivity( app ); + +} + static void file_factory_setup_callback( GtkListItemFactory* factory, GtkListItem* list_item ) { @@ -767,33 +867,78 @@ static void column_factory_bind_callback( } -static void frame_rate_factory_setup_callback( - GtkListItemFactory* factory, GtkListItem* list_item ) { +static void input_title_font_set( GtkFontChooser* font_button, + void* data ) { - (void) factory; + struct app* app = (struct app*) data; - GtkWidget* grid = gtk_grid_new(); + struct input* input = get_selected_input( app ); - GtkWidget* frame_rate_spin = gtk_spin_button_new( - gtk_adjustment_new( 1, 0, 1E30, 1, 10, 10 ), 1, 0 ); - gtk_grid_attach( GTK_GRID( grid ), frame_rate_spin, 0, 0, 1, 1 ); + char* error; + if ( 0 > get_font( gtk_font_chooser_get_font_desc( + GTK_FONT_CHOOSER( font_button ) ), + &( input->title_font ), &error ) ) { + assert( NULL != error ); + GtkWidget* message = gtk_message_dialog_new( + GTK_WINDOW( app->top_level_window ), + GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL, + GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, + "%s", error ); + g_signal_connect( message, "response", + G_CALLBACK( gtk_window_destroy ), NULL ); - static const char* rate_modes[] = { - [INPUT_RATE_FPS] = "FPS", - [INPUT_RATE_SPF] = "secs / frame", - [INPUT_RATE_MPF] = "mins / frame", - NULL, - }; - GtkWidget* rate_mode = gtk_drop_down_new_from_strings( rate_modes ); - gtk_grid_attach( GTK_GRID( grid ), rate_mode, 1, 0, 1, 1 ); + gtk_window_present( GTK_WINDOW( message ) ); + } + +} - gtk_list_item_set_child( list_item, grid ); +static void input_title_font_copy( GtkButton* button, void* data ) { + + (void) button; + + struct app* app = (struct app*) data; + + struct input* selected_input = get_selected_input( app ); + + size_t n = g_list_model_get_n_items( + G_LIST_MODEL( app->input_store ) ); + + for ( size_t i = 0; i < n; i++ ) { + + Input* Input = INPUT_INPUT( g_list_model_get_item( + G_LIST_MODEL( app->input_store ), i ) ); + struct input* input = Input->input; + + if ( input == selected_input ) { + continue; + } + + if ( NULL != input->title_font.font_name ) { + free( input->title_font.font_name ); + } + input->title_font.font_name = strdup( + selected_input->title_font.font_name ); + + input->title_font.font_size = + selected_input->title_font.font_size; + + input->title_font.font_colour[0] = + selected_input->title_font.font_colour[0]; + input->title_font.font_colour[1] = + selected_input->title_font.font_colour[1]; + input->title_font.font_colour[2] = + selected_input->title_font.font_colour[2]; + + } } static void input_frame_rate_changed( GtkAdjustment* adj, void* data ) { - struct input* input = (struct input*) data; + struct app* app = (struct app*) data; + + struct input* input = get_selected_input( app ); + input->frame_rate = gtk_adjustment_get_value( adj ); } @@ -803,34 +948,190 @@ static void input_rate_mode_changed( GObject* drop_down, (void) param_spec; - struct input* input = (struct input*) data; + struct app* app = (struct app*) data; + + struct input* input = get_selected_input( app ); + input->rate_unit = gtk_drop_down_get_selected( GTK_DROP_DOWN( drop_down ) ); } -static void frame_rate_factory_bind_callback( - GtkListItemFactory* factory, GtkListItem* list_item ) { +static void input_frame_rate_copy( GtkButton* button, void* data ) { - (void) factory; + (void) button; - GtkWidget* grid = gtk_list_item_get_child( list_item ); - Input* input = gtk_list_item_get_item( list_item ); - GtkWidget* frame_rate_spin = gtk_grid_get_child_at( - GTK_GRID( grid ), 0, 0 ); - GtkWidget* rate_mode = gtk_grid_get_child_at( - GTK_GRID( grid ), 1, 0 ); + struct app* app = (struct app*) data; - gtk_spin_button_set_value( GTK_SPIN_BUTTON( frame_rate_spin ), - input->input->frame_rate ); - g_signal_connect( gtk_spin_button_get_adjustment( - GTK_SPIN_BUTTON( frame_rate_spin ) ), "value-changed", - G_CALLBACK( input_frame_rate_changed ), input->input ); + struct input* selected_input = get_selected_input( app ); + + size_t n = g_list_model_get_n_items( + G_LIST_MODEL( app->input_store ) ); + + for ( size_t i = 0; i < n; i++ ) { + + Input* Input = INPUT_INPUT( g_list_model_get_item( + G_LIST_MODEL( app->input_store ), i ) ); + struct input* input = Input->input; + + if ( input == selected_input ) { + continue; + } - gtk_drop_down_set_selected( GTK_DROP_DOWN( rate_mode ), - input->input->rate_unit ); - g_signal_connect( rate_mode, "notify::selected", - G_CALLBACK( input_rate_mode_changed ), input->input ); + input->frame_rate = selected_input->frame_rate; + input->rate_unit = selected_input->rate_unit; + + } + +} + +static void input_scale_label_deleted( GtkEntryBuffer* buffer, + unsigned int position, unsigned int n_chars, void* data ) { + + (void) position; + (void) n_chars; + + struct app* app = (struct app*) data; + + struct input* input = get_selected_input( app ); + + strcpy( input->scale_label, gtk_entry_buffer_get_text( buffer ) ); + +} + +static void input_scale_label_inserted( GtkEntryBuffer* buffer, + unsigned int position, char* chars, + unsigned int n_chars, void* data ) { + + (void) position; + (void) chars; + (void) n_chars; + + struct app* app = (struct app*) data; + + struct input* input = get_selected_input( app ); + + free( input->scale_label ); + input->scale_label = strdup( gtk_entry_buffer_get_text( buffer ) ); + +} + +static void mu_button_clicked( GtkButton* button, void* data ) { + + (void) button; + + GtkEntry* entry = (GtkEntry*) data; + GtkEntryBuffer* buffer = gtk_entry_get_buffer( entry ); + + gtk_entry_buffer_insert_text( buffer, + gtk_entry_buffer_get_length( buffer), "µ", -1 ); + +} + +static void input_scale_len_changed( GtkAdjustment* adj, void* data ) { + + struct app* app = (struct app*) data; + + struct input* input = get_selected_input( app ); + + input->scale_length = gtk_adjustment_get_value( adj ); + +} + +static void input_scale_copy( GtkButton* button, void* data ) { + + (void) button; + + struct app* app = (struct app*) data; + + struct input* selected_input = get_selected_input( app ); + + size_t n = g_list_model_get_n_items( + G_LIST_MODEL( app->input_store ) ); + + for ( size_t i = 0; i < n; i++ ) { + + Input* Input = INPUT_INPUT( g_list_model_get_item( + G_LIST_MODEL( app->input_store ), i ) ); + struct input* input = Input->input; + + if ( input == selected_input ) { + continue; + } + + input->scale_length = selected_input->scale_length; + if ( NULL != input->scale_label ) { + free( input->scale_label ); + } + input->scale_label = strdup( selected_input->scale_label ); + + } + +} + +static void input_scale_font_set( GtkFontChooser* font_button, + void* data ) { + + struct app* app = (struct app*) data; + + struct input* input = get_selected_input( app ); + + char* error; + if ( 0 > get_font( gtk_font_chooser_get_font_desc( + GTK_FONT_CHOOSER( font_button ) ), + &( input->scale_font ), &error ) ) { + assert( NULL != error ); + GtkWidget* message = gtk_message_dialog_new( + GTK_WINDOW( app->top_level_window ), + GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL, + GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, + "%s", error ); + g_signal_connect( message, "response", + G_CALLBACK( gtk_window_destroy ), NULL ); + + gtk_window_present( GTK_WINDOW( message ) ); + } + +} + +static void input_scale_font_copy( GtkButton* button, void* data ) { + + (void) button; + + struct app* app = (struct app*) data; + + struct input* selected_input = get_selected_input( app ); + + size_t n = g_list_model_get_n_items( + G_LIST_MODEL( app->input_store ) ); + + for ( size_t i = 0; i < n; i++ ) { + + Input* Input = INPUT_INPUT( g_list_model_get_item( + G_LIST_MODEL( app->input_store ), i ) ); + struct input* input = Input->input; + + if ( input == selected_input ) { + continue; + } + + if ( NULL != input->scale_font.font_name ) { + free( input->scale_font.font_name ); + } + input->scale_font.font_name = strdup( + selected_input->scale_font.font_name ); + + input->scale_font.font_size = + selected_input->scale_font.font_size; + + input->scale_font.font_colour[0] = + selected_input->scale_font.font_colour[0]; + input->scale_font.font_colour[1] = + selected_input->scale_font.font_colour[1]; + input->scale_font.font_colour[2] = + selected_input->scale_font.font_colour[2]; + + } } @@ -846,10 +1147,19 @@ static void build_input_settings( struct app* app, GtkBox* container ) { app->input_store = g_list_store_new( INPUT_TYPE_INPUT ); GtkSingleSelection* selection = gtk_single_selection_new( G_LIST_MODEL( app->input_store ) ); + g_signal_connect( G_OBJECT( selection ), "selection-changed", + G_CALLBACK( input_selection_changed ), app ); + + GtkWidget* input_list_scroll = gtk_scrolled_window_new(); + gtk_widget_set_vexpand( input_list_scroll, true ); GtkWidget* input_list = gtk_column_view_new( GTK_SELECTION_MODEL( selection ) ); gtk_widget_set_hexpand( input_list, true ); + gtk_column_view_set_reorderable( + GTK_COLUMN_VIEW( input_list ), false ); + gtk_column_view_set_show_column_separators( + GTK_COLUMN_VIEW( input_list ), false ); GtkListItemFactory* file_item_factory = gtk_signal_list_item_factory_new(); @@ -859,6 +1169,8 @@ static void build_input_settings( struct app* app, GtkBox* container ) { G_CALLBACK( file_factory_bind_callback ), NULL ); GtkColumnViewColumn* file_column = gtk_column_view_column_new( "File", file_item_factory ); + gtk_column_view_column_set_resizable( file_column, true ); + gtk_column_view_column_set_expand( file_column, true ); gtk_column_view_append_column( GTK_COLUMN_VIEW( input_list ), file_column ); @@ -870,6 +1182,8 @@ static void build_input_settings( struct app* app, GtkBox* container ) { G_CALLBACK( title_factory_bind_callback ), NULL ); GtkColumnViewColumn* title_column = gtk_column_view_column_new( "Title", title_item_factory ); + gtk_column_view_column_set_resizable( title_column, true ); + gtk_column_view_column_set_expand( title_column, true ); gtk_column_view_append_column( GTK_COLUMN_VIEW( input_list ), title_column ); @@ -881,6 +1195,8 @@ static void build_input_settings( struct app* app, GtkBox* container ) { G_CALLBACK( row_factory_bind_callback ), NULL ); GtkColumnViewColumn* row_column = gtk_column_view_column_new( "Row", row_item_factory ); + gtk_column_view_column_set_resizable( row_column, true ); + gtk_column_view_column_set_expand( row_column, true ); gtk_column_view_append_column( GTK_COLUMN_VIEW( input_list ), row_column ); @@ -892,26 +1208,157 @@ static void build_input_settings( struct app* app, GtkBox* container ) { G_CALLBACK( column_factory_bind_callback ), NULL ); GtkColumnViewColumn* column_column = gtk_column_view_column_new( "Column", column_item_factory ); + gtk_column_view_column_set_resizable( column_column, true ); + gtk_column_view_column_set_expand( column_column, true ); gtk_column_view_append_column( GTK_COLUMN_VIEW( input_list ), column_column ); - GtkListItemFactory* frame_rate_item_factory = - gtk_signal_list_item_factory_new(); - g_signal_connect( frame_rate_item_factory, "setup", - G_CALLBACK( frame_rate_factory_setup_callback ), NULL ); - g_signal_connect( frame_rate_item_factory, "bind", - G_CALLBACK( frame_rate_factory_bind_callback ), NULL ); - GtkColumnViewColumn* frame_rate_column = gtk_column_view_column_new( - "Frame Rate", frame_rate_item_factory ); - gtk_column_view_append_column( GTK_COLUMN_VIEW( input_list ), - frame_rate_column ); + gtk_scrolled_window_set_child( + GTK_SCROLLED_WINDOW( input_list_scroll ), input_list ); - gtk_box_append( GTK_BOX( box ), input_list ); + gtk_box_append( GTK_BOX( box ), input_list_scroll ); app->input_selection = selection; + GtkWidget* options_grid = gtk_grid_new(); + + GtkWidget* title_font_label = gtk_label_new( "Title Font" ); + gtk_grid_attach( GTK_GRID( options_grid ), title_font_label, + 0, 0, 1, 1 ); + + GtkWidget* title_font_button = gtk_font_button_new(); + g_signal_connect( G_OBJECT( title_font_button ), "font-set", + G_CALLBACK( input_title_font_set ), app ); + gtk_grid_attach( GTK_GRID( options_grid ), title_font_button, + 1, 0, 1, 1 ); + + GtkWidget* title_font_copy_button = + gtk_button_new_from_icon_name( "edit-copy" ); + gtk_widget_set_tooltip_text( + title_font_copy_button, "Copy to all" ); + g_signal_connect( G_OBJECT( title_font_copy_button ), "clicked", + G_CALLBACK( input_title_font_copy ), app ); + gtk_grid_attach( GTK_GRID( options_grid ), title_font_copy_button, + 2, 0, 1, 1 ); + + GtkWidget* frame_rate_label = gtk_label_new( "Frame Rate" ); + gtk_grid_attach( GTK_GRID( options_grid ), frame_rate_label, + 0, 1, 1, 1 ); + + GtkWidget* frame_rate_box = gtk_box_new( + GTK_ORIENTATION_HORIZONTAL, 0 ); + + GtkWidget* frame_rate_spin = gtk_spin_button_new( + gtk_adjustment_new( 1, 0, 1E30, 1, 10, 10 ), 1, 0 ); + g_signal_connect( gtk_spin_button_get_adjustment( + GTK_SPIN_BUTTON( frame_rate_spin ) ), "value-changed", + G_CALLBACK( input_frame_rate_changed ), app ); + gtk_box_append( GTK_BOX( frame_rate_box ), frame_rate_spin ); + + static const char* rate_modes[] = { + [INPUT_RATE_FPS] = "FPS", + [INPUT_RATE_SPF] = "secs / frame", + [INPUT_RATE_MPF] = "mins / frame", + NULL, + }; + GtkWidget* frame_rate_mode = gtk_drop_down_new_from_strings( + rate_modes ); + g_signal_connect( frame_rate_mode, "notify::selected", + G_CALLBACK( input_rate_mode_changed ), app ); + gtk_box_append( GTK_BOX( frame_rate_box ), frame_rate_mode ); + gtk_grid_attach( GTK_GRID( options_grid ), frame_rate_box, + 1, 1, 1, 1 ); + + GtkWidget* frame_rate_copy_button = + gtk_button_new_from_icon_name( "edit-copy" ); + gtk_widget_set_tooltip_text( + frame_rate_copy_button, "Copy to all" ); + g_signal_connect( G_OBJECT( frame_rate_copy_button ), "clicked", + G_CALLBACK( input_frame_rate_copy ), app ); + gtk_grid_attach( GTK_GRID( options_grid ), frame_rate_copy_button, + 2, 1, 1, 1 ); + + GtkWidget* scale_label_label = gtk_label_new( "Scale Label" ); + gtk_grid_attach( GTK_GRID( options_grid ), scale_label_label, + 0, 2, 1, 1 ); + + GtkWidget* scale_label_box = gtk_box_new( + GTK_ORIENTATION_HORIZONTAL, 0 ); + + GtkWidget* scale_label_entry = gtk_entry_new(); + g_signal_connect( gtk_entry_get_buffer( + GTK_ENTRY( scale_label_entry) ), "inserted-text", + G_CALLBACK( input_scale_label_inserted ), app ); + g_signal_connect( gtk_entry_get_buffer( + GTK_ENTRY( scale_label_entry ) ), "deleted-text", + G_CALLBACK( input_scale_label_deleted ), app ); + gtk_box_append( GTK_BOX( scale_label_box ), scale_label_entry ); + + GtkWidget* scale_mu_button = gtk_button_new_with_label( "µ" ); + g_signal_connect( G_OBJECT( scale_mu_button ), "clicked", + G_CALLBACK( mu_button_clicked ), scale_label_entry ); + gtk_box_append( GTK_BOX( scale_label_box ), scale_mu_button ); + + gtk_grid_attach( GTK_GRID( options_grid ), scale_label_box, + 1, 2, 1, 1 ); + + GtkWidget* scale_len_label = gtk_label_new( "Scale Length (px)" ); + gtk_grid_attach( GTK_GRID( options_grid ), scale_len_label, + 0, 3, 1, 1 ); + + GtkWidget* scale_len_spin = gtk_spin_button_new( + gtk_adjustment_new( 0, 0, 1E5, 1, 10, 10 ), 1, 3 ); + g_signal_connect( gtk_spin_button_get_adjustment( + GTK_SPIN_BUTTON( scale_len_spin ) ), "value-changed", + G_CALLBACK( input_scale_len_changed ), app ); + gtk_grid_attach( GTK_GRID( options_grid ), scale_len_spin, + 1, 3, 1, 1 ); + + GtkWidget* scale_copy_button = + gtk_button_new_from_icon_name( "edit-copy" ); + gtk_widget_set_tooltip_text( + scale_copy_button, "Copy to all" ); + g_signal_connect( G_OBJECT( scale_copy_button ), "clicked", + G_CALLBACK( input_scale_copy ), app ); + gtk_grid_attach( GTK_GRID( options_grid ), scale_copy_button, + 2, 2, 1, 2 ); + + GtkWidget* scale_font_label = gtk_label_new( "Scale Label Font" ); + gtk_grid_attach( GTK_GRID( options_grid ), scale_font_label, + 0, 4, 1, 1 ); + + GtkWidget* scale_font_button = gtk_font_button_new(); + g_signal_connect( G_OBJECT( scale_font_button ), "font-set", + G_CALLBACK( input_scale_font_set ), app ); + gtk_grid_attach( GTK_GRID( options_grid ), scale_font_button, + 1, 4, 1, 1 ); + + GtkWidget* scale_font_copy_button = + gtk_button_new_from_icon_name( "edit-copy" ); + gtk_widget_set_tooltip_text( + scale_font_copy_button, "Copy to all" ); + g_signal_connect( G_OBJECT( scale_font_copy_button ), "clicked", + G_CALLBACK( input_scale_font_copy ), app ); + gtk_grid_attach( GTK_GRID( options_grid ), scale_font_copy_button, + 2, 4, 1, 1 ); + + gtk_box_append( GTK_BOX( box ), options_grid ); + gtk_box_append( container, frame ); + app->input_title_font = title_font_button; + app->input_frame_rate_spin = frame_rate_spin; + app->input_frame_rate_mode = frame_rate_mode; + app->input_scale_label = scale_label_entry; + app->input_scale_mu = scale_mu_button; + app->input_scale_length = scale_len_spin; + app->input_scale_font = scale_font_button; + + app->input_title_font_copy = title_font_copy_button; + app->input_frame_rate_copy = frame_rate_copy_button; + app->input_scale_copy = scale_copy_button; + app->input_scale_font_copy = scale_font_copy_button; + } static void application_callback( @@ -937,6 +1384,8 @@ static void application_callback( gtk_box_append( GTK_BOX( vbox ), hbox ); + update_export_sensitivity( app ); + gtk_window_present( (GtkWindow*) app->top_level_window ); } diff --git a/src/output.c b/src/output.c index e7e9fb529a98dd25a1ae4dafcd3fc515f4e65d41..6037be98a4bd4f27e22e3721b69079d6b0634e8b 100644 --- a/src/output.c +++ b/src/output.c @@ -457,7 +457,7 @@ void* output_all( void* data ) { config->title_font.font_colour[0], config->title_font.font_colour[1], config->title_font.font_colour[2], - config->title_font.font_path ); + config->title_font.font_name ); free( title_text );