]> Some of my projects - aniplayer.git/commitdiff
Introduce EventHandler
authorAPTX <marek321@gmail.com>
Sun, 20 Feb 2022 07:05:03 +0000 (16:05 +0900)
committerAPTX <marek321@gmail.com>
Mon, 21 Feb 2022 15:14:57 +0000 (00:14 +0900)
backendplugins/backend_mpv/backendmpv.cpp
backendplugins/backend_mpv/backendmpv.h
backendplugins/backend_mpv/mpvhelper.h

index 6df780790247b9e6d6dff6d6cc5e4188289e8df4..40a3c6ea8be8f433ae8a1f20cf1e10311f65e835 100644 (file)
@@ -34,6 +34,7 @@ MpvInstance::MpvInstance(PlayerPluginInterface *playerInterface,
     : QObject{parent}, m_player{playerInterface}, m_handle{
                                                       mpv::Handle::create()} {
   qCDebug(mpvBackend) << "Initialize";
+  m_eventHandler = std::make_unique<mpv::EventHandler<MpvInstance>>(this);
 
   qCDebug(mpvBackend()).nospace()
       << "Client API version: " << (mpv_client_api_version() >> 16) << '.'
@@ -107,6 +108,13 @@ MpvInstance::MpvInstance(PlayerPluginInterface *playerInterface,
     maxVolume /= 100.0;
     m_player->playbackMaxVolumeChanged(maxVolume);
   }
+  m_eventHandler->subscribe(mpv::event::LogMessage, &MpvInstance::onLogMessage);
+  m_eventHandler->subscribe(mpv::event::PropertyChange,
+                            &MpvInstance::onPropertyChange);
+  m_eventHandler->subscribe(mpv::event::FileLoaded, &MpvInstance::onFileLoaded);
+  m_eventHandler->subscribe(mpv::event::EndFile, &MpvInstance::onEndFile);
+  m_eventHandler->subscribe(mpv::event::AudioReconfig,
+                            &MpvInstance::onAudioReconfig);
 }
 
 MpvInstance::~MpvInstance() {
@@ -259,32 +267,7 @@ void MpvInstance::processMpvEvents() {
     qCDebug(mpvVerboseBackend).nospace()
         << "Event " << mpv_event_name(event->event_id) << '(' << event->event_id
         << "), error: " << event->error;
-    switch (event->event_id) {
-    case MPV_EVENT_PROPERTY_CHANGE: {
-      Q_CHECK_PTR(event->data);
-      auto property = static_cast<mpv_event_property *>(event->data);
-      Q_CHECK_PTR(property);
-      onPropertyChange(property);
-    } break;
-    case MPV_EVENT_LOG_MESSAGE: {
-      Q_CHECK_PTR(event->data);
-      auto log = static_cast<mpv_event_log_message *>(event->data);
-      Q_CHECK_PTR(log);
-      onLogMessage(log);
-    } break;
-    case MPV_EVENT_FILE_LOADED: {
-      onFileLoaded();
-    } break;
-    case MPV_EVENT_END_FILE: {
-      Q_CHECK_PTR(event->data);
-      auto endFile = static_cast<mpv_event_end_file *>(event->data);
-      onEndFile(endFile);
-    } break;
-    case MPV_EVENT_AUDIO_RECONFIG: {
-      onAudioReconfig();
-    } break;
-    default:;
-    }
+    m_eventHandler->handleEvent(event);
   } while (event->event_id != MPV_EVENT_NONE);
 }
 
index 88924f13547984a3e8fbd3e732b0dcc4d6168b3e..69013d3dc863d00b4949b909a0cefc6a7a4f1a96 100644 (file)
@@ -13,6 +13,11 @@ struct mpv_event_property;
 struct mpv_event_log_message;
 struct mpv_event_end_file;
 
+namespace mpv {
+template<typename T>
+class EventHandler;
+}
+
 class BACKEND_MPVSHARED_EXPORT BackendMpv : public QObject,
                                             public BackendPluginBase {
   Q_OBJECT
@@ -63,6 +68,7 @@ private:
 
   int readTrackIndex(struct mpv_event_property *);
 
+  std::unique_ptr<mpv::EventHandler<MpvInstance>> m_eventHandler;
   PlayerPluginInterface *m_player = nullptr;
   mpv::Handle m_handle;
   Volume m_volumeToSet = -1;
index d0612cbb14167244b1665c0605ba51ce95936fb9..375ab82215e0697add1dc5f281a70f8f9e0e2a2d 100644 (file)
@@ -9,6 +9,7 @@
 #include <QVariant>
 
 #include <memory>
+#include <unordered_map>
 
 #include <QLoggingCategory>
 
@@ -49,6 +50,7 @@ template<typename DataType = void>
 struct Event
 {
   using type = DataType;
+  using type_ptr = type *;
   const mpv_event_id id;
   constexpr explicit Event(mpv_event_id id) : id{id} {}
 };
@@ -232,6 +234,70 @@ int SetProperty(const Handle &handle, const Property &property,
   return detail::WriteFormat(handle, format, property.name, value);
 }
 
+template<typename Class>
+class EventHandler {
+  struct Callback
+  {
+    virtual ~Callback() = default;
+    virtual void run(Class *, mpv_event *) const = 0;
+  };
+  template<typename Event, typename CallbackType, bool IsVoid>
+  struct EventCallback : public Callback
+  {
+    const Event m_event;
+    CallbackType m_callback;
+
+    EventCallback(Event event, CallbackType callback)
+        : m_event{event}, m_callback{callback} {}
+
+    void run(Class *obj, mpv_event *event) const override {
+      assert(event->event_id == m_event.id);
+      if constexpr (IsVoid) {
+        (obj->*m_callback)();
+      } else {
+        assert(event->data != nullptr);
+        auto data = static_cast<typename Event::type_ptr>(event->data);
+        (obj->*m_callback)(data);
+      }
+    }
+  };
+
+  Class *const m_obj;
+
+  std::unordered_map<int, std::unique_ptr<Callback>> m_eventHandlers;
+
+public:
+  explicit EventHandler(Class *obj) : m_obj{obj} {}
+
+  template<typename Event>
+  std::enable_if_t<!std::is_same_v<typename Event::type, void>, bool>
+  subscribe(Event event, void (Class::*handler)(typename Event::type_ptr)) {
+    auto pair = m_eventHandlers.emplace(std::make_pair(
+        event.id,
+        std::make_unique<EventCallback<Event, decltype(handler), false>>(
+            event, handler)));
+    return !pair.second;
+  }
+
+  template<typename Event>
+  bool subscribe(Event event, void (Class::*handler)()) {
+    auto pair = m_eventHandlers.emplace(std::make_pair(
+        event.id,
+        std::make_unique<EventCallback<Event, decltype(handler), true>>(
+            event, handler)));
+    return !pair.second;
+  }
+
+  void handleEvent(mpv_event *event) {
+    assert(event != nullptr);
+    const auto it = m_eventHandlers.find(event->event_id);
+    if (it == std::end(m_eventHandlers)) {
+      return;
+    }
+    it->second->run(m_obj, event);
+  }
+};
+
 } // namespace mpv
 
 #endif // MPVHELPER_H