Skip to content

Commit

Permalink
lyrics-gtk: Restore lyrics plugin for GTK
Browse files Browse the repository at this point in the history
- Based on the original code which was removed with Audacious 4.1
- Add all new features from the Qt lyrics plugin
- Use new dependency "json-glib" to parse JSON strings
  • Loading branch information
radioactiveman committed Feb 11, 2024
1 parent f115459 commit e8243ee
Show file tree
Hide file tree
Showing 10 changed files with 315 additions and 14 deletions.
16 changes: 8 additions & 8 deletions .github/actions/install-dependencies/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ runs:
install: >-
mingw-w64-i686-autotools mingw-w64-i686-faad2 mingw-w64-i686-ffmpeg
mingw-w64-i686-flac mingw-w64-i686-fluidsynth mingw-w64-i686-gcc
mingw-w64-i686-gtk2 mingw-w64-i686-lame mingw-w64-i686-libbs2b
mingw-w64-i686-libcdio-paranoia mingw-w64-i686-libcue
mingw-w64-i686-libmodplug mingw-w64-i686-libopenmpt
mingw-w64-i686-libsamplerate mingw-w64-i686-libsidplayfp
mingw-w64-i686-libsoxr mingw-w64-i686-libvorbis mingw-w64-i686-meson
mingw-w64-i686-mpg123 mingw-w64-i686-neon mingw-w64-i686-opusfile
mingw-w64-i686-pkg-config mingw-w64-i686-qt5-base mingw-w64-i686-SDL2
mingw-w64-i686-wavpack
mingw-w64-i686-gtk2 mingw-w64-i686-json-glib mingw-w64-i686-lame
mingw-w64-i686-libbs2b mingw-w64-i686-libcdio-paranoia
mingw-w64-i686-libcue mingw-w64-i686-libmodplug
mingw-w64-i686-libopenmpt mingw-w64-i686-libsamplerate
mingw-w64-i686-libsidplayfp mingw-w64-i686-libsoxr
mingw-w64-i686-libvorbis mingw-w64-i686-meson mingw-w64-i686-mpg123
mingw-w64-i686-neon mingw-w64-i686-opusfile mingw-w64-i686-pkg-config
mingw-w64-i686-qt5-base mingw-w64-i686-SDL2 mingw-w64-i686-wavpack
7 changes: 4 additions & 3 deletions .github/actions/install-dependencies/install-dependencies.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ ubuntu_packages='gettext libadplug-dev libasound2-dev libavformat-dev
libbinio-dev libbs2b-dev libcddb2-dev libcdio-cdda-dev
libcue-dev libcurl4-gnutls-dev libdbus-glib-1-dev
libfaad-dev libflac-dev libfluidsynth-dev libgl1-mesa-dev
libjack-jackd2-dev liblircclient-dev libmms-dev libmodplug-dev
libmp3lame-dev libmpg123-dev libneon27-gnutls-dev libnotify-dev
libopenmpt-dev libopusfile-dev libpulse-dev libqt5opengl5-dev
libjack-jackd2-dev libjson-glib-dev liblircclient-dev
libmms-dev libmodplug-dev libmp3lame-dev libmpg123-dev
libneon27-gnutls-dev libnotify-dev libopenmpt-dev
libopusfile-dev libpulse-dev libqt5opengl5-dev
libqt5x11extras5-dev libsamplerate0-dev libsdl2-dev
libsidplayfp-dev libsndfile1-dev libsndio-dev libsoxr-dev
libvorbis-dev libwavpack-dev libxml2-dev qtbase5-dev
Expand Down
4 changes: 4 additions & 0 deletions acinclude.m4
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,10 @@ fi
AC_SUBST(USE_GTK)
if test $USE_GTK = yes ; then
PKG_CHECK_MODULES(JSON_GLIB, json-glib-1.0 >= 1.0)
fi
if test $HAVE_MSWINDOWS = yes ; then
PKG_CHECK_MODULES(GIO, gio-2.0 >= 2.32)
else
Expand Down
4 changes: 2 additions & 2 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ TRANSPORT_PLUGINS="gio"

if test "x$USE_GTK" = "xyes" ; then
EFFECT_PLUGINS="$EFFECT_PLUGINS ladspa"
GENERAL_PLUGINS="$GENERAL_PLUGINS albumart playlist-manager search-tool statusicon"
GENERAL_PLUGINS="$GENERAL_PLUGINS albumart lyrics-gtk playlist-manager search-tool statusicon"
GENERAL_PLUGINS="$GENERAL_PLUGINS gtkui skins"
VISUALIZATION_PLUGINS="$VISUALIZATION_PLUGINS blur_scope cairo-spectrum"
fi
Expand Down Expand Up @@ -829,6 +829,7 @@ echo " Ampache browser (requires Qt): $have_ampache"
echo " Delete Files: $USE_GTK_OR_QT"
echo " libnotify OSD: $have_notify"
echo " Linux Infrared Remote Control (LIRC): $have_lirc"
echo " Lyrics Viewer: yes"
echo " MPRIS 2 Server: $have_mpris2"
echo " Scrobbler 2.0: $have_scrobbler2"
echo " Song Change: $have_songchange"
Expand Down Expand Up @@ -859,7 +860,6 @@ if test "x$USE_QT" = "xyes" ; then
echo " Winamp Classic Interface: yes"
echo " Album Art: yes"
echo " Blur Scope: yes"
echo " Lyrics Viewer: yes"
echo " OpenGL Spectrum Analyzer: $have_qtglspectrum"
echo " Playlist Manager: yes"
echo " Search Tool: yes"
Expand Down
2 changes: 2 additions & 0 deletions extra.mk.in
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ GTK_CFLAGS ?= @GTK_CFLAGS@
GTK_LIBS ?= @GTK_LIBS@
JACK_CFLAGS ?= @JACK_CFLAGS@
JACK_LIBS ?= @JACK_LIBS@
JSON_GLIB_CFLAGS ?= @JSON_GLIB_CFLAGS@
JSON_GLIB_LIBS ?= @JSON_GLIB_LIBS@
LIBFLAC_LIBS ?= @LIBFLAC_LIBS@
LIBFLAC_CFLAGS ?= @LIBFLAC_CFLAGS@
MMS_CFLAGS ?= @MMS_CFLAGS@
Expand Down
2 changes: 1 addition & 1 deletion meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@ if meson.version().version_compare('>= 0.53')
'Delete Files': conf.has('USE_GTK_OR_QT'),
'Libnotify OSD': get_variable('have_notify', false),
'Linux Infrared Remote Control (LIRC)': get_variable('have_lirc', false),
'Lyrics Viewer': get_variable('have_lyrics', false),
'MPRIS 2 Server': get_variable('have_mpris2', false),
'Scrobbler 2.0': get_variable('have_scrobbler2', false),
'Song Change': get_option('songchange'),
Expand All @@ -307,7 +308,6 @@ if meson.version().version_compare('>= 0.53')
'Winamp Classic Interface': true,
'Album Art': true,
'Blur Scope': true,
'Lyrics Viewer': get_variable('have_lyrics', false),
'OpenGL Spectrum Analyzer': get_variable('have_qtglspectrum', false),
'Playlist Manager': true,
'Search Tool': true,
Expand Down
18 changes: 18 additions & 0 deletions src/lyrics-gtk/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
PLUGIN = lyrics-gtk${PLUGIN_SUFFIX}

SRCS = ../lyrics-common/chart_lyrics_provider.cc \
../lyrics-common/file_provider.cc \
../lyrics-common/lyrics_ovh_provider.cc \
../lyrics-common/utils.cc \
lyrics-gtk.cc

include ../../buildsys.mk
include ../../extra.mk

plugindir := ${plugindir}/${GENERAL_PLUGIN_DIR}

LD = ${CXX}

CFLAGS += ${PLUGIN_CFLAGS}
CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GTK_CFLAGS} ${GLIB_CFLAGS} ${JSON_GLIB_CFLAGS} ${XML_CFLAGS} -I../..
LIBS += ${GTK_LIBS} ${GLIB_LIBS} ${JSON_GLIB_LIBS} ${XML_LIBS} -laudgui
253 changes: 253 additions & 0 deletions src/lyrics-gtk/lyrics-gtk.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
/*
* Copyright (c) 2010-2019 Ariadne Conill <[email protected]>
* Copyright (c) 2024 Thomas Lange <[email protected]>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

#include <json-glib/json-glib.h>

#include <libaudcore/hook.h>
#include <libaudcore/plugin.h>
#include <libaudcore/plugins.h>
#include <libaudgui/gtk-compat.h>

#include "../lyrics-common/lyrics.h"
#include "../lyrics-common/preferences.h"

class Lyrics : public GeneralPlugin
{
public:
static const PluginPreferences prefs;
static constexpr PluginInfo info = {
N_("Lyrics"),
PACKAGE,
nullptr, // about
& prefs,
PluginGLibOnly
};

constexpr Lyrics () : GeneralPlugin (info, false) {}

bool init ();
void * get_gtk_widget ();
};

EXPORT Lyrics aud_plugin_instance;

const PluginPreferences Lyrics::prefs = {{widgets}};

FileProvider file_provider;
ChartLyricsProvider chart_lyrics_provider;
LyricsOVHProvider lyrics_ovh_provider;

LyricsState g_state;

static GtkTextView * textview;
static GtkTextBuffer * textbuffer;

bool Lyrics::init ()
{
aud_config_set_defaults (CFG_SECTION, defaults);
return true;
}

void update_lyrics_window (const char * title, const char * artist, const char * lyrics)
{
GtkTextIter iter;

if (! textbuffer)
return;

gtk_text_buffer_set_text (textbuffer, "", -1);

gtk_text_buffer_get_start_iter (textbuffer, & iter);

gtk_text_buffer_insert_with_tags_by_name (textbuffer, & iter, title, -1,
"weight_bold", "scale_large", nullptr);

if (artist)
{
gtk_text_buffer_insert (textbuffer, & iter, "\n", -1);
gtk_text_buffer_insert_with_tags_by_name (textbuffer, & iter, artist, -1,
"style_italic", nullptr);
}

gtk_text_buffer_insert (textbuffer, & iter, "\n\n", -1);
gtk_text_buffer_insert (textbuffer, & iter, lyrics, -1);

gtk_text_buffer_get_start_iter (textbuffer, & iter);
gtk_text_view_scroll_to_iter (textview, & iter, 0, true, 0, 0);
}

bool try_parse_json (const Index<char> & buf, const char * key, String & output)
{
JsonParser * parser = json_parser_new ();

if (! json_parser_load_from_data (parser, buf.begin (), buf.len (), nullptr))
{
g_object_unref (parser);
return false;
}

JsonNode * root = json_parser_get_root (parser);
JsonReader * reader = json_reader_new (root);

json_reader_read_member (reader, key);
output = String (json_reader_get_string_value (reader));
json_reader_end_member (reader);

g_object_unref (reader);
g_object_unref (parser);

return true;
}

static void destroy_cb ()
{
g_state.filename = String ();
g_state.title = String ();
g_state.artist = String ();
g_state.lyrics = String ();

hook_dissociate ("tuple change", (HookFunction) lyrics_playback_began);
hook_dissociate ("playback ready", (HookFunction) lyrics_playback_began);

textview = nullptr;
textbuffer = nullptr;
}

static GtkWidget * append_item_to_menu (GtkWidget * menu, const char * label)
{
GtkWidget * menu_item = (label != nullptr)
? gtk_menu_item_new_with_label (label)
: gtk_separator_menu_item_new ();

gtk_menu_shell_append ((GtkMenuShell *) menu, menu_item);
gtk_widget_show (menu_item);

return menu_item;
}

static void append_separator_to_menu (GtkWidget * menu)
{
append_item_to_menu (menu, nullptr);
}

static void edit_lyrics_cb (GtkMenuItem * menu_item, void * data)
{
const char * edit_uri = (const char *) data;
#ifdef USE_GTK3
gtk_show_uri_on_window (nullptr, edit_uri, GDK_CURRENT_TIME, nullptr);
#else
gtk_show_uri (nullptr, edit_uri, GDK_CURRENT_TIME, nullptr);
#endif
}

static void save_locally_cb (GtkMenuItem * menu_item, void * data)
{
file_provider.save (g_state);
}

static void refresh_cb (GtkMenuItem * menu_item, void * data)
{
LyricProvider * remote_provider = remote_source ();
if (remote_provider)
remote_provider->match (g_state);
}

static void populate_popup_cb (GtkTextView * text_view, GtkWidget * menu, void * data)
{
if (! g_state.artist || ! g_state.title || ! GTK_IS_MENU (menu))
return;

GtkWidget * menu_item;
append_separator_to_menu (menu);

if (g_state.lyrics && g_state.source != LyricsState::Source::Local && ! g_state.error)
{
LyricProvider * remote_provider = remote_source ();

if (remote_provider)
{
String edit_uri = remote_provider->edit_uri (g_state);

if (edit_uri && edit_uri[0])
{
menu_item = append_item_to_menu (menu, _("Edit Lyrics ..."));
g_signal_connect_data (menu_item, "activate", (GCallback) edit_lyrics_cb,
g_strdup (edit_uri), (GClosureNotify) g_free, (GConnectFlags) 0);
}
}

menu_item = append_item_to_menu (menu, _("Save Locally"));
g_signal_connect (menu_item, "activate", (GCallback) save_locally_cb, nullptr);
}

if (g_state.source == LyricsState::Source::Local || g_state.error)
{
menu_item = append_item_to_menu (menu, _("Refresh"));
g_signal_connect (menu_item, "activate", (GCallback) refresh_cb, nullptr);
}
}

static GtkWidget * build_widget ()
{
textview = (GtkTextView *) gtk_text_view_new ();
gtk_text_view_set_editable (textview, false);
gtk_text_view_set_cursor_visible (textview, false);
gtk_text_view_set_left_margin (textview, 4);
gtk_text_view_set_right_margin (textview, 4);
gtk_text_view_set_wrap_mode (textview, GTK_WRAP_WORD);
textbuffer = gtk_text_view_get_buffer (textview);

GtkWidget * scrollview = gtk_scrolled_window_new (nullptr, nullptr);
gtk_scrolled_window_set_shadow_type ((GtkScrolledWindow *) scrollview, GTK_SHADOW_IN);
gtk_scrolled_window_set_policy ((GtkScrolledWindow *) scrollview, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
GtkWidget * vbox = audgui_vbox_new (6);

g_signal_connect (textview, "populate-popup", (GCallback) populate_popup_cb, nullptr);

gtk_container_add ((GtkContainer *) scrollview, (GtkWidget *) textview);
gtk_box_pack_start ((GtkBox *) vbox, scrollview, true, true, 0);

gtk_widget_show_all (vbox);

gtk_text_buffer_create_tag (textbuffer, "weight_bold", "weight", PANGO_WEIGHT_BOLD, nullptr);
gtk_text_buffer_create_tag (textbuffer, "scale_large", "scale", PANGO_SCALE_LARGE, nullptr);
gtk_text_buffer_create_tag (textbuffer, "style_italic", "style", PANGO_STYLE_ITALIC, nullptr);

GtkWidget * hbox = audgui_hbox_new (6);
gtk_box_pack_start ((GtkBox *) vbox, hbox, false, false, 0);

return vbox;
}

void * Lyrics::get_gtk_widget ()
{
GtkWidget * vbox = build_widget ();

hook_associate ("tuple change", (HookFunction) lyrics_playback_began, nullptr);
hook_associate ("playback ready", (HookFunction) lyrics_playback_began, nullptr);

if (aud_drct_get_ready ())
lyrics_playback_began ();

g_signal_connect (vbox, "destroy", (GCallback) destroy_cb, nullptr);

return vbox;
}
22 changes: 22 additions & 0 deletions src/lyrics-gtk/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
have_lyrics = xml_dep.found()

json_glib_dep = dependency('json-glib-1.0', version: '>= 1.0', required: true)

lyrics_deps = [audacious_dep, audgui_dep, gtk_dep, glib_dep, json_glib_dep, xml_dep]
lyrics_src = [
'../lyrics-common/chart_lyrics_provider.cc',
'../lyrics-common/file_provider.cc',
'../lyrics-common/lyrics_ovh_provider.cc',
'../lyrics-common/utils.cc',
'lyrics-gtk.cc'
]

if have_lyrics
shared_module('lyrics-gtk',
lyrics_src,
dependencies: lyrics_deps,
name_prefix: '',
install: true,
install_dir: general_plugin_dir
)
endif
1 change: 1 addition & 0 deletions src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ if conf.has('USE_GTK')
subdir('cairo-spectrum')
subdir('gtkui')
subdir('ladspa')
subdir('lyrics-gtk')
subdir('playlist-manager')
subdir('search-tool')
subdir('skins')
Expand Down

0 comments on commit e8243ee

Please sign in to comment.