A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 378 lines 12 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (C) 2014 by Amaury Pouly 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License 14 * as published by the Free Software Foundation; either version 2 15 * of the License, or (at your option) any later version. 16 * 17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 * KIND, either express or implied. 19 * 20 ****************************************************************************/ 21#ifndef __BACKEND_H__ 22#define __BACKEND_H__ 23 24#include <QObject> 25#include <QStringList> 26#include <QMap> 27#include <QVector> 28#include <QMetaType> 29#include <QAbstractItemModel> 30#ifdef HAVE_HWSTUB 31#include "hwstub.hpp" 32#include "hwstub_usb.hpp" 33#include "hwstub_uri.hpp" 34#endif 35#include "soc_desc.hpp" 36 37/* we don't want to import the entire soc_desc except for a few selected 38 * pieces */ 39using soc_desc::soc_word_t; 40using soc_desc::soc_addr_t; 41using soc_desc::soc_id_t; 42 43class IoBackend : public QObject 44{ 45 Q_OBJECT 46public: 47 IoBackend() {} 48 virtual ~IoBackend() {} 49 50 enum WriteMode 51 { 52 Write, Set, Clear, Toggle 53 }; 54 55 /* report whether backend is valid */ 56 virtual bool IsValid() = 0; 57 /* get SoC name */ 58 virtual QString GetSocName() = 0; 59 /* read a register */ 60 virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value, unsigned width) = 0; 61 /* reload content (if it makes sense) */ 62 virtual bool Reload() = 0; 63 /* check whether backend supports writing */ 64 virtual bool IsReadOnly() = 0; 65 /* write a register by name or address 66 * NOTE: even on a read-only backend, a write is allowed to be successful as long 67 * as commit fails */ 68 virtual bool WriteRegister(soc_addr_t addr, soc_word_t value, unsigned width, 69 WriteMode mode = Write) = 0; 70 /* check whether backend contains uncommitted (ie cached) writes */ 71 virtual bool IsDirty() = 0; 72 /* commit all writes */ 73 virtual bool Commit() = 0; 74}; 75 76class DummyIoBackend : public IoBackend 77{ 78 Q_OBJECT 79public: 80 DummyIoBackend(); 81 82 virtual bool IsValid(); 83 virtual QString GetSocName(); 84 virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value, unsigned width); 85 virtual bool Reload(); 86 virtual bool IsReadOnly(); 87 virtual bool WriteRegister(soc_addr_t addr, soc_word_t value, unsigned width, 88 WriteMode mode); 89 virtual bool IsDirty(); 90 virtual bool Commit(); 91}; 92 93/** The RAM backend doesn't have any backend storage and stores all values in 94 * an associative map */ 95class RamIoBackend : public IoBackend 96{ 97 Q_OBJECT 98public: 99 RamIoBackend(const QString& soc_name = ""); 100 101 virtual bool IsValid(); 102 virtual QString GetSocName(); 103 virtual void SetSocName(const QString& soc_name); 104 virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value, unsigned width); 105 virtual bool Reload(); 106 virtual bool IsReadOnly(); 107 virtual bool WriteRegister(soc_addr_t addr, soc_word_t value, unsigned width, 108 WriteMode mode); 109 virtual bool IsDirty(); 110 virtual bool Commit(); 111 /* clear all entries of the backend */ 112 virtual void DeleteAll(); 113 114protected: 115 QString m_soc; 116 QMap< soc_addr_t, soc_word_t > m_map; 117}; 118 119/** NOTE the File backend makes a difference between writes and commits: 120 * a write will *never* touch the underlying file unless it was committed. */ 121class FileIoBackend : public RamIoBackend 122{ 123 Q_OBJECT 124public: 125 FileIoBackend(const QString& filename, const QString& soc_name = ""); 126 127 virtual bool IsValid(); 128 virtual bool Reload(); 129 virtual bool IsReadOnly(); 130 virtual bool WriteRegister(soc_addr_t addr, soc_word_t value, unsigned width, 131 WriteMode mode); 132 virtual bool IsDirty(); 133 virtual bool Commit(); 134 QString GetFileName(); 135 136protected: 137 QString m_filename; 138 bool m_readonly; 139 bool m_dirty; 140 bool m_valid; 141}; 142 143#ifdef HAVE_HWSTUB 144/* HWStub context manager: provides a centralized place to add/remove/get 145 * contexts */ 146class HWStubManager : public QAbstractTableModel 147{ 148 Q_OBJECT 149protected: 150 HWStubManager(); 151public: 152 virtual ~HWStubManager(); 153 /* Get manager */ 154 static HWStubManager *Get(); 155 /* Clear the context list */ 156 void Clear(); 157 bool Add(const QString& name, const QString& uri); 158 /* Model */ 159 virtual int rowCount(const QModelIndex& parent = QModelIndex()) const; 160 virtual int columnCount(const QModelIndex& parent = QModelIndex()) const; 161 virtual QVariant data(const QModelIndex& index, int role) const; 162 virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const; 163 virtual Qt::ItemFlags flags(const QModelIndex& index) const; 164 virtual bool setData(const QModelIndex& index, const QVariant& value, int role); 165 /* return predefined columns */ 166 int GetNameColumn() const; 167 int GetUriColumn() const; 168 std::shared_ptr< hwstub::context > GetContext(int row); 169 /* return a friendly name for a device */ 170 static QString GetFriendlyName(std::shared_ptr< hwstub::device > device); 171 172protected: 173 struct Context 174 { 175 std::shared_ptr< hwstub::context > context; 176 QString name; 177 QString uri; 178 }; 179 180 std::vector< Context > m_list; /* list of context */ 181 static HWStubManager *g_inst; /* unique instance */ 182}; 183 184/* HWStub context model: provides access to the device list using Qt MVC model. */ 185class HWStubContextModel : public QAbstractTableModel 186{ 187 Q_OBJECT 188public: 189 HWStubContextModel(QObject *parent = 0); 190 virtual ~HWStubContextModel(); 191 void SetContext(std::shared_ptr< hwstub::context > context); 192 /* Model */ 193 virtual int rowCount(const QModelIndex& parent = QModelIndex()) const; 194 virtual int columnCount(const QModelIndex& parent = QModelIndex()) const; 195 virtual QVariant data(const QModelIndex& index, int role) const; 196 virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const; 197 virtual Qt::ItemFlags flags(const QModelIndex& index) const; 198 /* return predefined columns */ 199 int GetNameColumn() const; 200 std::shared_ptr< hwstub::device > GetDevice(int row); 201 /* Add an entry in the model for "no selection", which will correspond to 202 * a dummy device. This function also allows the text to be customised. */ 203 void EnableDummy(bool en, const QString& text = ""); 204 205private slots: 206 void OnDevChangeUnsafe(void *data); 207protected: 208 QString GetFriendlyName(std::shared_ptr< hwstub::device > device); 209 void OnDevChangeLow(std::shared_ptr< hwstub::context > ctx, bool arrived, 210 std::shared_ptr< hwstub::device > device); 211 void OnDevChange(std::shared_ptr< hwstub::context > ctx, bool arrived, 212 std::shared_ptr< hwstub::device > device); 213 214 struct Device 215 { 216 QString name; 217 std::shared_ptr< hwstub::device > device; 218 }; 219 220 std::vector< Device > m_list; 221 std::weak_ptr< hwstub::context > m_context; 222 hwstub::context::callback_ref_t m_callback_ref; 223 bool m_has_dummy; 224 QString m_dummy_text; 225}; 226 227/* Abstract Virtual Class from where TCP and USB backend 228 * child classes are derived 229 */ 230class HWStubDevice 231{ 232public: 233 HWStubDevice(std::shared_ptr<hwstub::device> device); 234 virtual ~HWStubDevice(); 235 236 QString GetFriendlyName(); 237 bool IsValid(); 238 /* Calls below are cached */ 239 inline struct hwstub_version_desc_t GetVersionInfo() { return m_hwdev_ver; } 240 inline struct hwstub_target_desc_t GetTargetInfo() { return m_hwdev_target; } 241 inline struct hwstub_stmp_desc_t GetSTMPInfo() { return m_hwdev_stmp; } 242 inline struct hwstub_pp_desc_t GetPPInfo() { return m_hwdev_pp; } 243 inline struct hwstub_jz_desc_t GetJZInfo() { return m_hwdev_jz; } 244 bool ReadMem(soc_addr_t addr, size_t length, void *buffer); 245 bool WriteMem(soc_addr_t addr, size_t length, void *buffer); 246 247protected: 248 bool Probe(std::shared_ptr<hwstub::device> device); 249 250 std::shared_ptr<hwstub::handle> m_handle; 251 bool m_valid; 252 struct hwstub_device_t *m_hwdev; 253 struct hwstub_version_desc_t m_hwdev_ver; 254 struct hwstub_target_desc_t m_hwdev_target; 255 struct hwstub_stmp_desc_t m_hwdev_stmp; 256 struct hwstub_pp_desc_t m_hwdev_pp; 257 struct hwstub_jz_desc_t m_hwdev_jz; 258 QString m_name; 259}; 260 261/** NOTE the HWStub backend is never dirty: all wrnew ites are immediately committed */ 262class HWStubIoBackend : public IoBackend 263{ 264 Q_OBJECT 265public: 266 // NOTE: HWStubIoBackend takes ownership of the device and will delete it 267 HWStubIoBackend(HWStubDevice *dev); 268 virtual ~HWStubIoBackend(); 269 270 virtual bool IsValid(); 271 virtual QString GetSocName(); 272 virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value, unsigned width); 273 virtual bool Reload(); 274 virtual bool IsReadOnly(); 275 virtual bool WriteRegister(soc_addr_t addr, soc_word_t value, unsigned width, 276 WriteMode mode); 277 virtual bool IsDirty(); 278 virtual bool Commit(); 279 HWStubDevice *GetDevice(); 280 281protected: 282 QString m_soc; 283 HWStubDevice *m_dev; 284}; 285#endif 286 287class SocFile 288{ 289public: 290 SocFile(); 291 SocFile(const QString& filename); 292 bool IsValid(); 293 294 soc_desc::soc_ref_t GetSocRef(); 295 QString GetFilename(); 296 soc_desc::soc_t& GetSoc() { return m_soc; } 297 298protected: 299 bool m_valid; 300 QString m_filename; 301 soc_desc::soc_t m_soc; 302}; 303 304class SocFileRef 305{ 306public: 307 SocFileRef():m_socfile(0) {} 308 SocFileRef(SocFile *file):m_socfile(file) {} 309 SocFile *GetSocFile() const { return m_socfile; } 310 311protected: 312 SocFile *m_socfile; 313}; 314 315Q_DECLARE_METATYPE(SocFileRef) 316 317Q_DECLARE_METATYPE(soc_desc::instance_t::type_t) 318Q_DECLARE_METATYPE(soc_desc::range_t::type_t) 319 320Q_DECLARE_METATYPE(soc_desc::soc_ref_t) 321Q_DECLARE_METATYPE(soc_desc::node_ref_t) 322Q_DECLARE_METATYPE(soc_desc::register_ref_t) 323Q_DECLARE_METATYPE(soc_desc::field_ref_t) 324Q_DECLARE_METATYPE(soc_desc::node_inst_t) 325 326/** NOTE the Backend stores soc descriptions in a way that pointers are never 327 * invalidated */ 328class Backend : public QObject 329{ 330 Q_OBJECT 331public: 332 Backend(); 333 334 QList< SocFileRef > GetSocFileList(); 335 QList< soc_desc::soc_ref_t > GetSocList(); 336 bool LoadSocDesc(const QString& filename); 337 IoBackend *CreateDummyIoBackend(); 338 IoBackend *CreateFileIoBackend(const QString& filename); 339#ifdef HAVE_HWSTUB 340 IoBackend *CreateHWStubIoBackend(HWStubDevice *dev); 341#endif 342 343signals: 344 void OnSocAdded(const SocFileRef& ref); 345 346private: 347 /* store them as a list so that pointers are never invalidated */ 348 std::list< SocFile > m_socs; 349}; 350 351class BackendHelper 352{ 353public: 354 BackendHelper(IoBackend *io_backend, const soc_desc::soc_ref_t& soc); 355 QString GetPath(const soc_desc::node_inst_t& inst); 356 soc_desc::node_inst_t ParsePath(const QString& path); 357 bool ReadRegister(const soc_desc::node_inst_t& inst, soc_word_t& v); 358 bool ReadRegisterField(const soc_desc::node_inst_t& inst, 359 const QString& field, soc_word_t& v); 360 bool WriteRegister(const soc_desc::node_inst_t& inst, soc_word_t v, 361 IoBackend::WriteMode mode = IoBackend::Write); 362 bool GetRegisterAddress(const soc_desc::node_inst_t& inst, soc_addr_t& addr); 363 /* NOTE: does not commit writes to the backend 364 * if ignore_errors is true, the dump will continue even on errors, and the 365 * function will return false if one or more errors occured */ 366 bool DumpAllRegisters(IoBackend *backend, bool ignore_errors = true); 367 bool DumpAllRegisters(const QString& filename, bool ignore_errors = true); 368 369protected: 370 bool DumpAllRegisters(BackendHelper *bh, const soc_desc::node_inst_t& inst, 371 bool ignore_errors); 372 373private: 374 IoBackend *m_io_backend; 375 const soc_desc::soc_ref_t& m_soc; 376}; 377 378#endif /* __BACKEND_H__ */