A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
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__ */