~mr-unwell2006/mixxx/mixxx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/***************************************************************************
                          controlobject.h  -  description
                             -------------------
    begin                : Wed Feb 20 2002
    copyright            : (C) 2002 by Tue and Ken Haste Andersen
    email                :
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef CONTROLOBJECT_H
#define CONTROLOBJECT_H

#include <QObject>
#include <QEvent>
#include <QMutex>
#include "midi/midimessage.h"
#include "configobject.h"
#include "controlobjectthread.h"

class QWidget;
class ConfigKey;

struct QueueObjectThread
{
    ControlObjectThread *pControlObjectThread;
    ControlObject *pControlObject;
    double value;
};

struct QueueObjectMidi
{
    ControlObject *pControlObject;
    MidiCategory category;
    double value;
};

/**
  * ControlObjects is used as a way to share controller values between controllers, GUI and
  * the sound engine. Whenever the value is changed by either a connected widget or a ControlEventMidi
  * the emitValueChanged method is called which syncronizes the new value with the player thread
  * using the semaphore protected queue.
  *
  * The player thread has a corresponding ControlEngine object for each ControlObject. The
  * ControlEngine object updates the ControlObject by queueing the values, and sending them as an
  * event to the ControlObject.
  *
  *@author Tue and Ken Haste Andersen
  */

class ControlObject : public QObject
{
    Q_OBJECT
public:
    ControlObject();
    ControlObject(ConfigKey key, bool bIgnoreNops=true);
    virtual ~ControlObject();
    /** Connect two control objects dest and src, so each time src is updated, so is dest. */
    static bool connectControls(ConfigKey src, ConfigKey dest);
    /** Disonnect a control object. */
    static bool disconnectControl(ConfigKey key);
    /** Returns a pointer to the ControlObject matching the given ConfigKey */
    static ControlObject *getControl(ConfigKey key);

    // Adds all ControlObjects that currently exist to pControlList
    static void getControls(QList<ControlObject*>* pControlsList);

    /** Used to add a pointer to the corresponding ControlObjectThread of this ControlObject */
    void addProxy(ControlObjectThread *pControlObjectThread);
    // To get rid of a proxy when the corresponding object is being deleted for example
    void removeProxy(ControlObjectThread *pControlObjectThread);
    /** Update proxies, execep the one given a pointer to. Returns true if all updates
      * happend, otherwise false. */
    bool updateProxies(ControlObjectThread *pProxyNoUpdate=0);
    /** Return the key of the object */
    inline ConfigKey getKey() { return m_Key; }
    /** Return the value of the ControlObject */
    inline double get() { return m_dValue; }
    /** Add to value. Not thread safe. */
    void add(double dValue);
    /** Subtract from value. Not thread safe. */
    void sub(double dValue);
    /** Syncronizes all ControlObjects with their corresponding proxies. */
    static void sync();
    /** Queue a control change from a widget. Thread safe. Blocking. */
    void queueFromThread(double dValue, ControlObjectThread *pControlObjectThread=0);
    /** Queue a control change from MIDI. Thread safe. Blocking. */
    void queueFromMidi(MidiCategory c, double v);
    /** Return a ControlObject value, corresponding to the widget input value. Thread safe. */
    virtual double getValueFromWidget(double dValue);
    /** Return a widget value corresponding to the ControlObject input value. Thread safe. */
    virtual double getValueToWidget(double dValue);
    /** get value (range 0..127) **/
    virtual double GetMidiValue();

public slots:
    /** Sets the value of the object and updates associated proxy objects. Not thread safe. */
    void set(double dValue);

signals:
    void valueChanged(double);
    void valueChangedFromEngine(double);

protected:
    /** Sets the value of the object. Not thread safe. */
    virtual void setValueFromEngine(double dValue);
    /** Called when a widget has changed value. Not thread safe. */
    virtual void setValueFromMidi(MidiCategory, double v);
    /** Called when another thread has changed value. Not thread safe. */
    virtual void setValueFromThread(double dValue);

protected:
    /** The actual value of the controller */
    double m_dValue;
    /** Key of the object */
    ConfigKey m_Key;

private:
    // Whether to ignore set/add/sub()'s which would have no effect
    bool m_bIgnoreNops;
    /** List of associated proxy objects */
    QList<ControlObjectThread*> m_qProxyList;
    /** Mutex for the proxy list */
    QMutex m_qProxyListMutex;

    /** Hash of ControlObject instantiations */
    static QHash<ConfigKey,ControlObject*> m_sqCOHash;
    /** Mutex guarding access to the ControlObject hash **/
    static QMutex m_sqCOHashMutex;
    /** Mutex protecting access to the queues */
    static QMutex m_sqQueueMutexMidi, m_sqQueueMutexThread, m_sqQueueMutexChanges;
    /** Queue holding control changes from MIDI */
    static QQueue<QueueObjectMidi*> m_sqQueueMidi;
    /** Queues holding control changes from other application threads and from widgets */
    static QQueue<QueueObjectThread*> m_sqQueueThread;
    /** Queue holding ControlObjects that has changed, but not been syncronized with it's
     * associated ControlObjectProxy objects. */
    static QQueue<ControlObject*> m_sqQueueChanges;
};


#endif