1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 * Copyright (C) John Stebbins 2008 <stebbins@stebbins>
6 * audiohandler.c is free software.
8 * You may redistribute it and/or modify it under the terms of the
9 * GNU General Public License, as published by the Free Software
10 * Foundation; either version 2 of the License, or (at your option)
17 #include "hb-backend.h"
19 #include "callbacks.h"
21 #include "audiohandler.h"
24 ghb_adjust_audio_rate_combos(signal_user_data_t *ud)
26 gint titleindex, audioindex, acodec, mix;
27 ghb_audio_info_t ainfo;
31 g_debug("ghb_adjust_audio_rate_combos ()");
32 titleindex = ghb_settings_combo_int(ud->settings, "title");
34 widget = GHB_WIDGET(ud->builder, "AudioTrack");
35 gval = ghb_widget_value(widget);
36 audioindex = ghb_lookup_combo_int("AudioTrack", gval);
39 widget = GHB_WIDGET(ud->builder, "AudioEncoder");
40 gval = ghb_widget_value(widget);
41 acodec = ghb_lookup_combo_int("AudioEncoder", gval);
43 widget = GHB_WIDGET(ud->builder, "AudioMixdown");
44 gval = ghb_widget_value(widget);
45 mix = ghb_lookup_combo_int("AudioMixdown", gval);
48 if (ghb_audio_is_passthru (acodec))
50 ghb_set_default_bitrate_opts (ud->builder, 0, -1);
51 if (ghb_get_audio_info (&ainfo, titleindex, audioindex))
53 gint br = ainfo.bitrate / 1000;
54 // Set the values for bitrate and samplerate to the input rates
57 if (ghb_audio_is_passthru (ainfo.codec))
59 ghb_set_passthru_bitrate_opts (ud->builder, br);
60 ghb_ui_update(ud, "AudioMixdown", ghb_int64_value(0));
64 acodec = ghb_select_audio_codec(ud, audioindex);
65 br = ghb_find_closest_audio_bitrate(acodec, br);
66 mix = ghb_get_best_mix( titleindex, audioindex, acodec, 0);
67 ghb_ui_update(ud, "AudioMixdown", ghb_int64_value(mix));
69 ghb_ui_update(ud, "AudioBitrate", ghb_int64_value(br));
70 ghb_ui_update(ud, "AudioSamplerate", ghb_int64_value(0));
74 ghb_ui_update(ud, "AudioBitrate", ghb_int64_value(384));
75 ghb_ui_update(ud, "AudioSamplerate", ghb_int64_value(0));
76 ghb_ui_update(ud, "AudioMixdown", ghb_int64_value(0));
78 ghb_ui_update(ud, "AudioTrackDRCSlider", ghb_double_value(0));
80 else if (acodec == HB_ACODEC_FAAC)
82 gint br, last = 160, first = 0;
84 if (mix == HB_AMIXDOWN_6CH)
90 widget = GHB_WIDGET(ud->builder, "AudioBitrate");
91 gval = ghb_widget_value(widget);
92 br = ghb_lookup_combo_int("AudioBitrate", gval);
95 ghb_ui_update(ud, "AudioBitrate", ghb_int64_value(last));
97 ghb_ui_update(ud, "AudioBitrate", ghb_int64_value(first));
98 ghb_set_default_bitrate_opts (ud->builder, first, last);
102 ghb_set_default_bitrate_opts (ud->builder, 0, -1);
107 free_audio_hash_key_value(gpointer data)
113 ghb_get_user_audio_lang(signal_user_data_t *ud, gint titleindex, gint track)
115 GValue *audio_list, *asettings;
118 audio_list = ghb_settings_get_value(ud->settings, "audio_list");
119 if (ghb_array_len(audio_list) <= track)
121 asettings = ghb_array_get_nth(audio_list, track);
122 track = ghb_settings_get_int(asettings, "AudioTrack");
123 lang = ghb_get_source_audio_lang(titleindex, track);
128 ghb_set_pref_audio(gint titleindex, signal_user_data_t *ud)
130 gint fallback_acodec, track;
131 gchar *source_lang = NULL;
133 ghb_audio_info_t ainfo;
134 GHashTable *track_indices;
137 const GValue *pref_audio;
138 const GValue *audio, *drc;
139 gint acodec, bitrate, mix;
141 gint count, ii, list_count;
143 g_debug("set_pref_audio");
144 mux = ghb_settings_combo_int(ud->settings, "FileFormat");
145 if (mux == HB_MUX_MP4)
146 fallback_acodec = HB_ACODEC_FAAC;
148 fallback_acodec = HB_ACODEC_LAME;
149 track_indices = g_hash_table_new_full(g_int_hash, g_int_equal,
150 free_audio_hash_key_value, free_audio_hash_key_value);
151 // Clear the audio list
152 ghb_clear_audio_list(ud);
153 // Find "best" audio based on audio preferences
154 button = GHB_WIDGET (ud->builder, "audio_add");
155 if (!ghb_settings_get_boolean(ud->settings, "AudioDUB"))
157 source_lang = ghb_get_source_audio_lang(titleindex, 0);
159 if (source_lang == NULL)
160 source_lang = ghb_settings_get_string(ud->settings, "PreferredLanguage");
162 pref_audio = ghb_settings_get_value(ud->settings, "AudioList");
165 count = ghb_array_len(pref_audio);
166 for (ii = 0; ii < count; ii++)
168 audio = ghb_array_get_nth(pref_audio, ii);
169 acodec = ghb_settings_combo_int(audio, "AudioEncoder");
170 bitrate = ghb_settings_combo_int(audio, "AudioBitrate");
171 rate = ghb_settings_combo_double(audio, "AudioSamplerate");
172 mix = ghb_settings_combo_int(audio, "AudioMixdown");
173 drc = ghb_settings_get_value(audio, "AudioTrackDRCSlider");
174 //acodec_code = ghb_lookup_combo_int("AudioEncoder", acodec);
175 // If there are multiple audios using the same codec, then
176 // select sequential tracks for each. The hash keeps track
177 // of the tracks used for each codec.
178 track = ghb_find_audio_track(titleindex, source_lang,
179 acodec, fallback_acodec, track_indices);
181 // 1. pref codec is passthru
182 // 2. source codec is not passthru
183 // 3. next pref is enabled
184 if (ghb_get_audio_info (&ainfo, titleindex, track) &&
185 ghb_audio_is_passthru (acodec))
187 // HB_ACODEC_* are bit fields. Treat acodec as mask
188 if (!(ainfo.codec & acodec & (HB_ACODEC_AC3 | HB_ACODEC_DCA)))
190 acodec = fallback_acodec;
191 // If there's more audio to process, or we've already
192 // placed one in the list, then we can skip this one
193 if ((ii + 1 < count) || (list_count != 0))
200 bitrate = ainfo.bitrate / 1000;
204 mix = HB_AMIXDOWN_DOLBYPLII;
209 acodec &= ainfo.codec;
212 if (titleindex >= 0 && track < 0)
217 g_signal_emit_by_name(button, "clicked", ud);
219 ghb_ui_update(ud, "AudioTrack", ghb_int64_value(track));
220 ghb_ui_update(ud, "AudioEncoder", ghb_int64_value(acodec));
221 if (!ghb_audio_is_passthru (acodec))
223 // This gets set autimatically if the codec is passthru
224 ghb_ui_update(ud, "AudioBitrate", ghb_int64_value(bitrate));
225 ghb_ui_update(ud, "AudioSamplerate", ghb_double_value(rate));
226 mix = ghb_get_best_mix( titleindex, track, acodec, mix);
227 ghb_ui_update(ud, "AudioMixdown", ghb_int64_value(mix));
229 ghb_adjust_audio_rate_combos(ud);
230 ghb_ui_update(ud, "AudioTrackDRCSlider", drc);
234 g_hash_table_destroy(track_indices);
238 get_selected_asettings(signal_user_data_t *ud)
240 GtkTreeView *treeview;
241 GtkTreePath *treepath;
242 GtkTreeSelection *selection;
247 GValue *asettings = NULL;
248 const GValue *audio_list;
250 g_debug("get_selected_asettings ()");
251 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "audio_list"));
252 selection = gtk_tree_view_get_selection (treeview);
253 if (gtk_tree_selection_get_selected(selection, &store, &iter))
255 // Get the row number
256 treepath = gtk_tree_model_get_path (store, &iter);
257 indices = gtk_tree_path_get_indices (treepath);
259 gtk_tree_path_free(treepath);
260 // find audio settings
261 if (row < 0) return NULL;
262 audio_list = ghb_settings_get_value(ud->settings, "audio_list");
263 if (row >= ghb_array_len(audio_list))
265 asettings = ghb_array_get_nth(audio_list, row);
271 ghb_audio_list_refresh_selected(signal_user_data_t *ud)
273 GtkTreeView *treeview;
274 GtkTreePath *treepath;
275 GtkTreeSelection *selection;
280 GValue *asettings = NULL;
281 const GValue *audio_list;
283 g_debug("ghb_audio_list_refresh_selected ()");
284 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "audio_list"));
285 selection = gtk_tree_view_get_selection (treeview);
286 if (gtk_tree_selection_get_selected(selection, &store, &iter))
288 const gchar *track, *codec, *br, *sr, *mix;
289 gchar *s_drc, *s_track, *s_codec, *s_br, *s_sr, *s_mix;
292 // Get the row number
293 treepath = gtk_tree_model_get_path (store, &iter);
294 indices = gtk_tree_path_get_indices (treepath);
296 gtk_tree_path_free(treepath);
297 // find audio settings
299 audio_list = ghb_settings_get_value(ud->settings, "audio_list");
300 if (row >= ghb_array_len(audio_list))
302 asettings = ghb_array_get_nth(audio_list, row);
304 track = ghb_settings_combo_option(asettings, "AudioTrack");
305 itrack = ghb_settings_combo_int(asettings, "AudioTrack");
306 codec = ghb_settings_combo_option(asettings, "AudioEncoder");
307 icodec = ghb_settings_combo_int(asettings, "AudioEncoder");
308 br = ghb_settings_combo_option(asettings, "AudioBitrate");
309 sr = ghb_settings_combo_option(asettings, "AudioSamplerate");
310 mix = ghb_settings_combo_option(asettings, "AudioMixdown");
312 s_track = ghb_settings_get_string(asettings, "AudioTrack");
313 s_codec = ghb_settings_get_string(asettings, "AudioEncoder");
314 s_br = ghb_settings_get_string(asettings, "AudioBitrate");
315 s_sr = ghb_settings_get_string(asettings, "AudioSamplerate");
316 s_mix = ghb_settings_get_string(asettings, "AudioMixdown");
317 drc = ghb_settings_get_double(asettings, "AudioTrackDRCSlider");
319 s_drc = g_strdup("Off");
321 s_drc = g_strdup_printf("%.1f", drc);
323 if (icodec == HB_ACODEC_MASK)
324 codec = ghb_select_audio_codec_str(ud, itrack);
326 gtk_list_store_set(GTK_LIST_STORE(store), &iter,
327 // These are displayed in list
334 // These are used to set combo values when a list item is selected
352 audio_codec_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
354 static gint prev_acodec = 0;
355 gint acodec_code, mix_code;
356 GValue *asettings, *gval;
358 g_debug("audio_codec_changed_cb ()");
359 gval = ghb_widget_value(widget);
360 acodec_code = ghb_lookup_combo_int("AudioEncoder", gval);
361 ghb_value_free(gval);
362 if (ghb_audio_is_passthru (prev_acodec) &&
363 !ghb_audio_is_passthru (acodec_code))
365 // Transition from passthru to not, put some audio settings back to
370 titleindex = ghb_settings_combo_int(ud->settings, "title");
371 track = ghb_settings_combo_int(ud->settings, "AudioTrack");
373 ghb_ui_update(ud, "AudioBitrate", ghb_string_value("160"));
374 ghb_ui_update(ud, "AudioSamplerate", ghb_string_value("source"));
375 mix_code = ghb_lookup_combo_int("AudioMixdown", ghb_string_value("dpl2"));
376 mix_code = ghb_get_best_mix( titleindex, track, acodec_code, mix_code);
377 ghb_ui_update(ud, "AudioMixdown", ghb_int64_value(mix_code));
379 ghb_adjust_audio_rate_combos(ud);
380 ghb_grey_combo_options (ud->builder);
381 ghb_check_dependency(ud, widget, NULL);
382 prev_acodec = acodec_code;
383 asettings = get_selected_asettings(ud);
384 if (asettings != NULL)
386 ghb_widget_to_setting(asettings, widget);
387 ghb_audio_list_refresh_selected(ud);
389 ghb_update_destination_extension(ud);
394 audio_track_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
398 g_debug("audio_track_changed_cb ()");
399 ghb_adjust_audio_rate_combos(ud);
400 ghb_check_dependency(ud, widget, NULL);
401 ghb_grey_combo_options(ud->builder);
402 asettings = get_selected_asettings(ud);
403 if (asettings != NULL)
407 ghb_widget_to_setting(asettings, widget);
408 ghb_audio_list_refresh_selected(ud);
409 track = ghb_settings_combo_option(asettings, "AudioTrack");
410 ghb_settings_set_string(asettings, "AudioTrackDescription", track);
416 audio_mix_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
420 g_debug("audio_mix_changed_cb ()");
421 ghb_adjust_audio_rate_combos(ud);
422 ghb_check_dependency(ud, widget, NULL);
423 asettings = get_selected_asettings(ud);
424 if (asettings != NULL)
426 ghb_widget_to_setting(asettings, widget);
427 ghb_audio_list_refresh_selected(ud);
433 audio_widget_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
437 g_debug("audio_widget_changed_cb ()");
438 ghb_check_dependency(ud, widget, NULL);
439 asettings = get_selected_asettings(ud);
440 if (asettings != NULL)
442 ghb_widget_to_setting(asettings, widget);
443 ghb_audio_list_refresh_selected(ud);
449 drc_widget_changed_cb(GtkWidget *widget, gdouble val, signal_user_data_t *ud)
455 g_debug("drc_widget_changed_cb ()");
457 label = GTK_LABEL(GHB_WIDGET(ud->builder, "drc_label"));
459 drc = g_strdup_printf("Off");
461 drc = g_strdup_printf("%.1f", val);
462 gtk_label_set_text(label, drc);
464 ghb_check_dependency(ud, widget, NULL);
465 asettings = get_selected_asettings(ud);
466 if (asettings != NULL)
468 ghb_widget_to_setting(asettings, widget);
469 ghb_audio_list_refresh_selected(ud);
474 // subtitles differ from other settings in that
475 // the selection is updated automaitcally when the title
476 // changes. I don't want the preset selection changed as
477 // would happen for regular settings.
479 subtitle_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
481 const gchar *name = ghb_get_setting_key(widget);
482 g_debug("subtitle_changed_cb () %s", name);
483 ghb_widget_to_setting(ud->settings, widget);
484 ghb_check_dependency(ud, widget, NULL);
489 ghb_clear_audio_list(signal_user_data_t *ud)
491 GtkTreeView *treeview;
495 g_debug("clear_audio_list ()");
496 audio_list = ghb_settings_get_value(ud->settings, "audio_list");
497 if (audio_list == NULL)
499 audio_list = ghb_array_value_new(8);
500 ghb_settings_set_value(ud->settings, "audio_list", audio_list);
503 ghb_array_value_reset(audio_list, 8);
504 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "audio_list"));
505 store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview));
506 gtk_list_store_clear (store);
510 add_to_audio_list(signal_user_data_t *ud, GValue *settings)
512 GtkTreeView *treeview;
515 GtkTreeSelection *selection;
516 const gchar *track, *codec, *br, *sr, *mix;
517 gchar *s_drc, *s_track, *s_codec, *s_br, *s_sr, *s_mix;
521 g_debug("add_to_audio_list ()");
522 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "audio_list"));
523 selection = gtk_tree_view_get_selection (treeview);
524 store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview));
526 track = ghb_settings_combo_option(settings, "AudioTrack");
527 itrack = ghb_settings_combo_int(settings, "AudioTrack");
528 codec = ghb_settings_combo_option(settings, "AudioEncoder");
529 icodec = ghb_settings_combo_int(settings, "AudioEncoder");
530 br = ghb_settings_combo_option(settings, "AudioBitrate");
531 sr = ghb_settings_combo_option(settings, "AudioSamplerate");
532 mix = ghb_settings_combo_option(settings, "AudioMixdown");
534 s_track = ghb_settings_get_string(settings, "AudioTrack");
535 s_codec = ghb_settings_get_string(settings, "AudioEncoder");
536 s_br = ghb_settings_get_string(settings, "AudioBitrate");
537 s_sr = ghb_settings_get_string(settings, "AudioSamplerate");
538 s_mix = ghb_settings_get_string(settings, "AudioMixdown");
539 drc = ghb_settings_get_double(settings, "AudioTrackDRCSlider");
541 s_drc = g_strdup("Off");
543 s_drc = g_strdup_printf("%.1f", drc);
545 if (icodec == HB_ACODEC_MASK)
547 codec = ghb_select_audio_codec_str(ud, itrack);
550 gtk_list_store_append(store, &iter);
551 gtk_list_store_set(store, &iter,
552 // These are displayed in list
559 // These are used to set combo box values when a list item is selected
567 gtk_tree_selection_select_iter(selection, &iter);
577 audio_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_t *ud)
583 g_debug("audio_list_selection_changed_cb ()");
584 if (gtk_tree_selection_get_selected(selection, &store, &iter))
586 const gchar *track, *codec, *bitrate, *sample_rate, *mix;
589 gtk_tree_model_get(store, &iter,
597 ghb_ui_update(ud, "AudioTrack", ghb_string_value(track));
598 ghb_ui_update(ud, "AudioEncoder", ghb_string_value(codec));
599 ghb_ui_update(ud, "AudioBitrate", ghb_string_value(bitrate));
600 ghb_ui_update(ud, "AudioSamplerate", ghb_string_value(sample_rate));
601 ghb_ui_update(ud, "AudioMixdown", ghb_string_value(mix));
602 ghb_ui_update(ud, "AudioTrackDRCSlider", ghb_double_value(drc));
603 widget = GHB_WIDGET (ud->builder, "audio_remove");
604 gtk_widget_set_sensitive(widget, TRUE);
608 widget = GHB_WIDGET (ud->builder, "audio_remove");
609 gtk_widget_set_sensitive(widget, FALSE);
614 audio_add_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
616 // Add the current audio settings to the list.
623 g_debug("audio_add_clicked_cb ()");
624 asettings = ghb_dict_value_new();
625 // Only allow up to 8 audio entries
626 widget = GHB_WIDGET(ud->builder, "AudioTrack");
627 ghb_settings_take_value(asettings, "AudioTrack", ghb_widget_value(widget));
628 widget = GHB_WIDGET(ud->builder, "AudioEncoder");
629 ghb_settings_take_value(asettings, "AudioEncoder", ghb_widget_value(widget));
630 widget = GHB_WIDGET(ud->builder, "AudioBitrate");
631 ghb_settings_take_value(asettings, "AudioBitrate", ghb_widget_value(widget));
632 widget = GHB_WIDGET(ud->builder, "AudioSamplerate");
633 ghb_settings_take_value(asettings, "AudioSamplerate", ghb_widget_value(widget));
634 widget = GHB_WIDGET(ud->builder, "AudioMixdown");
635 ghb_settings_take_value(asettings, "AudioMixdown", ghb_widget_value(widget));
636 widget = GHB_WIDGET(ud->builder, "AudioTrackDRCSlider");
637 ghb_settings_take_value(asettings, "AudioTrackDRCSlider", ghb_widget_value(widget));
638 track = ghb_settings_combo_option(asettings, "AudioTrack");
639 ghb_settings_set_string(asettings, "AudioTrackDescription", track);
641 audio_list = ghb_settings_get_value(ud->settings, "audio_list");
642 if (audio_list == NULL)
644 audio_list = ghb_array_value_new(8);
645 ghb_settings_set_value(ud->settings, "audio_list", audio_list);
647 ghb_array_append(audio_list, asettings);
648 add_to_audio_list(ud, asettings);
649 count = ghb_array_len(audio_list);
652 gtk_widget_set_sensitive(xwidget, FALSE);
654 ghb_update_destination_extension(ud);
658 audio_remove_clicked_cb(GtkWidget *widget, signal_user_data_t *ud)
660 GtkTreeView *treeview;
661 GtkTreePath *treepath;
662 GtkTreeSelection *selection;
664 GtkTreeIter iter, nextIter;
669 g_debug("audio_remove_clicked_cb ()");
670 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "audio_list"));
671 selection = gtk_tree_view_get_selection (treeview);
672 if (gtk_tree_selection_get_selected(selection, &store, &iter))
675 if (!gtk_tree_model_iter_next(store, &nextIter))
678 if (gtk_tree_model_get_iter_first(store, &nextIter))
680 gtk_tree_selection_select_iter (selection, &nextIter);
685 gtk_tree_selection_select_iter (selection, &nextIter);
687 // Get the row number
688 treepath = gtk_tree_model_get_path (store, &iter);
689 indices = gtk_tree_path_get_indices (treepath);
691 gtk_tree_path_free(treepath);
692 // Remove the selected item
693 gtk_list_store_remove (GTK_LIST_STORE(store), &iter);
694 // remove from audio settings list
696 widget = GHB_WIDGET (ud->builder, "audio_add");
697 gtk_widget_set_sensitive(widget, TRUE);
698 audio_list = ghb_settings_get_value(ud->settings, "audio_list");
699 if (row >= ghb_array_len(audio_list))
701 GValue *old = ghb_array_get_nth(audio_list, row);
703 ghb_array_remove(audio_list, row);
708 ghb_set_audio(signal_user_data_t *ud, GValue *settings)
714 GValue *track, *audio, *acodec, *bitrate, *rate, *mix, *drc;
717 g_debug("set_audio");
718 // Clear the audio list
719 ghb_clear_audio_list(ud);
720 button = GHB_WIDGET (ud->builder, "audio_add");
721 alist = ghb_settings_get_value(settings, "audio_list");
723 count = ghb_array_len(alist);
724 for (ii = 0; ii < count; ii++)
726 audio = ghb_array_get_nth(alist, ii);
727 track = ghb_settings_get_value(audio, "AudioTrack");
728 acodec = ghb_settings_get_value(audio, "AudioEncoder");
729 bitrate = ghb_settings_get_value(audio, "AudioBitrate");
730 rate = ghb_settings_get_value(audio, "AudioSamplerate");
731 mix = ghb_settings_get_value(audio, "AudioMixdown");
732 drc = ghb_settings_get_value(audio, "AudioTrackDRCSlider");
733 acodec_code = ghb_lookup_combo_int("AudioEncoder", acodec);
735 if (acodec_code != 0)
738 g_signal_emit_by_name(button, "clicked", ud);
739 ghb_ui_update(ud, "AudioTrack", track);
740 ghb_ui_update(ud, "AudioEncoder", acodec);
741 if (!ghb_audio_is_passthru (acodec_code))
743 // This gets set autimatically if the codec is passthru
744 ghb_ui_update(ud, "AudioBitrate", bitrate);
745 ghb_ui_update(ud, "AudioSamplerate", rate);
746 ghb_ui_update(ud, "AudioMixdown", mix);
748 ghb_ui_update(ud, "AudioTrackDRCSlider", drc);