plugin: convert plugin_callback_t to class
authorMax Kellermann <max@musicpd.org>
Sat, 14 Sep 2019 11:26:46 +0000 (13:26 +0200)
committerMax Kellermann <max@musicpd.org>
Sat, 14 Sep 2019 11:26:46 +0000 (13:26 +0200)
src/LyricsPage.cxx
src/lyrics.cxx
src/lyrics.hxx
src/plugin.cxx
src/plugin.hxx

index 2fe3ef8..ab78c5b 100644 (file)
@@ -28,6 +28,7 @@
 #include "mpdclient.hxx"
 #include "screen.hxx"
 #include "lyrics.hxx"
+#include "plugin.hxx"
 #include "TextPage.hxx"
 #include "screen_utils.hxx"
 #include "ncu.hxx"
@@ -48,7 +49,7 @@
 static struct mpd_song *next_song;
 static bool follow = false;
 
-class LyricsPage final : public TextPage {
+class LyricsPage final : public TextPage, PluginResponseHandler {
        /** Set if the cursor position shall be kept during the next lyrics update. */
        bool reloading = false;
 
@@ -110,15 +111,6 @@ private:
        /** save current lyrics to a file and run editor on it */
        void Edit();
 
-       static void PluginCallback(std::string &&result, bool success,
-                                  const char *plugin_name, void *data) {
-               auto &p = *(LyricsPage *)data;
-               p.PluginCallback(std::move(result), success, plugin_name);
-       }
-
-       void PluginCallback(std::string &&result, bool success,
-                           const char *plugin_name);
-
        void OnTimeout(const boost::system::error_code &error) noexcept;
 
 public:
@@ -127,6 +119,12 @@ public:
        void Update(struct mpdclient &c, unsigned events) noexcept override;
        bool OnCommand(struct mpdclient &c, Command cmd) override;
        const char *GetTitle(char *, size_t) const noexcept override;
+
+private:
+       /* virtual methods from class PluginResponseHandler */
+       void OnPluginSuccess(const char *plugin_name,
+                            std::string result) noexcept override;
+       void OnPluginError(std::string error) noexcept override;
 };
 
 void
@@ -227,28 +225,32 @@ LyricsPage::Set(const char *s)
        RepaintIfActive();
 }
 
-inline void
-LyricsPage::PluginCallback(std::string &&result, const bool success,
-                          const char *_plugin_name)
+void
+LyricsPage::OnPluginSuccess(const char *_plugin_name,
+                           std::string result) noexcept
 {
-       assert(loader != nullptr);
+       plugin_name = _plugin_name;
 
-       if (_plugin_name != nullptr)
-               plugin_name = _plugin_name;
-       else
-               plugin_name.clear();
-
-       /* Display result, which may be lyrics or error messages */
        Set(result.c_str());
 
-       if (success == true) {
-               if (options.lyrics_autosave &&
-                   !exists_lyr_file(artist, title))
-                       Save();
-       } else {
-               /* translators: no lyrics were found for the song */
-               screen_status_message (_("No lyrics"));
-       }
+       if (options.lyrics_autosave && !exists_lyr_file(artist, title))
+               Save();
+
+       loader_timeout.cancel();
+
+       plugin_stop(loader);
+       loader = nullptr;
+}
+
+void
+LyricsPage::OnPluginError(std::string error) noexcept
+{
+       plugin_name.clear();
+
+       Set(error.c_str());
+
+       /* translators: no lyrics were found for the song */
+       screen_status_message(_("No lyrics"));
 
        loader_timeout.cancel();
 
@@ -280,7 +282,7 @@ LyricsPage::Load(const struct mpd_song &_song) noexcept
        title = mpd_song_get_tag(song, MPD_TAG_TITLE, 0);
 
        loader = lyrics_load(get_io_service(),
-                            artist, title, PluginCallback, this);
+                            artist, title, *this);
 
        if (options.lyrics_timeout > std::chrono::steady_clock::duration::zero()) {
                boost::system::error_code error;
@@ -306,7 +308,7 @@ LyricsPage::Reload()
        if (loader == nullptr && artist != nullptr && title != nullptr) {
                reloading = true;
                loader = lyrics_load(get_io_service(),
-                                    artist, title, PluginCallback, nullptr);
+                                    artist, title, *this);
                Repaint();
        }
 }
index d0e6bbc..ae1dd28 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include "lyrics.hxx"
+#include "plugin.hxx"
 #include "config.h"
 
 static PluginList empty, plugins;
@@ -30,12 +31,12 @@ void lyrics_init()
 PluginCycle *
 lyrics_load(boost::asio::io_service &io_service,
            const char *artist, const char *title,
-           plugin_callback_t callback, void *data)
+           PluginResponseHandler &handler)
 {
        const char *args[3] = { artist, title, nullptr };
 
        if (artist == nullptr || title == nullptr)
-               return plugin_run(io_service, &empty, args, callback, data);
+               return plugin_run(io_service, &empty, args, handler);
 
-       return plugin_run(io_service, &plugins, args, callback, data);
+       return plugin_run(io_service, &plugins, args, handler);
 }
index 2b7b435..33081ec 100644 (file)
 #ifndef LYRICS_H
 #define LYRICS_H
 
-#include "plugin.hxx"
 #include "AsioServiceFwd.hxx"
 
 struct PluginCycle;
+class PluginResponseHandler;
 
 void lyrics_init();
 
 PluginCycle *
 lyrics_load(boost::asio::io_service &io_service,
            const char *artist, const char *title,
-           plugin_callback_t callback, void *callback_data);
+           PluginResponseHandler &handler);
 
 #endif
index 39fda8a..98c8839 100644 (file)
@@ -88,10 +88,8 @@ struct PluginCycle {
        /** arguments passed to execv() */
        std::unique_ptr<char *[]> argv;
 
-       /** caller defined callback function */
-       plugin_callback_t callback;
-       /** caller defined pointer passed to #callback */
-       void *callback_data;
+       /** caller defined handler object */
+       PluginResponseHandler &handler;
 
        /** the index of the next plugin which is going to be
            invoked */
@@ -113,9 +111,9 @@ struct PluginCycle {
 
        PluginCycle(boost::asio::io_service &io_service,
                    PluginList &_list, std::unique_ptr<char *[]> &&_argv,
-                   plugin_callback_t _callback, void *_callback_data) noexcept
+                   PluginResponseHandler &_handler) noexcept
                :list(&_list), argv(std::move(_argv)),
-                callback(_callback), callback_data(_callback_data),
+                handler(_handler),
                 pipe_stdout(io_service, *this),
                 pipe_stderr(io_service, *this),
                 delayed_fail_timer(io_service) {}
@@ -208,8 +206,7 @@ PluginCycle::OnEof() noexcept
                TryNextPlugin();
        } else {
                /* success: invoke the callback */
-               callback(std::move(pipe_stdout.data), true,
-                        argv[0], callback_data);
+               handler.OnPluginSuccess(argv[0], std::move(pipe_stdout.data));
        }
 }
 
@@ -249,8 +246,7 @@ PluginCycle::OnDelayedFail(const boost::system::error_code &error) noexcept
        assert(!pipe_stderr.fd.is_open());
        assert(pid < 0);
 
-       callback(std::move(all_errors), false, nullptr,
-                callback_data);
+       handler.OnPluginError(std::move(all_errors));
 }
 
 int
@@ -363,12 +359,12 @@ make_argv(const char*const* args) noexcept
 PluginCycle *
 plugin_run(boost::asio::io_service &io_service,
           PluginList *list, const char *const*args,
-          plugin_callback_t callback, void *callback_data) noexcept
+          PluginResponseHandler &handler) noexcept
 {
        assert(args != nullptr);
 
        auto *cycle = new PluginCycle(io_service, *list, make_argv(args),
-                                     callback, callback_data);
+                                     handler);
        cycle->TryNextPlugin();
 
        return cycle;
index 8d6fb7a..50b11a7 100644 (file)
 #include <string>
 
 /**
- * A list of registered plugins.
+ * When a plugin cycle is finished, one method of this class is called.  In any
+ * case, plugin_stop() has to be called to free all memory.
  */
-struct PluginList {
-       std::vector<std::string> plugins;
+class PluginResponseHandler {
+public:
+       /**
+        * @param plugin_name the name of the plugin which succeeded
+        * @param result the plugin's output (stdout)
+        */
+       virtual void OnPluginSuccess(const char *plugin_name,
+                                    std::string result) noexcept = 0;
+
+       virtual void OnPluginError(std::string error) noexcept = 0;
 };
 
 /**
- * When a plugin cycle is finished, this function is called.  In any
- * case, plugin_stop() has to be called to free all memory.
- *
- * @param result the plugin's output (stdout) on success; summary of all error
- * messages on failure as determined by success
- * @param success result of the plugin cycle; true if result is meaningful
- * output, false if result contains error messages
- * @param plugin_name the name of the plugin which succeeded; becomes invalid
- * when plugin_stop is called (i.e. strdup it if you need it afterwards).
- * @param data the caller defined pointer passed to plugin_run()
+ * A list of registered plugins.
  */
-typedef void (*plugin_callback_t)(std::string &&result, const bool success,
-                                 const char *plugin_name, void *data);
+struct PluginList {
+       std::vector<std::string> plugins;
+};
 
 /**
  * This object represents a cycle through all available plugins, until
@@ -66,15 +67,13 @@ plugin_list_load_directory(const char *path) noexcept;
  * @param list the plugin list
  * @param args nullptr terminated command line arguments passed to the
  * plugin programs; they must remain valid while the plugin runs
- * @param callback the callback function which will be called when a
- * result is available
- * @param callback_data caller defined pointer which is passed to the
- * callback function
+ * @param handler the handler which will be called when a result is
+ * available
  */
 PluginCycle *
 plugin_run(boost::asio::io_service &io_service,
           PluginList *list, const char *const*args,
-          plugin_callback_t callback, void *callback_data) noexcept;
+          PluginResponseHandler &handler) noexcept;
 
 /**
  * Stops the plugin cycle and frees resources.  This can be called to