diff options
author | Andrej Shadura <andrewsh@debian.org> | 2019-02-20 19:35:42 +0100 |
---|---|---|
committer | Andrej Shadura <andrewsh@debian.org> | 2019-02-20 19:35:42 +0100 |
commit | 1a988068635ca5f8a74c4654098d07f92bc0dcf4 (patch) | |
tree | 04ab5d5c0ffbdc6d60621be489508bf7140c7b34 /src | |
parent | 20b38fea7b2b8e6dd31a62dbc5ec9e4c2888a013 (diff) |
New upstream version 3.10.1
Diffstat (limited to 'src')
-rw-r--r-- | src/audacious/dbus-server.cc | 31 | ||||
-rw-r--r-- | src/audtool/main.c | 37 | ||||
-rw-r--r-- | src/libaudcore/equalizer-preset.cc | 31 | ||||
-rw-r--r-- | src/libaudcore/hook.h | 6 | ||||
-rw-r--r-- | src/libaudcore/output.cc | 9 | ||||
-rw-r--r-- | src/libaudcore/playlist-files.cc | 11 | ||||
-rw-r--r-- | src/libaudcore/probe.cc | 9 | ||||
-rw-r--r-- | src/libaudgui/eq-preset.cc | 29 | ||||
-rw-r--r-- | src/libaudgui/infowin.cc | 35 | ||||
-rw-r--r-- | src/libaudqt/audqt.cc | 2 | ||||
-rw-r--r-- | src/libaudqt/infopopup-qt.cc | 14 | ||||
-rw-r--r-- | src/libaudqt/libaudqt-internal.h | 7 | ||||
-rw-r--r-- | src/libaudqt/util-qt.cc | 32 | ||||
-rw-r--r-- | src/libaudqt/volumebutton.cc | 4 |
14 files changed, 196 insertions, 61 deletions
diff --git a/src/audacious/dbus-server.cc b/src/audacious/dbus-server.cc index 7602ace..20a6c58 100644 --- a/src/audacious/dbus-server.cc +++ b/src/audacious/dbus-server.cc @@ -635,27 +635,30 @@ static gboolean do_song_title (Obj * obj, Invoc * invoc, unsigned pos) static gboolean do_song_tuple (Obj * obj, Invoc * invoc, unsigned pos, const char * key) { Tuple::Field field = Tuple::field_by_name (key); - Tuple tuple; - GVariant * var; + GVariant * var = nullptr; if (field >= 0) - tuple = CURRENT.entry_tuple (pos); - - switch (tuple.get_value_type (field)) { - case Tuple::String: - var = g_variant_new_string (tuple.get_str (field)); - break; + Tuple tuple = CURRENT.entry_tuple (pos); - case Tuple::Int: - var = g_variant_new_int32 (tuple.get_int (field)); - break; + switch (tuple.get_value_type (field)) + { + case Tuple::String: + var = g_variant_new_string (tuple.get_str (field)); + break; - default: - var = g_variant_new_string (""); - break; + case Tuple::Int: + var = g_variant_new_int32 (tuple.get_int (field)); + break; + + default: + break; + } } + if (! var) + var = g_variant_new_string (""); + FINISH2 (song_tuple, g_variant_new_variant (var)); return true; } diff --git a/src/audtool/main.c b/src/audtool/main.c index 345dcb1..a09c6b8 100644 --- a/src/audtool/main.c +++ b/src/audtool/main.c @@ -23,6 +23,10 @@ #include <string.h> #include <locale.h> +#ifdef _WIN32 +#include <windows.h> +#endif + #include "audtool.h" const struct commandhandler handlers[] = @@ -182,6 +186,35 @@ static void audtool_connect (int instance) atexit (audtool_disconnect); } +#ifdef _WIN32 +static void print_utf8 (const char * str) +{ + HANDLE h = GetStdHandle (STD_OUTPUT_HANDLE); + DWORD mode; + + if (h != INVALID_HANDLE_VALUE && GetConsoleMode (h, & mode)) + { + // stdout is the console, which needs special handling to display + // non-ASCII characters correctly (in 2018, the MS runtime *still* + // doesn't handle UTF-8 reliably). + glong n_converted; + gunichar2 * utf16 = g_utf8_to_utf16 (str, -1, NULL, & n_converted, NULL); + + if (utf16) + { + DWORD n_written; + WriteConsoleW (h, utf16, n_converted, & n_written, NULL); + g_free (utf16); + } + } + else + { + // fputs() works fine when stdout is redirected. + fputs (str, stdout); + } +} +#endif // _WIN32 + int main (int argc, char * * argv) { int instance = 1; @@ -193,6 +226,10 @@ int main (int argc, char * * argv) g_type_init(); #endif +#ifdef _WIN32 + g_set_print_handler (print_utf8); +#endif + // parse instance number (must come first) if (argc >= 2 && argv[1][0] == '-' && argv[1][1] >= '1' && argv[1][1] <= '9' && ! argv[1][2]) { diff --git a/src/libaudcore/equalizer-preset.cc b/src/libaudcore/equalizer-preset.cc index c57d5f0..933148f 100644 --- a/src/libaudcore/equalizer-preset.cc +++ b/src/libaudcore/equalizer-preset.cc @@ -92,8 +92,27 @@ EXPORT bool aud_eq_write_presets (const Index<EqualizerPreset> & list, const cha /* Note: Winamp 2.x had a +/- 20 dB range. * Winamp 5.x had a +/- 12 dB range, which we use here. */ -#define FROM_WINAMP_VAL(x) ((31.5 - (x)) * (12.0 / 31.5)) -#define TO_WINAMP_VAL(x) (round (31.5 - (x) * (31.5 / 12.0))) + +/* Encoded values range from 0 (+12 dB) to 63 (-12 dB). The sign is + * reversed for some unknown reason. Mathematically, there is no way + * to represent 0 dB exactly (31 is +0.19 dB, 32 is -0.19 dB) but we + * mimic WinAmp in letting 31 mean 0 dB as a special case. */ + +static float decode_winamp_val (int val) +{ + if (val == 31) + return 0.0f; + + return (31.5f - val) * (12.0f / 31.5f); +} + +static int encode_winamp_val (float val) +{ + if (val == 0.0f) + return 31; + + return lroundf (31.5f - val * (31.5f / 12.0f)); +} EXPORT Index<EqualizerPreset> aud_import_winamp_presets (VFSFile & file) { @@ -118,10 +137,10 @@ EXPORT Index<EqualizerPreset> aud_import_winamp_presets (VFSFile & file) break; EqualizerPreset & preset = list.append (String (preset_name)); - preset.preamp = FROM_WINAMP_VAL (bands[10]); + preset.preamp = decode_winamp_val (bands[10]); for (int i = 0; i < AUD_EQ_NBANDS; i ++) - preset.bands[i] = FROM_WINAMP_VAL (bands[i]); + preset.bands[i] = decode_winamp_val (bands[i]); } return list; @@ -141,9 +160,9 @@ EXPORT bool aud_export_winamp_preset (const EqualizerPreset & preset, VFSFile & return false; for (int i = 0; i < AUD_EQ_NBANDS; i ++) - bands[i] = TO_WINAMP_VAL (preset.bands[i]); + bands[i] = encode_winamp_val (preset.bands[i]); - bands[10] = TO_WINAMP_VAL (preset.preamp); + bands[10] = encode_winamp_val (preset.preamp); if (file.fwrite (bands, 1, 11) != 11) return false; diff --git a/src/libaudcore/hook.h b/src/libaudcore/hook.h index 147591a..5772844 100644 --- a/src/libaudcore/hook.h +++ b/src/libaudcore/hook.h @@ -99,9 +99,9 @@ void hook_call (const char * name, void * data); typedef void (* EventDestroyFunc) (void * data); -/* Schedules a call of the hook <name> from the program's main loop, to be - * executed in <time> milliseconds. If <destroy> is not nullptr, it will be called - * on <data> after the hook is called. */ +/* Schedules a call of the hook <name> from the program's main loop. + * If <destroy> is not nullptr, it will be called on <data> after the + * hook is called. */ void event_queue (const char * name, void * data, EventDestroyFunc destroy = nullptr); /* Cancels pending hook calls matching <name> and <data>. If <data> is nullptr, diff --git a/src/libaudcore/output.cc b/src/libaudcore/output.cc index 191884d..bb861e5 100644 --- a/src/libaudcore/output.cc +++ b/src/libaudcore/output.cc @@ -172,11 +172,14 @@ static void setup_output (bool new_input) bool automatic; int format = get_format (automatic); - AUDINFO ("Setup output, format %d, %d channels, %d Hz.\n", format, effect_channels, effect_rate); - - if (s_output && format == out_format && effect_channels == out_channels && + if (s_output && effect_channels == out_channels && effect_rate == out_rate && ! (new_input && cop->force_reopen)) + { + AUDINFO ("Reuse output, %d channels, %d Hz.\n", effect_channels, effect_rate); return; + } + + AUDINFO ("Setup output, format %d, %d channels, %d Hz.\n", format, effect_channels, effect_rate); cleanup_output (); cop->set_info (in_filename, in_tuple); diff --git a/src/libaudcore/playlist-files.cc b/src/libaudcore/playlist-files.cc index 29cbff0..a2914b1 100644 --- a/src/libaudcore/playlist-files.cc +++ b/src/libaudcore/playlist-files.cc @@ -142,14 +142,21 @@ EXPORT bool Playlist::save_to_file (const char * filename, GetMode mode) const VFSFile file (filename, "w"); if (! file) + { + aud_ui_show_error (str_printf (_("Error opening %s:\n%s"), + filename, file.error ())); return false; + } - return pp->save (filename, file, title, items) && file.fflush () == 0; + if (pp->save (filename, file, title, items) && file.fflush () == 0) + return true; + + aud_ui_show_error (str_printf (_("Error saving %s."), filename)); + return false; } } aud_ui_show_error (str_printf (_("Cannot save %s: unsupported file name extension."), filename)); - return false; } diff --git a/src/libaudcore/probe.cc b/src/libaudcore/probe.cc index 5c57ef8..38cf73d 100644 --- a/src/libaudcore/probe.cc +++ b/src/libaudcore/probe.cc @@ -242,6 +242,15 @@ EXPORT bool aud_custom_infowin (const char * filename, PluginHandle * decoder) if (! strncmp (filename, "stdin://", 8)) return false; + // In hindsight, a flag should have been added indicating whether a + // plugin provides a custom info window or not. Currently, only two + // plugins do so. Since custom info windows are deprecated anyway, + // check for those two plugins explicitly and in all other cases, + // don't open the input file to prevent freezing the UI. + const char * base = aud_plugin_get_basename (decoder); + if (strcmp (base, "amidi-plug") && strcmp (base, "vtx")) + return false; + auto ip = (InputPlugin *) aud_plugin_get_header (decoder); if (! ip) return false; diff --git a/src/libaudgui/eq-preset.cc b/src/libaudgui/eq-preset.cc index a2f1c9d..159fef9 100644 --- a/src/libaudgui/eq-preset.cc +++ b/src/libaudgui/eq-preset.cc @@ -188,6 +188,9 @@ static void revert_changes () static void cleanup_eq_preset_window () { + // also hide the preset browser window + audgui_hide_unique_window (AUDGUI_PRESET_BROWSER_WINDOW); + if (changes_made) { save_list (); @@ -312,22 +315,14 @@ static void merge_presets (const Index<EqualizerPreset> & presets) EXPORT void audgui_import_eq_presets (const Index<EqualizerPreset> & presets) { - if (list) - { - /* import via presets window if it exists */ - audgui_list_delete_rows (list, 0, preset_list.len ()); - merge_presets (presets); - audgui_list_insert_rows (list, 0, preset_list.len ()); + // make sure the presets window is displayed + if (! list) + return; - changes_made = true; - gtk_widget_set_sensitive (revert, true); - } - else - { - /* otherwise import directly to ~/.config/audacious/eq.preset */ - populate_list (); - merge_presets (presets); - save_list (); - preset_list.clear (); - } + audgui_list_delete_rows (list, 0, preset_list.len ()); + merge_presets (presets); + audgui_list_insert_rows (list, 0, preset_list.len ()); + + changes_made = true; + gtk_widget_set_sensitive (revert, true); } diff --git a/src/libaudgui/infowin.cc b/src/libaudgui/infowin.cc index b36c1a6..8f62856 100644 --- a/src/libaudgui/infowin.cc +++ b/src/libaudgui/infowin.cc @@ -141,22 +141,32 @@ static GtkWidget * small_label_new (const char * text) } static void set_entry_str_from_field (GtkWidget * widget, const Tuple & tuple, - Tuple::Field field, bool editable, bool clear) + Tuple::Field field, bool editable, bool clear, bool & changed) { String text = tuple.get_str (field); + if (! text && ! clear) + { + if (gtk_entry_get_text_length ((GtkEntry *) widget) > 0) + changed = true; return; + } gtk_entry_set_text ((GtkEntry *) widget, text ? text : ""); gtk_editable_set_editable ((GtkEditable *) widget, editable); } static void set_entry_int_from_field (GtkWidget * widget, const Tuple & tuple, - Tuple::Field field, bool editable, bool clear) + Tuple::Field field, bool editable, bool clear, bool & changed) { int value = tuple.get_int (field); + if (value <= 0 && ! clear) + { + if (gtk_entry_get_text_length ((GtkEntry *) widget) > 0) + changed = true; return; + } gtk_entry_set_text ((GtkEntry *) widget, (value > 0) ? (const char *) int_to_str (value) : ""); gtk_editable_set_editable ((GtkEditable *) widget, editable); @@ -424,19 +434,20 @@ static void infowin_show (Playlist list, int entry, const String & filename, can_write = writable; bool clear = aud_get_bool ("audgui", "clear_song_fields"); + bool changed = false; - set_entry_str_from_field (widgets.title, tuple, Tuple::Title, writable, clear); - set_entry_str_from_field (widgets.artist, tuple, Tuple::Artist, writable, clear); - set_entry_str_from_field (widgets.album, tuple, Tuple::Album, writable, clear); - set_entry_str_from_field (widgets.album_artist, tuple, Tuple::AlbumArtist, writable, clear); - set_entry_str_from_field (widgets.comment, tuple, Tuple::Comment, writable, clear); + set_entry_str_from_field (widgets.title, tuple, Tuple::Title, writable, clear, changed); + set_entry_str_from_field (widgets.artist, tuple, Tuple::Artist, writable, clear, changed); + set_entry_str_from_field (widgets.album, tuple, Tuple::Album, writable, clear, changed); + set_entry_str_from_field (widgets.album_artist, tuple, Tuple::AlbumArtist, writable, clear, changed); + set_entry_str_from_field (widgets.comment, tuple, Tuple::Comment, writable, clear, changed); set_entry_str_from_field (gtk_bin_get_child ((GtkBin *) widgets.genre), - tuple, Tuple::Genre, writable, clear); + tuple, Tuple::Genre, writable, clear, changed); gtk_label_set_text ((GtkLabel *) widgets.location, uri_to_display (filename)); - set_entry_int_from_field (widgets.year, tuple, Tuple::Year, writable, clear); - set_entry_int_from_field (widgets.track, tuple, Tuple::Track, writable, clear); + set_entry_int_from_field (widgets.year, tuple, Tuple::Year, writable, clear, changed); + set_entry_int_from_field (widgets.track, tuple, Tuple::Track, writable, clear, changed); String codec_values[CODEC_ITEMS]; @@ -455,9 +466,7 @@ static void infowin_show (Playlist list, int entry, const String & filename, infowin_display_image (filename); - /* nothing has been changed yet */ - gtk_widget_set_sensitive (widgets.apply, false); - + gtk_widget_set_sensitive (widgets.apply, changed); gtk_widget_grab_focus (widgets.title); if (! audgui_reshow_unique_window (AUDGUI_INFO_WINDOW)) diff --git a/src/libaudqt/audqt.cc b/src/libaudqt/audqt.cc index d44df33..0677b96 100644 --- a/src/libaudqt/audqt.cc +++ b/src/libaudqt/audqt.cc @@ -102,7 +102,7 @@ EXPORT void cleanup () aboutwindow_hide (); equalizer_hide (); - infopopup_hide (); + infopopup_hide_now (); infowin_hide (); log_inspector_hide (); prefswin_hide (); diff --git a/src/libaudqt/infopopup-qt.cc b/src/libaudqt/infopopup-qt.cc index fdbba41..de6d7b7 100644 --- a/src/libaudqt/infopopup-qt.cc +++ b/src/libaudqt/infopopup-qt.cc @@ -176,7 +176,9 @@ static InfoPopup * s_infopopup; static void infopopup_show (const String & filename, const Tuple & tuple) { - delete s_infopopup; + if (s_infopopup) + s_infopopup->deleteLater (); + s_infopopup = new InfoPopup (filename, tuple); QObject::connect (s_infopopup, & QObject::destroyed, [] () { @@ -206,6 +208,16 @@ EXPORT void infopopup_show_current () EXPORT void infopopup_hide () { + /* This function can be called from an enter/leave event, and Qt does not + * like widgets being deleted from such events. This is debatably a bug in + * Qt, but deleteLater() is an effective workaround. */ + if (s_infopopup) + s_infopopup->deleteLater (); +} + +void infopopup_hide_now () +{ + /* On exit, we really do want to delete the widget immediately. */ delete s_infopopup; } diff --git a/src/libaudqt/libaudqt-internal.h b/src/libaudqt/libaudqt-internal.h index 2aec88f..19dded2 100644 --- a/src/libaudqt/libaudqt-internal.h +++ b/src/libaudqt/libaudqt-internal.h @@ -28,6 +28,9 @@ class QString; namespace audqt { +/* infopopup.cc */ +void infopopup_hide_now (); + /* log-inspector.cc */ void log_init (); void log_cleanup (); @@ -35,7 +38,11 @@ void log_cleanup (); /* util-qt.cc */ class PopupWidget : public QWidget { +public: + PopupWidget (QWidget * parent = nullptr); + protected: + bool eventFilter (QObject *, QEvent * e) override; void showEvent (QShowEvent *) override; }; diff --git a/src/libaudqt/util-qt.cc b/src/libaudqt/util-qt.cc index 213e983..866f3a4 100644 --- a/src/libaudqt/util-qt.cc +++ b/src/libaudqt/util-qt.cc @@ -33,6 +33,38 @@ namespace audqt { +PopupWidget::PopupWidget (QWidget * parent) : + QWidget (parent) +{ + qApp->installEventFilter (this); +} + +// This event filter mimics QToolTip by hiding the popup widget when +// certain events are received by any widget. +bool PopupWidget::eventFilter (QObject *, QEvent * e) +{ + switch (e->type ()) + { + case QEvent::Leave: + case QEvent::WindowActivate: + case QEvent::WindowDeactivate: + case QEvent::FocusIn: + case QEvent::FocusOut: + case QEvent::Close: + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseButtonDblClick: + case QEvent::Wheel: + deleteLater (); + break; + + default: + break; + } + + return false; +} + void PopupWidget::showEvent (QShowEvent *) { auto pos = QCursor::pos (); diff --git a/src/libaudqt/volumebutton.cc b/src/libaudqt/volumebutton.cc index 673002d..9455c55 100644 --- a/src/libaudqt/volumebutton.cc +++ b/src/libaudqt/volumebutton.cc @@ -121,7 +121,9 @@ void VolumeButton::showSlider () int dy = container_size.height () / 2 - button_size.height () / 2; QPoint pos = mapToGlobal (QPoint (0, 0)); - pos += QPoint (-dx, -dy); + pos -= QPoint (dx, dy); + pos.setX(qMax(pos.x(), 0)); + pos.setY(qMax(pos.y(), 0)); m_container->move (pos); window_bring_to_front (m_container); |