Merge lp:~mixxxdevelopers/mixxx/features_spinny into lp:~mixxxdevelopers/mixxx/trunk

Proposed by Albert Santoni
Status: Merged
Merged at revision: 2794
Proposed branch: lp:~mixxxdevelopers/mixxx/features_spinny
Merge into: lp:~mixxxdevelopers/mixxx/trunk
Diff against target: 904 lines (+617/-26)
18 files modified
mixxx/build/depends.py (+2/-0)
mixxx/src/dlgprefvinyl.cpp (+17/-2)
mixxx/src/dlgprefvinyl.h (+4/-9)
mixxx/src/engine/positionscratchcontroller.cpp (+1/-0)
mixxx/src/engine/vinylcontrolcontrol.cpp (+13/-0)
mixxx/src/engine/vinylcontrolcontrol.h (+1/-0)
mixxx/src/mathstuff.h (+1/-1)
mixxx/src/sharedglcontext.cpp (+23/-0)
mixxx/src/sharedglcontext.h (+15/-0)
mixxx/src/skin/legacyskinparser.cpp (+19/-0)
mixxx/src/skin/legacyskinparser.h (+1/-0)
mixxx/src/vinylcontrol/vinylcontrol.h (+3/-0)
mixxx/src/waveformviewerfactory.cpp (+2/-11)
mixxx/src/waveformviewerfactory.h (+0/-1)
mixxx/src/widget/wglwaveformviewer.cpp (+13/-2)
mixxx/src/widget/wglwaveformviewer.h (+1/-0)
mixxx/src/widget/wspinny.cpp (+434/-0)
mixxx/src/widget/wspinny.h (+67/-0)
To merge this branch: bzr merge lp:~mixxxdevelopers/mixxx/features_spinny
Reviewer Review Type Date Requested Status
RJ Skerry-Ryan Approve
Owen Williams Needs Fixing
Review via email: mp+60327@code.launchpad.net

Description of the change

Spinning vinyl widget, and factors out GL context creation into its own class. Also makes the waveform grab used the _closed_ hand icon. :)

To post a comment you must log in.
Revision history for this message
RJ Skerry-Ryan (rryan) wrote :

* In SharedGLContext, are a constructor / destructor necessary? I don't think anything creates an instance, just uses the static methods.

* Check for PathBackground / PathForeground / PathGhost actually existing?

* WPixmapStore::getPixmap can return NULL if the pixmap doesn't exist. All uses of the member-variable pixmaps should be checked for non-NULL first

* QElapsedTimer, while much better than QTime, means we are ditching any platform <Qt 4.7 (e.g. Ubuntu 10.04 and earlier). I think it's a bit early to do that -- maybe stick to QTime for now?

Revision history for this message
RJ Skerry-Ryan (rryan) wrote :

* Qt::MiddleButton isn't compatible with <Qt 4.7 either, use Qt::MidButton instead

2775. By Albert Santoni

* Addressing RJ's code review:
    - Remove unnecessary SharedGLContext destructor (kept private constructor though).
    - Handle WSpinny math when track_samples or other params are NaN.
    - Protect all pixmap drawing in WSpinny against NULL pointers and pixmaps.
    - Fixes for Qt < 4.7 compatibility

Revision history for this message
Albert Santoni (gamegod) wrote :

k, fixed everything you pointed out in r2775 plus the ASSERTs Jus found when no tracks were loaded.

Thanks,
Albert

2776. By Albert Santoni

Squash WSpinny compiler warnings and my leftover qDebugs (oops)

2777. By Albert Santoni

* Merged from trunk

Revision history for this message
Owen Williams (ywwg) wrote :

This widget will need to understand 33 vs 45 rpm record speeds and move the spinner at a higher speed if the record is set to 45RPM. Use [ChannelX],"vinylcontrol_speed_type", which is either "33.3 RPM" or "45 RPM".

Also, is the spinny thing guaranteed to show the same angle for the same sample index number? That's the important part :).

also, "roughly 0.5" is not acceptable. This value needs to be exact (5/9).

review: Needs Fixing
2778. By Albert Santoni

Use exact 33.3 RPM rotational speed in WSpinny

Revision history for this message
Albert Santoni (gamegod) wrote :

Hey Owen,

I just jammed that fraction in there to make the rotation more precise.

The good news is that the spinny thing is guaranteed to show the same
angle for the same sample index.

The bad news is that I can't monitor for changes of that ConfigKey
because it's a ConfigKey and not a ControlObject. (ie. WSpinny can't
tell when the vinyl control speed preferences get changed.) In the
past, we've solved this problem by duplicating the ConfigKey's value
across to a ControlObject. For example, the [Master],"samplerate"
ControlObject just mirrors a ConfigKey that's hooked into the prefs. I
guess I'll have to fix this that way?

Thanks,
Albert

On Mon, May 9, 2011 at 7:18 AM, Owen Williams <email address hidden> wrote:
> Review: Needs Fixing
> This widget will need to understand 33 vs 45 rpm record speeds and move the spinner at a higher speed if the record is set to 45RPM.  Use [ChannelX],"vinylcontrol_speed_type", which is either "33.3 RPM" or "45 RPM".
>
> Also, is the spinny thing guaranteed to show the same angle for the same sample index number?  That's the important part :).
>
> also, "roughly 0.5" is not acceptable.  This value needs to be exact (5/9).
> --
> https://code.launchpad.net/~mixxxdevelopers/mixxx/features_spinny/+merge/60327
> Your team Mixxx Development Team is subscribed to branch lp:mixxx.
>

--
Albert Santoni
Developer, Mixxx
http://www.mixxx.org

2779. By Albert Santoni

* WSpinny respects the vinyl control RPM setting now so it always matches your turntables' speed.
* Minor cleanup in DlgPrefVinyl.

Revision history for this message
Albert Santoni (gamegod) wrote :

Ok that all up in r2779. Should be good to go now and matches your vinyl control speed.

Albert

Revision history for this message
Albert Santoni (gamegod) wrote :

"Ok, *fixed* that all up in r2779.

> Ok that all up in r2779. Should be good to go now and matches your vinyl
> control speed.
>
> Albert

Revision history for this message
RJ Skerry-Ryan (rryan) wrote :

LGTM! thanks albert

review: Approve
Revision history for this message
Owen Williams (ywwg) wrote :

> The bad news is that I can't monitor for changes of that ConfigKey
> because it's a ConfigKey and not a ControlObject. (ie. WSpinny can't
> tell when the vinyl control speed preferences get changed.) In the
> past, we've solved this problem by duplicating the ConfigKey's value
> across to a ControlObject. For example, the [Master],"samplerate"
> ControlObject just mirrors a ConfigKey that's hooked into the prefs. I
> guess I'll have to fix this that way?

We can either do that, or I can add a function in vinylcontrolproxy like getSpeed() that returns 1.0 for 33rpm, and 1.35 for 45rpm

Revision history for this message
Owen Williams (ywwg) wrote :

Is there a skin / example xml that shows this widget in action? It looks like it wants a couple pixmaps

Revision history for this message
RJ Skerry-Ryan (rryan) wrote :

Jus is cooking up some examples -- my guess is they will show up in his 1.10
branch soon.

On Wed, May 11, 2011 at 2:09 PM, Owen Williams <email address hidden> wrote:

> Is there a skin / example xml that shows this widget in action? It looks
> like it wants a couple pixmaps
> --
>
> https://code.launchpad.net/~mixxxdevelopers/mixxx/features_spinny/+merge/60327
> You are reviewing the proposed merge of
> lp:~mixxxdevelopers/mixxx/features_spinny into lp:mixxx.
>

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'mixxx/build/depends.py'
--- mixxx/build/depends.py 2011-04-28 21:54:22 +0000
+++ mixxx/build/depends.py 2011-05-11 04:41:18 +0000
@@ -414,6 +414,7 @@
414414
415 "soundsource.cpp",415 "soundsource.cpp",
416416
417 "sharedglcontext.cpp",
417 "widget/wwidget.cpp",418 "widget/wwidget.cpp",
418 "widget/wlabel.cpp",419 "widget/wlabel.cpp",
419 "widget/wtracktext.cpp",420 "widget/wtracktext.cpp",
@@ -428,6 +429,7 @@
428 "widget/wslider.cpp",429 "widget/wslider.cpp",
429 "widget/wstatuslight.cpp",430 "widget/wstatuslight.cpp",
430 "widget/woverview.cpp",431 "widget/woverview.cpp",
432 "widget/wspinny.cpp",
431 "widget/wskincolor.cpp",433 "widget/wskincolor.cpp",
432 "widget/wabstractcontrol.cpp",434 "widget/wabstractcontrol.cpp",
433 "widget/wsearchlineedit.cpp",435 "widget/wsearchlineedit.cpp",
434436
=== modified file 'mixxx/src/dlgprefvinyl.cpp'
--- mixxx/src/dlgprefvinyl.cpp 2011-04-17 04:16:00 +0000
+++ mixxx/src/dlgprefvinyl.cpp 2011-05-11 04:41:18 +0000
@@ -30,7 +30,9 @@
3030
31DlgPrefVinyl::DlgPrefVinyl(QWidget * parent, VinylControlManager *pVCMan,31DlgPrefVinyl::DlgPrefVinyl(QWidget * parent, VinylControlManager *pVCMan,
32 ConfigObject<ConfigValue> * _config) : QWidget(parent), Ui::DlgPrefVinylDlg(),32 ConfigObject<ConfigValue> * _config) : QWidget(parent), Ui::DlgPrefVinylDlg(),
33 m_COTMode(ControlObject::getControl(ConfigKey("[VinylControl]", "mode")))33 m_COMode(ControlObject::getControl(ConfigKey("[VinylControl]", "mode"))),
34 m_COSpeed1(ControlObject::getControl(ConfigKey("[Channel1]", "vinylcontrol_speed_type"))),
35 m_COSpeed2(ControlObject::getControl(ConfigKey("[Channel2]", "vinylcontrol_speed_type")))
34{36{
35 m_pVCManager = pVCMan;37 m_pVCManager = pVCMan;
36 config = _config;38 config = _config;
@@ -177,7 +179,7 @@
177179
178 ControlObject::getControl(ConfigKey("[Channel1]", "vinylcontrol_mode"))->set(iMode);180 ControlObject::getControl(ConfigKey("[Channel1]", "vinylcontrol_mode"))->set(iMode);
179 ControlObject::getControl(ConfigKey("[Channel2]", "vinylcontrol_mode"))->set(iMode);181 ControlObject::getControl(ConfigKey("[Channel2]", "vinylcontrol_mode"))->set(iMode);
180 m_COTMode.slotSet(iMode);182 m_COMode.slotSet(iMode);
181 config->set(ConfigKey("[VinylControl]","mode"), ConfigValue(iMode));183 config->set(ConfigKey("[VinylControl]","mode"), ConfigValue(iMode));
182 config->set(ConfigKey("[VinylControl]","needle_skip_prevention" ), ConfigValue( (int)(NeedleSkipEnable->isChecked( )) ) );184 config->set(ConfigKey("[VinylControl]","needle_skip_prevention" ), ConfigValue( (int)(NeedleSkipEnable->isChecked( )) ) );
183185
@@ -196,6 +198,19 @@
196 config->set(ConfigKey("[Channel2]","vinylcontrol_vinyl_type"), ConfigValue(ComboBoxVinylType2->currentText()));198 config->set(ConfigKey("[Channel2]","vinylcontrol_vinyl_type"), ConfigValue(ComboBoxVinylType2->currentText()));
197 config->set(ConfigKey("[Channel1]","vinylcontrol_speed_type"), ConfigValue(ComboBoxVinylSpeed1->currentText()));199 config->set(ConfigKey("[Channel1]","vinylcontrol_speed_type"), ConfigValue(ComboBoxVinylSpeed1->currentText()));
198 config->set(ConfigKey("[Channel2]","vinylcontrol_speed_type"), ConfigValue(ComboBoxVinylSpeed2->currentText()));200 config->set(ConfigKey("[Channel2]","vinylcontrol_speed_type"), ConfigValue(ComboBoxVinylSpeed2->currentText()));
201
202 //Save the vinylcontrol_speed_type in ControlObjects as well so it can be retrieved quickly
203 //on the fly. (eg. WSpinny needs to know how fast to spin)
204 if (ComboBoxVinylSpeed1->currentText() == MIXXX_VINYL_SPEED_33) {
205 m_COSpeed1.slotSet(MIXXX_VINYL_SPEED_33_NUM);
206 } else if (ComboBoxVinylSpeed1->currentText() == MIXXX_VINYL_SPEED_45) {
207 m_COSpeed1.slotSet(MIXXX_VINYL_SPEED_45_NUM);
208 }
209 if (ComboBoxVinylSpeed2->currentText() == MIXXX_VINYL_SPEED_33) {
210 m_COSpeed2.slotSet(MIXXX_VINYL_SPEED_33_NUM);
211 } else if (ComboBoxVinylSpeed2->currentText() == MIXXX_VINYL_SPEED_45) {
212 m_COSpeed2.slotSet(MIXXX_VINYL_SPEED_45_NUM);
213 }
199}214}
200215
201void DlgPrefVinyl::VinylGainSlotApply()216void DlgPrefVinyl::VinylGainSlotApply()
202217
=== modified file 'mixxx/src/dlgprefvinyl.h'
--- mixxx/src/dlgprefvinyl.h 2011-04-17 04:16:00 +0000
+++ mixxx/src/dlgprefvinyl.h 2011-05-11 04:41:18 +0000
@@ -21,7 +21,7 @@
21#include "ui_dlgprefvinyldlg.h"21#include "ui_dlgprefvinyldlg.h"
22#include "configobject.h"22#include "configobject.h"
23#include "vinylcontrol/vinylcontrolsignalwidget.h"23#include "vinylcontrol/vinylcontrolsignalwidget.h"
24#include "controlobjectthread.h"24#include "controlobjectthreadmain.h"
2525
26class QWidget;26class QWidget;
27class PlayerProxy;27class PlayerProxy;
@@ -61,14 +61,9 @@
61 VinylControlManager* m_pVCManager;61 VinylControlManager* m_pVCManager;
62 /** Pointer to config object */62 /** Pointer to config object */
63 ConfigObject<ConfigValue> *config;63 ConfigObject<ConfigValue> *config;
64 /** Indicates the strength of the timecode signal on each input */64 ControlObjectThreadMain m_COMode;
65 ControlObjectThreadMain* m_timecodeQuality1;65 ControlObjectThreadMain m_COSpeed1;
66 ControlObjectThreadMain* m_timecodeQuality2;66 ControlObjectThreadMain m_COSpeed2;
67 ControlObjectThreadMain* m_vinylControlInput1L;
68 ControlObjectThreadMain* m_vinylControlInput1R;
69 ControlObjectThreadMain* m_vinylControlInput2L;
70 ControlObjectThreadMain* m_vinylControlInput2R;
71 ControlObjectThread m_COTMode;
72};67};
7368
74#endif69#endif
7570
=== modified file 'mixxx/src/engine/positionscratchcontroller.cpp'
--- mixxx/src/engine/positionscratchcontroller.cpp 2011-04-26 23:57:28 +0000
+++ mixxx/src/engine/positionscratchcontroller.cpp 2011-05-11 04:41:18 +0000
@@ -113,6 +113,7 @@
113 m_bScratching = false;113 m_bScratching = false;
114 m_iScratchTime = 0;114 m_iScratchTime = 0;
115 m_bEnableInertia = false;115 m_bEnableInertia = false;
116 m_dRate = 0.;
116117
117 //m_pVelocityController->setPID(0.2, 1.0, 5.0);118 //m_pVelocityController->setPID(0.2, 1.0, 5.0);
118 //m_pVelocityController->setPID(0.1, 0.0, 5.0);119 //m_pVelocityController->setPID(0.1, 0.0, 5.0);
119120
=== modified file 'mixxx/src/engine/vinylcontrolcontrol.cpp'
--- mixxx/src/engine/vinylcontrolcontrol.cpp 2011-04-19 14:03:57 +0000
+++ mixxx/src/engine/vinylcontrolcontrol.cpp 2011-05-11 04:41:18 +0000
@@ -6,6 +6,19 @@
6VinylControlControl::VinylControlControl(const char* pGroup, ConfigObject<ConfigValue>* pConfig)6VinylControlControl::VinylControlControl(const char* pGroup, ConfigObject<ConfigValue>* pConfig)
7 : EngineControl(pGroup, pConfig) {7 : EngineControl(pGroup, pConfig) {
8 m_pControlVinylStatus = new ControlObject(ConfigKey(pGroup, "vinylcontrol_status"));8 m_pControlVinylStatus = new ControlObject(ConfigKey(pGroup, "vinylcontrol_status"));
9 m_pControlVinylSpeedType = new ControlObject(ConfigKey(pGroup, "vinylcontrol_speed_type"));
10
11 //Convert the ConfigKey's value into a double for the CO (for fast reads).
12 QString strVinylSpeedType = pConfig->getValueString(ConfigKey(pGroup,
13 "vinylcontrol_speed_type"));
14 if (strVinylSpeedType == MIXXX_VINYL_SPEED_33) {
15 m_pControlVinylSpeedType->set(MIXXX_VINYL_SPEED_33_NUM);
16 } else if (strVinylSpeedType == MIXXX_VINYL_SPEED_45) {
17 m_pControlVinylSpeedType->set(MIXXX_VINYL_SPEED_45_NUM);
18 } else {
19 m_pControlVinylSpeedType->set(MIXXX_VINYL_SPEED_33_NUM);
20 }
21
9 m_pControlVinylSeek = new ControlObject(ConfigKey(pGroup, "vinylcontrol_seek"));22 m_pControlVinylSeek = new ControlObject(ConfigKey(pGroup, "vinylcontrol_seek"));
10 connect(m_pControlVinylSeek, SIGNAL(valueChanged(double)),23 connect(m_pControlVinylSeek, SIGNAL(valueChanged(double)),
11 this, SLOT(slotControlVinylSeek(double)),24 this, SLOT(slotControlVinylSeek(double)),
1225
=== modified file 'mixxx/src/engine/vinylcontrolcontrol.h'
--- mixxx/src/engine/vinylcontrolcontrol.h 2011-04-17 02:42:45 +0000
+++ mixxx/src/engine/vinylcontrolcontrol.h 2011-05-11 04:41:18 +0000
@@ -21,6 +21,7 @@
2121
22 private:22 private:
23 ControlObject* m_pControlVinylSeek;23 ControlObject* m_pControlVinylSeek;
24 ControlObject* m_pControlVinylSpeedType;
24 ControlObject* m_pControlVinylStatus;25 ControlObject* m_pControlVinylStatus;
25 ControlPushButton* m_pControlVinylMode;26 ControlPushButton* m_pControlVinylMode;
26 ControlPushButton* m_pControlVinylEnabled;27 ControlPushButton* m_pControlVinylEnabled;
2728
=== modified file 'mixxx/src/mathstuff.h'
--- mixxx/src/mathstuff.h 2010-11-27 03:10:36 +0000
+++ mixxx/src/mathstuff.h 2011-05-11 04:41:18 +0000
@@ -23,7 +23,6 @@
23#include <math.h>23#include <math.h>
24#include <algorithm>24#include <algorithm>
2525
26static CSAMPLE two_pi = (2.f*acos(-1.f));
2726
28CSAMPLE besseli(CSAMPLE);27CSAMPLE besseli(CSAMPLE);
29int sign(CSAMPLE);28int sign(CSAMPLE);
@@ -44,6 +43,7 @@
44float sigmoid_zero(double t, double max_t);43float sigmoid_zero(double t, double max_t);
4544
46static CSAMPLE pi = acos(-1.0f);45static CSAMPLE pi = acos(-1.0f);
46static CSAMPLE two_pi = (2.f*acos(-1.f));
4747
48#ifdef _MSC_VER48#ifdef _MSC_VER
49#include <float.h> // for _isnan() on VC++49#include <float.h> // for _isnan() on VC++
5050
=== added file 'mixxx/src/sharedglcontext.cpp'
--- mixxx/src/sharedglcontext.cpp 1970-01-01 00:00:00 +0000
+++ mixxx/src/sharedglcontext.cpp 2011-05-11 04:41:18 +0000
@@ -0,0 +1,23 @@
1#include <QGLContext>
2#include <QGLFormat>
3#include "sharedglcontext.h"
4
5/** Singleton wrapper around QGLContext */
6
7QGLContext* SharedGLContext::s_pSharedGLContext = (QGLContext*)NULL;
8
9QGLContext* SharedGLContext::getContext()
10{
11 QGLContext *ctxt;
12
13 if (s_pSharedGLContext == (QGLContext*)NULL) {
14 s_pSharedGLContext = new QGLContext(QGLFormat(QGL::SampleBuffers));
15 s_pSharedGLContext->create();
16 s_pSharedGLContext->makeCurrent();
17 }
18
19 ctxt = new QGLContext(QGLFormat(QGL::SampleBuffers));
20 ctxt->create(s_pSharedGLContext);
21
22 return ctxt;
23}
024
=== added file 'mixxx/src/sharedglcontext.h'
--- mixxx/src/sharedglcontext.h 1970-01-01 00:00:00 +0000
+++ mixxx/src/sharedglcontext.h 2011-05-11 04:41:18 +0000
@@ -0,0 +1,15 @@
1#ifndef SHAREDGLCONTEXT_H_
2#define SHAREDGLCONTEXT_H_
3
4class QGLContext;
5
6class SharedGLContext
7{
8 public:
9 static QGLContext* getContext();
10 private:
11 SharedGLContext() { };
12 static QGLContext* s_pSharedGLContext;
13};
14
15#endif //SHAREDGLCONTEXT_H_
016
=== modified file 'mixxx/src/skin/legacyskinparser.cpp'
--- mixxx/src/skin/legacyskinparser.cpp 2011-04-24 06:00:11 +0000
+++ mixxx/src/skin/legacyskinparser.cpp 2011-05-11 04:41:18 +0000
@@ -39,6 +39,7 @@
39#include "widget/wnumberpos.h"39#include "widget/wnumberpos.h"
40#include "widget/wnumberrate.h"40#include "widget/wnumberrate.h"
41#include "widget/woverview.h"41#include "widget/woverview.h"
42#include "widget/wspinny.h"
4243
43#include "widget/wvisualsimple.h"44#include "widget/wvisualsimple.h"
44#include "widget/wglwaveformviewer.h"45#include "widget/wglwaveformviewer.h"
@@ -264,6 +265,8 @@
264 return parseWidgetGroup(node);265 return parseWidgetGroup(node);
265 } else if (nodeName == "Style") {266 } else if (nodeName == "Style") {
266 return parseStyle(node);267 return parseStyle(node);
268 } else if (nodeName == "Spinny") {
269 return parseSpinny(node);
267 } else {270 } else {
268 qDebug() << "Invalid node name in skin:" << nodeName;271 qDebug() << "Invalid node name in skin:" << nodeName;
269 }272 }
@@ -605,6 +608,22 @@
605 return p;608 return p;
606}609}
607610
611QWidget* LegacySkinParser::parseSpinny(QDomElement node) {
612 QString channelStr = lookupNodeGroup(node);
613 const char* pSafeChannelStr = safeChannelString(channelStr);
614 WSpinny* p = new WSpinny(m_pParent);
615 setupWidget(node, p);
616
617 connect(p, SIGNAL(trackDropped(QString, QString)),
618 m_pPlayerManager, SLOT(slotLoadToPlayer(QString, QString)));
619
620 p->setup(node, pSafeChannelStr);
621 setupConnections(node, p);
622 p->installEventFilter(m_pKeyboard);
623 return p;
624}
625
626
608QWidget* LegacySkinParser::parseTableView(QDomElement node) {627QWidget* LegacySkinParser::parseTableView(QDomElement node) {
609 QStackedWidget* pTabWidget = new QStackedWidget(m_pParent);628 QStackedWidget* pTabWidget = new QStackedWidget(m_pParent);
610629
611630
=== modified file 'mixxx/src/skin/legacyskinparser.h'
--- mixxx/src/skin/legacyskinparser.h 2011-03-26 02:04:46 +0000
+++ mixxx/src/skin/legacyskinparser.h 2011-05-11 04:41:18 +0000
@@ -59,6 +59,7 @@
59 QWidget* parseKnob(QDomElement node);59 QWidget* parseKnob(QDomElement node);
60 QWidget* parseTableView(QDomElement node);60 QWidget* parseTableView(QDomElement node);
61 QWidget* parseStyle(QDomElement node);61 QWidget* parseStyle(QDomElement node);
62 QWidget* parseSpinny(QDomElement node);
6263
63 void setupPosition(QDomNode node, QWidget* pWidget);64 void setupPosition(QDomNode node, QWidget* pWidget);
64 void setupSize(QDomNode node, QWidget* pWidget);65 void setupSize(QDomNode node, QWidget* pWidget);
6566
=== modified file 'mixxx/src/vinylcontrol/vinylcontrol.h'
--- mixxx/src/vinylcontrol/vinylcontrol.h 2011-04-17 04:16:00 +0000
+++ mixxx/src/vinylcontrol/vinylcontrol.h 2011-05-11 04:41:18 +0000
@@ -21,6 +21,9 @@
21#define MIXXX_VINYL_SPEED_33 "33.3 RPM"21#define MIXXX_VINYL_SPEED_33 "33.3 RPM"
22#define MIXXX_VINYL_SPEED_45 "45 RPM"22#define MIXXX_VINYL_SPEED_45 "45 RPM"
2323
24#define MIXXX_VINYL_SPEED_33_NUM 33.3f
25#define MIXXX_VINYL_SPEED_45_NUM 45.0f
26
24#define MIXXX_VCMODE_ABSOLUTE 027#define MIXXX_VCMODE_ABSOLUTE 0
25#define MIXXX_VCMODE_RELATIVE 128#define MIXXX_VCMODE_RELATIVE 1
26#define MIXXX_VCMODE_CONSTANT 229#define MIXXX_VCMODE_CONSTANT 2
2730
=== modified file 'mixxx/src/waveformviewerfactory.cpp'
--- mixxx/src/waveformviewerfactory.cpp 2011-01-14 09:50:57 +0000
+++ mixxx/src/waveformviewerfactory.cpp 2011-05-11 04:41:18 +0000
@@ -5,6 +5,7 @@
55
6#include "configobject.h"6#include "configobject.h"
7#include "waveformviewerfactory.h"7#include "waveformviewerfactory.h"
8#include "sharedglcontext.h"
89
9#include "waveform/waveformrenderer.h"10#include "waveform/waveformrenderer.h"
10#include "widget/wvisualsimple.h"11#include "widget/wvisualsimple.h"
@@ -17,21 +18,11 @@
17QList<WWaveformViewer*> WaveformViewerFactory::m_visualViewers = QList<WWaveformViewer*>();18QList<WWaveformViewer*> WaveformViewerFactory::m_visualViewers = QList<WWaveformViewer*>();
18QList<WGLWaveformViewer*> WaveformViewerFactory::m_visualGLViewers = QList<WGLWaveformViewer*>();19QList<WGLWaveformViewer*> WaveformViewerFactory::m_visualGLViewers = QList<WGLWaveformViewer*>();
19QTimer WaveformViewerFactory::s_waveformUpdateTimer;;20QTimer WaveformViewerFactory::s_waveformUpdateTimer;;
20QGLContext* WaveformViewerFactory::s_pSharedOGLCtxt = (QGLContext *)NULL;
2121
2222
23WaveformViewerType WaveformViewerFactory::createWaveformViewer(const char *group, QWidget *parent, ConfigObject<ConfigValue> *pConfig, QWidget **target, WaveformRenderer* pWaveformRenderer) {23WaveformViewerType WaveformViewerFactory::createWaveformViewer(const char *group, QWidget *parent, ConfigObject<ConfigValue> *pConfig, QWidget **target, WaveformRenderer* pWaveformRenderer) {
24 24
25 QGLContext *ctxt;25 QGLContext* ctxt = SharedGLContext::getContext();
26
27 if ( s_pSharedOGLCtxt == (QGLContext*)NULL ) {
28 s_pSharedOGLCtxt = new QGLContext(QGLFormat(QGL::SampleBuffers));
29 s_pSharedOGLCtxt->create();
30 s_pSharedOGLCtxt->makeCurrent();
31 }
32
33 ctxt = new QGLContext(QGLFormat(QGL::SampleBuffers));
34 ctxt->create(s_pSharedOGLCtxt);
3526
36 qDebug() << "createWaveformViewer()";27 qDebug() << "createWaveformViewer()";
3728
3829
=== modified file 'mixxx/src/waveformviewerfactory.h'
--- mixxx/src/waveformviewerfactory.h 2011-01-14 09:32:49 +0000
+++ mixxx/src/waveformviewerfactory.h 2011-05-11 04:41:18 +0000
@@ -34,7 +34,6 @@
34 static QList<WWaveformViewer*> m_visualViewers;34 static QList<WWaveformViewer*> m_visualViewers;
35 static QList<WGLWaveformViewer*> m_visualGLViewers;35 static QList<WGLWaveformViewer*> m_visualGLViewers;
36 static QTimer s_waveformUpdateTimer;36 static QTimer s_waveformUpdateTimer;
37 static QGLContext *s_pSharedOGLCtxt;
3837
39public:38public:
40 static WaveformViewerType createWaveformViewer(const char* group, QWidget *pParent, ConfigObject<ConfigValue> *pConfig, QWidget **target, WaveformRenderer *pWaveformRenderer);39 static WaveformViewerType createWaveformViewer(const char* group, QWidget *pParent, ConfigObject<ConfigValue> *pConfig, QWidget **target, WaveformRenderer *pWaveformRenderer);
4140
=== modified file 'mixxx/src/widget/wglwaveformviewer.cpp'
--- mixxx/src/widget/wglwaveformviewer.cpp 2011-04-26 02:43:58 +0000
+++ mixxx/src/widget/wglwaveformviewer.cpp 2011-05-11 04:41:18 +0000
@@ -13,6 +13,7 @@
13#include "wglwaveformviewer.h"13#include "wglwaveformviewer.h"
14#include "waveform/waveformrenderer.h"14#include "waveform/waveformrenderer.h"
15#include "controlobjectthreadmain.h"15#include "controlobjectthreadmain.h"
16#include "sharedglcontext.h"
1617
17WGLWaveformViewer::WGLWaveformViewer(18WGLWaveformViewer::WGLWaveformViewer(
18 const char *group,19 const char *group,
@@ -24,7 +25,6 @@
24 ) :25 ) :
25 QGLWidget(ctxt, pParent, pShareWidget)26 QGLWidget(ctxt, pParent, pShareWidget)
26{27{
27
28 m_pWaveformRenderer = pWaveformRenderer;28 m_pWaveformRenderer = pWaveformRenderer;
29 Q_ASSERT(m_pWaveformRenderer);29 Q_ASSERT(m_pWaveformRenderer);
3030
@@ -46,6 +46,9 @@
46 installEventFilter(this);46 installEventFilter(this);
4747
48 m_painting = false;48 m_painting = false;
49
50 setSizePolicy(QSizePolicy::MinimumExpanding,
51 QSizePolicy::MinimumExpanding);
49}52}
5053
51bool WGLWaveformViewer::directRendering()54bool WGLWaveformViewer::directRendering()
@@ -63,6 +66,14 @@
63 m_pWaveformRenderer->resize(w, h);66 m_pWaveformRenderer->resize(w, h);
64}67}
6568
69void WGLWaveformViewer::resizeEvent(QResizeEvent* e)
70{
71 const QSize newSize = e->size();
72 m_pWaveformRenderer->resize(newSize.width(),
73 newSize.height());
74}
75
76
66void WGLWaveformViewer::paintEvent(QPaintEvent *event) {77void WGLWaveformViewer::paintEvent(QPaintEvent *event) {
67 QPainter painter;78 QPainter painter;
68 painter.begin(this);79 painter.begin(this);
@@ -110,7 +121,7 @@
110 //qDebug() << "m_dInitialPlaypos" << m_dInitialPlaypos;121 //qDebug() << "m_dInitialPlaypos" << m_dInitialPlaypos;
111122
112 // Set the cursor to a hand while the mouse is down.123 // Set the cursor to a hand while the mouse is down.
113 setCursor(Qt::OpenHandCursor);124 setCursor(Qt::ClosedHandCursor);
114 }125 }
115 } else if(e->type() == QEvent::MouseMove) {126 } else if(e->type() == QEvent::MouseMove) {
116 // Only send signals for mouse moving if the left button is pressed127 // Only send signals for mouse moving if the left button is pressed
117128
=== modified file 'mixxx/src/widget/wglwaveformviewer.h'
--- mixxx/src/widget/wglwaveformviewer.h 2011-04-26 02:30:22 +0000
+++ mixxx/src/widget/wglwaveformviewer.h 2011-05-11 04:41:18 +0000
@@ -47,6 +47,7 @@
4747
48 protected:48 protected:
49 void paintEvent(QPaintEvent* event);49 void paintEvent(QPaintEvent* event);
50 void resizeEvent(QResizeEvent* e);
5051
51 private:52 private:
52 /** Used in mouse event handler */53 /** Used in mouse event handler */
5354
=== added file 'mixxx/src/widget/wspinny.cpp'
--- mixxx/src/widget/wspinny.cpp 1970-01-01 00:00:00 +0000
+++ mixxx/src/widget/wspinny.cpp 2011-05-11 04:41:18 +0000
@@ -0,0 +1,434 @@
1#include <math.h>
2#include "mathstuff.h"
3#include "wpixmapstore.h"
4#include "controlobject.h"
5#include "controlobjectthreadmain.h"
6#include "sharedglcontext.h"
7#include "wspinny.h"
8
9WSpinny::WSpinny(QWidget* parent) : QGLWidget(SharedGLContext::getContext(), parent),
10 m_pBG(NULL),
11 m_pFG(NULL),
12 m_pGhost(NULL),
13 m_pPlay(NULL),
14 m_pPlayPos(NULL),
15 m_pVisualPlayPos(NULL),
16 m_pDuration(NULL),
17 m_pTrackSamples(NULL),
18 m_pBPM(NULL),
19 m_pScratch(NULL),
20 m_pScratchToggle(NULL),
21 m_pScratchPos(NULL),
22 m_pVinylControlSpeedType(NULL),
23 m_fAngle(0.0f),
24 m_fGhostAngle(0.0f),
25 m_dPausedPosition(0.0f),
26 m_bGhostPlayback(false),
27 m_iStartMouseX(-1),
28 m_iStartMouseY(-1),
29 m_iFullRotations(0),
30 m_dPrevTheta(0.)
31{
32 //Drag and drop
33 setAcceptDrops(true);
34}
35
36WSpinny::~WSpinny()
37{
38 //Don't delete these because the pixmap store takes care of them.
39 //delete m_pBG;
40 //delete m_pFG;
41 //delete m_pGhost;
42 WPixmapStore::deletePixmap(m_pBG);
43 WPixmapStore::deletePixmap(m_pFG);
44 WPixmapStore::deletePixmap(m_pGhost);
45 delete m_pPlay;
46 delete m_pPlayPos;
47 delete m_pVisualPlayPos;
48 delete m_pDuration;
49 delete m_pTrackSamples;
50 delete m_pTrackSampleRate;
51 delete m_pBPM;
52 delete m_pScratch;
53 delete m_pScratchToggle;
54 delete m_pScratchPos;
55 delete m_pVinylControlSpeedType;
56}
57
58void WSpinny::setup(QDomNode node, QString group)
59{
60 m_group = group;
61
62 // Set pixmaps
63 m_pBG = WPixmapStore::getPixmap(WWidget::getPath(WWidget::selectNodeQString(node,
64 "PathBackground")));
65 m_pFG = WPixmapStore::getPixmap(WWidget::getPath(WWidget::selectNodeQString(node,
66 "PathForeground")));
67 m_pGhost = WPixmapStore::getPixmap(WWidget::getPath(WWidget::selectNodeQString(node,
68 "PathGhost")));
69 if (m_pBG && !m_pBG->isNull()) {
70 setFixedSize(m_pBG->size());
71 }
72
73 m_pPlay = new ControlObjectThreadMain(ControlObject::getControl(
74 ConfigKey(group, "play")));
75 m_pPlayPos = new ControlObjectThreadMain(ControlObject::getControl(
76 ConfigKey(group, "playposition")));
77 m_pVisualPlayPos = new ControlObjectThreadMain(ControlObject::getControl(
78 ConfigKey(group, "visual_playposition")));
79 m_pDuration = new ControlObjectThreadMain(ControlObject::getControl(
80 ConfigKey(group, "duration")));
81 m_pTrackSamples = new ControlObjectThreadMain(ControlObject::getControl(
82 ConfigKey(group, "track_samples")));
83 m_pTrackSampleRate = new ControlObjectThreadMain(
84 ControlObject::getControl(
85 ConfigKey(group, "track_samplerate")));
86 m_pBPM = new ControlObjectThreadMain(ControlObject::getControl(
87 ConfigKey(group, "bpm")));
88
89 m_pScratch = new ControlObjectThreadMain(ControlObject::getControl(
90 ConfigKey(group, "scratch2")));
91 m_pScratchToggle = new ControlObjectThreadMain(ControlObject::getControl(
92 ConfigKey(group, "scratch_position_enable")));
93 m_pScratchPos = new ControlObjectThreadMain(ControlObject::getControl(
94 ConfigKey(group, "scratch_position")));
95 m_pVinylControlSpeedType = new ControlObjectThreadMain(ControlObject::getControl(
96 ConfigKey(group, "vinylcontrol_speed_type")));
97 if (m_pVinylControlSpeedType)
98 {
99 //Initialize the rotational speed.
100 this->updateVinylControlSpeed(m_pVinylControlSpeedType->get());
101 }
102 Q_ASSERT(m_pPlayPos);
103 Q_ASSERT(m_pDuration);
104
105 //Repaint when visual_playposition changes.
106 connect(m_pVisualPlayPos, SIGNAL(valueChanged(double)),
107 this, SLOT(updateAngle(double)));
108
109 //Match the vinyl control's set RPM so that the spinny widget rotates at the same
110 //speed as your physical decks, if you're using vinyl control.
111 connect(m_pVinylControlSpeedType, SIGNAL(valueChanged(double)),
112 this, SLOT(updateVinylControlSpeed(double)));
113}
114
115void WSpinny::paintEvent(QPaintEvent *e)
116{
117 Q_UNUSED(e); //ditch unused param warning
118
119 QPainter p(this);
120
121 if (m_pBG) {
122 p.drawPixmap(0, 0, *m_pBG);
123 }
124
125 //To rotate the foreground pixmap around the center of the image,
126 //we use the classic trick of translating the coordinate system such that
127 //the origin is at the center of the image. We then rotate the coordinate system,
128 //and draw the pixmap at the corner.
129 p.translate(width() / 2, height() / 2);
130
131 if (m_bGhostPlayback)
132 p.save();
133
134 if (m_pFG && !m_pFG->isNull()) {
135 //Now rotate the pixmap and draw it on the screen.
136 p.rotate(m_fAngle);
137 p.drawPixmap(-(width() / 2), -(height() / 2), *m_pFG);
138 }
139
140 if (m_bGhostPlayback && m_pGhost && !m_pGhost->isNull())
141 {
142 p.restore();
143 p.save();
144 p.rotate(m_fGhostAngle);
145 p.drawPixmap(-(width() / 2), -(height() / 2), *m_pGhost);
146
147 //Rotate back to the playback position (not the ghost positon),
148 //and draw the beat marks from there.
149 p.restore();
150
151 /*
152 //Draw a line where the next 4 beats are
153 double bpm = m_pBPM->get();
154 double duration = m_pDuration->get();
155 if (bpm <= 0. || duration <= 0.) {
156 return; //Prevent div by zero
157 }
158 double beatLengthInSec = 60. / bpm;
159 double beatLengthNormalized = beatLengthInSec / duration; //Noramlized to duration
160 double beatAngle = calculateAngle(beatLengthNormalized);
161 //qDebug() << "beatAngle:" << beatAngle;
162 //qDebug() << "beatLenInSec:" << beatLengthInSec << "norm:" << beatLengthNormalized;
163 p.rotate(m_fAngle);
164 for (int i = 0; i < 4; i++) {
165 QLineF beatLine(-(width()*0.6 / 2), -(height()*0.6 / 2),
166 -(width()*0.8 / 2), -(height()*0.8 / 2));
167 //p.drawPoint(-(width()*0.5 / 2), -(height()*0.5 / 2));
168 p.drawLine(beatLine);
169 p.rotate(beatAngle);
170 } */
171 }
172}
173
174/* Convert between a normalized playback position (0.0 - 1.0) and an angle
175 in our polar coordinate system.
176 Returns an angle clamped between -180 and 180 degrees. */
177double WSpinny::calculateAngle(double playpos)
178{
179 if (isnan(playpos))
180 return 0.0f;
181
182 //Convert playpos to seconds.
183 //double t = playpos * m_pDuration->get();
184 double t = playpos * (m_pTrackSamples->get()/2 / // Stereo audio!
185 m_pTrackSampleRate->get());
186
187 if (isnan(t)) //Bad samplerate or number of track samples.
188 return 0.0f;
189
190 //33 RPM is approx. 0.5 rotations per second.
191 double angle = 360*m_dRotationsPerSecond*t;
192 //Clamp within -180 and 180 degrees
193 //qDebug() << "pc:" << angle;
194 //angle = ((angle + 180) % 360.) - 180;
195 //modulo for doubles :)
196 if (angle > 0)
197 {
198 int x = (angle+180)/360;
199 angle = angle - (360*x);
200 } else
201 {
202 int x = (angle-180)/360;
203 angle = angle - (360*x);
204 }
205
206 Q_ASSERT(angle <= 180 && angle >= -180);
207 return angle;
208}
209
210/** Given a normalized playpos, calculate the integer number of rotations
211 that it would take to wind the vinyl to that position. */
212int WSpinny::calculateFullRotations(double playpos)
213{
214 if (isnan(playpos))
215 return 0.0f;
216 //Convert playpos to seconds.
217 //double t = playpos * m_pDuration->get();
218 double t = playpos * (m_pTrackSamples->get()/2 / // Stereo audio!
219 m_pTrackSampleRate->get());
220
221 //33 RPM is approx. 0.5 rotations per second.
222 //qDebug() << t;
223 double angle = 360*m_dRotationsPerSecond*t;
224
225 return (((int)angle+180) / 360);
226}
227
228//Inverse of calculateAngle()
229double WSpinny::calculatePositionFromAngle(double angle)
230{
231 if (isnan(angle))
232 return 0.0f;
233
234 //33 RPM is approx. 0.5 rotations per second.
235 double t = angle/(360*m_dRotationsPerSecond); //time in seconds
236
237 //Convert t from seconds into a normalized playposition value.
238 //double playpos = t / m_pDuration->get();
239 double playpos = t / (m_pTrackSamples->get()/2 / // Stereo audio!
240 m_pTrackSampleRate->get());
241 return playpos;
242}
243
244/** Update the playback angle saved in the widget and repaint.
245 @param playpos A normalized (0.0-1.0) playback position. (Not an angle!)
246*/
247void WSpinny::updateAngle(double playpos)
248{
249 m_fAngle = calculateAngle(playpos);
250 update();
251}
252
253//Update the angle using the ghost playback position.
254void WSpinny::updateAngleForGhost()
255{
256 qint64 elapsed = m_time.elapsed();
257 double duration = m_pDuration->get();
258 double newPlayPos = m_dPausedPosition +
259 (((double)elapsed)/1000.)/duration;
260 m_fGhostAngle = calculateAngle(newPlayPos);
261 update();
262}
263
264void WSpinny::updateVinylControlSpeed(double rpm)
265{
266 m_dRotationsPerSecond = rpm/60.;
267}
268
269void WSpinny::mouseMoveEvent(QMouseEvent * e)
270{
271 int y = e->y();
272 int x = e->x();
273
274 //Keeping these around in case we want to switch to control relative
275 //to the original mouse position.
276 //int dX = x-m_iStartMouseX;
277 //int dY = y-m_iStartMouseY;
278
279 //Coordinates from center of widget
280 int c_x = x - width()/2;
281 int c_y = y - height()/2;
282 double theta = (180.0f/M_PI)*atan2(c_x, -c_y);
283
284 //qDebug() << "c_x:" << c_x << "c_y:" << c_y <<
285 // "dX:" << dX << "dY:" << dY;
286
287 //When we finish one full rotation (clockwise or anticlockwise),
288 //we'll need to manually add/sub 360 degrees because atan2()'s range is
289 //only within -180 to 180 degrees. We need a wider range so your position
290 //in the song can be tracked.
291 if (m_dPrevTheta > 100 && theta < 0) {
292 m_iFullRotations++;
293 }
294 else if (m_dPrevTheta < -100 && theta > 0) {
295 m_iFullRotations--;
296 }
297
298 m_dPrevTheta = theta;
299 theta += m_iFullRotations*360;
300
301 //qDebug() << "c t:" << theta << "pt:" << m_dPrevTheta <<
302 // "icr" << m_iFullRotations;
303
304 if (e->buttons() & Qt::LeftButton)
305 {
306 //Convert deltaTheta into a percentage of song length.
307 double absPos = calculatePositionFromAngle(theta);
308
309 double absPosInSamples = absPos * m_pTrackSamples->get();
310 m_pScratchPos->slotSet(absPosInSamples);
311 }
312 else if (e->buttons() & Qt::MidButton)
313 {
314 }
315 else if (e->buttons() & Qt::NoButton)
316 {
317 setCursor(QCursor(Qt::OpenHandCursor));
318 }
319}
320
321void WSpinny::mousePressEvent(QMouseEvent * e)
322{
323 int y = e->y();
324 int x = e->x();
325
326 m_iStartMouseX = x;
327 m_iStartMouseY = y;
328
329 if (e->button() == Qt::LeftButton)
330 {
331 QApplication::setOverrideCursor(QCursor(Qt::ClosedHandCursor));
332
333 double initialPosInSamples = m_pPlayPos->get() * m_pTrackSamples->get();
334 m_pScratchPos->slotSet(initialPosInSamples);
335 m_pScratchToggle->slotSet(1.0f);
336
337 m_iFullRotations = calculateFullRotations(m_pPlayPos->get());
338
339 m_dPrevTheta = calculateAngle(m_pPlayPos->get());
340
341 //Trigger a mouse move to immediately line up the vinyl with the cursor
342 mouseMoveEvent(e);
343 }
344 else if (e->button() == Qt::MidButton)
345 {
346 }
347 else if (e->button() == Qt::RightButton)
348 {
349 //Stop playback and start the timer for ghost playback
350 m_time.start();
351 m_dPausedPosition = m_pPlayPos->get();
352 updateAngleForGhost(); //Need to recalc the ghost angle right away
353 m_bGhostPlayback = true;
354 m_ghostPaintTimer.start(30);
355 connect(&m_ghostPaintTimer, SIGNAL(timeout()),
356 this, SLOT(updateAngleForGhost()));
357
358 //TODO: Ramp down (brake) over a period of 1 beat
359 // instead? Would be sweet.
360 m_pPlay->slotSet(0.0f);
361 }
362}
363
364void WSpinny::mouseReleaseEvent(QMouseEvent * e)
365{
366 if (e->button() == Qt::LeftButton)
367 {
368 QApplication::restoreOverrideCursor();
369 m_pScratchToggle->slotSet(0.0f);
370 m_iFullRotations = 0;
371 }
372 else if (e->button() == Qt::RightButton)
373 {
374 //Start playback by jumping forwards in the song as if playback
375 //was never paused. (useful for bleeping or adding silence breaks)
376 qint64 elapsed = m_time.elapsed();
377 //qDebug() << "elapsed:" << elapsed;
378 m_ghostPaintTimer.stop();
379 m_bGhostPlayback = false;
380
381 //Convert elapsed to seconds, then normalize it to the duration so we can
382 //move the playback position ahead by the elapsed amount.
383 double duration = m_pDuration->get();
384 double newPlayPos = m_dPausedPosition + (((double)elapsed)/1000.)/duration;
385 //qDebug() << m_dPausedPosition << newPlayPos;
386 m_pPlay->slotSet(1.0f);
387 m_pPlayPos->slotSet(newPlayPos);
388 //m_bRightButtonPressed = true;
389 }
390}
391
392void WSpinny::wheelEvent(QWheelEvent *e)
393{
394 Q_UNUSED(e); //ditch unused param warning
395
396 /*
397 double wheelDirection = ((QWheelEvent *)e)->delta() / 120.;
398 double newValue = getValue() + (wheelDirection);
399 this->updateValue(newValue);
400
401 e->accept();
402 */
403}
404
405/** DRAG AND DROP **/
406void WSpinny::dragEnterEvent(QDragEnterEvent * event)
407{
408 // Accept the enter event if the thing is a filepath and nothing's playing
409 // in this deck.
410 if (event->mimeData()->hasUrls()) {
411 if (m_pPlay && m_pPlay->get()) {
412 event->ignore();
413 } else {
414 event->acceptProposedAction();
415 }
416 }
417}
418
419void WSpinny::dropEvent(QDropEvent * event)
420{
421 if (event->mimeData()->hasUrls()) {
422 QList<QUrl> urls(event->mimeData()->urls());
423 QUrl url = urls.first();
424 QString name = url.toLocalFile();
425 //If the file is on a network share, try just converting the URL to a string...
426 if (name == "")
427 name = url.toString();
428
429 event->accept();
430 emit(trackDropped(name, m_group));
431 } else {
432 event->ignore();
433 }
434}
0435
=== added file 'mixxx/src/widget/wspinny.h'
--- mixxx/src/widget/wspinny.h 1970-01-01 00:00:00 +0000
+++ mixxx/src/widget/wspinny.h 2011-05-11 04:41:18 +0000
@@ -0,0 +1,67 @@
1
2#ifndef _WSPINNY_H
3#define _WSPINNY_H
4
5#include <QGLWidget>
6#include "wwidget.h"
7
8class ControlObjectThreadMain;
9
10class WSpinny : public QGLWidget
11{
12 Q_OBJECT
13 public:
14 WSpinny(QWidget* parent);
15 ~WSpinny();
16 void setup(QDomNode node, QString group);
17 void dragEnterEvent(QDragEnterEvent *event);
18 void dropEvent(QDropEvent *event);
19 public slots:
20 void updateAngle(double);
21 void updateAngleForGhost();
22 void updateVinylControlSpeed(double rpm);
23 signals:
24 void trackDropped(QString filename, QString group);
25 protected:
26 //QWidget:
27 void paintEvent(QPaintEvent*);
28 void mouseMoveEvent(QMouseEvent * e);
29 void mousePressEvent(QMouseEvent * e);
30 void mouseReleaseEvent(QMouseEvent * e);
31 void wheelEvent(QWheelEvent *e);
32
33 double calculateAngle(double playpos);
34 int calculateFullRotations(double playpos);
35 double calculatePositionFromAngle(double angle);
36 private:
37 QPixmap* m_pBG;
38 QPixmap* m_pFG;
39 QPixmap* m_pGhost;
40 ControlObjectThreadMain* m_pPlay;
41 ControlObjectThreadMain* m_pPlayPos;
42 ControlObjectThreadMain* m_pVisualPlayPos;
43 ControlObjectThreadMain* m_pDuration;
44 ControlObjectThreadMain* m_pTrackSamples;
45 ControlObjectThreadMain* m_pTrackSampleRate;
46 ControlObjectThreadMain* m_pBPM;
47 ControlObjectThreadMain* m_pScratch;
48 ControlObjectThreadMain* m_pScratchToggle;
49 ControlObjectThreadMain* m_pScratchPos;
50 ControlObjectThreadMain* m_pVinylControlSpeedType;
51 QString m_group;
52 float m_fAngle; //Degrees
53 float m_fGhostAngle;
54 QTime m_time;
55 double m_dPausedPosition;
56 bool m_bGhostPlayback;
57 QTimer m_ghostPaintTimer;
58 int m_iStartMouseX;
59 int m_iStartMouseY;
60 int m_iFullRotations;
61 double m_dPrevTheta;
62 double m_dTheta;
63 /** Speed of the vinyl rotation. */
64 double m_dRotationsPerSecond;
65};
66
67#endif //_WSPINNY_H

Subscribers

People subscribed via source and target branches