diff options
-rw-r--r-- | contrib/ffmpeg/module.defs | 1 | ||||
-rw-r--r-- | contrib/libmkv/A00-update-track-private-data.patch | 144 | ||||
-rw-r--r-- | gtk/src/audiohandler.c | 255 | ||||
-rw-r--r-- | gtk/src/audiohandler.h | 2 | ||||
-rw-r--r-- | gtk/src/callbacks.c | 12 | ||||
-rw-r--r-- | gtk/src/ghb.ui | 499 | ||||
-rw-r--r-- | gtk/src/hb-backend.c | 66 | ||||
-rw-r--r-- | gtk/src/hb-backend.h | 5 | ||||
-rw-r--r-- | gtk/src/internal_defaults.xml | 4 | ||||
-rw-r--r-- | gtk/src/makedeps.py | 16 | ||||
-rw-r--r-- | gtk/src/queuehandler.c | 86 | ||||
-rw-r--r-- | libhb/common.c | 183 | ||||
-rw-r--r-- | libhb/common.h | 21 | ||||
-rw-r--r-- | libhb/encavcodecaudio.c | 66 | ||||
-rw-r--r-- | libhb/encfaac.c | 4 | ||||
-rw-r--r-- | libhb/enclame.c | 17 | ||||
-rw-r--r-- | libhb/encvorbis.c | 44 | ||||
-rw-r--r-- | libhb/internal.h | 2 | ||||
-rw-r--r-- | libhb/muxmkv.c | 61 | ||||
-rw-r--r-- | libhb/muxmp4.c | 8 | ||||
-rw-r--r-- | libhb/platform/macosx/encca_aac.c | 89 | ||||
-rw-r--r-- | libhb/stream.c | 6 | ||||
-rw-r--r-- | libhb/work.c | 172 | ||||
-rw-r--r-- | macosx/Controller.m | 1 | ||||
-rw-r--r-- | macosx/English.lproj/MainMenu.xib | 1452 | ||||
-rw-r--r-- | macosx/HBAudio.m | 95 | ||||
-rw-r--r-- | macosx/HBAudioController.m | 1 | ||||
-rwxr-xr-x | scripts/manicure.rb | 4 | ||||
-rw-r--r-- | test/test.c | 165 |
29 files changed, 1729 insertions, 1752 deletions
diff --git a/contrib/ffmpeg/module.defs b/contrib/ffmpeg/module.defs index 36c486463..732b7778a 100644 --- a/contrib/ffmpeg/module.defs +++ b/contrib/ffmpeg/module.defs @@ -18,6 +18,7 @@ FFMPEG.CONFIGURE.extra = \ --disable-vaapi \ --disable-dxva2 \ --enable-bzlib \ + --enable-encoder=flac \ --enable-encoder=ac3 \ --enable-encoder=aac \ --enable-encoder=mpeg4 \ diff --git a/contrib/libmkv/A00-update-track-private-data.patch b/contrib/libmkv/A00-update-track-private-data.patch new file mode 100644 index 000000000..97afcf93c --- /dev/null +++ b/contrib/libmkv/A00-update-track-private-data.patch @@ -0,0 +1,144 @@ +diff --git a/include/libmkv.h b/include/libmkv.h +index 4bd6f8c..146a91f 100644 +--- a/include/libmkv.h ++++ b/include/libmkv.h +@@ -216,6 +216,7 @@ struct mk_TrackConfig_s { + mk_Writer *mk_createWriter(const char *filename, int64_t timescale, + uint8_t vlc_compat); + mk_Track *mk_createTrack(mk_Writer *w, mk_TrackConfig *tc); ++int mk_updateTrackPrivateData(mk_Writer *w, mk_Track *track, uint8_t * data, int size ); + int mk_writeHeader(mk_Writer *w, const char *writingApp); + int mk_startFrame(mk_Writer *w, mk_Track *track); + int mk_flushFrame(mk_Writer *w, mk_Track *track); +diff --git a/src/matroska.c b/src/matroska.c +index f61b6f2..b14fd4c 100644 +--- a/src/matroska.c ++++ b/src/matroska.c +@@ -171,8 +171,17 @@ int mk_writeHeader(mk_Writer *w, const char *writingApp) + + w->seek_data.tracks = w->root->d_cur - w->segment_ptr; + +- if (w->tracks) +- CHECK(mk_closeContext(w->tracks, 0)); ++ if (w->tracks) { ++ mk_Track * tk; ++ int i; ++ ++ CHECK(mk_closeContext(w->tracks, &offset)); ++ for (i = 0; i < w->num_tracks; i++) { ++ tk = w->tracks_arr[i]; ++ if (tk->private_data_size) ++ tk->private_data_ptr += offset; ++ } ++ } + + CHECK(mk_flushContextData(w->root)); + +@@ -487,12 +496,8 @@ int mk_close(mk_Writer *w) + + for (i = w->num_tracks - 1; i >= 0; i--) { + tk = w->tracks_arr[i]; +- w->tracks_arr[i] = NULL; +- --w->num_tracks; + if (mk_flushFrame(w, tk) < 0) + ret = -1; +- free(tk); +- tk = NULL; + } + + if (mk_closeCluster(w) < 0) +@@ -611,6 +616,24 @@ int mk_close(mk_Writer *w) + ret = -1; + } + ++ /* update any track private data that may have changed */ ++ for (i = w->num_tracks - 1; i >= 0; i--) { ++ tk = w->tracks_arr[i]; ++ if (tk->private_data_size && tk->private_data) ++ { ++ if (mk_seekFile(w, tk->private_data_ptr) < 0) ++ ret = -1; ++ if (mk_writeBin(w->root, MATROSKA_ID_CODECPRIVATE, ++ tk->private_data, tk->private_data_size) < 0 || ++ mk_flushContextData(w->root) < 0) ++ ret = -1; ++ free(tk->private_data); ++ } ++ w->tracks_arr[i] = NULL; ++ --w->num_tracks; ++ free(tk); ++ } ++ + if (mk_closeContext(w->root, 0) < 0) + ret = -1; + mk_destroyContexts(w); +diff --git a/src/matroska.h b/src/matroska.h +index 515c5ab..2e1eb2f 100644 +--- a/src/matroska.h ++++ b/src/matroska.h +@@ -269,6 +269,9 @@ struct mk_Track_s { + uint64_t default_duration; + mk_TrackType track_type; + int64_t prev_cue_pos; ++ uint8_t *private_data; ++ unsigned private_data_size; ++ int64_t private_data_ptr; + + struct { + mk_Context *data; +diff --git a/src/tracks.c b/src/tracks.c +index d9fc38b..0e224e4 100644 +--- a/src/tracks.c ++++ b/src/tracks.c +@@ -81,6 +81,8 @@ mk_Track *mk_createTrack(mk_Writer *w, mk_TrackConfig *tc) + return NULL; + if (tc->codecPrivateSize && (tc->codecPrivate != NULL)) { + /* CodecPrivate */ ++ track->private_data_size = tc->codecPrivateSize; ++ track->private_data_ptr = ti->d_cur; + if (mk_writeBin(ti, MATROSKA_ID_CODECPRIVATE, tc->codecPrivate, tc->codecPrivateSize) < 0) + return NULL; + } +@@ -191,17 +193,40 @@ mk_Track *mk_createTrack(mk_Writer *w, mk_TrackConfig *tc) + return NULL; + } + +- if (mk_closeContext(ti, 0) < 0) ++ int64_t offset = 0; ++ if (mk_closeContext(ti, &offset) < 0) + return NULL; ++ track->private_data_ptr += offset; + + return track; + } + ++int mk_updateTrackPrivateData(mk_Writer *w, mk_Track *track, uint8_t * data, int size ) ++{ ++ /* can not write data larger than was previously reserved */ ++ if (size > track->private_data_size) ++ return -1; ++ ++ if (track->private_data == NULL) ++ track->private_data = calloc(1, track->private_data_size); ++ memcpy(track->private_data, data, size); ++} ++ + int mk_writeTracks(mk_Writer *w, mk_Context *tracks) + { ++ int i; ++ mk_Track * tk; ++ int64_t offset = 0; ++ + w->seek_data.tracks = w->root->d_cur; + +- CHECK(mk_closeContext(w->tracks, 0)); ++ CHECK(mk_closeContext(w->tracks, &offset)); ++ ++ for (i = 0; i < w->num_tracks; i++) { ++ tk = w->tracks_arr[i]; ++ if (tk->private_data_size) ++ tk->private_data_ptr += offset; ++ } + + return 0; + } diff --git a/gtk/src/audiohandler.c b/gtk/src/audiohandler.c index 90256d6cf..13c26e90d 100644 --- a/gtk/src/audiohandler.c +++ b/gtk/src/audiohandler.c @@ -175,7 +175,7 @@ ghb_adjust_audio_rate_combos(signal_user_data_t *ud) bitrate = aconfig->in.bitrate / 1000; // Set the values for bitrate and samplerate to the input rates - ghb_set_passthru_bitrate_opts (ud->builder, bitrate); + ghb_set_bitrate_opts (ud->builder, bitrate, bitrate, bitrate); mix = 0; ghb_ui_update(ud, "AudioMixdown", ghb_int64_value(mix)); select_acodec &= aconfig->in.codec | HB_ACODEC_PASS_FLAG; @@ -203,7 +203,7 @@ ghb_adjust_audio_rate_combos(signal_user_data_t *ud) int low, high; mix = ghb_get_best_mix( aconfig, select_acodec, mix); hb_get_audio_bitrate_limits(select_acodec, sr, mix, &low, &high); - ghb_set_default_bitrate_opts (ud->builder, low, high); + ghb_set_bitrate_opts (ud->builder, low, high, -1); } ghb_ui_update(ud, "AudioBitrate", ghb_int64_value(bitrate)); @@ -250,9 +250,9 @@ ghb_set_pref_audio(gint titleindex, signal_user_data_t *ud) gint mux; const GValue *pref_audio; - const GValue *audio, *drc, *gain; + const GValue *audio, *drc, *gain, *enable_qual; gint acodec, bitrate, mix; - gdouble rate; + gdouble rate, quality; gint count, ii, list_count; g_debug("set_pref_audio"); @@ -288,6 +288,8 @@ ghb_set_pref_audio(gint titleindex, signal_user_data_t *ud) mix = ghb_settings_combo_int(audio, "AudioMixdown"); drc = ghb_settings_get_value(audio, "AudioTrackDRCSlider"); gain = ghb_settings_get_value(audio, "AudioTrackGain"); + enable_qual = ghb_settings_get_value(audio, "AudioTrackQualityEnable"); + quality = ghb_settings_get_double(audio, "AudioTrackQuality"); // If there are multiple audios using the same codec, then // select sequential tracks for each. The hash keeps track // of the tracks used for each codec. @@ -324,6 +326,7 @@ ghb_set_pref_audio(gint titleindex, signal_user_data_t *ud) bitrate = aconfig->in.bitrate / 1000; bitrate = hb_get_best_audio_bitrate(select_acodec, bitrate, aconfig->in.samplerate, mix); + quality = hb_get_default_audio_quality( select_acodec ); rate = 0; } } @@ -342,6 +345,8 @@ ghb_set_pref_audio(gint titleindex, signal_user_data_t *ud) ghb_lookup_combo_string("AudioEncoder", ghb_int_value(acodec))); ghb_settings_set_value(settings, "AudioEncoderActual", ghb_lookup_acodec_value(select_acodec)); + ghb_settings_set_value(settings, "AudioTrackQualityEnable", enable_qual); + ghb_settings_set_double(settings, "AudioTrackQuality", quality); // This gets set autimatically if the codec is passthru ghb_settings_set_string(settings, "AudioBitrate", ghb_lookup_combo_string("AudioBitrate", ghb_int_value(bitrate))); @@ -412,7 +417,7 @@ ghb_audio_list_refresh_selected(signal_user_data_t *ud) if (gtk_tree_selection_get_selected(selection, &store, &iter)) { const gchar *track, *codec, *br, *sr, *mix; - gchar *s_drc, *s_gain; + gchar *s_drc, *s_gain, *s_quality = NULL; gint itrack; gdouble drc, gain; // Get the row number @@ -430,7 +435,17 @@ ghb_audio_list_refresh_selected(signal_user_data_t *ud) track = ghb_settings_combo_option(asettings, "AudioTrack"); itrack = ghb_settings_combo_int(asettings, "AudioTrack"); codec = ghb_settings_combo_option(asettings, "AudioEncoderActual"); - br = ghb_settings_combo_option(asettings, "AudioBitrate"); + double quality = ghb_settings_get_double(asettings, "AudioTrackQuality"); + if (ghb_settings_get_boolean(asettings, "AudioTrackQualityEnable") && + quality >= 0) + { + int codec = ghb_settings_combo_int(asettings, "AudioEncoderActual"); + s_quality = ghb_format_quality("Q/", codec, quality); + } + else + { + br = ghb_settings_combo_option(asettings, "AudioBitrate"); + } sr = ghb_settings_combo_option(asettings, "AudioSamplerate"); mix = ghb_settings_combo_option(asettings, "AudioMixdown"); gain = ghb_settings_get_double(asettings, "AudioTrackGain"); @@ -446,7 +461,7 @@ ghb_audio_list_refresh_selected(signal_user_data_t *ud) // These are displayed in list 0, track, 1, codec, - 2, br, + 2, s_quality ? s_quality : br, 3, sr, 4, mix, 5, s_gain, @@ -454,6 +469,78 @@ ghb_audio_list_refresh_selected(signal_user_data_t *ud) -1); g_free(s_drc); g_free(s_gain); + g_free(s_quality); + } +} + +void +ghb_audio_list_refresh(signal_user_data_t *ud) +{ + GtkTreeView *treeview; + GtkTreeIter iter; + GtkListStore *store; + gboolean done; + gint row = 0; + const GValue *audio_list; + + g_debug("ghb_audio_list_refresh ()"); + treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "audio_list")); + store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview)); + if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter)) + { + do + { + const gchar *track, *codec, *br, *sr, *mix; + gchar *s_drc, *s_gain, *s_quality = NULL; + gint itrack; + gdouble drc, gain; + GValue *asettings; + + audio_list = ghb_settings_get_value(ud->settings, "audio_list"); + if (row >= ghb_array_len(audio_list)) + return; + asettings = ghb_array_get_nth(audio_list, row); + + track = ghb_settings_combo_option(asettings, "AudioTrack"); + itrack = ghb_settings_combo_int(asettings, "AudioTrack"); + codec = ghb_settings_combo_option(asettings, "AudioEncoderActual"); + double quality = ghb_settings_get_double(asettings, "AudioTrackQuality"); + if (ghb_settings_get_boolean(asettings, "AudioTrackQualityEnable") && + quality >= 0) + { + int codec = ghb_settings_combo_int(asettings, "AudioEncoderActual"); + s_quality = ghb_format_quality("Q/", codec, quality); + } + else + { + br = ghb_settings_combo_option(asettings, "AudioBitrate"); + } + sr = ghb_settings_combo_option(asettings, "AudioSamplerate"); + mix = ghb_settings_combo_option(asettings, "AudioMixdown"); + gain = ghb_settings_get_double(asettings, "AudioTrackGain"); + s_gain = g_strdup_printf("%.fdB", gain); + + drc = ghb_settings_get_double(asettings, "AudioTrackDRCSlider"); + if (drc < 1.0) + s_drc = g_strdup("Off"); + else + s_drc = g_strdup_printf("%.1f", drc); + + gtk_list_store_set(GTK_LIST_STORE(store), &iter, + // These are displayed in list + 0, track, + 1, codec, + 2, s_quality ? s_quality : br, + 3, sr, + 4, mix, + 5, s_gain, + 6, s_drc, + -1); + g_free(s_drc); + g_free(s_gain); + done = !gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter); + row++; + } while (!done); } } @@ -467,17 +554,16 @@ audio_codec_changed_cb(GtkWidget *widget, signal_user_data_t *ud) g_debug("audio_codec_changed_cb ()"); gval = ghb_widget_value(widget); acodec_code = ghb_lookup_combo_int("AudioEncoder", gval); + ghb_value_free(gval); + if (block_updates) { prev_acodec = acodec_code; ghb_grey_combo_options (ud); + ghb_check_dependency(ud, widget, NULL); return; } - gval = ghb_widget_value(widget); - acodec_code = ghb_lookup_combo_int("AudioEncoder", gval); - ghb_value_free(gval); - asettings = get_selected_asettings(ud); if (ghb_audio_is_passthru (prev_acodec) && !ghb_audio_is_passthru (acodec_code)) @@ -533,6 +619,21 @@ audio_codec_changed_cb(GtkWidget *widget, signal_user_data_t *ud) } ghb_update_destination_extension(ud); ghb_live_reset(ud); + + float low, high, gran, defval; + int dir; + hb_get_audio_quality_limits(acodec_code, &low, &high, &gran, &dir); + defval = hb_get_default_audio_quality(acodec_code); + GtkScaleButton *sb; + GtkAdjustment *adj; + sb = GTK_SCALE_BUTTON(GHB_WIDGET(ud->builder, "AudioTrackQuality")); + adj = gtk_scale_button_get_adjustment(sb); + if (dir) + { + // Quality values are inverted + defval = high - defval + low; + } + gtk_adjustment_configure (adj, defval, low, high, gran, gran * 10, 0); } G_MODULE_EXPORT void @@ -543,6 +644,7 @@ audio_track_changed_cb(GtkWidget *widget, signal_user_data_t *ud) g_debug("audio_track_changed_cb ()"); if (block_updates) { + ghb_check_dependency(ud, widget, NULL); ghb_grey_combo_options (ud); return; } @@ -569,7 +671,11 @@ audio_mix_changed_cb(GtkWidget *widget, signal_user_data_t *ud) GValue *asettings; g_debug("audio_mix_changed_cb ()"); - if (block_updates) return; + if (block_updates) + { + ghb_check_dependency(ud, widget, NULL); + return; + } ghb_adjust_audio_rate_combos(ud); ghb_check_dependency(ud, widget, NULL); @@ -588,10 +694,13 @@ audio_widget_changed_cb(GtkWidget *widget, signal_user_data_t *ud) GValue *asettings; g_debug("audio_widget_changed_cb ()"); - if (block_updates) return; + if (block_updates) + { + ghb_check_dependency(ud, widget, NULL); + return; + } ghb_adjust_audio_rate_combos(ud); - ghb_check_dependency(ud, widget, NULL); asettings = get_selected_asettings(ud); if (asettings != NULL) { @@ -605,7 +714,11 @@ G_MODULE_EXPORT void global_audio_widget_changed_cb(GtkWidget *widget, signal_user_data_t *ud) { g_debug("global_audio_widget_changed_cb ()"); - if (block_updates) return; + if (block_updates) + { + ghb_check_dependency(ud, widget, NULL); + return; + } ghb_check_dependency(ud, widget, NULL); ghb_widget_to_setting(ud->settings, widget); @@ -623,6 +736,64 @@ format_drc_cb(GtkScale *scale, gdouble val, signal_user_data_t *ud) return g_strdup_printf("%-7.1f", val); } +static inline int is_close(float a, float b, float metric) +{ + float diff = a - b; + diff = (diff > 0) ? diff : -diff; + return diff < metric; +} + +char * ghb_format_quality( const char *prefix, int codec, double quality ) +{ + float low, high, gran; + int dir; + hb_get_audio_quality_limits(codec, &low, &high, &gran, &dir); + + int digits; + float tmp = gran; + while (1) + { + if (is_close(tmp, (int)tmp, gran / 10)) + break; + digits++; + tmp *= 10; + } + return g_strdup_printf("%s%.*f", prefix, digits, quality); +} + +G_MODULE_EXPORT void +quality_widget_changed_cb(GtkWidget *widget, signal_user_data_t *ud) +{ + GValue *asettings; + + g_debug("quality_widget_changed_cb ()"); + + ghb_check_dependency(ud, widget, NULL); + float low, high, gran; + int dir; + int codec = ghb_settings_combo_int(ud->settings, "AudioEncoderActual"); + hb_get_audio_quality_limits(codec, &low, &high, &gran, &dir); + double quality = ghb_widget_double(widget); + if (dir) + { + // Quality values are inverted + quality = high - quality + low; + } + char *s_quality = ghb_format_quality("", codec, quality); + ghb_ui_update( ud, "AudioTrackQualityValue", ghb_string_value(s_quality)); + g_free(s_quality); + + if (block_updates) return; + + asettings = get_selected_asettings(ud); + if (asettings != NULL) + { + ghb_settings_set_double(asettings, "AudioTrackQuality", quality); + ghb_audio_list_refresh_selected(ud); + } + ghb_live_reset(ud); +} + G_MODULE_EXPORT void drc_widget_changed_cb(GtkWidget *widget, signal_user_data_t *ud) { @@ -630,8 +801,18 @@ drc_widget_changed_cb(GtkWidget *widget, signal_user_data_t *ud) g_debug("drc_widget_changed_cb ()"); - if (block_updates) return; ghb_check_dependency(ud, widget, NULL); + if (block_updates) return; + + double drc = ghb_widget_double(widget); + char *s_drc; + if (drc < 0.99) + s_drc = g_strdup("Off"); + else + s_drc = g_strdup_printf("%.1f", drc); + ghb_ui_update( ud, "AudioTrackDRCValue", ghb_string_value(s_drc)); + g_free(s_drc); + asettings = get_selected_asettings(ud); if (asettings != NULL) { @@ -656,9 +837,19 @@ gain_widget_changed_cb(GtkWidget *widget, signal_user_data_t *ud) g_debug("gain_widget_changed_cb ()"); - if (block_updates) return; ghb_check_dependency(ud, widget, NULL); + if (block_updates) return; asettings = get_selected_asettings(ud); + + int gain = ghb_widget_int(widget); + char *s_gain; + if ( gain >= 21.0 ) + s_gain = g_strdup_printf("*11*"); + else + s_gain = g_strdup_printf("%ddB", gain); + ghb_ui_update( ud, "AudioTrackGainValue", ghb_string_value(s_gain)); + g_free(s_gain); + if (asettings != NULL) { ghb_widget_to_setting(asettings, widget); @@ -696,7 +887,7 @@ add_to_audio_list(signal_user_data_t *ud, GValue *settings) GtkListStore *store; GtkTreeSelection *selection; const gchar *track, *codec, *br, *sr, *mix; - gchar *s_drc, *s_gain; + gchar *s_drc, *s_gain, *s_quality = NULL; gint itrack; gdouble drc; gdouble gain; @@ -709,7 +900,17 @@ add_to_audio_list(signal_user_data_t *ud, GValue *settings) track = ghb_settings_combo_option(settings, "AudioTrack"); itrack = ghb_settings_combo_int(settings, "AudioTrack"); codec = ghb_settings_combo_option(settings, "AudioEncoderActual"); - br = ghb_settings_combo_option(settings, "AudioBitrate"); + double quality = ghb_settings_get_double(settings, "AudioTrackQuality"); + if (ghb_settings_get_boolean(settings, "AudioTrackQualityEnable") && + quality >= 0) + { + int codec = ghb_settings_combo_int(settings, "AudioEncoderActual"); + s_quality = ghb_format_quality("Q/", codec, quality); + } + else + { + br = ghb_settings_combo_option(settings, "AudioBitrate"); + } sr = ghb_settings_combo_option(settings, "AudioSamplerate"); mix = ghb_settings_combo_option(settings, "AudioMixdown"); gain = ghb_settings_get_double(settings, "AudioTrackGain"); @@ -726,7 +927,7 @@ add_to_audio_list(signal_user_data_t *ud, GValue *settings) // These are displayed in list 0, track, 1, codec, - 2, br, + 2, s_quality ? s_quality : br, 3, sr, 4, mix, 5, s_gain, @@ -735,6 +936,7 @@ add_to_audio_list(signal_user_data_t *ud, GValue *settings) gtk_tree_selection_select_iter(selection, &iter); g_free(s_drc); g_free(s_gain); + g_free(s_quality); } G_MODULE_EXPORT void @@ -779,6 +981,8 @@ audio_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_t ghb_ui_update(ud, "AudioMixdown", ghb_settings_get_value(asettings, "AudioMixdown")); ghb_ui_update(ud, "AudioTrackDRCSlider", ghb_settings_get_value(asettings, "AudioTrackDRCSlider")); ghb_ui_update(ud, "AudioTrackGain", ghb_settings_get_value(asettings, "AudioTrackGain")); + ghb_ui_update(ud, "AudioTrackQuality", ghb_settings_get_value(asettings, "AudioTrackQuality")); + ghb_ui_update(ud, "AudioTrackQualityEnable", ghb_settings_get_value(asettings, "AudioTrackQualityEnable")); block_updates = FALSE; widget = GHB_WIDGET (ud->builder, "audio_remove"); gtk_widget_set_sensitive(widget, TRUE); @@ -838,6 +1042,10 @@ audio_add_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) ghb_settings_take_value(asettings, "AudioEncoder", ghb_widget_value(widget)); ghb_settings_set_value(asettings, "AudioEncoderActual", ghb_settings_get_value(ud->settings, "AudioEncoderActual")); + widget = GHB_WIDGET(ud->builder, "AudioTrackQualityEnable"); + ghb_settings_take_value(asettings, "AudioTrackQualityEnable", ghb_widget_value(widget)); + widget = GHB_WIDGET(ud->builder, "AudioTrackQuality"); + ghb_settings_take_value(asettings, "AudioTrackQuality", ghb_widget_value(widget)); widget = GHB_WIDGET(ud->builder, "AudioBitrate"); ghb_settings_take_value(asettings, "AudioBitrate", ghb_widget_value(widget)); widget = GHB_WIDGET(ud->builder, "AudioSamplerate"); @@ -931,7 +1139,8 @@ ghb_set_audio(signal_user_data_t *ud, GValue *settings) gint acodec_code; GValue *alist; - GValue *track, *audio, *acodec, *acodec_actual, *bitrate, *rate, *mix, *drc, *gain; + GValue *track, *audio, *acodec, *acodec_actual, *bitrate, *rate, + *mix, *drc, *gain, *quality, *enable_quality; gint count, ii; g_debug("set_audio"); @@ -946,6 +1155,8 @@ ghb_set_audio(signal_user_data_t *ud, GValue *settings) track = ghb_settings_get_value(audio, "AudioTrack"); acodec = ghb_settings_get_value(audio, "AudioEncoder"); acodec_actual = ghb_settings_get_value(audio, "AudioEncoderActual"); + enable_quality = ghb_settings_get_value(audio, "AudioTrackQualityEnable"); + quality = ghb_settings_get_value(audio, "AudioTrackQuality"); bitrate = ghb_settings_get_value(audio, "AudioBitrate"); rate = ghb_settings_get_value(audio, "AudioSamplerate"); mix = ghb_settings_get_value(audio, "AudioMixdown"); @@ -959,6 +1170,8 @@ ghb_set_audio(signal_user_data_t *ud, GValue *settings) ghb_settings_set_value(settings, "AudioTrack", track); ghb_settings_set_value(settings, "AudioEncoder", acodec); ghb_settings_set_value(settings, "AudioEncoderActual", acodec_actual); + ghb_settings_set_value(settings, "AudioTrackQualityEnable", enable_quality); + ghb_settings_set_value(settings, "AudioTrackQuality", quality); // This gets set autimatically if the codec is passthru ghb_settings_set_value(settings, "AudioBitrate", bitrate); diff --git a/gtk/src/audiohandler.h b/gtk/src/audiohandler.h index 88ee306ae..6ecca9983 100644 --- a/gtk/src/audiohandler.h +++ b/gtk/src/audiohandler.h @@ -36,5 +36,7 @@ gchar* ghb_get_user_audio_lang( void ghb_audio_list_refresh_selected(signal_user_data_t *ud); gint ghb_select_audio_codec(gint mux, hb_audio_config_t *aconfig, gint acodec, gint fallback_acodec, gint copy_mask); int ghb_get_copy_mask(GValue *settings); +void ghb_audio_list_refresh(signal_user_data_t *ud); +char * ghb_format_quality( const char *prefix, int codec, double quality ); #endif // _AUDIOHANDLER_H_ diff --git a/gtk/src/callbacks.c b/gtk/src/callbacks.c index 7b7b81f52..cce28befd 100644 --- a/gtk/src/callbacks.c +++ b/gtk/src/callbacks.c @@ -237,7 +237,6 @@ ghb_check_dependency( continue; } sensitive = dep_check(ud, dep_name, &hide); - g_free(dep_name); if (GTK_IS_ACTION(dep_object)) { gtk_action_set_sensitive(GTK_ACTION(dep_object), sensitive); @@ -248,13 +247,20 @@ ghb_check_dependency( gtk_widget_set_sensitive(GTK_WIDGET(dep_object), sensitive); if (!sensitive && hide) { - gtk_widget_hide(GTK_WIDGET(dep_object)); + if (gtk_widget_get_visible(GTK_WIDGET(dep_object))) + { + gtk_widget_hide(GTK_WIDGET(dep_object)); + } } else { - gtk_widget_show_now(GTK_WIDGET(dep_object)); + if (!gtk_widget_get_visible(GTK_WIDGET(dep_object))) + { + gtk_widget_show_now(GTK_WIDGET(dep_object)); + } } } + g_free(dep_name); } } diff --git a/gtk/src/ghb.ui b/gtk/src/ghb.ui index 5ef2664e6..b25120594 100644 --- a/gtk/src/ghb.ui +++ b/gtk/src/ghb.ui @@ -288,6 +288,14 @@ <property name="page_size">0</property> <property name="value">10</property> </object> + <object class="GtkAdjustment" id="audio_quality_adj"> + <property name="upper">10</property> + <property name="lower">0</property> + <property name="page_increment">1</property> + <property name="step_increment">0.1</property> + <property name="page_size">0</property> + <property name="value">0.0</property> + </object> <object class="GtkImage" id="subtitle_add_image"> <property name="visible">True</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> @@ -2159,6 +2167,22 @@ FFMpeg's and Theora's scale is more linear. These encoders do not have a lossle </packing> </child> <child> + <object class="GtkLabel" id="labela6"> + <property name="visible">True</property> + <property name="xalign">1</property> + <property name="label" translatable="yes"></property> + <property name="use_markup">True</property> + </object> + <packing> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="left_attach">3</property> + <property name="right_attach">3</property> + <property name="x_options">GTK_EXPAND</property> + <property name="y_options">GTK_FILL</property> + </packing> + </child> + <child> <object class="GtkExpander" id="expander1"> <property name="visible">True</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> @@ -2169,186 +2193,279 @@ FFMpeg's and Theora's scale is more linear. These encoders do not have a lossle <property name="visible">True</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <property name="n_rows">4</property> - <property name="n_columns">5</property> + <property name="n_columns">8</property> <property name="row_spacing">5</property> <property name="column_spacing">5</property> <child> - <object class="GtkLabel" id="audio_name_label"> + <object class="GtkHBox" id="hbox40"> <property name="visible">True</property> - <property name="xalign">1</property> - <property name="label" translatable="yes">Track Name:</property> - <property name="use_markup">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="spacing">5</property> + <child> + <object class="GtkLabel" id="labela3"> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="xalign">1</property> + <property name="label" translatable="yes">Auto Passthru:</property> + </object> + <packing> + <property name="position">0</property> + <property name="expand">False</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="AudioAllowMP3Pass"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip-text" translatable="yes">Enable this if your playback device supports AAC. This permits AAC passthru to be selected when automatic passthru selection is enabled.</property> + <property name="label" translatable="yes">MP3</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + <signal handler="global_audio_widget_changed_cb" name="toggled"/> + </object> + <packing> + <property name="position">1</property> + <property name="expand">False</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="AudioAllowAACPass"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip-text" translatable="yes">Enable this if your playback device supports AAC. This permits AAC passthru to be selected when automatic passthru selection is enabled.</property> + <property name="label" translatable="yes">AAC</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + <signal handler="global_audio_widget_changed_cb" name="toggled"/> + </object> + <packing> + <property name="position">2</property> + <property name="expand">False</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="AudioAllowAC3Pass"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip-text" translatable="yes">Enable this if your playback device supports AC-3. This permits AC-3 passthru to be selected when automatic passthru selection is enabled.</property> + <property name="label" translatable="yes">AC-3</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + <signal handler="global_audio_widget_changed_cb" name="toggled"/> + </object> + <packing> + <property name="position">3</property> + <property name="expand">False</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="AudioAllowDTSPass"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip-text" translatable="yes">Enable this if your playback device supports DTS. This permits DTS passthru to be selected when automatic passthru selection is enabled.</property> + <property name="label" translatable="yes">DTS</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + <signal handler="global_audio_widget_changed_cb" name="toggled"/> + </object> + <packing> + <property name="position">4</property> + <property name="expand">False</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="AudioAllowDTSHDPass"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip-text" translatable="yes">Enable this if your playback device supports DTS-HD. This permits DTS-HD passthru to be selected when automatic passthru selection is enabled.</property> + <property name="label" translatable="yes">DTS-HD</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + <signal handler="global_audio_widget_changed_cb" name="toggled"/> + </object> + <packing> + <property name="position">5</property> + <property name="expand">False</property> + </packing> + </child> </object> <packing> <property name="top_attach">0</property> <property name="bottom_attach">1</property> <property name="left_attach">0</property> - <property name="right_attach">1</property> + <property name="right_attach">4</property> <property name="x_options">GTK_FILL</property> </packing> </child> <child> - <object class="GtkAlignment" id="alignment25"> + <object class="GtkLabel" id="labela4"> <property name="visible">True</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="xalign">0</property> - <child> - <object class="GtkEntry" id="AudioTrackName"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="max_length">40</property> - <property name="activates_default">True</property> - <property name="width_chars">20</property> - <property name="truncate_multiline">True</property> - <property name="tooltip-text" translatable="yes">Set the audio track name. Players may use this in the audio selection list.</property> - <signal handler="audio_widget_changed_cb" name="changed"/> - </object> - </child> + <property name="xalign">1</property> + <property name="label" translatable="yes">Passthru Fallback:</property> </object> <packing> <property name="top_attach">0</property> <property name="bottom_attach">1</property> - <property name="left_attach">1</property> - <property name="right_attach">2</property> + <property name="left_attach">4</property> + <property name="right_attach">7</property> <property name="x_options">GTK_FILL</property> </packing> </child> <child> - <object class="GtkLabel" id="fill_label1"> + <object class="GtkComboBox" id="AudioEncoderFallback"> <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_markup">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip-text" translatable="yes">Set the audio codec to encode with when a suitable track can not be found for audio passthru.</property> + <signal handler="global_audio_widget_changed_cb" name="changed"/> </object> <packing> <property name="top_attach">0</property> <property name="bottom_attach">1</property> - <property name="left_attach">2</property> - <property name="right_attach">3</property> - <property name="x_options">GTK_FILL|GTK_EXPAND</property> + <property name="left_attach">7</property> + <property name="right_attach">8</property> + <property name="x_options">GTK_FILL</property> </packing> </child> <child> - <object class="GtkLabel" id="sr_label"> + <object class="GtkHSeparator" id="separator1"> <property name="visible">True</property> - <property name="xalign">1</property> - <property name="label" translatable="yes">Sample Rate:</property> - <property name="use_markup">True</property> + <property name="orientation">horizontal</property> </object> <packing> <property name="top_attach">1</property> <property name="bottom_attach">2</property> <property name="left_attach">0</property> - <property name="right_attach">1</property> + <property name="right_attach">8</property> <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> </packing> </child> <child> - <object class="GtkAlignment" id="alignment34"> + <object class="GtkAlignment" id="alignment59"> <property name="visible">True</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <property name="xalign">0</property> - <property name="xscale">0</property> + <property name="top_padding">8</property> <child> - <object class="GtkComboBox" id="AudioSamplerate"> + <object class="GtkLabel" id="audio_name_label"> <property name="visible">True</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip-text" translatable="yes">Set the sample rate of the output audio track.</property> - <signal handler="audio_widget_changed_cb" name="changed"/> + <property name="xalign">0.5</property> + <property name="label" translatable="yes">Track Name:</property> + <property name="use_markup">True</property> </object> </child> </object> <packing> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="left_attach">1</property> - <property name="right_attach">2</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="left_attach">0</property> + <property name="right_attach">1</property> <property name="x_options">GTK_FILL</property> </packing> </child> <child> - <object class="GtkLabel" id="gain_label"> + <object class="GtkAlignment" id="alignment25"> <property name="visible">True</property> - <property name="xalign">1</property> - <property name="label" translatable="yes">Gain:</property> - <property name="use_markup">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="xalign">0</property> + <child> + <object class="GtkEntry" id="AudioTrackName"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="max_length">40</property> + <property name="activates_default">True</property> + <property name="width_chars">20</property> + <property name="truncate_multiline">True</property> + <property name="tooltip-text" translatable="yes">Set the audio track name. Players may use this in the audio selection list.</property> + <signal handler="audio_widget_changed_cb" name="changed"/> + </object> + </child> </object> <packing> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="left_attach">3</property> - <property name="right_attach">4</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="left_attach">0</property> + <property name="right_attach">1</property> <property name="x_options">GTK_FILL</property> </packing> </child> <child> - <object class="GtkHScale" id="AudioTrackGain"> + <object class="GtkLabel" id="AudioSamplerateLabel"> <property name="visible">True</property> - <property name="width-request">150</property> - <property name="orientation">horizontal</property> - <property name="adjustment">adjustment35</property> - <property name="value_pos">right</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip-markup" translatable="yes"><b>Audio Gain:</b> Adjust the amplification or attenuation of the output audio track.</property> - <signal handler="gain_widget_changed_cb" name="value_changed"/> - <signal name="format_value" handler="format_gain_cb"/> + <property name="xalign">0.5</property> + <property name="label" translatable="yes">Sample Rate:</property> + <property name="use_markup">True</property> </object> <packing> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="left_attach">4</property> - <property name="right_attach">5</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="left_attach">1</property> + <property name="right_attach">2</property> <property name="x_options">GTK_FILL</property> </packing> </child> <child> - <object class="GtkLabel" id="drc_label"> + <object class="GtkAlignment" id="alignment34"> <property name="visible">True</property> - <property name="xalign">1</property> - <property name="label" translatable="yes">Dynamic Range Compression:</property> - <property name="use_markup">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="xalign">0.5</property> + <property name="xscale">0</property> + <child> + <object class="GtkComboBox" id="AudioSamplerate"> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip-text" translatable="yes">Set the sample rate of the output audio track.</property> + <signal handler="audio_widget_changed_cb" name="changed"/> + </object> + </child> </object> <packing> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="left_attach">3</property> - <property name="right_attach">4</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="left_attach">1</property> + <property name="right_attach">2</property> <property name="x_options">GTK_FILL</property> </packing> </child> <child> - <object class="GtkHScale" id="AudioTrackDRCSlider"> + <object class="GtkLabel" id="AudioTrackGainLabel"> <property name="visible">True</property> - <property name="width-request">100</property> - <property name="orientation">horizontal</property> - <property name="value_pos">right</property> - <property name="adjustment">adjustment28</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip-markup" translatable="yes"><b>Dynamic Range Compression:</b> Adjust the dynamic range of the output audio track. - - For source audio that has a wide dynamic range (very loud and very soft sequences), DRC allows you to 'compress' the range by making loud sections softer and soft sections louder.</property> - <signal handler="drc_widget_changed_cb" name="value_changed"/> - <signal name="format_value" handler="format_drc_cb"/> + <property name="xalign">0.5</property> + <property name="label" translatable="yes">Gain:</property> + <property name="use_markup">True</property> </object> <packing> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="left_attach">4</property> - <property name="right_attach">5</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="left_attach">2</property> + <property name="right_attach">3</property> <property name="x_options">GTK_FILL</property> </packing> </child> <child> - <object class="GtkHBox" id="hbox40"> + <object class="GtkHBox" id="hbox34"> <property name="visible">True</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="spacing">5</property> + <property name="spacing">0</property> <child> - <object class="GtkLabel" id="labela3"> + <object class="GtkScaleButton" id="AudioTrackGain"> <property name="visible">True</property> + <property name="orientation">vertical</property> + <property name="icons">audio-volume-muted +audio-volume-high +audio-volume-low +audio-volume-medium</property> + <property name="adjustment">adjustment35</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="xalign">1</property> - <property name="label" translatable="yes">Auto Passthru:</property> + <property name="tooltip-markup" translatable="yes"><b>Audio Gain:</b> Adjust the amplification or attenuation of the output audio track.</property> + <signal handler="gain_widget_changed_cb" name="value_changed"/> </object> <packing> <property name="position">0</property> @@ -2356,130 +2473,194 @@ FFMpeg's and Theora's scale is more linear. These encoders do not have a lossle </packing> </child> <child> - <object class="GtkCheckButton" id="AudioAllowMP3Pass"> + <object class="GtkLabel" id="AudioTrackGainValue"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip-text" translatable="yes">Enable this if your playback device supports AAC. This permits AAC passthru to be selected when automatic passthru selection is enabled.</property> - <property name="label" translatable="yes">MP3</property> - <property name="active">True</property> - <property name="draw_indicator">True</property> - <signal handler="global_audio_widget_changed_cb" name="toggled"/> + <property name="width_chars">6</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">0dB</property> + <property name="use_markup">True</property> </object> <packing> <property name="position">1</property> <property name="expand">False</property> </packing> </child> + </object> + <packing> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="left_attach">2</property> + <property name="right_attach">3</property> + <property name="x_options">GTK_FILL</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="AudioTrackDRCSliderLabel"> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="label" translatable="yes">DRC:</property> + <property name="tooltip-markup" translatable="yes"><b>Dynamic Range Compression:</b> Adjust the dynamic range of the output audio track. + + For source audio that has a wide dynamic range (very loud and very soft sequences), DRC allows you to 'compress' the range by making loud sections softer and soft sections louder.</property> + <property name="use_markup">True</property> + </object> + <packing> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="left_attach">3</property> + <property name="right_attach">4</property> + <property name="x_options">GTK_FILL</property> + </packing> + </child> + <child> + <object class="GtkHBox" id="hbox33"> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="spacing">0</property> <child> - <object class="GtkCheckButton" id="AudioAllowAACPass"> + <object class="GtkScaleButton" id="AudioTrackDRCSlider"> <property name="visible">True</property> - <property name="can_focus">True</property> + <property name="orientation">vertical</property> + <property name="icons">audio-input-microphone</property> + <property name="adjustment">adjustment28</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip-text" translatable="yes">Enable this if your playback device supports AAC. This permits AAC passthru to be selected when automatic passthru selection is enabled.</property> - <property name="label" translatable="yes">AAC</property> - <property name="active">True</property> - <property name="draw_indicator">True</property> - <signal handler="global_audio_widget_changed_cb" name="toggled"/> + <property name="tooltip-markup" translatable="yes"><b>Dynamic Range Compression:</b> Adjust the dynamic range of the output audio track. + + For source audio that has a wide dynamic range (very loud and very soft sequences), DRC allows you to 'compress' the range by making loud sections softer and soft sections louder.</property> + <signal handler="drc_widget_changed_cb" name="value_changed"/> </object> <packing> - <property name="position">2</property> + <property name="position">0</property> <property name="expand">False</property> </packing> </child> <child> - <object class="GtkCheckButton" id="AudioAllowAC3Pass"> + <object class="GtkLabel" id="AudioTrackDRCValue"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip-text" translatable="yes">Enable this if your playback device supports AC-3. This permits AC-3 passthru to be selected when automatic passthru selection is enabled.</property> - <property name="label" translatable="yes">AC-3</property> - <property name="active">True</property> - <property name="draw_indicator">True</property> - <signal handler="global_audio_widget_changed_cb" name="toggled"/> + <property name="width_chars">4</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Off</property> + <property name="use_markup">True</property> </object> <packing> - <property name="position">3</property> + <property name="position">1</property> <property name="expand">False</property> </packing> </child> + </object> + <packing> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="left_attach">3</property> + <property name="right_attach">4</property> + <property name="x_options">GTK_FILL</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="AudioTrackQualityEnable"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="label" translatable="yes">Quality:</property> + <property name="tooltip-markup" translatable="yes"><b>Quality:</b> For output codec's that support it, adjust the quality of the output.</property> + <property name="active">False</property> + <property name="draw_indicator">True</property> + <signal handler="audio_widget_changed_cb" name="toggled"/> + </object> + <packing> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="left_attach">4</property> + <property name="right_attach">5</property> + <property name="x_options">GTK_FILL</property> + </packing> + </child> + <child> + <object class="GtkHBox" id="hbox32"> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="spacing">0</property> <child> - <object class="GtkCheckButton" id="AudioAllowDTSPass"> + <object class="GtkScaleButton" id="AudioTrackQuality"> <property name="visible">True</property> - <property name="can_focus">True</property> + <property name="orientation">vertical</property> + <property name="icons">weather-storm +weather-clear +weather-storm +weather-showers-scattered +weather-showers +weather-overcast +weather-few-clouds +weather-clear</property> + <property name="adjustment">audio_quality_adj</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip-text" translatable="yes">Enable this if your playback device supports DTS. This permits DTS passthru to be selected when automatic passthru selection is enabled.</property> - <property name="label" translatable="yes">DTS</property> - <property name="active">True</property> - <property name="draw_indicator">True</property> - <signal handler="global_audio_widget_changed_cb" name="toggled"/> + <property name="tooltip-markup" translatable="yes"><b>Quality:</b> For output codec's that support it, adjust the quality of the output.</property> + <signal handler="quality_widget_changed_cb" name="value_changed"/> </object> <packing> - <property name="position">4</property> + <property name="position">0</property> <property name="expand">False</property> </packing> </child> <child> - <object class="GtkCheckButton" id="AudioAllowDTSHDPass"> + <object class="GtkLabel" id="AudioTrackQualityValue"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip-text" translatable="yes">Enable this if your playback device supports DTS-HD. This permits DTS-HD passthru to be selected when automatic passthru selection is enabled.</property> - <property name="label" translatable="yes">DTS-HD</property> - <property name="active">True</property> - <property name="draw_indicator">True</property> - <signal handler="global_audio_widget_changed_cb" name="toggled"/> + <property name="width_chars">4</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">00.0</property> + <property name="use_markup">True</property> </object> <packing> - <property name="position">5</property> + <property name="position">1</property> <property name="expand">False</property> </packing> </child> </object> <packing> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="left_attach">0</property> - <property name="right_attach">4</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="left_attach">4</property> + <property name="right_attach">5</property> + <property name="x_options">GTK_FILL</property> </packing> </child> <child> - <object class="GtkLabel" id="labela4"> + <object class="GtkLabel" id="filler_label0"> <property name="visible">True</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="xalign">1</property> - <property name="label" translatable="yes">Passthru Fallback:</property> + <property name="label" translatable="yes"></property> + <property name="xalign">0</property> + <property name="use_markup">True</property> </object> <packing> <property name="top_attach">3</property> <property name="bottom_attach">4</property> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="x_options">GTK_FILL</property> + <property name="left_attach">5</property> + <property name="right_attach">8</property> + <property name="x_options">GTK_FILL|GTK_EXPAND</property> </packing> </child> <child> - <object class="GtkComboBox" id="AudioEncoderFallback"> + <object class="GtkLabel" id="filler_label1"> <property name="visible">True</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip-text" translatable="yes">Set the audio codec to encode with when a suitable track can not be found for audio passthru.</property> - <signal handler="global_audio_widget_changed_cb" name="changed"/> + <property name="label" translatable="yes"></property> + <property name="xalign">0</property> + <property name="use_markup">True</property> </object> <packing> - <property name="top_attach">3</property> - <property name="bottom_attach">4</property> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="x_options">GTK_FILL</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="left_attach">5</property> + <property name="right_attach">8</property> + <property name="x_options">GTK_FILL|GTK_EXPAND</property> </packing> </child> </object> </child> </object> <packing> - <property name="top_attach">0</property> + <property name="top_attach">1</property> <property name="bottom_attach">2</property> - <property name="left_attach">2</property> + <property name="left_attach">0</property> <property name="right_attach">3</property> <property name="x_options">GTK_FILL|GTK_EXPAND</property> <property name="y_options"></property> @@ -2526,7 +2707,7 @@ FFMpeg's and Theora's scale is more linear. These encoders do not have a lossle </packing> </child> <child> - <object class="GtkLabel" id="label69"> + <object class="GtkLabel" id="AudioBitrateLabel"> <property name="visible">True</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <property name="label" translatable="yes">Bitrate</property> @@ -2542,7 +2723,7 @@ FFMpeg's and Theora's scale is more linear. These encoders do not have a lossle </packing> </child> <child> - <object class="GtkLabel" id="label24"> + <object class="GtkLabel" id="AudioMixdownLabel"> <property name="visible">True</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <property name="label" translatable="yes">Mix</property> diff --git a/gtk/src/hb-backend.c b/gtk/src/hb-backend.c index 98a13079d..ea817b7ff 100644 --- a/gtk/src/hb-backend.c +++ b/gtk/src/hb-backend.c @@ -3219,21 +3219,30 @@ audio_bitrate_opts_add(GtkBuilder *builder, const gchar *name, gint rate) g_debug("audio_bitrate_opts_add ()\n"); - if (rate < 8) return; + if (rate >= 0 && rate < 8) return; if (ghb_audio_bitrates[hb_audio_bitrates_count].string) { g_free(ghb_audio_bitrates[hb_audio_bitrates_count].string); } ghb_audio_bitrates[hb_audio_bitrates_count].rate = rate; - ghb_audio_bitrates[hb_audio_bitrates_count].string = - g_strdup_printf("%d", rate); + if (rate < 0) + { + ghb_audio_bitrates[hb_audio_bitrates_count].string = + g_strdup_printf("N/A"); + } + else + { + ghb_audio_bitrates[hb_audio_bitrates_count].string = + g_strdup_printf("%d", rate); + } ghb_audio_bitrates_count = hb_audio_bitrates_count + 1; store = get_combo_box_store(builder, name); if (!find_combo_item_by_int(GTK_TREE_MODEL(store), rate, &iter)) { - str = g_strdup_printf ("<small>%d</small>", rate); + str = g_strdup_printf ("<small>%s</small>", + ghb_audio_bitrates[hb_audio_bitrates_count].string); gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, 0, str, @@ -3247,11 +3256,12 @@ audio_bitrate_opts_add(GtkBuilder *builder, const gchar *name, gint rate) } static void -audio_bitrate_opts_clean( +audio_bitrate_opts_update( GtkBuilder *builder, const gchar *name, gint first_rate, - gint last_rate) + gint last_rate, + gint extra_rate) { GtkTreeIter iter; GtkListStore *store; @@ -3270,12 +3280,14 @@ audio_bitrate_opts_clean( do { gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, 3, &ivalue, -1); - if (search_rates( + if (ivalue != first_rate && ivalue != last_rate && + !(ivalue == extra_rate && extra_rate >= first_rate) && + search_rates( ghb_audio_bitrates, ivalue, ghb_audio_bitrates_count) < 0) { done = !gtk_list_store_remove(store, &iter); } - else if (ivalue < first || ivalue > last) + else if ((int)ivalue < first || (int)ivalue > last) { ii++; gtk_list_store_set(store, &iter, 1, FALSE, -1); @@ -3289,6 +3301,8 @@ audio_bitrate_opts_clean( } } while (!done); } + if (extra_rate >= first_rate) + audio_bitrate_opts_add(builder, name, extra_rate); } static void @@ -3327,18 +3341,13 @@ audio_bitrate_opts_set(GtkBuilder *builder, const gchar *name) } void -ghb_set_passthru_bitrate_opts(GtkBuilder *builder, gint bitrate) -{ - audio_bitrate_opts_add(builder, "AudioBitrate", bitrate); -} - -void -ghb_set_default_bitrate_opts( +ghb_set_bitrate_opts( GtkBuilder *builder, gint first_rate, - gint last_rate) + gint last_rate, + gint extra_rate) { - audio_bitrate_opts_clean(builder, "AudioBitrate", first_rate, last_rate); + audio_bitrate_opts_update(builder, "AudioBitrate", first_rate, last_rate, extra_rate); } static ghb_status_t hb_status; @@ -4906,17 +4915,28 @@ add_job(hb_handle_t *h, GValue *js, gint unique_id, gint titleindex) // Make sure the mixdown is valid and pick a new one if not. audio.out.mixdown = ghb_get_best_mix(aconfig, audio.out.codec, audio.out.mixdown); - audio.out.bitrate = - ghb_settings_combo_int(asettings, "AudioBitrate"); + double quality = ghb_settings_get_double(asettings, "AudioTrackQuality"); + if (ghb_settings_get_boolean(asettings, "AudioTrackQualityEnable") && + quality >= 0) + { + audio.out.quality = quality; + audio.out.bitrate = -1; + } + else + { + audio.out.quality = -1; + audio.out.bitrate = + ghb_settings_combo_int(asettings, "AudioBitrate"); + + audio.out.bitrate = hb_get_best_audio_bitrate( + audio.out.codec, audio.out.bitrate, + audio.out.samplerate, audio.out.mixdown); + } gint srate = ghb_settings_combo_int(asettings, "AudioSamplerate"); if (srate == 0) // 0 is same as source audio.out.samplerate = aconfig->in.samplerate; else audio.out.samplerate = srate; - - audio.out.bitrate = hb_get_best_audio_bitrate( - audio.out.codec, audio.out.bitrate, - audio.out.samplerate, audio.out.mixdown); } // Add it to the jobs audio list diff --git a/gtk/src/hb-backend.h b/gtk/src/hb-backend.h index 683ead9c1..4d6f1efa3 100644 --- a/gtk/src/hb-backend.h +++ b/gtk/src/hb-backend.h @@ -135,9 +135,8 @@ gboolean ghb_audio_is_passthru(gint acodec); gboolean ghb_audio_can_passthru(gint acodec); gint ghb_get_default_acodec(void); hb_audio_config_t* ghb_get_scan_audio_info(gint titleindex, gint audioindex); -void ghb_set_passthru_bitrate_opts(GtkBuilder *builder, gint bitrate); -void ghb_set_default_bitrate_opts( - GtkBuilder *builder, gint first_rate, gint last_rate); +void ghb_set_bitrate_opts( + GtkBuilder *builder, gint first_rate, gint last_rate, gint extra_rate); void ghb_grey_combo_options(signal_user_data_t *ud); void ghb_update_ui_combo_box( signal_user_data_t *ud, const gchar *name, gint user_data, gboolean all); diff --git a/gtk/src/internal_defaults.xml b/gtk/src/internal_defaults.xml index b4d06694d..0a6f65aba 100644 --- a/gtk/src/internal_defaults.xml +++ b/gtk/src/internal_defaults.xml @@ -318,6 +318,10 @@ <integer>1</integer> <key>AudioTrackDescription</key> <string></string> + <key>AudioTrackQualityEnable</key> + <false /> + <key>AudioTrackQuality</key> + <real>-1</real> <key>AudioTrackGain</key> <real>0</real> <key>AudioTrackDRCSlider</key> diff --git a/gtk/src/makedeps.py b/gtk/src/makedeps.py index a3c3bdf62..d7c2fa762 100644 --- a/gtk/src/makedeps.py +++ b/gtk/src/makedeps.py @@ -49,13 +49,25 @@ dep_map = ( DepEntry("VideoEncoder", "x264_tab", "x264", False, True), DepEntry("VideoEncoder", "lavc_mpeg4_tab", "ffmpeg|ffmpeg2", False, True), DepEntry("VideoEncoder", "Mp4iPodCompatible", "x264", False, False), + DepEntry("AudioTrackQualityEnable", "AudioTrackQuality", "FALSE", True, False), + DepEntry("AudioTrackQualityEnable", "AudioTrackQualityValue", "FALSE", True, False), + DepEntry("AudioTrackQualityEnable", "AudioBitrateLabel", "TRUE", True, False), + DepEntry("AudioTrackQualityEnable", "AudioBitrate", "TRUE", True, False), + DepEntry("AudioEncoderActual", "AudioTrackQualityEnable", "lame|vorbis", False, True), + DepEntry("AudioEncoderActual", "AudioTrackQuality", "lame|vorbis", False, True), + DepEntry("AudioEncoderActual", "AudioTrackQualityValue", "lame|vorbis", False, True), + DepEntry("AudioEncoderActual", "AudioBitrateLabel", "copy:mp3|copy:aac|copy:ac3|copy:dts|copy:dtshd", True, False), DepEntry("AudioEncoderActual", "AudioBitrate", "copy:mp3|copy:aac|copy:ac3|copy:dts|copy:dtshd", True, False), + DepEntry("AudioEncoderActual", "AudioSamplerateLabel", "copy:mp3|copy:aac|copy:ac3|copy:dts|copy:dtshd", True, False), DepEntry("AudioEncoderActual", "AudioSamplerate", "copy:mp3|copy:aac|copy:ac3|copy:dts|copy:dtshd", True, False), + DepEntry("AudioEncoderActual", "AudioMixdownLabel", "copy:mp3|copy:aac|copy:ac3|copy:dts|copy:dtshd", True, False), DepEntry("AudioEncoderActual", "AudioMixdown", "copy:mp3|copy:aac|copy:ac3|copy:dts|copy:dtshd", True, False), + DepEntry("AudioEncoderActual", "AudioTrackDRCSliderLabel", "copy:mp3|copy:aac|copy:ac3|copy:dts|copy:dtshd", True, False), DepEntry("AudioEncoderActual", "AudioTrackDRCSlider", "copy:mp3|copy:aac|copy:ac3|copy:dts|copy:dtshd", True, False), - DepEntry("AudioEncoderActual", "drc_label", "copy:mp3|copy:aac|copy:ac3|copy:dts|copy:dtshd", True, False), + DepEntry("AudioEncoderActual", "AudioTrackDRCValue", "copy:mp3|copy:aac|copy:ac3|copy:dts|copy:dtshd", True, False), + DepEntry("AudioEncoderActual", "AudioTrackGainLabel", "copy:mp3|copy:aac|copy:ac3|copy:dts|copy:dtshd", True, False), DepEntry("AudioEncoderActual", "AudioTrackGain", "copy:mp3|copy:aac|copy:ac3|copy:dts|copy:dtshd", True, False), - DepEntry("AudioEncoderActual", "gain_label", "copy:mp3|copy:aac|copy:ac3|copy:dts|copy:dtshd", True, False), + DepEntry("AudioEncoderActual", "AudioTrackGainValue", "copy:mp3|copy:aac|copy:ac3|copy:dts|copy:dtshd", True, False), DepEntry("AudioEncoder", "AudioAllowMP3Pass", "copy", False, False), DepEntry("AudioEncoder", "AudioAllowAACPass", "copy", False, False), DepEntry("AudioEncoder", "AudioAllowAC3Pass", "copy", False, False), diff --git a/gtk/src/queuehandler.c b/gtk/src/queuehandler.c index 6b934c14e..8769ad5b3 100644 --- a/gtk/src/queuehandler.c +++ b/gtk/src/queuehandler.c @@ -20,6 +20,7 @@ #include "values.h" #include "callbacks.h" #include "presets.h" +#include "audiohandler.h" #include "ghb-dvd.h" G_MODULE_EXPORT void @@ -400,7 +401,7 @@ add_to_queue_list(signal_user_data_t *ud, GValue *settings, GtkTreeIter *piter) count = ghb_array_len(audio_list); for (ii = 0; ii < count; ii++) { - gchar *bitrate, *samplerate, *track; + gchar *quality = NULL, *samplerate, *track; const gchar *acodec, *mix; GValue *asettings; gdouble sr; @@ -408,7 +409,19 @@ add_to_queue_list(signal_user_data_t *ud, GValue *settings, GtkTreeIter *piter) asettings = ghb_array_get_nth(audio_list, ii); acodec = ghb_settings_combo_option(asettings, "AudioEncoderActual"); - bitrate = ghb_settings_get_string(asettings, "AudioBitrate"); + double q = ghb_settings_get_double(asettings, "AudioTrackQuality"); + if (ghb_settings_get_boolean(asettings, "AudioTrackQualityEnable") && + q >= 0) + { + int codec = ghb_settings_combo_int(asettings, "AudioEncoderActual"); + quality = ghb_format_quality("Quality: ", codec, q); + } + else + { + const char *br; + br = ghb_settings_combo_option(asettings, "AudioBitrate"); + quality = g_strdup_printf("Bitrate: %s", br); + } sr = ghb_settings_get_double(asettings, "AudioSamplerate"); samplerate = ghb_settings_get_string(asettings, "AudioSamplerate"); if ((int)sr == 0) @@ -429,10 +442,10 @@ add_to_queue_list(signal_user_data_t *ud, GValue *settings, GtkTreeIter *piter) g_string_append_printf(str, "\t"); g_string_append_printf(str, - "<small> %s, Encoder: %s, Mixdown: %s, SampleRate: %s, Bitrate: %s</small>\n", - track, acodec, mix, samplerate, bitrate); + "<small> %s, Encoder: %s, Mixdown: %s, SampleRate: %s, %s</small>\n", + track, acodec, mix, samplerate, quality); g_free(track); - g_free(bitrate); + g_free(quality); g_free(samplerate); } @@ -505,67 +518,6 @@ add_to_queue_list(signal_user_data_t *ud, GValue *settings, GtkTreeIter *piter) g_free(preset); } -void -audio_list_refresh(signal_user_data_t *ud) -{ - GtkTreeView *treeview; - GtkTreeIter iter; - GtkListStore *store; - gboolean done; - gint row = 0; - const GValue *audio_list; - - g_debug("ghb_audio_list_refresh ()"); - treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "audio_list")); - store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview)); - if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter)) - { - do - { - const gchar *track, *codec, *br, *sr, *mix; - gchar *s_drc, *s_gain; - gint itrack; - gdouble drc, gain; - GValue *asettings; - - audio_list = ghb_settings_get_value(ud->settings, "audio_list"); - if (row >= ghb_array_len(audio_list)) - return; - asettings = ghb_array_get_nth(audio_list, row); - - track = ghb_settings_combo_option(asettings, "AudioTrack"); - itrack = ghb_settings_combo_int(asettings, "AudioTrack"); - codec = ghb_settings_combo_option(asettings, "AudioEncoderActual"); - br = ghb_settings_combo_option(asettings, "AudioBitrate"); - sr = ghb_settings_combo_option(asettings, "AudioSamplerate"); - mix = ghb_settings_combo_option(asettings, "AudioMixdown"); - gain = ghb_settings_get_double(asettings, "AudioTrackGain"); - s_gain = g_strdup_printf("%.fdB", gain); - - drc = ghb_settings_get_double(asettings, "AudioTrackDRCSlider"); - if (drc < 1.0) - s_drc = g_strdup("Off"); - else - s_drc = g_strdup_printf("%.1f", drc); - - gtk_list_store_set(GTK_LIST_STORE(store), &iter, - // These are displayed in list - 0, track, - 1, codec, - 2, br, - 3, sr, - 4, mix, - 5, s_gain, - 6, s_drc, - -1); - g_free(s_drc); - g_free(s_gain); - done = !gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter); - row++; - } while (!done); - } -} - static gboolean validate_settings(signal_user_data_t *ud) { @@ -711,7 +663,7 @@ validate_settings(signal_user_data_t *ud) { return FALSE; } - audio_list_refresh(ud); + ghb_audio_list_refresh(ud); return TRUE; } diff --git a/libhb/common.c b/libhb/common.c index 5abc9b950..4620602a7 100644 --- a/libhb/common.c +++ b/libhb/common.c @@ -75,6 +75,7 @@ hb_encoder_t hb_audio_encoders[] = { "MP3 (lame)", "lame", HB_ACODEC_LAME, HB_MUX_MP4|HB_MUX_MKV }, { "MP3 Passthru", "copy:mp3", HB_ACODEC_MP3_PASS, HB_MUX_MP4|HB_MUX_MKV }, { "Vorbis (vorbis)", "vorbis", HB_ACODEC_VORBIS, HB_MUX_MKV }, + { "FLAC (ffmpeg)", "ffflac", HB_ACODEC_FFFLAC, HB_MUX_MKV }, { "Auto Passthru", "copy", HB_ACODEC_AUTO_PASS, HB_MUX_MP4|HB_MUX_MKV } }; int hb_audio_encoders_count = sizeof( hb_audio_encoders ) / sizeof( hb_encoder_t ); @@ -211,6 +212,10 @@ int hb_find_closest_audio_bitrate(int bitrate) int ii; int result; + // Check if bitrate mode was disabled + if( bitrate <= 0 ) + return bitrate; + // result is highest rate if none found during search. // rate returned will always be <= rate asked for. result = hb_audio_bitrates[0].rate; @@ -262,8 +267,19 @@ void hb_get_audio_bitrate_limits(uint32_t codec, int samplerate, int mixdown, in int channels; channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(mixdown); - switch (codec) + if( codec & HB_ACODEC_PASS_FLAG ) + { + // Bitrates don't apply to "lossless" audio (Passthru, FLAC) + *low = *high = -1; + return; + } + switch( codec ) { + case HB_ACODEC_FFFLAC: + // Bitrates don't apply to "lossless" audio (Passthru, FLAC) + *high = *low = -1; + break; + case HB_ACODEC_AC3: *low = 32 * channels; if (samplerate > 24000) @@ -432,6 +448,9 @@ int hb_get_default_audio_bitrate( uint32_t codec, int samplerate, int mixdown ) int bitrate, channels; int sr_shift; + if( codec & HB_ACODEC_PASS_FLAG ) + return -1; + channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(mixdown); // Min bitrate is established such that we get good quality @@ -440,6 +459,10 @@ int hb_get_default_audio_bitrate( uint32_t codec, int samplerate, int mixdown ) switch ( codec ) { + case HB_ACODEC_FFFLAC: + bitrate = -1; + sr_shift = 0; + break; case HB_ACODEC_AC3: if (channels == 1) bitrate = 96; @@ -453,12 +476,156 @@ int hb_get_default_audio_bitrate( uint32_t codec, int samplerate, int mixdown ) break; default: bitrate = channels * 80; + break; } bitrate >>= sr_shift; bitrate = hb_get_best_audio_bitrate( codec, bitrate, samplerate, mixdown ); return bitrate; } +// Get limits and hints for the UIs. +// +// granularity sets the minimum step increments that should be used +// (it's ok to round up to some nice multiple if you like) +// +// direction says whether 'low' limit is highest or lowest +// quality (direction 0 == lowest value is worst quality) +void hb_get_audio_quality_limits(uint32_t codec, float *low, float *high, float *granularity, int *direction) +{ + switch( codec ) + { + case HB_ACODEC_LAME: + *direction = 1; + *granularity = 0.5; + *low = 0.; + *high = 10.0; + break; + + case HB_ACODEC_VORBIS: + *direction = 0; + *granularity = 0.05; + *low = 0.; + *high = 1.0; + break; + + case HB_ACODEC_CA_AAC: + *direction = 0; + *granularity = 9; + *low = 0.; + *high = 127.0; + break; + + default: + *direction = 0; + *granularity = 1; + *low = *high = -1.; + break; + } +} + +float hb_get_best_audio_quality( uint32_t codec, float quality) +{ + float low, high, granularity; + int direction; + + hb_get_audio_quality_limits(codec, &low, &high, &granularity, &direction); + if (quality > high) + quality = high; + if (quality < low) + quality = low; + return quality; +} + +float hb_get_default_audio_quality( uint32_t codec ) +{ + float quality; + switch( codec ) + { + case HB_ACODEC_LAME: + quality = 2.; + break; + + case HB_ACODEC_VORBIS: + quality = .5; + break; + + case HB_ACODEC_CA_AAC: + quality = 91.; + break; + + default: + quality = -1.; + break; + } + return quality; +} + +// Get limits and hints for the UIs. +// +// granularity sets the minimum step increments that should be used +// (it's ok to round up to some nice multiple if you like) +// +// direction says whether 'low' limit is highest or lowest +// compression level (direction 0 == lowest value is worst compression level) +void hb_get_audio_compression_limits(uint32_t codec, float *low, float *high, float *granularity, int *direction) +{ + switch( codec ) + { + case HB_ACODEC_FFFLAC: + *direction = 0; + *granularity = 1; + *high = 12; + *low = 0; + break; + + case HB_ACODEC_LAME: + *direction = 1; + *granularity = 1; + *high = 9; + *low = 0; + break; + + default: + *direction = 0; + *granularity = 1; + *low = *high = -1; + break; + } +} + +float hb_get_best_audio_compression( uint32_t codec, float compression) +{ + float low, high, granularity; + int direction; + + hb_get_audio_compression_limits( codec, &low, &high, &granularity, &direction ); + if( compression > high ) + compression = high; + if( compression < low ) + compression = low; + return compression; +} + +float hb_get_default_audio_compression( uint32_t codec ) +{ + float compression; + switch( codec ) + { + case HB_ACODEC_FFFLAC: + compression = 5; + break; + + case HB_ACODEC_LAME: + compression = 2; + break; + + default: + compression = -1; + break; + } + return compression; +} + int hb_get_best_mixdown( uint32_t codec, int layout, int mixdown ) { @@ -527,7 +694,7 @@ int hb_get_best_mixdown( uint32_t codec, int layout, int mixdown ) } // return the best that is not greater than the requested mixdown // 0 means the caller requested the best available mixdown - if( best_mixdown > mixdown && mixdown != 0 ) + if( best_mixdown > mixdown && mixdown > 0 ) best_mixdown = mixdown; return best_mixdown; @@ -539,6 +706,7 @@ int hb_get_default_mixdown( uint32_t codec, int layout ) switch (codec) { // the AC3 encoder defaults to the best mixdown up to 6-channel + case HB_ACODEC_FFFLAC: case HB_ACODEC_AC3: mixdown = HB_AMIXDOWN_6CH; break; @@ -1328,11 +1496,14 @@ void hb_audio_config_init(hb_audio_config_t * audiocfg) /* Initalize some sensable defaults */ audiocfg->in.track = audiocfg->out.track = 0; audiocfg->out.codec = HB_ACODEC_FAAC; - audiocfg->out.bitrate = 128; - audiocfg->out.samplerate = 44100; - audiocfg->out.mixdown = HB_AMIXDOWN_DOLBYPLII; + audiocfg->out.bitrate = -1; + audiocfg->out.quality = -1; + audiocfg->out.compression_level = -1; + audiocfg->out.samplerate = -1; + audiocfg->out.mixdown = -1; audiocfg->out.dynamic_range_compression = 0; audiocfg->out.name = NULL; + } /********************************************************************** @@ -1386,6 +1557,8 @@ int hb_audio_add(const hb_job_t * job, const hb_audio_config_t * audiocfg) audio->config.out.codec &= ~HB_ACODEC_PASS_FLAG; audio->config.out.samplerate = audiocfg->out.samplerate; audio->config.out.bitrate = audiocfg->out.bitrate; + audio->config.out.compression_level = audiocfg->out.compression_level; + audio->config.out.quality = audiocfg->out.quality; audio->config.out.dynamic_range_compression = audiocfg->out.dynamic_range_compression; audio->config.out.mixdown = audiocfg->out.mixdown; audio->config.out.gain = audiocfg->out.gain; diff --git a/libhb/common.h b/libhb/common.h index 2d275978f..65e022880 100644 --- a/libhb/common.h +++ b/libhb/common.h @@ -172,6 +172,12 @@ int hb_find_closest_audio_bitrate(int bitrate); void hb_get_audio_bitrate_limits(uint32_t codec, int samplerate, int mixdown, int *low, int *high); int hb_get_best_audio_bitrate( uint32_t codec, int bitrate, int samplerate, int mixdown); int hb_get_default_audio_bitrate( uint32_t codec, int samplerate, int mixdown ); +void hb_get_audio_quality_limits(uint32_t codec, float *low, float *high, float *granularity, int *direction); +float hb_get_best_audio_quality( uint32_t codec, float quality); +float hb_get_default_audio_quality( uint32_t codec ); +void hb_get_audio_compression_limits(uint32_t codec, float *low, float *high, float *granularity, int *direction); +float hb_get_best_audio_compression( uint32_t codec, float compression); +float hb_get_default_audio_compression( uint32_t codec ); /****************************************************************************** * hb_job_t: settings to be filled by the UI @@ -332,7 +338,7 @@ struct hb_job_s /* Audio starts here */ /* Audio Codecs */ -#define HB_ACODEC_MASK 0x000FFF00 +#define HB_ACODEC_MASK 0x001FFF00 #define HB_ACODEC_FAAC 0x00000100 #define HB_ACODEC_LAME 0x00000200 #define HB_ACODEC_VORBIS 0x00000400 @@ -345,7 +351,8 @@ struct hb_job_s #define HB_ACODEC_FFMPEG 0x00020000 #define HB_ACODEC_DCA_HD 0x00040000 #define HB_ACODEC_MP3 0x00080000 -#define HB_ACODEC_FF_MASK 0x000f0000 +#define HB_ACODEC_FFFLAC 0x00100000 +#define HB_ACODEC_FF_MASK 0x001f0000 #define HB_ACODEC_PASS_FLAG 0x40000000 #define HB_ACODEC_PASS_MASK (HB_ACODEC_MP3 | HB_ACODEC_FFAAC | HB_ACODEC_DCA_HD | HB_ACODEC_AC3 | HB_ACODEC_DCA) #define HB_ACODEC_AUTO_PASS (HB_ACODEC_PASS_MASK | HB_ACODEC_PASS_FLAG) @@ -431,10 +438,12 @@ struct hb_audio_config_s * HB_ACODEC_AC3 means pass-through, then bitrate and samplerate * are ignored. */ - int samplerate; /* Output sample rate (Hz) */ - int samples_per_frame; /* Number of samples per frame */ - int bitrate; /* Output bitrate (kbps) */ - int mixdown; /* The mixdown format to be used for this audio track (see HB_AMIXDOWN_*) */ + int samplerate; /* Output sample rate (Hz) */ + int samples_per_frame; /* Number of samples per frame */ + int bitrate; /* Output bitrate (kbps) */ + float quality; /* Output quality */ + float compression_level; /* Output compression level */ + int mixdown; /* The mixdown format to be used for this audio track (see HB_AMIXDOWN_*) */ double dynamic_range_compression; /* Amount of DRC that gets applied to this track */ double gain; /* Gain in dB. negative is quieter */ char * name; /* Output track name */ diff --git a/libhb/encavcodecaudio.c b/libhb/encavcodecaudio.c index 92d2e36d6..cf27f0405 100644 --- a/libhb/encavcodecaudio.c +++ b/libhb/encavcodecaudio.c @@ -95,7 +95,17 @@ static int encavcodecaInit( hb_work_object_t * w, hb_job_t * job ) break; } - context->bit_rate = audio->config.out.bitrate * 1000; + if( audio->config.out.bitrate > 0 ) + context->bit_rate = audio->config.out.bitrate * 1000; + else if( audio->config.out.quality >= 0 ) + { + context->global_quality = audio->config.out.quality * FF_QP2LAMBDA; + context->flags |= CODEC_FLAG_QSCALE; + } + + if( audio->config.out.compression_level >= 0 ) + context->compression_level = audio->config.out.compression_level; + context->sample_rate = audio->config.out.samplerate; context->channels = pv->out_discrete_channels; // Try to set format to float. Fallback to whatever is supported. @@ -120,10 +130,10 @@ static int encavcodecaInit( hb_work_object_t * w, hb_job_t * job ) pv->list = hb_list_init(); - if ( w->codec_param == CODEC_ID_AAC && context->extradata ) + if ( context->extradata ) { - memcpy( w->config->aac.bytes, context->extradata, context->extradata_size ); - w->config->aac.length = context->extradata_size; + memcpy( w->config->extradata.bytes, context->extradata, context->extradata_size ); + w->config->extradata.length = context->extradata_size; } return 0; @@ -134,6 +144,19 @@ static int encavcodecaInit( hb_work_object_t * w, hb_job_t * job ) *********************************************************************** * **********************************************************************/ +// Some encoders (e.g. flac) require a final NULL encode in order to +// finalize things. +static void Finalize( hb_work_object_t * w ) +{ + hb_work_private_t * pv = w->private_data; + hb_buffer_t * buf = hb_buffer_init( pv->output_bytes ); + + // Finalize with NULL input needed by FLAC to generate md5sum + // in context extradata + avcodec_encode_audio( pv->context, buf->data, buf->alloc, NULL ); + hb_buffer_close( &buf ); +} + static void encavcodecaClose( hb_work_object_t * w ) { hb_work_private_t * pv = w->private_data; @@ -142,6 +165,7 @@ static void encavcodecaClose( hb_work_object_t * w ) { if( pv->context ) { + Finalize( w ); hb_deep_log( 2, "encavcodeca: closing libavcodec" ); if ( pv->context->codec ) avcodec_flush_buffers( pv->context ); @@ -238,6 +262,35 @@ static hb_buffer_t * Encode( hb_work_object_t * w ) return buf; } +static hb_buffer_t * Flush( hb_work_object_t * w ) +{ + hb_work_private_t * pv = w->private_data; + hb_buffer_t *first, *buf, *last; + + first = last = buf = Encode( w ); + while( buf ) + { + last = buf; + buf->next = Encode( w ); + buf = buf->next; + } + + if( last ) + { + last->next = hb_buffer_init( pv->output_bytes ); + buf = last->next; + } + else + { + first = buf = hb_buffer_init( pv->output_bytes ); + } + // Finalize with NULL input needed by FLAC to generate md5sum + // in context extradata + avcodec_encode_audio( pv->context, buf->data, buf->alloc, NULL ); + buf->size = 0; + return first; +} + /*********************************************************************** * Work *********************************************************************** @@ -252,9 +305,8 @@ static int encavcodecaWork( hb_work_object_t * w, hb_buffer_t ** buf_in, if ( in->size <= 0 ) { /* EOF on input - send it downstream & say we're done */ - *buf_out = in; - *buf_in = NULL; - return HB_WORK_DONE; + *buf_out = Flush( w ); + return HB_WORK_DONE; } if ( pv->context == NULL || pv->context->codec == NULL ) diff --git a/libhb/encfaac.c b/libhb/encfaac.c index 0ab9124c8..36c69a24d 100644 --- a/libhb/encfaac.c +++ b/libhb/encfaac.c @@ -155,8 +155,8 @@ int encfaacInit( hb_work_object_t * w, hb_job_t * job ) *job->die = 1; return 0; } - memcpy( w->config->aac.bytes, bytes, length ); - w->config->aac.length = length; + memcpy( w->config->extradata.bytes, bytes, length ); + w->config->extradata.length = length; free( bytes ); pv->list = hb_list_init(); diff --git a/libhb/enclame.c b/libhb/enclame.c index 434aa185e..000e0cef5 100644 --- a/libhb/enclame.c +++ b/libhb/enclame.c @@ -51,8 +51,21 @@ int enclameInit( hb_work_object_t * w, hb_job_t * job ) pv->lame = lame_init(); // use ABR lame_set_scale( pv->lame, 32768.0 ); - lame_set_VBR( pv->lame, vbr_abr ); - lame_set_VBR_mean_bitrate_kbps( pv->lame, audio->config.out.bitrate ); + if( audio->config.out.compression_level >= 0 ) + { + lame_set_quality( pv->lame, audio->config.out.compression_level ); + } + if( audio->config.out.bitrate > 0 ) + { + lame_set_VBR( pv->lame, vbr_abr ); + lame_set_VBR_mean_bitrate_kbps( pv->lame, audio->config.out.bitrate ); + } + else if( audio->config.out.quality >= 0 ) + { + lame_set_brate( pv->lame, 0 ); + lame_set_VBR( pv->lame, vbr_default ); + lame_set_VBR_quality( pv->lame, audio->config.out.quality ); + } lame_set_in_samplerate( pv->lame, audio->config.out.samplerate ); lame_set_out_samplerate( pv->lame, audio->config.out.samplerate ); diff --git a/libhb/encvorbis.c b/libhb/encvorbis.c index fc186e089..8ac2e1a58 100644 --- a/libhb/encvorbis.c +++ b/libhb/encvorbis.c @@ -56,16 +56,6 @@ int encvorbisInit( hb_work_object_t * w, hb_job_t * job ) hb_log( "encvorbis: opening libvorbis" ); - /* 28kbps/channel seems to be the minimum for 6ch vorbis. */ - int min_bitrate = 28 * pv->out_discrete_channels; - if (pv->out_discrete_channels > 2 && audio->config.out.bitrate < min_bitrate) - { - hb_log( "encvorbis: Selected bitrate (%d kbps) too low for %d channel audio.", audio->config.out.bitrate, pv->out_discrete_channels); - hb_log( "encvorbis: Resetting bitrate to %d kbps", min_bitrate); - /* Naughty! We shouldn't modify the audio from here. */ - audio->config.out.bitrate = min_bitrate; - } - /* init */ for( i = 0; i < 3; i++ ) { @@ -74,12 +64,36 @@ int encvorbisInit( hb_work_object_t * w, hb_job_t * job ) memset( w->config->vorbis.headers[i], 0, sizeof( ogg_packet ) ); } vorbis_info_init( &pv->vi ); - if( vorbis_encode_setup_managed( &pv->vi, pv->out_discrete_channels, - audio->config.out.samplerate, -1, 1000 * audio->config.out.bitrate, -1 ) ) + + if( audio->config.out.bitrate > 0 ) { - hb_error( "encvorbis: vorbis_encode_setup_managed failed.\n" ); - *job->die = 1; - return 0; + /* 28kbps/channel seems to be the minimum for 6ch vorbis. */ + int min_bitrate = 28 * pv->out_discrete_channels; + if (pv->out_discrete_channels > 2 && audio->config.out.bitrate < min_bitrate) + { + hb_log( "encvorbis: Selected bitrate (%d kbps) too low for %d channel audio.", audio->config.out.bitrate, pv->out_discrete_channels); + hb_log( "encvorbis: Resetting bitrate to %d kbps", min_bitrate); + /* Naughty! We shouldn't modify the audio from here. */ + audio->config.out.bitrate = min_bitrate; + } + + if( vorbis_encode_setup_managed( &pv->vi, pv->out_discrete_channels, + audio->config.out.samplerate, -1, 1000 * audio->config.out.bitrate, -1 ) ) + { + hb_error( "encvorbis: vorbis_encode_setup_managed failed.\n" ); + *job->die = 1; + return 0; + } + } + else if( audio->config.out.quality >= 0 ) + { + if( vorbis_encode_setup_vbr( &pv->vi, pv->out_discrete_channels, + audio->config.out.samplerate, audio->config.out.quality ) ) + { + hb_error( "encvorbis: vorbis_encode_setup_vbr failed.\n" ); + *job->die = 1; + return 0; + } } if( vorbis_encode_ctl( &pv->vi, OV_ECTL_RATEMANAGE2_SET, NULL ) || diff --git a/libhb/internal.h b/libhb/internal.h index 63220f5cb..be9144821 100644 --- a/libhb/internal.h +++ b/libhb/internal.h @@ -307,7 +307,7 @@ union hb_esconfig_u { uint8_t bytes[HB_CONFIG_MAX_SIZE]; int length; - } aac; + } extradata; struct { diff --git a/libhb/muxmkv.c b/libhb/muxmkv.c index 2ec32139d..524ca9d0a 100644 --- a/libhb/muxmkv.c +++ b/libhb/muxmkv.c @@ -35,6 +35,19 @@ struct hb_mux_data_s int sub_format; }; +static uint8_t * create_flac_header( uint8_t *data, int size ) +{ + uint8_t * out; + uint8_t header[8] = { + 0x66, 0x4C, 0x61, 0x43, 0x80, 0x00, 0x00, 0x22 + }; + + out = malloc( size + 8 ); + memcpy( out, header, 8 ); + memcpy( out + 8, data, size ); + return out; +} + /********************************************************************** * MKVInit ********************************************************************** @@ -228,12 +241,22 @@ static int MKVInit( hb_mux_object_t * m ) track->codecPrivateSize = cp_size; } break; + case HB_ACODEC_FFFLAC: + if( audio->priv.config.extradata.bytes ) + { + track->codecPrivate = create_flac_header( + audio->priv.config.extradata.bytes, + audio->priv.config.extradata.length ); + track->codecPrivateSize = audio->priv.config.extradata.length + 8; + } + track->codecID = MK_ACODEC_FLAC; + break; case HB_ACODEC_FAAC: case HB_ACODEC_FFAAC: case HB_ACODEC_CA_AAC: case HB_ACODEC_CA_HAAC: - track->codecPrivate = audio->priv.config.aac.bytes; - track->codecPrivateSize = audio->priv.config.aac.length; + track->codecPrivate = audio->priv.config.extradata.bytes; + track->codecPrivateSize = audio->priv.config.extradata.length; track->codecID = MK_ACODEC_AAC; break; default: @@ -267,7 +290,8 @@ static int MKVInit( hb_mux_object_t * m ) } // track->defaultDuration = job->arate * 1000; mux_data->track = mk_createTrack(m->file, track); - if (audio->config.out.codec == HB_ACODEC_VORBIS && track->codecPrivate != NULL) + if ( audio->config.out.codec == HB_ACODEC_VORBIS || + audio->config.out.codec == HB_ACODEC_FFFLAC ) free(track->codecPrivate); } @@ -545,6 +569,37 @@ static int MKVEnd( hb_mux_object_t * m ) mk_createTagSimple( m->file, MK_TAG_GENRE, md->genre ); } + // Update and track private data that can change during + // encode. + int i; + for( i = 0; i < hb_list_count( title->list_audio ); i++ ) + { + mk_Track * track; + hb_audio_t * audio; + + audio = hb_list_item( title->list_audio, i ); + track = audio->priv.mux_data->track; + + switch (audio->config.out.codec & HB_ACODEC_MASK) + { + case HB_ACODEC_FFFLAC: + if( audio->priv.config.extradata.bytes ) + { + uint8_t *header; + header = create_flac_header( + audio->priv.config.extradata.bytes, + audio->priv.config.extradata.length ); + mk_updateTrackPrivateData( m->file, track, + header, + audio->priv.config.extradata.length + 8 ); + free( header ); + } + break; + default: + break; + } + } + if( mk_close(m->file) < 0 ) { hb_error( "Failed to flush the last frame and close the output file, Disk Full?" ); diff --git a/libhb/muxmp4.c b/libhb/muxmp4.c index 8d93d361a..5234c5a7a 100644 --- a/libhb/muxmp4.c +++ b/libhb/muxmp4.c @@ -379,8 +379,8 @@ static int MP4Init( hb_mux_object_t * m ) case HB_ACODEC_DCA_HD: case HB_ACODEC_DCA: { - uint8_t audio_type; - int samplerate, samples_per_frame, channels, config_len; + uint8_t audio_type = MP4_MPEG4_AUDIO_TYPE; + int samplerate, samples_per_frame, channels, config_len = 0; uint8_t *config_bytes = NULL; switch ( audio->config.out.codec & HB_ACODEC_MASK ) @@ -391,8 +391,8 @@ static int MP4Init( hb_mux_object_t * m ) case HB_ACODEC_CA_HAAC: { audio_type = MP4_MPEG4_AUDIO_TYPE; - config_bytes = audio->priv.config.aac.bytes; - config_len = audio->priv.config.aac.length; + config_bytes = audio->priv.config.extradata.bytes; + config_len = audio->priv.config.extradata.length; } break; case HB_ACODEC_LAME: case HB_ACODEC_MP3: diff --git a/libhb/platform/macosx/encca_aac.c b/libhb/platform/macosx/encca_aac.c index 35b737e79..35eee4a00 100644 --- a/libhb/platform/macosx/encca_aac.c +++ b/libhb/platform/macosx/encca_aac.c @@ -200,33 +200,58 @@ int encCoreAudioInit( hb_work_object_t * w, hb_job_t * job, enum AAC_MODE mode ) AudioConverterSetProperty( pv->converter, kAudioConverterCodecQuality, sizeof( tmp ), &tmp ); - // set encoder bitrate control mode to constrained variable - tmp = kAudioCodecBitRateControlMode_VariableConstrained; - AudioConverterSetProperty( pv->converter, kAudioCodecPropertyBitRateControlMode, - sizeof( tmp ), &tmp ); - - // get available bitrates - AudioValueRange *bitrates; - ssize_t bitrateCounts; - err = AudioConverterGetPropertyInfo( pv->converter, kAudioConverterApplicableEncodeBitRates, - &tmpsiz, NULL); - bitrates = malloc( tmpsiz ); - err = AudioConverterGetProperty( pv->converter, kAudioConverterApplicableEncodeBitRates, - &tmpsiz, bitrates); - bitrateCounts = tmpsiz / sizeof( AudioValueRange ); - - // set bitrate - tmp = audio->config.out.bitrate * 1000; - if( tmp < bitrates[0].mMinimum ) - tmp = bitrates[0].mMinimum; - if( tmp > bitrates[bitrateCounts-1].mMinimum ) - tmp = bitrates[bitrateCounts-1].mMinimum; - free( bitrates ); - if( tmp != audio->config.out.bitrate * 1000 ) - hb_log( "encca_aac: sanitizing track %d audio bitrate %d to %"PRIu32"", - audio->config.out.track, audio->config.out.bitrate, tmp/1000 ); - AudioConverterSetProperty( pv->converter, kAudioConverterEncodeBitRate, - sizeof( tmp ), &tmp ); + if( audio->config.out.bitrate > 0 ) + { + // set encoder bitrate control mode to constrained variable + tmp = kAudioCodecBitRateControlMode_VariableConstrained; + AudioConverterSetProperty( pv->converter, kAudioCodecPropertyBitRateControlMode, + sizeof( tmp ), &tmp ); + + // get available bitrates + AudioValueRange *bitrates; + ssize_t bitrateCounts; + err = AudioConverterGetPropertyInfo( pv->converter, kAudioConverterApplicableEncodeBitRates, + &tmpsiz, NULL); + bitrates = malloc( tmpsiz ); + err = AudioConverterGetProperty( pv->converter, kAudioConverterApplicableEncodeBitRates, + &tmpsiz, bitrates); + bitrateCounts = tmpsiz / sizeof( AudioValueRange ); + + // set bitrate + tmp = audio->config.out.bitrate * 1000; + if( tmp < bitrates[0].mMinimum ) + tmp = bitrates[0].mMinimum; + if( tmp > bitrates[bitrateCounts-1].mMinimum ) + tmp = bitrates[bitrateCounts-1].mMinimum; + free( bitrates ); + if( tmp != audio->config.out.bitrate * 1000 ) + hb_log( "encca_aac: sanitizing track %d audio bitrate %d to %"PRIu32"", + audio->config.out.track, audio->config.out.bitrate, tmp/1000 ); + AudioConverterSetProperty( pv->converter, kAudioConverterEncodeBitRate, + sizeof( tmp ), &tmp ); + } + else if( audio->config.out.quality >= 0 ) + { + if( mode != AAC_MODE_LC ) + { + hb_log( "encCoreAudioInit: internal error, VBR set but not applicable" ); + return 1; + } + // set encoder bitrate control mode to variable + tmp = kAudioCodecBitRateControlMode_Variable; + AudioConverterSetProperty( pv->converter, kAudioCodecPropertyBitRateControlMode, + sizeof( tmp ), &tmp ); + + // set quality + tmp = audio->config.out.quality; + AudioConverterSetProperty( pv->converter, kAudioCodecPropertySoundQualityForVBR, + sizeof( tmp ), &tmp ); + } + else + { + hb_log( "encCoreAudioInit: internal error, bitrate/quality not set" ); + return 1; + } // get real input tmpsiz = sizeof( input ); @@ -272,14 +297,14 @@ int encCoreAudioInit( hb_work_object_t * w, hb_job_t * job, enum AAC_MODE mode ) tmp = HB_CONFIG_MAX_SIZE; AudioConverterGetProperty( pv->converter, kAudioConverterCompressionMagicCookie, - &tmp, w->config->aac.bytes ); + &tmp, w->config->extradata.bytes ); // CoreAudio returns a complete ESDS, but we only need // the DecoderSpecific info. UInt8* buffer = NULL; - ReadESDSDescExt(w->config->aac.bytes, &buffer, &tmpsiz, 0); - w->config->aac.length = tmpsiz; - memmove( w->config->aac.bytes, buffer, - w->config->aac.length ); + ReadESDSDescExt(w->config->extradata.bytes, &buffer, &tmpsiz, 0); + w->config->extradata.length = tmpsiz; + memmove( w->config->extradata.bytes, buffer, + w->config->extradata.length ); pv->list = hb_list_init(); pv->buf = NULL; diff --git a/libhb/stream.c b/libhb/stream.c index f9200ef63..9f2775a4b 100644 --- a/libhb/stream.c +++ b/libhb/stream.c @@ -4923,8 +4923,8 @@ static void add_ffmpeg_audio( hb_title_t *title, hb_stream_t *stream, int id ) else if ( codec->codec_id == CODEC_ID_AAC ) { int len = MIN(codec->extradata_size, HB_CONFIG_MAX_SIZE); - memcpy(audio->priv.config.aac.bytes, codec->extradata, len); - audio->priv.config.aac.length = len; + memcpy(audio->priv.config.extradata.bytes, codec->extradata, len); + audio->priv.config.extradata.length = len; audio->config.in.codec = HB_ACODEC_FFAAC; } else if ( codec->codec_id == CODEC_ID_MP3 ) @@ -4948,6 +4948,7 @@ static void add_ffmpeg_audio( hb_title_t *title, hb_stream_t *stream, int id ) set_audio_description( stream, audio, lang_for_code2( tag ? tag->value : "und" ) ); + audio->config.in.track = id; hb_list_add( title->list_audio, audio ); } } @@ -5127,6 +5128,7 @@ static void add_ffmpeg_subtitle( hb_title_t *title, hb_stream_t *stream, int id memcpy( subtitle->extradata, codec->extradata, codec->extradata_size ); subtitle->extradata_size = codec->extradata_size; + subtitle->track = id; hb_list_add(title->list_subtitle, subtitle); } diff --git a/libhb/work.c b/libhb/work.c index d8cb7b919..ea05c098f 100644 --- a/libhb/work.c +++ b/libhb/work.c @@ -139,6 +139,12 @@ hb_work_object_t * hb_codec_encoder( int codec ) w->codec_param = CODEC_ID_AAC; return w; } + case HB_ACODEC_FFFLAC: + { + w = hb_get_work( WORK_ENCAVCODEC_AUDIO ); + w->codec_param = CODEC_ID_FLAC; + return w; + } case HB_ACODEC_AC3: { w = hb_get_work( WORK_ENCAVCODEC_AUDIO ); @@ -399,7 +405,15 @@ void hb_display_job_info( hb_job_t * job ) if( hb_audio_encoders[j].encoder == audio->config.out.codec ) { hb_log( " + encoder: %s", hb_audio_encoders[j].human_readable_name ); - hb_log( " + bitrate: %d kbps, samplerate: %d Hz", audio->config.out.bitrate, audio->config.out.samplerate ); + if( audio->config.out.bitrate > 0 ) + hb_log( " + bitrate: %d kbps, samplerate: %d Hz", audio->config.out.bitrate, audio->config.out.samplerate ); + else if( audio->config.out.quality >= 0 ) + hb_log( " + quality: %.2f, samplerate: %d Hz", audio->config.out.quality, audio->config.out.samplerate ); + else if( audio->config.out.samplerate > 0 ) + hb_log( " + samplerate: %d Hz", audio->config.out.samplerate ); + if( audio->config.out.compression_level >= 0 ) + hb_log( " + compression level: %.2f", + audio->config.out.compression_level ); break; } } @@ -558,19 +572,19 @@ static void do_job( hb_job_t * job ) free( audio ); continue; } - if( !(audio->config.out.codec & HB_ACODEC_PASS_FLAG) && - audio->config.out.samplerate > 48000 ) + if( !(audio->config.out.codec & HB_ACODEC_PASS_FLAG) ) { - hb_log( "Sample rate %d not supported. Down-sampling to 48kHz.", - audio->config.out.samplerate ); - audio->config.out.samplerate = 48000; - } - if( audio->config.out.codec == HB_ACODEC_AC3 && - audio->config.out.bitrate > 640 ) - { - hb_log( "Bitrate %d not supported. Reducing to 640Kbps.", - audio->config.out.bitrate ); - audio->config.out.bitrate = 640; + if( audio->config.out.samplerate > 48000 ) + { + hb_log( "Sample rate %d not supported. Down-sampling to 48kHz.", + audio->config.out.samplerate ); + audio->config.out.samplerate = 48000; + } + // if not specified, set to same as input + if( audio->config.out.samplerate < 0 ) + { + audio->config.out.samplerate = audio->config.in.samplerate; + } } if( audio->config.out.codec == HB_ACODEC_CA_HAAC ) { @@ -598,20 +612,14 @@ static void do_job( hb_job_t * job ) int requested_mixdown = 0; int requested_mixdown_index = 0; int best_mixdown = 0; - int requested_bitrate = 0; int best_bitrate = 0; for( i = 0; i < hb_list_count( title->list_audio ); i++ ) { audio = hb_list_item( title->list_audio, i ); - best_mixdown = hb_get_best_mixdown( audio->config.out.codec, - audio->config.in.channel_layout, 0 ); - - /* sense-check the current mixdown options */ - /* sense-check the requested mixdown */ - if( audio->config.out.mixdown == 0 && + if( audio->config.out.mixdown <= 0 && !( audio->config.out.codec & HB_ACODEC_PASS_FLAG ) ) { /* @@ -639,12 +647,12 @@ static void do_job( hb_job_t * job ) } } - if ( !( audio->config.out.codec & HB_ACODEC_PASS_FLAG ) ) + best_mixdown = hb_get_best_mixdown( audio->config.out.codec, + audio->config.in.channel_layout, 0 ); + + if ( audio->config.out.mixdown > best_mixdown ) { - if ( audio->config.out.mixdown > best_mixdown ) - { - audio->config.out.mixdown = best_mixdown; - } + audio->config.out.mixdown = best_mixdown; } if ( audio->config.out.mixdown != requested_mixdown ) @@ -663,45 +671,99 @@ static void do_job( hb_job_t * job ) } } - /* sense-check the current bitrates */ - - /* sense-check the requested bitrate */ - if( audio->config.out.bitrate == 0 && - !( audio->config.out.codec & HB_ACODEC_PASS_FLAG ) ) + /* sense-check the requested compression level */ + if( audio->config.out.compression_level < 0 ) { - /* - * Bitrate wasn't specified and this is not pass-through, - * set a default bitrate - */ - audio->config.out.bitrate = hb_get_default_audio_bitrate( audio->config.out.codec, - audio->config.out.samplerate, - audio->config.out.mixdown ); - - hb_log( "work: bitrate not specified, track %d setting bitrate %d", - audio->config.out.track, audio->config.out.bitrate ); + audio->config.out.compression_level = + hb_get_default_audio_compression( audio->config.out.codec ); + if( audio->config.out.compression_level >= 0 ) + { + hb_log( "work: compression level not specified, track %d setting compression level %.2f", + audio->config.out.track, audio->config.out.compression_level ); + } + } + + if( audio->config.out.compression_level >= 0 ) + { + float best_compression = hb_get_best_audio_compression( + audio->config.out.codec, + audio->config.out.compression_level ); + if( best_compression != audio->config.out.compression_level ) + { + if( best_compression == -1 ) + { + hb_log( "work: compression levels not supported by codec" ); + } + else + { + hb_log( "work: sanitizing track %d audio compression level %.2f to %.2f", + audio->config.out.track, + audio->config.out.compression_level, + best_compression ); + } + audio->config.out.compression_level = best_compression; + } } - /* log the requested bitrate */ - requested_bitrate = audio->config.out.bitrate; - best_bitrate = hb_get_best_audio_bitrate( audio->config.out.codec, - audio->config.out.bitrate, - audio->config.out.samplerate, - audio->config.out.mixdown ); - - if ( !( audio->config.out.codec & HB_ACODEC_PASS_FLAG ) ) + /* sense-check the requested quality */ + if( audio->config.out.quality >= 0 ) { - if ( audio->config.out.bitrate != best_bitrate ) + float best_quality = hb_get_best_audio_quality( + audio->config.out.codec, audio->config.out.quality ); + if( best_quality != audio->config.out.quality ) { - audio->config.out.bitrate = best_bitrate; + if( best_quality == -1.0 ) + { + hb_log( "work: quality mode not supported by codec" ); + } + else + { + hb_log( "work: sanitizing track %d audio quality %.2f to %.2f", + audio->config.out.track, + audio->config.out.quality, + best_quality ); + } + audio->config.out.quality = best_quality; } } - if ( audio->config.out.bitrate != requested_bitrate ) + /* sense-check the requested bitrate */ + if( audio->config.out.quality < 0 ) { - /* log the output bitrate */ - hb_log( "work: sanitizing track %d audio bitrate %d to %d", - audio->config.out.track, requested_bitrate, - audio->config.out.bitrate); + if( audio->config.out.bitrate <= 0 ) + { + /* + * Bitrate wasn't specified and this is not pass-through, + * set a default bitrate + */ + audio->config.out.bitrate = + hb_get_default_audio_bitrate( audio->config.out.codec, + audio->config.out.samplerate, + audio->config.out.mixdown ); + + if( audio->config.out.bitrate > 0 ) + { + hb_log( "work: bitrate not specified, track %d setting bitrate %d", + audio->config.out.track, audio->config.out.bitrate ); + } + } + + /* log the requested bitrate */ + best_bitrate = hb_get_best_audio_bitrate( audio->config.out.codec, + audio->config.out.bitrate, + audio->config.out.samplerate, + audio->config.out.mixdown ); + + if ( audio->config.out.bitrate != best_bitrate && + best_bitrate > 0 ) + { + /* log the output bitrate */ + hb_log( "work: sanitizing track %d audio bitrate %d to %d", + audio->config.out.track, + audio->config.out.bitrate, + best_bitrate ); + } + audio->config.out.bitrate = best_bitrate; } if (audio->config.out.codec == HB_ACODEC_VORBIS) diff --git a/macosx/Controller.m b/macosx/Controller.m index 390a0e001..df7770c32 100644 --- a/macosx/Controller.m +++ b/macosx/Controller.m @@ -3781,6 +3781,7 @@ bool one_burned = FALSE; audio->out.gain = [[queueToApply objectForKey: [prefix stringByAppendingString: @"TrackGainSlider"]] floatValue]; prefix = [NSString stringWithFormat: @"JobAudio%d", counter + 1]; audio->out.codec = [[queueToApply objectForKey: [prefix stringByAppendingString: @"Encoder"]] intValue]; + audio->out.compression_level = hb_get_default_audio_compression(audio->out.codec); audio->out.mixdown = [[queueToApply objectForKey: [prefix stringByAppendingString: @"Mixdown"]] intValue]; audio->out.bitrate = [[queueToApply objectForKey: [prefix stringByAppendingString: @"Bitrate"]] intValue]; audio->out.samplerate = [[queueToApply objectForKey: [prefix stringByAppendingString: @"Samplerate"]] intValue]; diff --git a/macosx/English.lproj/MainMenu.xib b/macosx/English.lproj/MainMenu.xib index 6e9fb8a0c..0c0ea86c2 100644 --- a/macosx/English.lproj/MainMenu.xib +++ b/macosx/English.lproj/MainMenu.xib @@ -3,17 +3,46 @@ <data> <int key="IBDocument.SystemTarget">1050</int> <string key="IBDocument.SystemVersion">10K549</string> - <string key="IBDocument.InterfaceBuilderVersion">851</string> + <string key="IBDocument.InterfaceBuilderVersion">1306</string> <string key="IBDocument.AppKitVersion">1038.36</string> <string key="IBDocument.HIToolboxVersion">461.00</string> <object class="NSMutableDictionary" key="IBDocument.PluginVersions"> <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string> - <string key="NS.object.0">851</string> + <string key="NS.object.0">1306</string> </object> - <object class="NSMutableArray" key="IBDocument.EditedObjectIDs"> + <object class="NSArray" key="IBDocument.IntegratedClassDependencies"> <bool key="EncodedWithXMLCoder">YES</bool> - <integer value="1209"/> - <integer value="2"/> + <string>NSTabView</string> + <string>NSScroller</string> + <string>NSMenu</string> + <string>NSSliderCell</string> + <string>NSButton</string> + <string>NSTableHeaderView</string> + <string>NSMatrix</string> + <string>NSCustomObject</string> + <string>NSArrayController</string> + <string>NSImageView</string> + <string>NSTableView</string> + <string>NSCustomView</string> + <string>NSSlider</string> + <string>NSImageCell</string> + <string>NSTextField</string> + <string>NSNumberFormatter</string> + <string>NSWindowTemplate</string> + <string>NSTextFieldCell</string> + <string>NSButtonCell</string> + <string>NSTableColumn</string> + <string>NSBox</string> + <string>NSView</string> + <string>NSOutlineView</string> + <string>NSPopUpButtonCell</string> + <string>NSScrollView</string> + <string>NSTabViewItem</string> + <string>NSProgressIndicator</string> + <string>NSUserDefaultsController</string> + <string>NSPopUpButton</string> + <string>NSMenuItem</string> + <string>NSDrawer</string> </object> <object class="NSArray" key="IBDocument.PluginDependencies"> <bool key="EncodedWithXMLCoder">YES</bool> @@ -46,7 +75,6 @@ <object class="NSMutableString" key="NSViewClass"> <characters key="NS.bytes">View</characters> </object> - <string key="NSWindowContentMaxSize">{1.79769e+308, 1.79769e+308}</string> <string key="NSWindowContentMinSize">{213, 107}</string> <object class="NSView" key="NSWindowView" id="168918359"> <reference key="NSNextResponder"/> @@ -58,6 +86,8 @@ <int key="NSvFlags">264</int> <string key="NSFrame">{{18, 2}, {711, 28}}</string> <reference key="NSSuperview" ref="168918359"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="1007421233"/> <bool key="NSEnabled">YES</bool> <object class="NSTextFieldCell" key="NSCell" id="10523918"> <int key="NSCellFlags">67239424</int> @@ -95,6 +125,8 @@ <object class="NSPSMatrix" key="NSDrawMatrix"/> <string key="NSFrame">{{18, -26}, {930, 20}}</string> <reference key="NSSuperview" ref="168918359"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView"/> <int key="NSpiFlags">16396</int> <double key="NSMaxValue">100</double> </object> @@ -103,6 +135,8 @@ <int key="NSvFlags">264</int> <string key="NSFrame">{{13, 28}, {940, 343}}</string> <reference key="NSSuperview" ref="168918359"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="738554558"/> <object class="NSMutableArray" key="NSTabViewItems"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSTabViewItem" id="107038816"> @@ -256,9 +290,7 @@ <object class="NSArray" key="dict.sortedKeys" id="0"> <bool key="EncodedWithXMLCoder">YES</bool> </object> - <object class="NSMutableArray" key="dict.values"> - <bool key="EncodedWithXMLCoder">YES</bool> - </object> + <reference key="dict.values" ref="0"/> </object> </object> <object class="NSDecimalNumberPlaceholder" key="NS.min" id="464006568"> @@ -944,12 +976,16 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">256</int> <string key="NSFrameSize">{884, 241}</string> <reference key="NSSuperview" ref="528259747"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="794651271"/> <bool key="NSEnabled">YES</bool> <object class="NSTableHeaderView" key="NSHeaderView" id="146611085"> <reference key="NSNextResponder" ref="230332532"/> <int key="NSvFlags">256</int> <string key="NSFrameSize">{884, 17}</string> <reference key="NSSuperview" ref="230332532"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="528259747"/> <reference key="NSTableView" ref="792464451"/> </object> <object class="_NSCornerView" key="NSCornerView" id="727606062"> @@ -957,6 +993,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">-2147483392</int> <string key="NSFrame">{{-26, 0}, {16, 17}}</string> <reference key="NSSuperview" ref="933946879"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="230332532"/> </object> <object class="NSMutableArray" key="NSTableColumns"> <bool key="EncodedWithXMLCoder">YES</bool> @@ -1396,6 +1434,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> </object> <string key="NSFrame">{{1, 17}, {884, 241}}</string> <reference key="NSSuperview" ref="933946879"/> + <reference key="NSWindow"/> <reference key="NSNextKeyView" ref="792464451"/> <reference key="NSDocView" ref="792464451"/> <reference key="NSBGColor" ref="355843302"/> @@ -1406,6 +1445,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">-2147483392</int> <string key="NSFrame">{{-100, -100}, {15, 206}}</string> <reference key="NSSuperview" ref="933946879"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="821562152"/> <reference key="NSTarget" ref="933946879"/> <string key="NSAction">_doScroller:</string> <double key="NSCurValue">37</double> @@ -1416,6 +1457,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">-2147483392</int> <string key="NSFrame">{{-100, -100}, {685, 15}}</string> <reference key="NSSuperview" ref="933946879"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="727606062"/> <int key="NSsFlags">1</int> <reference key="NSTarget" ref="933946879"/> <string key="NSAction">_doScroller:</string> @@ -1430,6 +1473,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> </object> <string key="NSFrame">{{1, 0}, {884, 17}}</string> <reference key="NSSuperview" ref="933946879"/> + <reference key="NSWindow"/> <reference key="NSNextKeyView" ref="146611085"/> <reference key="NSDocView" ref="146611085"/> <reference key="NSBGColor" ref="355843302"/> @@ -1439,7 +1483,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> </object> <string key="NSFrame">{{17, 17}, {886, 259}}</string> <reference key="NSSuperview" ref="577274772"/> - <reference key="NSNextKeyView" ref="528259747"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="496546489"/> <int key="NSsFlags">530</int> <reference key="NSVScroller" ref="496546489"/> <reference key="NSHScroller" ref="821562152"/> @@ -1453,6 +1498,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">268</int> <string key="NSFrame">{{16, 282}, {116, 16}}</string> <reference key="NSSuperview" ref="577274772"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="933946879"/> <bool key="NSEnabled">YES</bool> <object class="NSButtonCell" key="NSCell" id="327570663"> <int key="NSCellFlags">67239424</int> @@ -1471,10 +1518,14 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> </object> <string key="NSFrameSize">{920, 305}</string> <reference key="NSSuperview" ref="738554558"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="883603583"/> </object> </object> <string key="NSFrame">{{10, 25}, {920, 305}}</string> <reference key="NSSuperview" ref="712502892"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="577274772"/> </object> <string key="NSLabel">Audio</string> <reference key="NSColor" ref="242973447"/> @@ -2075,7 +2126,6 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">256</int> <string key="NSFrame">{{870, 17}, {15, 242}}</string> <reference key="NSSuperview" ref="307620967"/> - <reference key="NSNextKeyView" ref="712502892"/> <reference key="NSTarget" ref="307620967"/> <string key="NSAction">_doScroller:</string> <double key="NSPercent">0.9736842</double> @@ -2203,6 +2253,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">268</int> <string key="NSFrame">{{20, 530}, {45, 14}}</string> <reference key="NSSuperview" ref="168918359"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="854767306"/> <bool key="NSEnabled">YES</bool> <object class="NSTextFieldCell" key="NSCell" id="121574898"> <int key="NSCellFlags">67239424</int> @@ -2223,6 +2275,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">264</int> <string key="NSFrame">{{17, 501}, {35, 14}}</string> <reference key="NSSuperview" ref="168918359"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="766125203"/> <bool key="NSEnabled">YES</bool> <object class="NSTextFieldCell" key="NSCell" id="177567437"> <int key="NSCellFlags">67239424</int> @@ -2239,6 +2293,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">264</int> <string key="NSFrame">{{55, 501}, {323, 15}}</string> <reference key="NSSuperview" ref="168918359"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="303369850"/> <bool key="NSEnabled">YES</bool> <object class="NSPopUpButtonCell" key="NSCell" id="821198683"> <int key="NSCellFlags">-2076049856</int> @@ -2291,6 +2347,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">264</int> <string key="NSFrame">{{483, 500}, {77, 15}}</string> <reference key="NSSuperview" ref="168918359"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="971754180"/> <bool key="NSEnabled">YES</bool> <object class="NSPopUpButtonCell" key="NSCell" id="266952854"> <int key="NSCellFlags">-2076049856</int> @@ -2328,6 +2386,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">264</int> <string key="NSFrame">{{385, 498}, {46, 17}}</string> <reference key="NSSuperview" ref="168918359"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="460320725"/> <bool key="NSEnabled">YES</bool> <object class="NSTextFieldCell" key="NSCell" id="677126774"> <int key="NSCellFlags">67239424</int> @@ -2344,6 +2404,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">264</int> <string key="NSFrame">{{433, 500}, {41, 15}}</string> <reference key="NSSuperview" ref="168918359"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="482831442"/> <bool key="NSEnabled">YES</bool> <object class="NSPopUpButtonCell" key="NSCell" id="567459641"> <int key="NSCellFlags">-2076049856</int> @@ -2392,6 +2454,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">264</int> <string key="NSFrame">{{5, 444}, {47, 17}}</string> <reference key="NSSuperview" ref="168918359"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="186223550"/> <bool key="NSEnabled">YES</bool> <object class="NSTextFieldCell" key="NSCell" id="834340599"> <int key="NSCellFlags">67239424</int> @@ -2408,6 +2472,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">264</int> <string key="NSFrame">{{751, 501}, {57, 14}}</string> <reference key="NSSuperview" ref="168918359"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="955053416"/> <bool key="NSEnabled">YES</bool> <object class="NSTextFieldCell" key="NSCell" id="1038625481"> <int key="NSCellFlags">67239424</int> @@ -2424,6 +2490,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">264</int> <string key="NSFrame">{{808, 501}, {79, 14}}</string> <reference key="NSSuperview" ref="168918359"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="138115732"/> <bool key="NSEnabled">YES</bool> <object class="NSTextFieldCell" key="NSCell" id="362196160"> <int key="NSCellFlags">67239424</int> @@ -2443,6 +2511,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">264</int> <string key="NSFrame">{{20, 476}, {70, 14}}</string> <reference key="NSSuperview" ref="168918359"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="104002862"/> <bool key="NSEnabled">YES</bool> <object class="NSTextFieldCell" key="NSCell" id="510160694"> <int key="NSCellFlags">67239424</int> @@ -2459,6 +2529,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">264</int> <string key="NSFrame">{{76, 388}, {177, 22}}</string> <reference key="NSSuperview" ref="168918359"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="553453876"/> <bool key="NSEnabled">YES</bool> <object class="NSPopUpButtonCell" key="NSCell" id="264217237"> <int key="NSCellFlags">-2076049856</int> @@ -2505,6 +2577,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">264</int> <string key="NSFrame">{{755, 440}, {90, 28}}</string> <reference key="NSSuperview" ref="168918359"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="35106907"/> <bool key="NSEnabled">YES</bool> <object class="NSButtonCell" key="NSCell" id="295879492"> <int key="NSCellFlags">67239424</int> @@ -2528,6 +2602,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">264</int> <string key="NSFrame">{{98, 480}, {842, 5}}</string> <reference key="NSSuperview" ref="168918359"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="1023408378"/> <string key="NSOffsets">{0, 0}</string> <object class="NSTextFieldCell" key="NSTitleCell"> <int key="NSCellFlags">67239424</int> @@ -2550,6 +2626,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">264</int> <string key="NSFrame">{{70, 530}, {309, 14}}</string> <reference key="NSSuperview" ref="168918359"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="519699512"/> <bool key="NSEnabled">YES</bool> <object class="NSTextFieldCell" key="NSCell" id="689580100"> <int key="NSCellFlags">69336641</int> @@ -2569,6 +2647,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">264</int> <string key="NSFrame">{{56, 445}, {684, 19}}</string> <reference key="NSSuperview" ref="168918359"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="210289606"/> <bool key="NSEnabled">YES</bool> <object class="NSTextFieldCell" key="NSCell" id="988599137"> <int key="NSCellFlags">-1804468671</int> @@ -2586,6 +2666,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">264</int> <string key="NSFrame">{{571, 485}, {54, 16}}</string> <reference key="NSSuperview" ref="168918359"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="978025076"/> <bool key="NSEnabled">YES</bool> <object class="NSTextFieldCell" key="NSCell" id="371961838"> <int key="NSCellFlags">-1804468671</int> @@ -2603,6 +2685,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">264</int> <string key="NSFrame">{{628, 485}, {54, 16}}</string> <reference key="NSSuperview" ref="168918359"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="453345136"/> <bool key="NSEnabled">YES</bool> <object class="NSTextFieldCell" key="NSCell" id="506346481"> <int key="NSCellFlags">-1804468671</int> @@ -2620,6 +2704,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">264</int> <string key="NSFrame">{{686, 485}, {54, 16}}</string> <reference key="NSSuperview" ref="168918359"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="164276139"/> <bool key="NSEnabled">YES</bool> <object class="NSTextFieldCell" key="NSCell" id="778187711"> <int key="NSCellFlags">-1804468671</int> @@ -2637,6 +2723,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">264</int> <string key="NSFrame">{{748, 485}, {54, 16}}</string> <reference key="NSSuperview" ref="168918359"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="10346684"/> <bool key="NSEnabled">YES</bool> <object class="NSTextFieldCell" key="NSCell" id="1039518079"> <int key="NSCellFlags">-1804468671</int> @@ -2654,6 +2742,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">264</int> <string key="NSFrame">{{20, 420}, {96, 14}}</string> <reference key="NSSuperview" ref="168918359"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="574185541"/> <bool key="NSEnabled">YES</bool> <object class="NSTextFieldCell" key="NSCell" id="293028864"> <int key="NSCellFlags">67239424</int> @@ -2670,6 +2760,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">264</int> <string key="NSFrame">{{294, 424}, {646, 5}}</string> <reference key="NSSuperview" ref="168918359"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="87961628"/> <string key="NSOffsets">{0, 0}</string> <object class="NSTextFieldCell" key="NSTitleCell"> <int key="NSCellFlags">67239424</int> @@ -2692,6 +2784,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">264</int> <string key="NSFrame">{{124, 420}, {162, 14}}</string> <reference key="NSSuperview" ref="168918359"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="151388399"/> <bool key="NSEnabled">YES</bool> <object class="NSTextFieldCell" key="NSCell" id="488791842"> <int key="NSCellFlags">67239424</int> @@ -2708,6 +2802,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">264</int> <string key="NSFrame">{{731, 15}, {218, 14}}</string> <reference key="NSSuperview" ref="168918359"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="222334056"/> <bool key="NSEnabled">YES</bool> <object class="NSTextFieldCell" key="NSCell" id="224806210"> <int key="NSCellFlags">67239424</int> @@ -2724,6 +2820,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">264</int> <string key="NSFrame">{{21, 393}, {53, 14}}</string> <reference key="NSSuperview" ref="168918359"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="732193996"/> <bool key="NSEnabled">YES</bool> <object class="NSTextFieldCell" key="NSCell" id="51600927"> <int key="NSCellFlags">67239424</int> @@ -2740,6 +2838,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">268</int> <string key="NSFrame">{{386, 533}, {554, 5}}</string> <reference key="NSSuperview" ref="168918359"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="806469067"/> <string key="NSOffsets">{0, 0}</string> <object class="NSTextFieldCell" key="NSTitleCell"> <int key="NSCellFlags">67239424</int> @@ -2763,6 +2863,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <object class="NSPSMatrix" key="NSDrawMatrix"/> <string key="NSFrame">{{385, 532}, {562, 12}}</string> <reference key="NSSuperview" ref="168918359"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="454206717"/> <int key="NSpiFlags">16648</int> <double key="NSMaxValue">100</double> </object> @@ -2771,6 +2873,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">264</int> <string key="NSFrame">{{399, 391}, {141, 18}}</string> <reference key="NSSuperview" ref="168918359"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="921877174"/> <bool key="NSEnabled">YES</bool> <object class="NSButtonCell" key="NSCell" id="832863281"> <int key="NSCellFlags">67239424</int> @@ -2793,6 +2897,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">264</int> <string key="NSFrame">{{283, 391}, {102, 18}}</string> <reference key="NSSuperview" ref="168918359"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="581806074"/> <bool key="NSEnabled">YES</bool> <object class="NSButtonCell" key="NSCell" id="294332300"> <int key="NSCellFlags">67239424</int> @@ -2815,6 +2921,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">264</int> <string key="NSFrame">{{541, 391}, {141, 18}}</string> <reference key="NSSuperview" ref="168918359"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="712502892"/> <bool key="NSEnabled">YES</bool> <object class="NSButtonCell" key="NSCell" id="547085070"> <int key="NSCellFlags">67239424</int> @@ -2837,6 +2945,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">264</int> <string key="NSFrame">{{627, 500}, {56, 15}}</string> <reference key="NSSuperview" ref="168918359"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="398989741"/> <bool key="NSEnabled">YES</bool> <object class="NSTextFieldCell" key="NSCell" id="138681808"> <int key="NSCellFlags">67239424</int> @@ -2853,6 +2963,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">264</int> <string key="NSFrame">{{570, 500}, {57, 15}}</string> <reference key="NSSuperview" ref="168918359"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="713493964"/> <bool key="NSEnabled">YES</bool> <object class="NSPopUpButtonCell" key="NSCell" id="286887304"> <int key="NSCellFlags">-2076049856</int> @@ -2901,6 +3013,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <int key="NSvFlags">264</int> <string key="NSFrame">{{685, 500}, {57, 15}}</string> <reference key="NSSuperview" ref="168918359"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="19055068"/> <bool key="NSEnabled">YES</bool> <object class="NSPopUpButtonCell" key="NSCell" id="564669343"> <int key="NSCellFlags">-2076049856</int> @@ -2945,12 +3059,14 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> </object> </object> </object> - <string key="NSFrameSize">{959, 558}</string> + <string key="NSFrame">{{7, 11}, {959, 558}}</string> <reference key="NSSuperview"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="586321835"/> </object> <string key="NSScreenRect">{{0, 0}, {1920, 1178}}</string> <string key="NSMinSize">{213, 129}</string> - <string key="NSMaxSize">{1.79769e+308, 1.79769e+308}</string> + <string key="NSMaxSize">{1e+13, 1e+13}</string> </object> <object class="NSMenu" id="840340181"> <string key="NSTitle">MainMenu</string> @@ -3676,7 +3792,6 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <object class="NSMutableString" key="NSViewClass"> <characters key="NS.bytes">View</characters> </object> - <string key="NSWindowContentMaxSize">{1.79769e+308, 1.79769e+308}</string> <string key="NSWindowContentMinSize">{213, 107}</string> <object class="NSView" key="NSWindowView" id="168254512"> <nil key="NSNextResponder"/> @@ -3761,7 +3876,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> </object> <string key="NSScreenRect">{{0, 0}, {1920, 1178}}</string> <string key="NSMinSize">{213, 129}</string> - <string key="NSMaxSize">{1.79769e+308, 1.79769e+308}</string> + <string key="NSMaxSize">{1e+13, 1e+13}</string> </object> <object class="NSDrawer" id="972647787"> <nil key="NSNextResponder"/> @@ -4029,7 +4144,6 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <object class="NSMutableString" key="NSViewClass"> <characters key="NS.bytes">View</characters> </object> - <string key="NSWindowContentMaxSize">{1.79769e+308, 1.79769e+308}</string> <string key="NSWindowContentMinSize">{338, 232}</string> <object class="NSView" key="NSWindowView" id="69290042"> <nil key="NSNextResponder"/> @@ -4444,7 +4558,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> </object> <string key="NSScreenRect">{{0, 0}, {1920, 1178}}</string> <string key="NSMinSize">{338, 254}</string> - <string key="NSMaxSize">{1.79769e+308, 1.79769e+308}</string> + <string key="NSMaxSize">{1e+13, 1e+13}</string> </object> <object class="NSWindowTemplate" id="687953568"> <int key="NSWindowStyleMask">1</int> @@ -4458,7 +4572,6 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <object class="NSMutableString" key="NSViewClass"> <characters key="NS.bytes">View</characters> </object> - <string key="NSWindowContentMaxSize">{1.79769e+308, 1.79769e+308}</string> <string key="NSWindowContentMinSize">{213, 107}</string> <object class="NSView" key="NSWindowView" id="867624722"> <nil key="NSNextResponder"/> @@ -4627,7 +4740,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> </object> <string key="NSScreenRect">{{0, 0}, {1920, 1178}}</string> <string key="NSMinSize">{213, 129}</string> - <string key="NSMaxSize">{1.79769e+308, 1.79769e+308}</string> + <string key="NSMaxSize">{1e+13, 1e+13}</string> </object> <object class="NSCustomObject" id="2258723"> <string key="NSClassName">HBController</string> @@ -4676,6 +4789,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <string>gain</string> <string>PassThruEnabled</string> <string>PassThruDisabled</string> + <string>bitrateEnabled</string> </object> <bool key="NSEditable">YES</bool> <object class="_NSManagedProxy" key="_NSManagedProxy"/> @@ -6152,22 +6266,6 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> </object> <object class="IBConnectionRecord"> <object class="IBBindingConnection" key="connection"> - <string key="label">enabled: arrangedObjects.enabled</string> - <reference key="source" ref="590927656"/> - <reference key="destination" ref="141316080"/> - <object class="NSNibBindingConnector" key="connector"> - <reference key="NSSource" ref="590927656"/> - <reference key="NSDestination" ref="141316080"/> - <string key="NSLabel">enabled: arrangedObjects.enabled</string> - <string key="NSBinding">enabled</string> - <string key="NSKeyPath">arrangedObjects.enabled</string> - <int key="NSNibBindingConnectorVersion">2</int> - </object> - </object> - <int key="connectionID">5776</int> - </object> - <object class="IBConnectionRecord"> - <object class="IBBindingConnection" key="connection"> <string key="label">enabled: arrangedObjects.mixdownEnabled</string> <reference key="source" ref="1063255"/> <reference key="destination" ref="141316080"/> @@ -6184,22 +6282,6 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> </object> <object class="IBConnectionRecord"> <object class="IBBindingConnection" key="connection"> - <string key="label">enabled: arrangedObjects.mixdownEnabled</string> - <reference key="source" ref="596723553"/> - <reference key="destination" ref="141316080"/> - <object class="NSNibBindingConnector" key="connector"> - <reference key="NSSource" ref="596723553"/> - <reference key="NSDestination" ref="141316080"/> - <string key="NSLabel">enabled: arrangedObjects.mixdownEnabled</string> - <string key="NSBinding">enabled</string> - <string key="NSKeyPath">arrangedObjects.mixdownEnabled</string> - <int key="NSNibBindingConnectorVersion">2</int> - </object> - </object> - <int key="connectionID">5780</int> - </object> - <object class="IBConnectionRecord"> - <object class="IBBindingConnection" key="connection"> <string key="label">selectedObject: arrangedObjects.codec</string> <reference key="source" ref="200958136"/> <reference key="destination" ref="141316080"/> @@ -6602,6 +6684,38 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> </object> <int key="connectionID">5899</int> </object> + <object class="IBConnectionRecord"> + <object class="IBBindingConnection" key="connection"> + <string key="label">enabled: arrangedObjects.mixdownEnabled</string> + <reference key="source" ref="590927656"/> + <reference key="destination" ref="141316080"/> + <object class="NSNibBindingConnector" key="connector"> + <reference key="NSSource" ref="590927656"/> + <reference key="NSDestination" ref="141316080"/> + <string key="NSLabel">enabled: arrangedObjects.mixdownEnabled</string> + <string key="NSBinding">enabled</string> + <string key="NSKeyPath">arrangedObjects.mixdownEnabled</string> + <int key="NSNibBindingConnectorVersion">2</int> + </object> + </object> + <int key="connectionID">5901</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBBindingConnection" key="connection"> + <string key="label">enabled: arrangedObjects.bitrateEnabled</string> + <reference key="source" ref="596723553"/> + <reference key="destination" ref="141316080"/> + <object class="NSNibBindingConnector" key="connector"> + <reference key="NSSource" ref="596723553"/> + <reference key="NSDestination" ref="141316080"/> + <string key="NSLabel">enabled: arrangedObjects.bitrateEnabled</string> + <string key="NSBinding">enabled</string> + <string key="NSKeyPath">arrangedObjects.bitrateEnabled</string> + <int key="NSNibBindingConnectorVersion">2</int> + </object> + </object> + <int key="connectionID">5903</int> + </object> </object> <object class="IBMutableOrderedSet" key="objectRecords"> <object class="NSArray" key="orderedObjects"> @@ -9669,10 +9783,6 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <string>1867.IBWindowTemplateEditedContentRect</string> <string>1867.ImportedFromIB2</string> <string>1867.editorWindowContentRectSynchronizationRect</string> - <string>1867.windowTemplate.hasMaxSize</string> - <string>1867.windowTemplate.hasMinSize</string> - <string>1867.windowTemplate.maxSize</string> - <string>1867.windowTemplate.minSize</string> <string>1868.IBPluginDependency</string> <string>1868.ImportedFromIB2</string> <string>1870.IBPluginDependency</string> @@ -9743,10 +9853,6 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <string>21.IBWindowTemplateEditedContentRect</string> <string>21.ImportedFromIB2</string> <string>21.editorWindowContentRectSynchronizationRect</string> - <string>21.windowTemplate.hasMaxSize</string> - <string>21.windowTemplate.hasMinSize</string> - <string>21.windowTemplate.maxSize</string> - <string>21.windowTemplate.minSize</string> <string>2295.IBPluginDependency</string> <string>2295.ImportedFromIB2</string> <string>2361.IBPluginDependency</string> @@ -9796,10 +9902,6 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <string>2701.IBWindowTemplateEditedContentRect</string> <string>2701.ImportedFromIB2</string> <string>2701.editorWindowContentRectSynchronizationRect</string> - <string>2701.windowTemplate.hasMaxSize</string> - <string>2701.windowTemplate.hasMinSize</string> - <string>2701.windowTemplate.maxSize</string> - <string>2701.windowTemplate.minSize</string> <string>2702.IBPluginDependency</string> <string>2702.ImportedFromIB2</string> <string>2703.IBPluginDependency</string> @@ -9855,10 +9957,6 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <string>434.IBWindowTemplateEditedContentRect</string> <string>434.ImportedFromIB2</string> <string>434.editorWindowContentRectSynchronizationRect</string> - <string>434.windowTemplate.hasMaxSize</string> - <string>434.windowTemplate.hasMinSize</string> - <string>434.windowTemplate.maxSize</string> - <string>434.windowTemplate.minSize</string> <string>435.IBPluginDependency</string> <string>435.ImportedFromIB2</string> <string>436.IBPluginDependency</string> @@ -10326,10 +10424,6 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <string>{{329, 373}, {338, 318}}</string> <integer value="1"/> <string>{{421, 536}, {338, 318}}</string> - <boolean value="NO"/> - <integer value="1"/> - <string>{3.40282e+38, 3.40282e+38}</string> - <string>{338, 232}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> @@ -10400,10 +10494,6 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <string>{{132, 289}, {959, 558}}</string> <integer value="1"/> <string>{{65, 541}, {760, 550}}</string> - <boolean value="NO"/> - <integer value="1"/> - <string>{754, 556}</string> - <string>{213, 107}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> @@ -10460,10 +10550,6 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <string>{{72, 712}, {392, 144}}</string> <integer value="1"/> <string>{{303, 988}, {392, 144}}</string> - <boolean value="NO"/> - <integer value="1"/> - <string>{3.40282e+38, 3.40282e+38}</string> - <string>{213, 107}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> @@ -10519,10 +10605,6 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <string>{{57, 766}, {300, 233}}</string> <integer value="1"/> <string>{{57, 766}, {300, 233}}</string> - <boolean value="NO"/> - <integer value="1"/> - <string>{3.40282e+38, 3.40282e+38}</string> - <string>{213, 107}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> @@ -10802,20 +10884,16 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <object class="NSMutableDictionary" key="unlocalizedProperties"> <bool key="EncodedWithXMLCoder">YES</bool> <reference key="dict.sortedKeys" ref="0"/> - <object class="NSMutableArray" key="dict.values"> - <bool key="EncodedWithXMLCoder">YES</bool> - </object> + <reference key="dict.values" ref="0"/> </object> <nil key="activeLocalization"/> <object class="NSMutableDictionary" key="localizations"> <bool key="EncodedWithXMLCoder">YES</bool> <reference key="dict.sortedKeys" ref="0"/> - <object class="NSMutableArray" key="dict.values"> - <bool key="EncodedWithXMLCoder">YES</bool> - </object> + <reference key="dict.values" ref="0"/> </object> <nil key="sourceID"/> - <int key="maxID">5899</int> + <int key="maxID">5903</int> </object> <object class="IBClassDescriber" key="IBDocument.Classes"> <object class="NSMutableArray" key="referencedPartialClassDescriptions"> @@ -10836,7 +10914,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> </object> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBProjectSource</string> - <string key="minorKey">HBAudioController.h</string> + <string key="minorKey">./Classes/HBAudioController.h</string> </object> </object> <object class="IBPartialClassDescription"> @@ -10881,6 +10959,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <string>openHomepage:</string> <string>openMainWindow:</string> <string>openUserGuide:</string> + <string>presetSelected:</string> <string>qualitySliderChanged:</string> <string>revertPictureSizeToMax:</string> <string>selectDefaultPreset:</string> @@ -10894,6 +10973,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <string>showPreferencesWindow:</string> <string>showPreviewWindow:</string> <string>showQueueWindow:</string> + <string>showScanPanel:</string> <string>showSourceTitleScanPanel:</string> <string>startEndFrameValueChanged:</string> <string>startEndSecValueChanged:</string> @@ -10961,6 +11041,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <string>id</string> <string>id</string> <string>id</string> + <string>id</string> + <string>id</string> </object> </object> <object class="NSMutableDictionary" key="actionInfosByName"> @@ -11002,6 +11084,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <string>openHomepage:</string> <string>openMainWindow:</string> <string>openUserGuide:</string> + <string>presetSelected:</string> <string>qualitySliderChanged:</string> <string>revertPictureSizeToMax:</string> <string>selectDefaultPreset:</string> @@ -11015,6 +11098,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <string>showPreferencesWindow:</string> <string>showPreviewWindow:</string> <string>showQueueWindow:</string> + <string>showScanPanel:</string> <string>showSourceTitleScanPanel:</string> <string>startEndFrameValueChanged:</string> <string>startEndSecValueChanged:</string> @@ -11167,6 +11251,10 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <string key="candidateClassName">id</string> </object> <object class="IBActionInfo"> + <string key="name">presetSelected:</string> + <string key="candidateClassName">id</string> + </object> + <object class="IBActionInfo"> <string key="name">qualitySliderChanged:</string> <string key="candidateClassName">id</string> </object> @@ -11219,6 +11307,10 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <string key="candidateClassName">id</string> </object> <object class="IBActionInfo"> + <string key="name">showScanPanel:</string> + <string key="candidateClassName">id</string> + </object> + <object class="IBActionInfo"> <string key="name">showSourceTitleScanPanel:</string> <string key="candidateClassName">id</string> </object> @@ -11276,6 +11368,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <string>fFramerateMatrix</string> <string>fFramerateVfrPfrCell</string> <string>fLoadChaptersButton</string> + <string>fOpenSourceTitleMMenu</string> <string>fPictureCroppingField</string> <string>fPictureSizeField</string> <string>fPresetDrawer</string> @@ -11338,6 +11431,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <string>fVidTwoPassCheck</string> <string>fVideoFiltersField</string> <string>fWindow</string> + <string>tableView</string> </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> @@ -11361,6 +11455,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <string>NSMatrix</string> <string>NSButtonCell</string> <string>NSButton</string> + <string>NSMenuItem</string> <string>NSTextField</string> <string>NSTextField</string> <string>NSDrawer</string> @@ -11423,6 +11518,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <string>NSButton</string> <string>NSTextField</string> <string>NSWindow</string> + <string>NSTableView</string> </object> </object> <object class="NSMutableDictionary" key="toOneOutletInfosByName"> @@ -11449,6 +11545,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <string>fFramerateMatrix</string> <string>fFramerateVfrPfrCell</string> <string>fLoadChaptersButton</string> + <string>fOpenSourceTitleMMenu</string> <string>fPictureCroppingField</string> <string>fPictureSizeField</string> <string>fPresetDrawer</string> @@ -11511,6 +11608,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <string>fVidTwoPassCheck</string> <string>fVideoFiltersField</string> <string>fWindow</string> + <string>tableView</string> </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> @@ -11595,6 +11693,10 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <string key="candidateClassName">NSButton</string> </object> <object class="IBToOneOutletInfo"> + <string key="name">fOpenSourceTitleMMenu</string> + <string key="candidateClassName">NSMenuItem</string> + </object> + <object class="IBToOneOutletInfo"> <string key="name">fPictureCroppingField</string> <string key="candidateClassName">NSTextField</string> </object> @@ -11842,74 +11944,6 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <string key="name">fWindow</string> <string key="candidateClassName">NSWindow</string> </object> - </object> - </object> - <object class="IBClassDescriptionSource" key="sourceIdentifier" id="896678678"> - <string key="majorKey">IBProjectSource</string> - <string key="minorKey">Controller.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">HBController</string> - <string key="superclassName">NSObject</string> - <object class="NSMutableDictionary" key="actions"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSArray" key="dict.sortedKeys"> - <bool key="EncodedWithXMLCoder">YES</bool> - <string>presetSelected:</string> - <string>showScanPanel:</string> - </object> - <object class="NSMutableArray" key="dict.values"> - <bool key="EncodedWithXMLCoder">YES</bool> - <string>id</string> - <string>id</string> - </object> - </object> - <object class="NSMutableDictionary" key="actionInfosByName"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSArray" key="dict.sortedKeys"> - <bool key="EncodedWithXMLCoder">YES</bool> - <string>presetSelected:</string> - <string>showScanPanel:</string> - </object> - <object class="NSMutableArray" key="dict.values"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="IBActionInfo"> - <string key="name">presetSelected:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">showScanPanel:</string> - <string key="candidateClassName">id</string> - </object> - </object> - </object> - <object class="NSMutableDictionary" key="outlets"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSArray" key="dict.sortedKeys"> - <bool key="EncodedWithXMLCoder">YES</bool> - <string>fOpenSourceTitleMMenu</string> - <string>tableView</string> - </object> - <object class="NSMutableArray" key="dict.values"> - <bool key="EncodedWithXMLCoder">YES</bool> - <string>NSMenuItem</string> - <string>NSTableView</string> - </object> - </object> - <object class="NSMutableDictionary" key="toOneOutletInfosByName"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSArray" key="dict.sortedKeys"> - <bool key="EncodedWithXMLCoder">YES</bool> - <string>fOpenSourceTitleMMenu</string> - <string>tableView</string> - </object> - <object class="NSMutableArray" key="dict.values"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="IBToOneOutletInfo"> - <string key="name">fOpenSourceTitleMMenu</string> - <string key="candidateClassName">NSMenuItem</string> - </object> <object class="IBToOneOutletInfo"> <string key="name">tableView</string> <string key="candidateClassName">NSTableView</string> @@ -11917,1103 +11951,17 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> </object> </object> <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBUserSource</string> - <string key="minorKey"/> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">./Classes/HBController.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">HBPresetsOutlineView</string> <string key="superclassName">NSOutlineView</string> - <reference key="sourceIdentifier" ref="896678678"/> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBUserSource</string> - <string key="minorKey"/> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">SUUpdater</string> - <string key="superclassName">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBUserSource</string> - <string key="minorKey"/> - </object> - </object> - </object> - <object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="IBPartialClassDescription"> - <string key="className">NSActionCell</string> - <string key="superclassName">NSCell</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSActionCell.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSApplication</string> - <string key="superclassName">NSResponder</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier" id="186343158"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSApplication.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSApplication</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier" id="994302592"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSApplicationScripting.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSApplication</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier" id="329150619"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSColorPanel.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSApplication</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSHelpManager.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSApplication</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSPageLayout.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSApplication</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSUserInterfaceItemSearching.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSArrayController</string> - <string key="superclassName">NSObjectController</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSArrayController.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSBox</string> - <string key="superclassName">NSView</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSBox.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSBrowser</string> - <string key="superclassName">NSControl</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSBrowser.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSButton</string> - <string key="superclassName">NSControl</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSButton.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSButtonCell</string> - <string key="superclassName">NSActionCell</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSButtonCell.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSCell</string> - <string key="superclassName">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSCell.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSControl</string> - <string key="superclassName">NSView</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier" id="93521313"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSControl.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSController</string> - <string key="superclassName">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSController.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSDrawer</string> - <string key="superclassName">NSResponder</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier" id="255346542"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSDrawer.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSFormatter</string> - <string key="superclassName">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">Foundation.framework/Headers/NSFormatter.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSImageCell</string> - <string key="superclassName">NSCell</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSImageCell.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSImageView</string> - <string key="superclassName">NSControl</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSImageView.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSMatrix</string> - <string key="superclassName">NSControl</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSMatrix.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSMenu</string> - <string key="superclassName">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier" id="662939028"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSMenu.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSMenuItem</string> - <string key="superclassName">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier" id="955768185"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSMenuItem.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSMenuItemCell</string> - <string key="superclassName">NSButtonCell</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSMenuItemCell.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSMovieView</string> - <string key="superclassName">NSView</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSMovieView.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSNumberFormatter</string> - <string key="superclassName">NSFormatter</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">Foundation.framework/Headers/NSNumberFormatter.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSAccessibility.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <reference key="sourceIdentifier" ref="186343158"/> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <reference key="sourceIdentifier" ref="994302592"/> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <reference key="sourceIdentifier" ref="329150619"/> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <reference key="sourceIdentifier" ref="93521313"/> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSDictionaryController.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSDragging.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSFontManager.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSFontPanel.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSKeyValueBinding.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <reference key="sourceIdentifier" ref="662939028"/> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSNibLoading.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier" id="474309511"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSOutlineView.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSPasteboard.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSSavePanel.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier" id="10931481"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSTableView.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSToolbarItem.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier" id="986196456"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSView.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">Foundation.framework/Headers/NSArchiver.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">Foundation.framework/Headers/NSClassDescription.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">Foundation.framework/Headers/NSError.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">Foundation.framework/Headers/NSFileManager.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">Foundation.framework/Headers/NSKeyValueCoding.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">Foundation.framework/Headers/NSKeyValueObserving.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">Foundation.framework/Headers/NSKeyedArchiver.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">Foundation.framework/Headers/NSObject.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">Foundation.framework/Headers/NSObjectScripting.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">Foundation.framework/Headers/NSPortCoder.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">Foundation.framework/Headers/NSRunLoop.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">Foundation.framework/Headers/NSScriptClassDescription.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">Foundation.framework/Headers/NSScriptKeyValueCoding.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">Foundation.framework/Headers/NSScriptObjectSpecifiers.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">Foundation.framework/Headers/NSScriptWhoseTests.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">Foundation.framework/Headers/NSThread.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">Foundation.framework/Headers/NSURL.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">Foundation.framework/Headers/NSURLConnection.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">Foundation.framework/Headers/NSURLDownload.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">Growl.framework/Headers/GrowlApplicationBridge.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">ImageKit.framework/Headers/IKImageBrowserView.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">ImageKit.framework/Headers/IKSaveOptions.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">ImageKit.framework/Headers/ImageKitDeprecated.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">PDFKit.framework/Headers/PDFDocument.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier" id="654570508"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">PDFKit.framework/Headers/PDFView.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">QTKit.framework/Headers/QTCaptureDecompressedAudioOutput.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">QTKit.framework/Headers/QTCaptureDecompressedVideoOutput.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">QTKit.framework/Headers/QTCaptureFileOutput.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">QTKit.framework/Headers/QTCaptureVideoPreviewOutput.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">QTKit.framework/Headers/QTCaptureView.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">QTKit.framework/Headers/QTMovie.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier" id="281869804"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">QTKit.framework/Headers/QTMovieView.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">QuartzComposer.framework/Headers/QCCompositionParameterView.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">QuartzComposer.framework/Headers/QCCompositionPickerView.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">QuartzFilters.framework/Headers/QuartzFilterManager.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">QuickLookUI.framework/Headers/QLPreviewPanel.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">Sparkle.framework/Headers/SUAppcast.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier" id="675455814"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">Sparkle.framework/Headers/SUUpdater.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObjectController</string> - <string key="superclassName">NSController</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSObjectController.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSOutlineView</string> - <string key="superclassName">NSTableView</string> - <reference key="sourceIdentifier" ref="474309511"/> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSPanel</string> - <string key="superclassName">NSWindow</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSPanel.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSPopUpButton</string> - <string key="superclassName">NSButton</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSPopUpButton.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSPopUpButtonCell</string> - <string key="superclassName">NSMenuItemCell</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSPopUpButtonCell.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSProgressIndicator</string> - <string key="superclassName">NSView</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSProgressIndicator.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSResponder</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSInterfaceStyle.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSResponder</string> - <string key="superclassName">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSResponder.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSScrollView</string> - <string key="superclassName">NSView</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSScrollView.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSScroller</string> - <string key="superclassName">NSControl</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSScroller.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSSlider</string> - <string key="superclassName">NSControl</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSSlider.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSSliderCell</string> - <string key="superclassName">NSActionCell</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSSliderCell.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSTabView</string> - <string key="superclassName">NSView</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSTabView.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSTabViewItem</string> - <string key="superclassName">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSTabViewItem.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSTableColumn</string> - <string key="superclassName">NSObject</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSTableColumn.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSTableHeaderView</string> - <string key="superclassName">NSView</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSTableHeaderView.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSTableView</string> - <string key="superclassName">NSControl</string> - <reference key="sourceIdentifier" ref="10931481"/> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSText</string> - <string key="superclassName">NSView</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSText.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSTextField</string> - <string key="superclassName">NSControl</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSTextField.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSTextFieldCell</string> - <string key="superclassName">NSActionCell</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSTextFieldCell.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSUserDefaultsController</string> - <string key="superclassName">NSController</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSUserDefaultsController.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSView</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSClipView.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSView</string> - <reference key="sourceIdentifier" ref="955768185"/> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSView</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSRulerView.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSView</string> - <string key="superclassName">NSResponder</string> - <reference key="sourceIdentifier" ref="986196456"/> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSWindow</string> - <reference key="sourceIdentifier" ref="255346542"/> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSWindow</string> - <string key="superclassName">NSResponder</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSWindow.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSWindow</string> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">AppKit.framework/Headers/NSWindowScripting.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">PDFView</string> - <string key="superclassName">NSView</string> - <object class="NSMutableDictionary" key="actions"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSArray" key="dict.sortedKeys"> - <bool key="EncodedWithXMLCoder">YES</bool> - <string>goBack:</string> - <string>goForward:</string> - <string>goToFirstPage:</string> - <string>goToLastPage:</string> - <string>goToNextPage:</string> - <string>goToPreviousPage:</string> - <string>selectAll:</string> - <string>takeBackgroundColorFrom:</string> - <string>zoomIn:</string> - <string>zoomOut:</string> - </object> - <object class="NSMutableArray" key="dict.values"> - <bool key="EncodedWithXMLCoder">YES</bool> - <string>id</string> - <string>id</string> - <string>id</string> - <string>id</string> - <string>id</string> - <string>id</string> - <string>id</string> - <string>id</string> - <string>id</string> - <string>id</string> - </object> - </object> - <object class="NSMutableDictionary" key="actionInfosByName"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSArray" key="dict.sortedKeys"> - <bool key="EncodedWithXMLCoder">YES</bool> - <string>goBack:</string> - <string>goForward:</string> - <string>goToFirstPage:</string> - <string>goToLastPage:</string> - <string>goToNextPage:</string> - <string>goToPreviousPage:</string> - <string>selectAll:</string> - <string>takeBackgroundColorFrom:</string> - <string>zoomIn:</string> - <string>zoomOut:</string> - </object> - <object class="NSMutableArray" key="dict.values"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="IBActionInfo"> - <string key="name">goBack:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">goForward:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">goToFirstPage:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">goToLastPage:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">goToNextPage:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">goToPreviousPage:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">selectAll:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">takeBackgroundColorFrom:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">zoomIn:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">zoomOut:</string> - <string key="candidateClassName">id</string> - </object> - </object> - </object> - <reference key="sourceIdentifier" ref="654570508"/> - </object> - <object class="IBPartialClassDescription"> - <string key="className">QCView</string> - <string key="superclassName">NSView</string> - <object class="NSMutableDictionary" key="actions"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSArray" key="dict.sortedKeys"> - <bool key="EncodedWithXMLCoder">YES</bool> - <string>play:</string> - <string>start:</string> - <string>stop:</string> - </object> - <object class="NSMutableArray" key="dict.values"> - <bool key="EncodedWithXMLCoder">YES</bool> - <string>id</string> - <string>id</string> - <string>id</string> - </object> - </object> - <object class="NSMutableDictionary" key="actionInfosByName"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSArray" key="dict.sortedKeys"> - <bool key="EncodedWithXMLCoder">YES</bool> - <string>play:</string> - <string>start:</string> - <string>stop:</string> - </object> - <object class="NSMutableArray" key="dict.values"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="IBActionInfo"> - <string key="name">play:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">start:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">stop:</string> - <string key="candidateClassName">id</string> - </object> - </object> - </object> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBFrameworkSource</string> - <string key="minorKey">QuartzComposer.framework/Headers/QCView.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">QTMovieView</string> - <string key="superclassName">NSView</string> - <object class="NSMutableDictionary" key="actions"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSArray" key="dict.sortedKeys"> - <bool key="EncodedWithXMLCoder">YES</bool> - <string>add:</string> - <string>addScaled:</string> - <string>copy:</string> - <string>cut:</string> - <string>delete:</string> - <string>gotoBeginning:</string> - <string>gotoEnd:</string> - <string>gotoNextSelectionPoint:</string> - <string>gotoPosterFrame:</string> - <string>gotoPreviousSelectionPoint:</string> - <string>paste:</string> - <string>pause:</string> - <string>play:</string> - <string>replace:</string> - <string>selectAll:</string> - <string>selectNone:</string> - <string>stepBackward:</string> - <string>stepForward:</string> - <string>trim:</string> - </object> - <object class="NSMutableArray" key="dict.values"> - <bool key="EncodedWithXMLCoder">YES</bool> - <string>id</string> - <string>id</string> - <string>id</string> - <string>id</string> - <string>id</string> - <string>id</string> - <string>id</string> - <string>id</string> - <string>id</string> - <string>id</string> - <string>id</string> - <string>id</string> - <string>id</string> - <string>id</string> - <string>id</string> - <string>id</string> - <string>id</string> - <string>id</string> - <string>id</string> - </object> - </object> - <object class="NSMutableDictionary" key="actionInfosByName"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSArray" key="dict.sortedKeys"> - <bool key="EncodedWithXMLCoder">YES</bool> - <string>add:</string> - <string>addScaled:</string> - <string>copy:</string> - <string>cut:</string> - <string>delete:</string> - <string>gotoBeginning:</string> - <string>gotoEnd:</string> - <string>gotoNextSelectionPoint:</string> - <string>gotoPosterFrame:</string> - <string>gotoPreviousSelectionPoint:</string> - <string>paste:</string> - <string>pause:</string> - <string>play:</string> - <string>replace:</string> - <string>selectAll:</string> - <string>selectNone:</string> - <string>stepBackward:</string> - <string>stepForward:</string> - <string>trim:</string> - </object> - <object class="NSMutableArray" key="dict.values"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="IBActionInfo"> - <string key="name">add:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">addScaled:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">copy:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">cut:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">delete:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">gotoBeginning:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">gotoEnd:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">gotoNextSelectionPoint:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">gotoPosterFrame:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">gotoPreviousSelectionPoint:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">paste:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">pause:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">play:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">replace:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">selectAll:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">selectNone:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">stepBackward:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">stepForward:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">trim:</string> - <string key="candidateClassName">id</string> - </object> - </object> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">./Classes/HBPresetsOutlineView.h</string> </object> - <reference key="sourceIdentifier" ref="281869804"/> </object> <object class="IBPartialClassDescription"> <string key="className">SUUpdater</string> @@ -13040,7 +11988,10 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <string key="candidateClassName">id</string> </object> </object> - <reference key="sourceIdentifier" ref="675455814"/> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">./Classes/SUUpdater.h</string> + </object> </object> </object> </object> @@ -13055,7 +12006,6 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <integer value="3000" key="NS.object.0"/> </object> <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool> - <string key="IBDocument.LastKnownRelativeProjectPath">../HandBrake.xcodeproj</string> <int key="IBDocument.defaultPropertyAccessControl">3</int> <object class="NSMutableDictionary" key="IBDocument.LastKnownImageSizes"> <bool key="EncodedWithXMLCoder">YES</bool> diff --git a/macosx/HBAudio.m b/macosx/HBAudio.m index 10522b3d3..6b9c7a558 100644 --- a/macosx/HBAudio.m +++ b/macosx/HBAudio.m @@ -274,7 +274,8 @@ static NSMutableArray *masterBitRateArray = nil; // Select the proper one if (shouldSetDefault) { - [self setMixdown: [permittedMixdowns dictionaryWithObject: [NSNumber numberWithInt: theDefaultMixdown] matchingKey: keyAudioMixdown]]; + [self setMixdown: [permittedMixdowns dictionaryWithObject: [NSNumber numberWithInt: theDefaultMixdown] + matchingKey: keyAudioMixdown]]; } if (![self mixdown] || ![permittedMixdowns containsObject: [self mixdown]]) @@ -295,7 +296,6 @@ static NSMutableArray *masterBitRateArray = nil; unsigned int count = [masterBitRateArray count]; int trackInputBitRate = [[[self track] objectForKey: keyAudioInputBitrate] intValue]; - BOOL limitsToTrackInputBitRate = ([[codec objectForKey: keyAudioCodec] intValue] & HB_ACODEC_PASS_FLAG) ? YES : NO; int theSampleRate = [[[self sampleRate] objectForKey: keyAudioSamplerate] intValue]; if (0 == theSampleRate) // this means Auto @@ -308,45 +308,46 @@ static NSMutableArray *masterBitRateArray = nil; hb_get_audio_bitrate_limits(ourCodec, theSampleRate, ourMixdown, &minBitRate, &maxBitRate); int theDefaultBitRate = hb_get_default_audio_bitrate(ourCodec, theSampleRate, ourMixdown); - for (unsigned int i = 0; i < count; i++) - { - dict = [masterBitRateArray objectAtIndex: i]; - currentBitRate = [[dict objectForKey: keyAudioBitrate] intValue]; - - // First ensure the bitrate falls within range of the codec - shouldAdd = (currentBitRate >= minBitRate && currentBitRate <= maxBitRate); + BOOL codecIsPassthru = ([[codec objectForKey: keyAudioCodec] intValue] & HB_ACODEC_PASS_FLAG) ? YES : NO; + BOOL codecIsLossless = (theDefaultBitRate == -1) ? YES : NO; - // Now make sure the mixdown is not limiting us to the track input bitrate - if (shouldAdd && limitsToTrackInputBitRate) - { - if (currentBitRate != trackInputBitRate) - { - shouldAdd = NO; - } - } - - if (shouldAdd) + if (codecIsPassthru) + { + NSDictionary *sourceBitRate = [masterBitRateArray dictionaryWithObject: [NSNumber numberWithInt: trackInputBitRate] + matchingKey: keyAudioBitrate]; + if (!sourceBitRate) { - [permittedBitRates addObject: dict]; + // the source bitrate isn't in the master array - create it + sourceBitRate = [NSDictionary dictionaryWithObjectsAndKeys: + [NSString stringWithFormat: @"%d", trackInputBitRate], keyAudioBitrateName, + [NSNumber numberWithInt: trackInputBitRate], keyAudioBitrate, + nil]; } + [permittedBitRates addObject: sourceBitRate]; } - - // There is a situation where we have a mixdown requirement to match the track input bit rate, - // but it does not fall into the range the codec supports. Therefore, we force it here. - if (limitsToTrackInputBitRate && 0 == [permittedBitRates count]) + else if (codecIsLossless) { - NSDictionary *missingBitRate = [masterBitRateArray dictionaryWithObject: [NSNumber numberWithInt: trackInputBitRate] matchingKey: keyAudioBitrate]; - if (!missingBitRate) + NSDictionary *bitRateNotApplicable = [NSDictionary dictionaryWithObjectsAndKeys: + [NSString stringWithString: @"N/A"], keyAudioBitrateName, + [NSNumber numberWithInt: -1], keyAudioBitrate, + nil]; + [permittedBitRates addObject: bitRateNotApplicable]; + } + else + { + for (unsigned int i = 0; i < count; i++) { - // We are in an even worse situation where the requested bit rate does not even exist in the underlying - // library of supported bitrates. Of course since this value is ignored we can freely make a bogus one - // for the UI just to make the user a little more aware. - missingBitRate = [NSDictionary dictionaryWithObjectsAndKeys: - [NSString stringWithFormat: @"%d", trackInputBitRate], keyAudioBitrateName, - [NSNumber numberWithInt: trackInputBitRate], keyAudioBitrate, - nil]; + dict = [masterBitRateArray objectAtIndex: i]; + currentBitRate = [[dict objectForKey: keyAudioBitrate] intValue]; + + // First ensure the bitrate falls within range of the codec + shouldAdd = (currentBitRate >= minBitRate && currentBitRate <= maxBitRate); + + if (shouldAdd) + { + [permittedBitRates addObject: dict]; + } } - [permittedBitRates addObject: missingBitRate]; } if (![self enabled]) @@ -479,7 +480,8 @@ static NSMutableArray *masterBitRateArray = nil; - (void) setTrackFromIndex: (int) aValue { - [self setTrack: [self.controller.masterTrackArray dictionaryWithObject: [NSNumber numberWithInt: aValue] matchingKey: keyAudioTrackIndex]]; + [self setTrack: [self.controller.masterTrackArray dictionaryWithObject: [NSNumber numberWithInt: aValue] + matchingKey: keyAudioTrackIndex]]; } // This returns whether it is able to set the actual codec desired. @@ -594,12 +596,29 @@ static NSMutableArray *masterBitRateArray = nil; return retval; } +- (BOOL) bitrateEnabled + +{ + BOOL retval = [self enabled]; + + if (retval) + { + int myCodecCodec = [[[self codec] objectForKey: keyAudioCodec] intValue]; + int myCodecDefaultBitrate = hb_get_default_audio_bitrate(myCodecCodec, 0, 0); + if (myCodecDefaultBitrate < 0) + { + retval = NO; + } + } + return retval; +} + - (BOOL) AC3Enabled { BOOL retval = [self enabled]; - if ( retval) + if (retval) { int myTrackCodec = [[[self track] objectForKey: keyAudioInputCodec] intValue]; int myCodecCodec = [[[self codec] objectForKey: keyAudioCodec] intValue]; @@ -644,6 +663,10 @@ static NSMutableArray *masterBitRateArray = nil; { retval = [NSSet setWithObjects: @"track", @"codec", nil]; } + else if ([key isEqualToString: @"bitrateEnabled"]) + { + retval = [NSSet setWithObjects: @"track", @"codec", nil]; + } else if ([key isEqualToString: @"mixdownEnabled"]) { retval = [NSSet setWithObjects: @"track", @"mixdown", nil]; diff --git a/macosx/HBAudioController.m b/macosx/HBAudioController.m index cc1a62165..09cc27f37 100644 --- a/macosx/HBAudioController.m +++ b/macosx/HBAudioController.m @@ -163,6 +163,7 @@ NSString *HBMixdownChangedNotification = @"HBMixdownChangedNotification"; /* We go ahead and assign values to our audio->out.<properties> */ audio->out.track = audio->in.track; audio->out.codec = [[[anAudio codec] objectForKey: keyAudioCodec] intValue]; + audio->out.compression_level = hb_get_default_audio_compression(audio->out.codec); audio->out.mixdown = [[[anAudio mixdown] objectForKey: keyAudioMixdown] intValue]; audio->out.bitrate = [[[anAudio bitRate] objectForKey: keyAudioBitrate] intValue]; audio->out.samplerate = [sampleRateToUse intValue]; diff --git a/scripts/manicure.rb b/scripts/manicure.rb index a732b63bd..039a6c9a6 100755 --- a/scripts/manicure.rb +++ b/scripts/manicure.rb @@ -921,8 +921,8 @@ class Display commandString << "if( !abitrates )\n " commandString << "{\n " - commandString << " abitrates = strdup(\"" << audioBitrates - commandString << "\");\n " + commandString << " abitrates = str_split(\"" << audioBitrates + commandString << "\", ',');\n " commandString << "}\n " commandString << "if( !mixdowns )\n " diff --git a/test/test.c b/test/test.c index fac25e8bc..3d217a9a7 100644 --- a/test/test.c +++ b/test/test.c @@ -72,7 +72,9 @@ static char * dynamic_range_compression = NULL; static char * audio_gain = NULL; static char * atracks = NULL; static char * arates = NULL; -static char * abitrates = NULL; +static char ** abitrates = NULL; +static char ** aqualities = NULL; +static char ** acompressions = NULL; static char * acodec_fallback = NULL; static char * acodecs = NULL; static char ** anames = NULL; @@ -156,6 +158,8 @@ static int HandleEvents( hb_handle_t * h ); static int get_acodec_for_string( char *codec ); static int is_sample_rate_valid(int rate); +static void str_vfree( char **strv ); +static char** str_split( char *str, char delem ); #ifdef __APPLE_CC__ static char* bsd_name_for_path(char *path); @@ -356,7 +360,9 @@ int main( int argc, char ** argv ) if( audio_gain ) free( audio_gain ); if( atracks ) free( atracks ); if( arates ) free( arates ); - if( abitrates ) free( abitrates ); + str_vfree( abitrates ); + str_vfree( aqualities ); + str_vfree( acompressions ); if( acodecs ) free( acodecs ); if (native_language ) free (native_language ); if( advanced_opts ) free (advanced_opts ); @@ -590,6 +596,8 @@ static int HandleEvents( hb_handle_t * h ) /* Audio argument string parsing variables */ int acodec = 0; int abitrate = 0; + float aquality = 0; + float acompression = 0; int arate = 0; int mixdown = HB_AMIXDOWN_DOLBYPLII; double d_r_c = 0; @@ -705,7 +713,7 @@ static int HandleEvents( hb_handle_t * h ) } if( !abitrates ) { - abitrates = strdup("160,160"); + abitrates = str_split("160,160", ','); } if( !mixdowns ) { @@ -751,7 +759,7 @@ static int HandleEvents( hb_handle_t * h ) } if( !abitrates ) { - abitrates = strdup("160"); + abitrates = str_split("160", ','); } if( !mixdowns ) { @@ -792,7 +800,7 @@ static int HandleEvents( hb_handle_t * h ) } if( !abitrates ) { - abitrates = strdup("128"); + abitrates = str_split("128", ','); } if( !mixdowns ) { @@ -836,7 +844,7 @@ static int HandleEvents( hb_handle_t * h ) } if( !abitrates ) { - abitrates = strdup("160"); + abitrates = str_split("160", ','); } if( !mixdowns ) { @@ -880,7 +888,7 @@ static int HandleEvents( hb_handle_t * h ) } if( !abitrates ) { - abitrates = strdup("160"); + abitrates = str_split("160", ','); } if( !mixdowns ) { @@ -922,7 +930,7 @@ static int HandleEvents( hb_handle_t * h ) } if( !abitrates ) { - abitrates = strdup("160,160"); + abitrates = str_split("160,160", ','); } if( !mixdowns ) { @@ -970,7 +978,7 @@ static int HandleEvents( hb_handle_t * h ) } if( !abitrates ) { - abitrates = strdup("160,160"); + abitrates = str_split("160,160", ','); } if( !mixdowns ) { @@ -1013,7 +1021,7 @@ static int HandleEvents( hb_handle_t * h ) } if( !abitrates ) { - abitrates = strdup("128"); + abitrates = str_split("128", ','); } if( !mixdowns ) { @@ -1055,7 +1063,7 @@ static int HandleEvents( hb_handle_t * h ) } if( !abitrates ) { - abitrates = strdup("128"); + abitrates = str_split("128", ','); } if( !mixdowns ) { @@ -1099,7 +1107,7 @@ static int HandleEvents( hb_handle_t * h ) } if( !abitrates ) { - abitrates = strdup("160"); + abitrates = str_split("160", ','); } if( !mixdowns ) { @@ -1144,7 +1152,7 @@ static int HandleEvents( hb_handle_t * h ) } if( !abitrates ) { - abitrates = strdup("160,160"); + abitrates = str_split("160,160", ','); } if( !mixdowns ) { @@ -1189,7 +1197,7 @@ static int HandleEvents( hb_handle_t * h ) } if( !abitrates ) { - abitrates = strdup("160"); + abitrates = str_split("160", ','); } if( !mixdowns ) { @@ -1225,7 +1233,7 @@ static int HandleEvents( hb_handle_t * h ) } if( !abitrates ) { - abitrates = strdup("160"); + abitrates = str_split("160", ','); } if( !mixdowns ) { @@ -1757,6 +1765,7 @@ static int HandleEvents( hb_handle_t * h ) /* Audio Codecs */ /* Sample Rate */ + int auto_sample_rate = 0; i = 0; if( arates ) { @@ -1783,6 +1792,7 @@ static int HandleEvents( hb_handle_t * h ) if ( !strcasecmp( token, "auto" ) ) { arate = audio->in.samplerate; + auto_sample_rate = 1; } if (!is_sample_rate_valid(arate)) { @@ -1806,11 +1816,15 @@ static int HandleEvents( hb_handle_t * h ) /* We have fewer inputs than audio tracks, use default sample rate. * Unless we only have one input, then use that for all tracks. */ - if (i != 1) - arate = audio->in.samplerate; + int use_default = 0; + if( i != 1 || auto_sample_rate ) + use_default = 1; + for ( ; i < num_audio_tracks; i++) { audio = hb_list_audio_config_item(job->list_audio, i); + if( use_default ) + arate = audio->in.samplerate; audio->out.samplerate = arate; } } @@ -1840,23 +1854,14 @@ static int HandleEvents( hb_handle_t * h ) token = strtok(NULL, ","); } } - if (i < num_audio_tracks) + if (i < num_audio_tracks && i == 1) { - /* We have fewer inputs than audio tracks, use the default mixdown for the rest. Unless - * we only have one input, then use that. + /* We have fewer inputs than audio tracks + * and we only have one input, then use that. */ - int use_default = 0; - if (i != 1) - use_default = 1; - for (; i < num_audio_tracks; i++) { audio = hb_list_audio_config_item(job->list_audio, i); - if (use_default) - { - // Get default for this tracks codec and layout - mixdown = hb_get_default_mixdown( audio->out.codec, audio->in.channel_layout ); - } audio->out.mixdown = mixdown; } } @@ -1866,11 +1871,9 @@ static int HandleEvents( hb_handle_t * h ) i = 0; if( abitrates ) { - char * token = strtok(abitrates, ","); - if (token == NULL) - token = abitrates; - while ( token != NULL ) + for ( i = 0; abitrates[i] != NULL && i < num_audio_tracks; i++ ) { + char * token = abitrates[i]; abitrate = atoi(token); audio = hb_list_audio_config_item(job->list_audio, i); @@ -1884,32 +1887,81 @@ static int HandleEvents( hb_handle_t * h ) { fprintf(stderr, "Ignoring bitrate %d, no audio tracks\n", abitrate); } - token = strtok(NULL, ","); } } - if (i < num_audio_tracks) + if (i < num_audio_tracks && i == 1) { - /* We have fewer inputs than audio tracks, use the default bitrate - * for the remaining tracks. Unless we only have one input, then use + /* We have fewer inputs than audio tracks, + * and we only have one input, use * that for all tracks. */ - int use_default = 0; - if (i != 1) - use_default = 1; + for (; i < num_audio_tracks; i++) + { + audio = hb_list_audio_config_item(job->list_audio, i); + audio->out.bitrate = abitrate; + } + } + /* Audio Bitrate */ + + /* Audio Quality */ + i = 0; + if( aqualities ) + { + for ( i = 0; aqualities[i] != NULL && i < num_audio_tracks; i++ ) + { + char * token = aqualities[i]; + audio = hb_list_audio_config_item(job->list_audio, i); + if( audio == NULL ) + { + fprintf(stderr, "Ignoring quality %.3f, no audio tracks\n", aquality); + } + else if( *token != 0 ) + { + aquality = atof(token); + audio->out.quality = aquality; + audio->out.bitrate = -1; + } + } + } + if (i < num_audio_tracks && i == 1) + { + /* We have fewer inputs than audio tracks, + * and we only have one input, use + * that for all tracks. + */ for (; i < num_audio_tracks; i++) { audio = hb_list_audio_config_item(job->list_audio, i); - if (use_default) + if( audio->out.bitrate <= 0 ) + audio->out.quality = aquality; + } + } + /* Audio Quality */ + + /* Audio Compression Level */ + i = 0; + if( acompressions ) + { + for ( i = 0; acompressions[i] != NULL && i < num_audio_tracks; i++ ) + { + char * token = acompressions[i]; + audio = hb_list_audio_config_item(job->list_audio, i); + if( audio == NULL ) { - abitrate = hb_get_default_audio_bitrate( - audio->out.codec, audio->out.samplerate, - audio->out.mixdown ); + fprintf(stderr, "Ignoring compression level %.2f, no audio tracks\n", acompression); + } + else if( *token != 0 ) + { + acompression = atof(token); + + audio->out.compression_level = acompression; } - audio->out.bitrate = abitrate; } } - /* Audio Bitrate */ + // Compression levels are codec specific values. So don't + // try to apply to other tracks. + /* Audio Compression Level */ /* Audio DRC */ i = 0; @@ -2763,6 +2815,12 @@ static void ShowHelp() " -B, --ab <kb/s> Set audio bitrate(s) (default: depends on the\n" " selected codec, mixdown and samplerate)\n" " Separated by commas for more than one audio track.\n" + " -Q, --aq <quality> Set audio quality metric (default: depends on the\n" + " selected codec)\n" + " Separated by commas for more than one audio track.\n" + " -C, --ac <compression> Set audio compression metric (default: depends on the\n" + " selected codec)\n" + " Separated by commas for more than one audio track.\n" " -6, --mixdown <string> Format(s) for surround sound downmixing\n" " Separated by commas for more than one audio track.\n" " (mono/stereo/dpl1/dpl2/6ch, default: up to 6ch for ac3,\n" @@ -3117,6 +3175,8 @@ static int ParseOptions( int argc, char ** argv ) { "vb", required_argument, NULL, 'b' }, { "quality", required_argument, NULL, 'q' }, { "ab", required_argument, NULL, 'B' }, + { "aq", required_argument, NULL, 'Q' }, + { "ac", required_argument, NULL, 'C' }, { "rate", required_argument, NULL, 'r' }, { "arate", required_argument, NULL, 'R' }, { "encopts", required_argument, NULL, 'x' }, @@ -3152,7 +3212,7 @@ static int ParseOptions( int argc, char ** argv ) cur_optind = optind; c = getopt_long( argc, argv, - "hv::uC:f:4i:Io:t:c:m::M:a:A:6:s:UF::N:e:E:" + "hv::uC:f:4i:Io:t:c:m::M:a:A:6:s:UF::N:e:E:Q:C:" "2dD:7895gOw:l:n:b:q:S:B:r:R:x:TY:X:Z:z", long_options, &option_index ); if( c < 0 ) @@ -3524,10 +3584,13 @@ static int ParseOptions( int argc, char ** argv ) vquality = atof( optarg ); break; case 'B': - if( optarg != NULL ) - { - abitrates = strdup( optarg ); - } + abitrates = str_split( optarg, ',' ); + break; + case 'Q': + aqualities = str_split( optarg, ',' ); + break; + case 'C': + acompressions = str_split( optarg, ',' ); break; case 'x': advanced_opts = strdup( optarg ); |