Merge lp:~kabelfrickler/mixxx/modplug into lp:~mixxxdevelopers/mixxx/trunk

Proposed by Stefan Nürnberger
Status: Superseded
Proposed branch: lp:~kabelfrickler/mixxx/modplug
Merge into: lp:~mixxxdevelopers/mixxx/trunk
Diff against target: 1462 lines (+1302/-0)
11 files modified
mixxx/SConstruct (+1/-0)
mixxx/build/features.py (+34/-0)
mixxx/src/dlgpreferences.cpp (+28/-0)
mixxx/src/dlgpreferences.h (+9/-0)
mixxx/src/dlgprefmodplug.cpp (+161/-0)
mixxx/src/dlgprefmodplug.h (+49/-0)
mixxx/src/dlgprefmodplugdlg.ui (+728/-0)
mixxx/src/mixxx.cpp (+12/-0)
mixxx/src/soundsourcemodplug.cpp (+196/-0)
mixxx/src/soundsourcemodplug.h (+74/-0)
mixxx/src/soundsourceproxy.cpp (+10/-0)
To merge this branch: bzr merge lp:~kabelfrickler/mixxx/modplug
Reviewer Review Type Date Requested Status
Stefan Nürnberger (community) Needs Fixing
Mixxx Development Team Pending
Review via email: mp+153265@code.launchpad.net

This proposal has been superseded by a proposal from 2013-03-14.

Description of the change

Add module tracker support through libmodplug

This branch adds a soundsource for files supported by modplug (MOD/MED/IT/STM/S3M/XM/OKT/...)
It also includes a preferences dialog through which the decoder can be configured.

Module tracker formats do not play well with seeking, therefore files are decoded to 16bit stereo samples on track load and kept in a QByteArray until the soundsource is destroyed. Maximum size of this buffer per track (i.e. per soundsource instance) is also configurable through the preferences dialog.

Building this requires libmodplug and the modplug.h header file. Most linux distributions offer modplug packages. I have not attempted a build under Mac or Windows.

Modplug support is activated with by appending "modplug=1" to the scons command. This will also add the __MODPLUG__ define to the compiler flags. All code concerning modplug is guarded by this define.

For modplug to work correctly the settings which are stored in the mixxx.cfg need to be applied once before loading a module file. Currently this is done in mixxx.cpp when the program loads by creating an instance of the preferences dialog and letting it deal with the configuration. Maybe there is a more elegant way?

To post a comment you must log in.
Revision history for this message
Stefan Nürnberger (kabelfrickler) wrote :

Hmm, ok the branch is not completely clean. I will try to remove every change that is not directly concerned with modplug (whitespace fixes etc.) and the remaining reference to "plugin" in the SConstruct file. Then I will merge with latest trunk to resolve the conflict and resubmit the merge request.

review: Needs Fixing
lp:~kabelfrickler/mixxx/modplug updated
3296. By Stefan Nuernberger <email address hidden>

Remove remaining reference to modplug plugin from SConstruct file. Modplug is now builtin.

3297. By Stefan Nuernberger <email address hidden>

revert unrelated changes in dlgpreferences.

3298. By Stefan Nuernberger <email address hidden>

Change description of modplug feature.

3299. By Stefan Nuernberger <email address hidden>

Remove unused include from soundsourceproxy.

3300. By Stefan Nuernberger <email address hidden>

merge with latest trunk.

3301. By Stefan Nuernberger <email address hidden>

Fix build error due to incorrectly positioned code.

3302. By Stefan Nuernberger <email address hidden>

Correct typo in features.py

3303. By Stefan Nuernberger <email address hidden>

Refactoring SoundSourceModPlug. Obey coding styleguide. Estimate sample buffer size. Get rid of temp buffer in open().

3304. By Stefan Nuernberger <email address hidden>

Use memcpy for SoundSourceModPlug::read(). Add ScopedTimer for SoundSourceModPlug::open().

3305. By Stefan Nuernberger <email address hidden>

Refactored modplug preferences dialog. Introduced advanced options switch. Adhere to coding style guide.

3306. By Stefan Nuernberger <email address hidden>

insert spaces in front of class scope identifiers as demanded by style guide.

3307. By Stefan Nuernberger <email address hidden>

Fix a comment about samplerate.

3308. By Stefan Nuernberger <email address hidden>

Changed placement of controls in modplug preferences dialog.

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'mixxx/SConstruct'
--- mixxx/SConstruct 2013-02-09 00:38:39 +0000
+++ mixxx/SConstruct 2013-03-14 18:33:22 +0000
@@ -48,6 +48,7 @@
48 features.Optimize,48 features.Optimize,
49 features.FAAD,49 features.FAAD,
50 features.WavPack,50 features.WavPack,
51 features.ModPlug,
51 features.TestSuite,52 features.TestSuite,
52 features.LADSPA,53 features.LADSPA,
53 features.MSVCDebug,54 features.MSVCDebug,
5455
=== modified file 'mixxx/build/features.py'
--- mixxx/build/features.py 2013-02-09 00:49:59 +0000
+++ mixxx/build/features.py 2013-03-14 18:33:22 +0000
@@ -483,6 +483,40 @@
483 '%s/RealTime.cpp'])483 '%s/RealTime.cpp'])
484 return sources484 return sources
485485
486
487class ModPlug(Feature):
488 def description(self):
489 return "Modplug module decoder plugin"
490
491 def enabled(self, build):
492 build.flags['modplug'] = util.get_flags(build.env, 'modplug', 0)
493 if int(build.flags['modplug']):
494 return True
495 return False
496
497 def add_options(self, build, vars):
498 vars.Add('modplug', 'Set to 1 to enable libmbodplug based module tracker support.', 0)
499
500 def configure(self, build, conf):
501 if not self.enabled(build):
502 return
503
504 build.env.Append(CPPDEFINES = '__MODPLUG__')
505
506 have_modplug_h = conf.CheckHeader('libmodplug/modplug.h')
507 have_modplug = conf.CheckLib(['modplug','libmodplug'], autoadd=True)
508
509 if not have_modplug_h:
510 raise Exception('Could not find libmodplug development headers.')
511
512 if not have_modplug:
513 raise Exception('Could not find libmodplug shared library.')
514
515 def sources(self, build):
516 build.env.Uic4('dlgprefmodplugdlg.ui')
517 return ['soundsourcemodplug.cpp', 'dlgprefmodplug.cpp']
518
519
486class FAAD(Feature):520class FAAD(Feature):
487 def description(self):521 def description(self):
488 return "FAAD AAC audio file decoder plugin"522 return "FAAD AAC audio file decoder plugin"
489523
=== modified file 'mixxx/src/dlgpreferences.cpp'
--- mixxx/src/dlgpreferences.cpp 2012-11-27 16:19:52 +0000
+++ mixxx/src/dlgpreferences.cpp 2013-03-14 18:33:22 +0000
@@ -37,6 +37,10 @@
37 #include "dlgprefbpm.h"37 #include "dlgprefbpm.h"
38#endif38#endif
3939
40#ifdef __MODPLUG__
41 #include "dlgprefmodplug.h"
42#endif
43
40#include "dlgpreferences.h"44#include "dlgpreferences.h"
41#include "dlgprefsound.h"45#include "dlgprefsound.h"
42#include "controllers/dlgprefmappablecontroller.h"46#include "controllers/dlgprefmappablecontroller.h"
@@ -109,6 +113,10 @@
109 m_wshoutcast = new DlgPrefShoutcast(this, config);113 m_wshoutcast = new DlgPrefShoutcast(this, config);
110 addPageWidget(m_wshoutcast);114 addPageWidget(m_wshoutcast);
111#endif115#endif
116#ifdef __MODPLUG__
117 m_wmodplug = new DlgPrefModplug(this, config);
118 addPageWidget(m_wmodplug);
119#endif
112 m_wNoControllers = new DlgPrefNoControllers(this, config);120 m_wNoControllers = new DlgPrefNoControllers(this, config);
113 addPageWidget(m_wNoControllers);121 addPageWidget(m_wNoControllers);
114 setupControllerWidgets();122 setupControllerWidgets();
@@ -152,6 +160,10 @@
152 connect(this, SIGNAL(showDlg()), m_wshoutcast,SLOT(slotUpdate()));160 connect(this, SIGNAL(showDlg()), m_wshoutcast,SLOT(slotUpdate()));
153#endif161#endif
154162
163#ifdef __MODPLUG__
164 connect(this, SIGNAL(showDlg()), m_wmodplug,SLOT(slotUpdate()));
165#endif
166
155#ifdef __VINYLCONTROL__167#ifdef __VINYLCONTROL__
156 connect(buttonBox, SIGNAL(accepted()), m_wvinylcontrol, SLOT(slotApply())); //It's important for this to be before the168 connect(buttonBox, SIGNAL(accepted()), m_wvinylcontrol, SLOT(slotApply())); //It's important for this to be before the
157 //connect for wsound...169 //connect for wsound...
@@ -173,6 +185,9 @@
173#ifdef __SHOUTCAST__185#ifdef __SHOUTCAST__
174 connect(buttonBox, SIGNAL(accepted()), m_wshoutcast,SLOT(slotApply()));186 connect(buttonBox, SIGNAL(accepted()), m_wshoutcast,SLOT(slotApply()));
175#endif187#endif
188#ifdef __MODPLUG__
189 connect(buttonBox, SIGNAL(accepted()), m_wmodplug,SLOT(slotApply()));
190#endif
176191
177 //Update the library when you change the options192 //Update the library when you change the options
178 /*if (m_pTrack && wplaylist)193 /*if (m_pTrack && wplaylist)
@@ -276,6 +291,15 @@
276 m_pShoutcastButton->setTextAlignment(0, Qt::AlignLeft | Qt::AlignVCenter);291 m_pShoutcastButton->setTextAlignment(0, Qt::AlignLeft | Qt::AlignVCenter);
277 m_pShoutcastButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);292 m_pShoutcastButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
278#endif293#endif
294
295#ifdef __MODPLUG__
296 m_pModplugButton = new QTreeWidgetItem(contentsTreeWidget, QTreeWidgetItem::Type);
297 m_pModplugButton->setIcon(0, QIcon(":/images/preferences/ic_preferences_sampler.png"));
298 m_pModplugButton->setText(0, tr("Modplug Decoder"));
299 m_pModplugButton->setTextAlignment(0, Qt::AlignLeft | Qt::AlignVCenter);
300 m_pModplugButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
301#endif
302
279 connect(contentsTreeWidget,303 connect(contentsTreeWidget,
280 SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),304 SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
281 this, SLOT(changePage(QTreeWidgetItem *, QTreeWidgetItem*)));305 this, SLOT(changePage(QTreeWidgetItem *, QTreeWidgetItem*)));
@@ -321,6 +345,10 @@
321 } else if (current == m_pShoutcastButton) {345 } else if (current == m_pShoutcastButton) {
322 pagesWidget->setCurrentWidget(m_wshoutcast->parentWidget()->parentWidget());346 pagesWidget->setCurrentWidget(m_wshoutcast->parentWidget()->parentWidget());
323#endif347#endif
348#ifdef __MODPLUG__
349 } else if (current == m_pModplugButton) {
350 pagesWidget->setCurrentWidget(m_wmodplug->parentWidget()->parentWidget());
351#endif
324 //Handle selection of controller items352 //Handle selection of controller items
325 } else if (m_controllerWindowLinks.indexOf(current) >= 0) {353 } else if (m_controllerWindowLinks.indexOf(current) >= 0) {
326 int index = m_controllerWindowLinks.indexOf(current);354 int index = m_controllerWindowLinks.indexOf(current);
327355
=== modified file 'mixxx/src/dlgpreferences.h'
--- mixxx/src/dlgpreferences.h 2012-04-25 15:40:15 +0000
+++ mixxx/src/dlgpreferences.h 2013-03-14 18:33:22 +0000
@@ -45,6 +45,9 @@
45class SkinLoader;45class SkinLoader;
46class PlayerManager;46class PlayerManager;
47class VinylControlManager;47class VinylControlManager;
48#ifdef __MODPLUG__
49class DlgPrefModplug;
50#endif
4851
49/**52/**
50 *@author Tue & Ken Haste Andersen53 *@author Tue & Ken Haste Andersen
@@ -93,6 +96,9 @@
93 DlgPrefNoVinyl* m_wnovinylcontrol;96 DlgPrefNoVinyl* m_wnovinylcontrol;
94 DlgPrefShoutcast* m_wshoutcast;97 DlgPrefShoutcast* m_wshoutcast;
95 DlgPrefReplayGain* m_wreplaygain;98 DlgPrefReplayGain* m_wreplaygain;
99#ifdef __MODPLUG__
100 DlgPrefModplug* m_wmodplug;
101#endif
96102
97 /*103 /*
98 QScrollArea* m_sasound;104 QScrollArea* m_sasound;
@@ -120,6 +126,9 @@
120 QTreeWidgetItem* m_pVinylControlButton;126 QTreeWidgetItem* m_pVinylControlButton;
121 QTreeWidgetItem* m_pShoutcastButton;127 QTreeWidgetItem* m_pShoutcastButton;
122 QTreeWidgetItem* m_pReplayGainButton;128 QTreeWidgetItem* m_pReplayGainButton;
129#ifdef __MODPLUG__
130 QTreeWidgetItem* m_pModplugButton;
131#endif
123 QTreeWidgetItem* m_pControllerTreeItem;132 QTreeWidgetItem* m_pControllerTreeItem;
124 QList<QTreeWidgetItem*> m_controllerWindowLinks;133 QList<QTreeWidgetItem*> m_controllerWindowLinks;
125134
126135
=== added file 'mixxx/src/dlgprefmodplug.cpp'
--- mixxx/src/dlgprefmodplug.cpp 1970-01-01 00:00:00 +0000
+++ mixxx/src/dlgprefmodplug.cpp 2013-03-14 18:33:22 +0000
@@ -0,0 +1,161 @@
1/***************************************************************************
2 dlgprefmodplug.cpp - modplug settings dialog
3 -------------------
4 copyright : (C) 2013 by Stefan Nuernberger
5 email : kabelfricker@gmail.com
6***************************************************************************/
7
8/***************************************************************************
9* *
10* This program is free software; you can redistribute it and/or modify *
11* it under the terms of the GNU General Public License as published by *
12* the Free Software Foundation; either version 2 of the License, or *
13* (at your option) any later version. *
14* *
15***************************************************************************/
16
17#include "dlgprefmodplug.h"
18#include "ui_dlgprefmodplugdlg.h"
19#include "configobject.h"
20#include "soundsourcemodplug.h"
21
22#include <QtDebug>
23
24#define CONFIG_KEY "[Modplug]"
25
26DlgPrefModplug::DlgPrefModplug(QWidget *parent, ConfigObject<ConfigValue> *_config) :
27 QDialog(parent),
28 ui(new Ui::DlgPrefModplug),
29 config(_config)
30{
31 ui->setupUi(this);
32}
33
34DlgPrefModplug::~DlgPrefModplug()
35{
36 delete ui;
37}
38
39void DlgPrefModplug::slotApply()
40{
41 qDebug() << "Modplug Preferences - Apply and save configuration changes";
42
43 applySettings();
44 saveSettings();
45}
46
47void DlgPrefModplug::slotUpdate()
48{
49 qDebug() << "Modplug Preferences - Update Configuration Dialog from saved settings";
50
51 loadSettings();
52}
53
54void DlgPrefModplug::loadSettings()
55{
56 ui->memoryLimit->setValue(
57 config->getValueString(ConfigKey(CONFIG_KEY,"PerTrackMemoryLimitMB"),"256").toInt());
58 ui->oversampling->setChecked(
59 config->getValueString(ConfigKey(CONFIG_KEY,"OversamplingEnabled"),"1") == QString("1"));
60 ui->noiseReduction->setChecked(
61 config->getValueString(ConfigKey(CONFIG_KEY,"NoiseReductionEnabled"),"1") == QString("1"));
62 ui->stereoSeparation->setValue(
63 config->getValueString(ConfigKey(CONFIG_KEY,"StereoSeparation"),"1").toInt());
64 ui->maxMixChannels->setValue(
65 config->getValueString(ConfigKey(CONFIG_KEY,"MaxMixChannels"),"128").toInt());
66 ui->resampleMode->setCurrentIndex(
67 config->getValueString(ConfigKey(CONFIG_KEY,"ResamplingMode"),"3").toInt());
68 ui->reverb->setChecked(
69 config->getValueString(ConfigKey(CONFIG_KEY,"ReverbEnabled"),"0") == QString("1"));
70 ui->reverbDepth->setValue(
71 config->getValueString(ConfigKey(CONFIG_KEY,"ReverbLevel"),"30").toInt());
72 ui->reverbDelay->setValue(
73 config->getValueString(ConfigKey(CONFIG_KEY,"ReverbDelay"),"50").toInt());
74 ui->megabass->setChecked(
75 config->getValueString(ConfigKey(CONFIG_KEY,"MegabassEnabled"),"0") == QString("1"));
76 ui->bassDepth->setValue(
77 config->getValueString(ConfigKey(CONFIG_KEY,"MegabassLevel"),"30").toInt());
78 ui->bassCutoff->setValue(
79 config->getValueString(ConfigKey(CONFIG_KEY,"MegabassCutoff"),"80").toInt());
80 ui->surround->setChecked(
81 config->getValueString(ConfigKey(CONFIG_KEY,"SurroundEnabled"),"0") == QString("1"));
82 ui->surroundDepth->setValue(
83 config->getValueString(ConfigKey(CONFIG_KEY,"SurroundLevel"),"30").toInt());
84 ui->surroundDelay->setValue(
85 config->getValueString(ConfigKey(CONFIG_KEY,"SurroundDelay"),"10").toInt());
86}
87
88void DlgPrefModplug::saveSettings()
89{
90 config->set(ConfigKey(CONFIG_KEY,"PerTrackMemoryLimitMB"),ConfigValue(ui->memoryLimit->value()));
91 config->set(ConfigKey(CONFIG_KEY,"OversamplingEnabled"), ConfigValue(ui->oversampling->isChecked()));
92 config->set(ConfigKey(CONFIG_KEY,"NoiseReductionEnabled"), ConfigValue(ui->noiseReduction->isChecked()));
93 config->set(ConfigKey(CONFIG_KEY,"StereoSeparation"),ConfigValue(ui->stereoSeparation->value()));
94 config->set(ConfigKey(CONFIG_KEY,"MaxMixChannels"),ConfigValue(ui->maxMixChannels->value()));
95 config->set(ConfigKey(CONFIG_KEY,"ResamplingMode"),ConfigValue(ui->resampleMode->currentIndex()));
96 config->set(ConfigKey(CONFIG_KEY,"ReverbEnabled"),ConfigValue(ui->reverb->isChecked()));
97 config->set(ConfigKey(CONFIG_KEY,"ReverbLevel"),ConfigValue(ui->reverbDepth->value()));
98 config->set(ConfigKey(CONFIG_KEY,"ReverbDelay"),ConfigValue(ui->reverbDelay->value()));
99 config->set(ConfigKey(CONFIG_KEY,"MegabassEnabled"),ConfigValue(ui->megabass->isChecked()));
100 config->set(ConfigKey(CONFIG_KEY,"MegabassLevel"),ConfigValue(ui->bassDepth->value()));
101 config->set(ConfigKey(CONFIG_KEY,"MegabassCutoff"),ConfigValue(ui->bassCutoff->value()));
102 config->set(ConfigKey(CONFIG_KEY,"SurroundEnabled"),ConfigValue(ui->surround->isChecked()));
103 config->set(ConfigKey(CONFIG_KEY,"SurroundLevel"),ConfigValue(ui->surroundDepth->value()));
104 config->set(ConfigKey(CONFIG_KEY,"SurroundDelay"),ConfigValue(ui->surroundDelay->value()));
105}
106
107void DlgPrefModplug::applySettings()
108{
109 // read ui parameters and configure soundsource
110 unsigned int bufferSizeLimit = ui->memoryLimit->value() * 1024 * 1024;
111 ModPlug::ModPlug_Settings settings;
112
113 // Currently this is fixed to 16bit 44.1kHz stereo */
114 /* Note that ModPlug always decodes sound at 44100kHz, 32 bit, stereo and then
115 * down-mixes to the settings you choose. */
116 settings.mChannels = 2; /* Number of channels - 1 for mono or 2 for stereo */
117 settings.mBits = 16; /* Bits per sample - 8, 16, or 32 */
118 settings.mFrequency = 44100; /* Sampling rate - 11025, 22050, or 44100 */
119
120 settings.mFlags = 0;
121 if (ui->oversampling->isChecked())
122 settings.mFlags |= ModPlug::MODPLUG_ENABLE_OVERSAMPLING;
123 if (ui->noiseReduction->isChecked())
124 settings.mFlags |= ModPlug::MODPLUG_ENABLE_NOISE_REDUCTION;
125 if (ui->reverb->isChecked())
126 settings.mFlags |= ModPlug::MODPLUG_ENABLE_REVERB;
127 if (ui->megabass->isChecked())
128 settings.mFlags |= ModPlug::MODPLUG_ENABLE_MEGABASS;
129 if (ui->surround->isChecked())
130 settings.mFlags |= ModPlug::MODPLUG_ENABLE_SURROUND;
131
132 switch (ui->resampleMode->currentIndex())
133 {
134 case 0: /* nearest neighbor */
135 settings.mResamplingMode = ModPlug::MODPLUG_RESAMPLE_NEAREST;
136 break;
137 case 1: /* linear */
138 settings.mResamplingMode = ModPlug::MODPLUG_RESAMPLE_LINEAR;
139 break;
140 case 2: /* cubic spline */
141 settings.mResamplingMode = ModPlug::MODPLUG_RESAMPLE_SPLINE;
142 break;
143 case 3: /* 8 bit FIR (also default) */
144 default:
145 settings.mResamplingMode = ModPlug::MODPLUG_RESAMPLE_FIR;
146 break;
147 }
148
149 settings.mStereoSeparation = ui->stereoSeparation->value();
150 settings.mMaxMixChannels = ui->maxMixChannels->value();
151 settings.mReverbDepth = ui->reverbDepth->value(); /* Reverb level 0(quiet)-100(loud) */
152 settings.mReverbDelay = ui->reverbDelay->value(); /* Reverb delay in ms, usually 40-200ms */
153 settings.mBassAmount = ui->bassDepth->value(); /* XBass level 0(quiet)-100(loud) */
154 settings.mBassRange = ui->bassCutoff->value(); /* XBass cutoff in Hz 10-100 */
155 settings.mSurroundDepth = ui->surroundDepth->value(); /* Surround level 0(quiet)-100(heavy) */
156 settings.mSurroundDelay = ui->surroundDelay->value(); /* Surround delay in ms, usually 5-40ms */
157 settings.mLoopCount = 0; /* Number of times to loop. Zero prevents looping. -1 loops forever. */
158
159 // apply modplug settings
160 SoundSourceModPlug::configure(bufferSizeLimit, settings);
161}
0162
=== added file 'mixxx/src/dlgprefmodplug.h'
--- mixxx/src/dlgprefmodplug.h 1970-01-01 00:00:00 +0000
+++ mixxx/src/dlgprefmodplug.h 2013-03-14 18:33:22 +0000
@@ -0,0 +1,49 @@
1/***************************************************************************
2 dlgprefmodplug.h - modplug settings dialog
3 -------------------
4 copyright : (C) 2013 by Stefan Nuernberger
5 email : kabelfrickler@gmail.com
6 ***************************************************************************/
7
8/***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 ***************************************************************************/
16
17#ifndef DLGPREFMODPLUG_H
18#define DLGPREFMODPLUG_H
19
20#include <QDialog>
21#include "configobject.h"
22
23namespace Ui {
24class DlgPrefModplug;
25}
26
27class DlgPrefModplug : public QDialog
28{
29 Q_OBJECT
30
31public:
32 explicit DlgPrefModplug(QWidget *parent, ConfigObject<ConfigValue> *_config);
33 ~DlgPrefModplug();
34
35public slots:
36 /** Apply changes to widget */
37 void slotApply();
38 void slotUpdate();
39
40 void loadSettings();
41 void saveSettings();
42 void applySettings();
43
44private:
45 Ui::DlgPrefModplug *ui;
46 ConfigObject<ConfigValue> *config;
47};
48
49#endif // DLGPREFMODPLUG_H
050
=== added file 'mixxx/src/dlgprefmodplugdlg.ui'
--- mixxx/src/dlgprefmodplugdlg.ui 1970-01-01 00:00:00 +0000
+++ mixxx/src/dlgprefmodplugdlg.ui 2013-03-14 18:33:22 +0000
@@ -0,0 +1,728 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<ui version="4.0">
3 <class>DlgPrefModplug</class>
4 <widget class="QDialog" name="DlgPrefModplug">
5 <property name="geometry">
6 <rect>
7 <x>0</x>
8 <y>0</y>
9 <width>593</width>
10 <height>538</height>
11 </rect>
12 </property>
13 <property name="windowTitle">
14 <string>Modplug Preferences</string>
15 </property>
16 <layout class="QGridLayout" name="gridLayout">
17 <property name="spacing">
18 <number>10</number>
19 </property>
20 <item row="13" column="4">
21 <widget class="QSlider" name="surroundDelay">
22 <property name="maximum">
23 <number>100</number>
24 </property>
25 <property name="value">
26 <number>10</number>
27 </property>
28 <property name="orientation">
29 <enum>Qt::Horizontal</enum>
30 </property>
31 </widget>
32 </item>
33 <item row="5" column="0" colspan="5">
34 <widget class="QCheckBox" name="noiseReduction">
35 <property name="text">
36 <string>Enable noise reduction</string>
37 </property>
38 </widget>
39 </item>
40 <item row="10" column="0">
41 <widget class="QCheckBox" name="megabass">
42 <property name="text">
43 <string>Enable megabass</string>
44 </property>
45 </widget>
46 </item>
47 <item row="8" column="0">
48 <widget class="QCheckBox" name="reverb">
49 <property name="text">
50 <string>Enable reverb</string>
51 </property>
52 </widget>
53 </item>
54 <item row="14" column="1">
55 <spacer name="verticalSpacer">
56 <property name="orientation">
57 <enum>Qt::Vertical</enum>
58 </property>
59 <property name="sizeHint" stdset="0">
60 <size>
61 <width>20</width>
62 <height>40</height>
63 </size>
64 </property>
65 </spacer>
66 </item>
67 <item row="6" column="0" colspan="3">
68 <widget class="QLabel" name="label_4">
69 <property name="text">
70 <string>Stereo separation</string>
71 </property>
72 </widget>
73 </item>
74 <item row="10" column="1" colspan="2">
75 <widget class="QLabel" name="label_2">
76 <property name="text">
77 <string>Bass level</string>
78 </property>
79 </widget>
80 </item>
81 <item row="2" column="0" colspan="3">
82 <widget class="QLabel" name="label_10">
83 <property name="text">
84 <string>Memory limit for single track (MB)</string>
85 </property>
86 </widget>
87 </item>
88 <item row="12" column="5">
89 <widget class="QSpinBox" name="surroundDepthSpin">
90 <property name="maximum">
91 <number>100</number>
92 </property>
93 <property name="value">
94 <number>30</number>
95 </property>
96 </widget>
97 </item>
98 <item row="4" column="0" colspan="3">
99 <widget class="QLabel" name="label">
100 <property name="text">
101 <string>Resampling mode (interpolation)</string>
102 </property>
103 </widget>
104 </item>
105 <item row="2" column="4">
106 <widget class="QSlider" name="memoryLimit">
107 <property name="toolTip">
108 <string extracomment="1 minute of decoded audio requires about 10MB of RAM."/>
109 </property>
110 <property name="minimum">
111 <number>16</number>
112 </property>
113 <property name="maximum">
114 <number>512</number>
115 </property>
116 <property name="value">
117 <number>256</number>
118 </property>
119 <property name="sliderPosition">
120 <number>256</number>
121 </property>
122 <property name="orientation">
123 <enum>Qt::Horizontal</enum>
124 </property>
125 </widget>
126 </item>
127 <item row="7" column="0" colspan="3">
128 <widget class="QLabel" name="label_5">
129 <property name="text">
130 <string>Maximum Number of Mixing Channels</string>
131 </property>
132 </widget>
133 </item>
134 <item row="10" column="4">
135 <widget class="QSlider" name="bassDepth">
136 <property name="maximum">
137 <number>100</number>
138 </property>
139 <property name="value">
140 <number>30</number>
141 </property>
142 <property name="orientation">
143 <enum>Qt::Horizontal</enum>
144 </property>
145 </widget>
146 </item>
147 <item row="2" column="5">
148 <widget class="QSpinBox" name="memoryLimitSpin">
149 <property name="minimum">
150 <number>16</number>
151 </property>
152 <property name="maximum">
153 <number>512</number>
154 </property>
155 <property name="value">
156 <number>256</number>
157 </property>
158 </widget>
159 </item>
160 <item row="11" column="4">
161 <widget class="QSlider" name="bassCutoff">
162 <property name="minimum">
163 <number>10</number>
164 </property>
165 <property name="maximum">
166 <number>100</number>
167 </property>
168 <property name="value">
169 <number>80</number>
170 </property>
171 <property name="orientation">
172 <enum>Qt::Horizontal</enum>
173 </property>
174 </widget>
175 </item>
176 <item row="11" column="1" colspan="2">
177 <widget class="QLabel" name="label_3">
178 <property name="text">
179 <string>Bass cutoff (Hz)</string>
180 </property>
181 </widget>
182 </item>
183 <item row="12" column="1" colspan="2">
184 <widget class="QLabel" name="label_8">
185 <property name="text">
186 <string>Surround level</string>
187 </property>
188 </widget>
189 </item>
190 <item row="13" column="1" colspan="2">
191 <widget class="QLabel" name="label_9">
192 <property name="text">
193 <string>Surround delay (ms)</string>
194 </property>
195 </widget>
196 </item>
197 <item row="8" column="4">
198 <widget class="QSlider" name="reverbDepth">
199 <property name="maximum">
200 <number>100</number>
201 </property>
202 <property name="value">
203 <number>30</number>
204 </property>
205 <property name="orientation">
206 <enum>Qt::Horizontal</enum>
207 </property>
208 </widget>
209 </item>
210 <item row="9" column="4">
211 <widget class="QSlider" name="reverbDelay">
212 <property name="minimum">
213 <number>10</number>
214 </property>
215 <property name="maximum">
216 <number>250</number>
217 </property>
218 <property name="value">
219 <number>50</number>
220 </property>
221 <property name="orientation">
222 <enum>Qt::Horizontal</enum>
223 </property>
224 </widget>
225 </item>
226 <item row="6" column="4">
227 <widget class="QSlider" name="stereoSeparation">
228 <property name="minimum">
229 <number>1</number>
230 </property>
231 <property name="maximum">
232 <number>256</number>
233 </property>
234 <property name="value">
235 <number>64</number>
236 </property>
237 <property name="orientation">
238 <enum>Qt::Horizontal</enum>
239 </property>
240 <property name="tickPosition">
241 <enum>QSlider::NoTicks</enum>
242 </property>
243 </widget>
244 </item>
245 <item row="9" column="1" colspan="2">
246 <widget class="QLabel" name="label_7">
247 <property name="text">
248 <string>Reverb delay (ms)</string>
249 </property>
250 </widget>
251 </item>
252 <item row="12" column="0">
253 <widget class="QCheckBox" name="surround">
254 <property name="text">
255 <string>Enable surround</string>
256 </property>
257 </widget>
258 </item>
259 <item row="3" column="0" colspan="5">
260 <widget class="QCheckBox" name="oversampling">
261 <property name="text">
262 <string>Enable oversampling (*highly* recommended)</string>
263 </property>
264 <property name="checked">
265 <bool>true</bool>
266 </property>
267 </widget>
268 </item>
269 <item row="7" column="4">
270 <widget class="QSlider" name="maxMixChannels">
271 <property name="minimum">
272 <number>32</number>
273 </property>
274 <property name="maximum">
275 <number>256</number>
276 </property>
277 <property name="value">
278 <number>128</number>
279 </property>
280 <property name="orientation">
281 <enum>Qt::Horizontal</enum>
282 </property>
283 </widget>
284 </item>
285 <item row="12" column="4">
286 <widget class="QSlider" name="surroundDepth">
287 <property name="maximum">
288 <number>100</number>
289 </property>
290 <property name="value">
291 <number>30</number>
292 </property>
293 <property name="orientation">
294 <enum>Qt::Horizontal</enum>
295 </property>
296 </widget>
297 </item>
298 <item row="8" column="1" colspan="2">
299 <widget class="QLabel" name="label_6">
300 <property name="text">
301 <string>Reverb level</string>
302 </property>
303 </widget>
304 </item>
305 <item row="6" column="5">
306 <widget class="QSpinBox" name="stereoSeparationSpin">
307 <property name="minimum">
308 <number>1</number>
309 </property>
310 <property name="maximum">
311 <number>256</number>
312 </property>
313 </widget>
314 </item>
315 <item row="7" column="5">
316 <widget class="QSpinBox" name="maxMixChannelsSpin">
317 <property name="minimum">
318 <number>32</number>
319 </property>
320 <property name="maximum">
321 <number>256</number>
322 </property>
323 <property name="value">
324 <number>128</number>
325 </property>
326 </widget>
327 </item>
328 <item row="4" column="4" colspan="2">
329 <widget class="QComboBox" name="resampleMode">
330 <property name="currentIndex">
331 <number>3</number>
332 </property>
333 <item>
334 <property name="text">
335 <string>Nearest (very fast, extremely bad quality)</string>
336 </property>
337 </item>
338 <item>
339 <property name="text">
340 <string>Linear (fast, good quality)</string>
341 </property>
342 </item>
343 <item>
344 <property name="text">
345 <string>Cubic Spline (high quality)</string>
346 </property>
347 </item>
348 <item>
349 <property name="text">
350 <string>8-tap FIR (extremely high quality)</string>
351 </property>
352 </item>
353 </widget>
354 </item>
355 <item row="8" column="5">
356 <widget class="QSpinBox" name="reverbDepthSpin">
357 <property name="maximum">
358 <number>100</number>
359 </property>
360 <property name="value">
361 <number>30</number>
362 </property>
363 </widget>
364 </item>
365 <item row="9" column="5">
366 <widget class="QSpinBox" name="reverbDelaySpin">
367 <property name="minimum">
368 <number>10</number>
369 </property>
370 <property name="maximum">
371 <number>250</number>
372 </property>
373 <property name="value">
374 <number>50</number>
375 </property>
376 </widget>
377 </item>
378 <item row="10" column="5">
379 <widget class="QSpinBox" name="bassDepthSpin">
380 <property name="maximum">
381 <number>100</number>
382 </property>
383 <property name="value">
384 <number>30</number>
385 </property>
386 </widget>
387 </item>
388 <item row="11" column="5">
389 <widget class="QSpinBox" name="bassCutoffSpin">
390 <property name="minimum">
391 <number>10</number>
392 </property>
393 <property name="maximum">
394 <number>100</number>
395 </property>
396 <property name="value">
397 <number>80</number>
398 </property>
399 </widget>
400 </item>
401 <item row="13" column="5">
402 <widget class="QSpinBox" name="surroundDelaySpin">
403 <property name="maximum">
404 <number>100</number>
405 </property>
406 <property name="value">
407 <number>10</number>
408 </property>
409 </widget>
410 </item>
411 <item row="0" column="0" colspan="5">
412 <widget class="QLabel" name="label_11">
413 <property name="text">
414 <string>Decoding options for libmodplug. Module files are decoded at once
415and kept in RAM to allow for seeking and smooth operation in Mixxx.</string>
416 </property>
417 </widget>
418 </item>
419 <item row="8" column="3">
420 <spacer name="horizontalSpacer">
421 <property name="orientation">
422 <enum>Qt::Horizontal</enum>
423 </property>
424 <property name="sizeType">
425 <enum>QSizePolicy::Minimum</enum>
426 </property>
427 <property name="sizeHint" stdset="0">
428 <size>
429 <width>40</width>
430 <height>20</height>
431 </size>
432 </property>
433 </spacer>
434 </item>
435 </layout>
436 </widget>
437 <resources/>
438 <connections>
439 <connection>
440 <sender>memoryLimit</sender>
441 <signal>valueChanged(int)</signal>
442 <receiver>memoryLimitSpin</receiver>
443 <slot>setValue(int)</slot>
444 <hints>
445 <hint type="sourcelabel">
446 <x>405</x>
447 <y>58</y>
448 </hint>
449 <hint type="destinationlabel">
450 <x>556</x>
451 <y>58</y>
452 </hint>
453 </hints>
454 </connection>
455 <connection>
456 <sender>memoryLimitSpin</sender>
457 <signal>valueChanged(int)</signal>
458 <receiver>memoryLimit</receiver>
459 <slot>setValue(int)</slot>
460 <hints>
461 <hint type="sourcelabel">
462 <x>556</x>
463 <y>58</y>
464 </hint>
465 <hint type="destinationlabel">
466 <x>405</x>
467 <y>58</y>
468 </hint>
469 </hints>
470 </connection>
471 <connection>
472 <sender>stereoSeparation</sender>
473 <signal>valueChanged(int)</signal>
474 <receiver>stereoSeparationSpin</receiver>
475 <slot>setValue(int)</slot>
476 <hints>
477 <hint type="sourcelabel">
478 <x>405</x>
479 <y>186</y>
480 </hint>
481 <hint type="destinationlabel">
482 <x>556</x>
483 <y>186</y>
484 </hint>
485 </hints>
486 </connection>
487 <connection>
488 <sender>stereoSeparationSpin</sender>
489 <signal>valueChanged(int)</signal>
490 <receiver>stereoSeparation</receiver>
491 <slot>setValue(int)</slot>
492 <hints>
493 <hint type="sourcelabel">
494 <x>556</x>
495 <y>186</y>
496 </hint>
497 <hint type="destinationlabel">
498 <x>405</x>
499 <y>186</y>
500 </hint>
501 </hints>
502 </connection>
503 <connection>
504 <sender>maxMixChannels</sender>
505 <signal>valueChanged(int)</signal>
506 <receiver>maxMixChannelsSpin</receiver>
507 <slot>setValue(int)</slot>
508 <hints>
509 <hint type="sourcelabel">
510 <x>405</x>
511 <y>220</y>
512 </hint>
513 <hint type="destinationlabel">
514 <x>556</x>
515 <y>220</y>
516 </hint>
517 </hints>
518 </connection>
519 <connection>
520 <sender>maxMixChannelsSpin</sender>
521 <signal>valueChanged(int)</signal>
522 <receiver>maxMixChannels</receiver>
523 <slot>setValue(int)</slot>
524 <hints>
525 <hint type="sourcelabel">
526 <x>556</x>
527 <y>220</y>
528 </hint>
529 <hint type="destinationlabel">
530 <x>405</x>
531 <y>220</y>
532 </hint>
533 </hints>
534 </connection>
535 <connection>
536 <sender>reverbDepth</sender>
537 <signal>valueChanged(int)</signal>
538 <receiver>reverbDepthSpin</receiver>
539 <slot>setValue(int)</slot>
540 <hints>
541 <hint type="sourcelabel">
542 <x>405</x>
543 <y>254</y>
544 </hint>
545 <hint type="destinationlabel">
546 <x>556</x>
547 <y>254</y>
548 </hint>
549 </hints>
550 </connection>
551 <connection>
552 <sender>reverbDepthSpin</sender>
553 <signal>valueChanged(int)</signal>
554 <receiver>reverbDepth</receiver>
555 <slot>setValue(int)</slot>
556 <hints>
557 <hint type="sourcelabel">
558 <x>556</x>
559 <y>254</y>
560 </hint>
561 <hint type="destinationlabel">
562 <x>405</x>
563 <y>254</y>
564 </hint>
565 </hints>
566 </connection>
567 <connection>
568 <sender>reverbDelay</sender>
569 <signal>valueChanged(int)</signal>
570 <receiver>reverbDelaySpin</receiver>
571 <slot>setValue(int)</slot>
572 <hints>
573 <hint type="sourcelabel">
574 <x>405</x>
575 <y>288</y>
576 </hint>
577 <hint type="destinationlabel">
578 <x>556</x>
579 <y>288</y>
580 </hint>
581 </hints>
582 </connection>
583 <connection>
584 <sender>bassDepth</sender>
585 <signal>valueChanged(int)</signal>
586 <receiver>bassDepthSpin</receiver>
587 <slot>setValue(int)</slot>
588 <hints>
589 <hint type="sourcelabel">
590 <x>405</x>
591 <y>322</y>
592 </hint>
593 <hint type="destinationlabel">
594 <x>556</x>
595 <y>322</y>
596 </hint>
597 </hints>
598 </connection>
599 <connection>
600 <sender>bassDepthSpin</sender>
601 <signal>valueChanged(int)</signal>
602 <receiver>bassDepth</receiver>
603 <slot>setValue(int)</slot>
604 <hints>
605 <hint type="sourcelabel">
606 <x>556</x>
607 <y>322</y>
608 </hint>
609 <hint type="destinationlabel">
610 <x>405</x>
611 <y>322</y>
612 </hint>
613 </hints>
614 </connection>
615 <connection>
616 <sender>reverbDelaySpin</sender>
617 <signal>valueChanged(int)</signal>
618 <receiver>reverbDelay</receiver>
619 <slot>setValue(int)</slot>
620 <hints>
621 <hint type="sourcelabel">
622 <x>556</x>
623 <y>288</y>
624 </hint>
625 <hint type="destinationlabel">
626 <x>405</x>
627 <y>288</y>
628 </hint>
629 </hints>
630 </connection>
631 <connection>
632 <sender>bassCutoff</sender>
633 <signal>valueChanged(int)</signal>
634 <receiver>bassCutoffSpin</receiver>
635 <slot>setValue(int)</slot>
636 <hints>
637 <hint type="sourcelabel">
638 <x>405</x>
639 <y>356</y>
640 </hint>
641 <hint type="destinationlabel">
642 <x>556</x>
643 <y>356</y>
644 </hint>
645 </hints>
646 </connection>
647 <connection>
648 <sender>bassCutoffSpin</sender>
649 <signal>valueChanged(int)</signal>
650 <receiver>bassCutoff</receiver>
651 <slot>setValue(int)</slot>
652 <hints>
653 <hint type="sourcelabel">
654 <x>556</x>
655 <y>356</y>
656 </hint>
657 <hint type="destinationlabel">
658 <x>405</x>
659 <y>356</y>
660 </hint>
661 </hints>
662 </connection>
663 <connection>
664 <sender>surroundDepth</sender>
665 <signal>valueChanged(int)</signal>
666 <receiver>surroundDepthSpin</receiver>
667 <slot>setValue(int)</slot>
668 <hints>
669 <hint type="sourcelabel">
670 <x>405</x>
671 <y>390</y>
672 </hint>
673 <hint type="destinationlabel">
674 <x>556</x>
675 <y>390</y>
676 </hint>
677 </hints>
678 </connection>
679 <connection>
680 <sender>surroundDepthSpin</sender>
681 <signal>valueChanged(int)</signal>
682 <receiver>surroundDepth</receiver>
683 <slot>setValue(int)</slot>
684 <hints>
685 <hint type="sourcelabel">
686 <x>556</x>
687 <y>390</y>
688 </hint>
689 <hint type="destinationlabel">
690 <x>405</x>
691 <y>390</y>
692 </hint>
693 </hints>
694 </connection>
695 <connection>
696 <sender>surroundDelay</sender>
697 <signal>valueChanged(int)</signal>
698 <receiver>surroundDelaySpin</receiver>
699 <slot>setValue(int)</slot>
700 <hints>
701 <hint type="sourcelabel">
702 <x>405</x>
703 <y>424</y>
704 </hint>
705 <hint type="destinationlabel">
706 <x>556</x>
707 <y>424</y>
708 </hint>
709 </hints>
710 </connection>
711 <connection>
712 <sender>surroundDelaySpin</sender>
713 <signal>valueChanged(int)</signal>
714 <receiver>surroundDelay</receiver>
715 <slot>setValue(int)</slot>
716 <hints>
717 <hint type="sourcelabel">
718 <x>556</x>
719 <y>424</y>
720 </hint>
721 <hint type="destinationlabel">
722 <x>405</x>
723 <y>424</y>
724 </hint>
725 </hints>
726 </connection>
727 </connections>
728</ui>
0729
=== modified file 'mixxx/src/mixxx.cpp'
--- mixxx/src/mixxx.cpp 2013-02-10 20:59:19 +0000
+++ mixxx/src/mixxx.cpp 2013-03-14 18:33:22 +0000
@@ -60,6 +60,10 @@
60#include "vinylcontrol/vinylcontrolmanager.h"60#include "vinylcontrol/vinylcontrolmanager.h"
61#endif61#endif
6262
63#ifdef __MODPLUG__
64#include "dlgprefmodplug.h"
65#endif
66
63extern "C" void crashDlg()67extern "C" void crashDlg()
64{68{
65 QMessageBox::critical(0, "Mixxx",69 QMessageBox::critical(0, "Mixxx",
@@ -340,6 +344,14 @@
340 m_pVCManager->init();344 m_pVCManager->init();
341#endif345#endif
342346
347#ifdef __MODPLUG__
348 // restore the configuration for the modplug library before trying to load a module
349 DlgPrefModplug* pModplugPrefs = new DlgPrefModplug(0, m_pConfig);
350 pModplugPrefs->loadSettings();
351 pModplugPrefs->applySettings();
352 delete pModplugPrefs; // not needed anymore
353#endif
354
343 m_pLibrary = new Library(this, m_pConfig,355 m_pLibrary = new Library(this, m_pConfig,
344 bFirstRun || bUpgraded,356 bFirstRun || bUpgraded,
345 m_pRecordingManager);357 m_pRecordingManager);
346358
=== added file 'mixxx/src/soundsourcemodplug.cpp'
--- mixxx/src/soundsourcemodplug.cpp 1970-01-01 00:00:00 +0000
+++ mixxx/src/soundsourcemodplug.cpp 2013-03-14 18:33:22 +0000
@@ -0,0 +1,196 @@
1/***************************************************************************
2 soundsourcemodplug.cpp - module tracker support
3 -------------------
4 copyright : (C) 2012 by Stefan Nuernberger
5 email : kabelfricker@gmail.com
6***************************************************************************/
7
8/***************************************************************************
9* *
10* This program is free software; you can redistribute it and/or modify *
11* it under the terms of the GNU General Public License as published by *
12* the Free Software Foundation; either version 2 of the License, or *
13* (at your option) any later version. *
14* *
15***************************************************************************/
16
17#include "soundsourcemodplug.h"
18#include <stdlib.h>
19#include <unistd.h>
20#include <QFile>
21
22/* read files in 512k chunks */
23#define CHUNKSIZE 524288
24
25// reserve some static space for settings...
26ModPlug::ModPlug_Settings SoundSourceModPlug::settings;
27unsigned int SoundSourceModPlug::bufferSizeLimit;
28
29SoundSourceModPlug::SoundSourceModPlug(QString qFilename) :
30 SoundSource(qFilename)
31{
32 opened = false;
33 filelength = 0;
34 file = 0;
35
36 qDebug() << "Loading ModPlug module " << m_qFilename;
37
38 // read module file to byte array
39 QFile modfile(m_qFilename);
40 modfile.open(QIODevice::ReadOnly);
41 filebuf = modfile.readAll();
42 modfile.close();
43 // get ModPlugFile
44 file = ModPlug::ModPlug_Load(filebuf.data(), filebuf.length());
45}
46
47SoundSourceModPlug::~SoundSourceModPlug()
48{
49 if (file) {
50 ModPlug::ModPlug_Unload(file);
51 file = NULL;
52 }
53}
54
55QList<QString> SoundSourceModPlug::supportedFileExtensions()
56{
57 QList<QString> list;
58 /* ModPlug supports more formats but file name
59 * extensions are not always present with modules.
60 */
61 list.push_back("mod");
62 list.push_back("med");
63 list.push_back("okt");
64 list.push_back("s3m");
65 list.push_back("stm");
66 list.push_back("xm");
67 list.push_back("it");
68 return list;
69}
70
71void SoundSourceModPlug::configure(unsigned int bLimit, const ModPlug::ModPlug_Settings &config)
72{
73 bufferSizeLimit = bLimit;
74 settings = config;
75
76 ModPlug::ModPlug_SetSettings(&settings);
77}
78
79int SoundSourceModPlug::open() {
80 if (file == NULL) {
81 // an error occured
82 qDebug() << "Could not load module file: "
83 << m_qFilename;
84 return ERR;
85 }
86
87 // temporary buffer to read samples
88 char *tmpbuf = new char[CHUNKSIZE];
89 int count = 1;
90 while ((count != 0) && (smplbuf.length() < bufferSizeLimit))
91 {
92 /* Read sample data into the buffer. Returns the number of bytes read. If the end
93 * of the module has been reached, zero is returned. */
94 count = ModPlug::ModPlug_Read(file, tmpbuf, CHUNKSIZE);
95 smplbuf.append(tmpbuf, count);
96 }
97 delete tmpbuf;
98 qDebug() << "Filled Sample buffer with " << smplbuf.length() << " bytes.";
99
100 // smplbuf holds 44.1kHz 16bit integer stereo samples.
101 // We count the number of samples by dividing number of
102 // bytes in smplbuf by 2 (bytes per sample).
103 filelength = smplbuf.length() >> 1;
104 m_iSampleRate = 44100; // ModPlug uses 44.1kHz
105 opened = true;
106 seekpos = 0;
107 return OK;
108}
109
110long SoundSourceModPlug::seek(long filepos)
111{
112 if (filelength > 0)
113 {
114 seekpos = math_min((unsigned long)filepos, filelength);
115 return seekpos;
116 }
117 return 0;
118}
119
120/*
121 read <size> samples into <destination>, and return the number of
122 samples actually read.
123 */
124unsigned SoundSourceModPlug::read(unsigned long size, const SAMPLE * destination)
125{
126 unsigned char * dest = (unsigned char *) destination;
127 if (filelength > 0)
128 {
129 unsigned count = 0;
130 while ((seekpos < filelength) && (count < (size << 1 )))
131 {
132 // copy a 16bit sample
133 dest[count++] = smplbuf[seekpos << 1];
134 dest[count++] = smplbuf[(seekpos << 1) + 1];
135 ++seekpos;
136 }
137 return count >> 1; ///< number of bytes divided by bytes per sample
138 }
139 // The file has errors or is not open. Tell the truth and return 0.
140 return 0;
141}
142
143int SoundSourceModPlug::parseHeader()
144{
145 if (file == NULL) {
146 // an error occured
147 qDebug() << "Could not parse module header of " << m_qFilename;
148 return ERR;
149 }
150
151 switch (ModPlug::ModPlug_GetModuleType(file))
152 {
153 case NONE:
154 setType(QString("None"));
155 break;
156 case MOD:
157 setType(QString("Protracker"));
158 break;
159 case S3M:
160 setType(QString("Scream Tracker 3"));
161 break;
162 case XM:
163 setType(QString("FastTracker2"));
164 break;
165 case MED:
166 setType(QString("OctaMed"));
167 break;
168 case IT:
169 setType(QString("Impulse Tracker"));
170 break;
171 case STM:
172 setType(QString("Scream Tracker"));
173 break;
174 case OKT:
175 setType(QString("Oktalyzer"));
176 break;
177 default:
178 setType(QString("Module"));
179 break;
180 }
181 setComment(QString(ModPlug::ModPlug_GetMessage(file)));
182 setTitle(QString(ModPlug::ModPlug_GetName(file)));
183 setDuration(ModPlug::ModPlug_GetLength(file) / 1000);
184 setBitrate(8); // not really, but fill in something...
185 setSampleRate(44100);
186 setChannels(2);
187 return OK;
188}
189
190/*
191 Return the length of the file in samples.
192 */
193inline long unsigned SoundSourceModPlug::length()
194{
195 return filelength;
196}
0197
=== added file 'mixxx/src/soundsourcemodplug.h'
--- mixxx/src/soundsourcemodplug.h 1970-01-01 00:00:00 +0000
+++ mixxx/src/soundsourcemodplug.h 2013-03-14 18:33:22 +0000
@@ -0,0 +1,74 @@
1/***************************************************************************
2 soundsourcemodplug.h - modplug tracker support
3 -------------------
4 copyright : (C) 2012 by Stefan Nuernberger
5 email : kabelfrickler@gmail.com
6 ***************************************************************************/
7
8/***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 ***************************************************************************/
16
17#ifndef SOUNDSOURCEMODPLUG_H
18#define SOUNDSOURCEMODPLUG_H
19
20#include "soundsource.h"
21#include "defs_version.h"
22#include <QByteArray>
23#include <QList>
24#include <QString>
25#include <QtDebug>
26
27namespace ModPlug {
28#include "libmodplug/modplug.h"
29}
30
31/*
32 Class for reading tracker files using libmodplug
33 The whole file is decoded at once and saved
34 in RAM to allow seeking and smooth operation in Mixxx.
35 */
36class SoundSourceModPlug : public Mixxx::SoundSource
37{
38public:
39 SoundSourceModPlug(QString qFilename);
40 ~SoundSourceModPlug();
41 int open();
42 long seek(long);
43 unsigned read(unsigned long size, const SAMPLE*);
44 inline long unsigned length();
45 int parseHeader();
46 static QList<QString> supportedFileExtensions();
47
48 static void configure(unsigned int bufferSizeLimit,
49 const ModPlug::ModPlug_Settings &settings);
50private:
51 static unsigned int bufferSizeLimit;
52 static ModPlug::ModPlug_Settings settings; ///< struct of parameters
53
54 bool opened;
55 unsigned long filelength;
56 unsigned int seekpos;
57 ModPlug::ModPlugFile *file; ///< pointer to ModPlugFile struct
58 QByteArray filebuf; ///< original module file data
59 QByteArray smplbuf; ///< 16bit stereo samples, 44.1kHz
60
61 /// identification of modplug module type
62 enum ModuleTypes {
63 NONE = 0x00,
64 MOD = 0x01,
65 S3M = 0x02,
66 XM = 0x04,
67 MED = 0x08,
68 IT = 0x20,
69 STM = 0x100,
70 OKT = 0x8000
71 };
72};
73
74#endif
075
=== modified file 'mixxx/src/soundsourceproxy.cpp'
--- mixxx/src/soundsourceproxy.cpp 2012-11-20 00:40:18 +0000
+++ mixxx/src/soundsourceproxy.cpp 2013-03-14 18:33:22 +0000
@@ -31,6 +31,9 @@
31#ifdef __FFMPEGFILE__31#ifdef __FFMPEGFILE__
32#include "soundsourceffmpeg.h"32#include "soundsourceffmpeg.h"
33#endif33#endif
34#ifdef __MODPLUG__
35#include "soundsourcemodplug.h"
36#endif
34#include "soundsourceflac.h"37#include "soundsourceflac.h"
3538
36#include "mixxx.h"39#include "mixxx.h"
@@ -139,6 +142,10 @@
139 } else if (SoundSourceCoreAudio::supportedFileExtensions().contains(extension)) {142 } else if (SoundSourceCoreAudio::supportedFileExtensions().contains(extension)) {
140 return new SoundSourceCoreAudio(qFilename);143 return new SoundSourceCoreAudio(qFilename);
141#endif144#endif
145#ifdef __MODPLUG__
146 } else if (SoundSourceModPlug::supportedFileExtensions().contains(extension)) {
147 return new SoundSourceModPlug(qFilename);
148#endif
142 } else if (m_extensionsSupportedByPlugins.contains(extension)) {149 } else if (m_extensionsSupportedByPlugins.contains(extension)) {
143 getSoundSourceFunc getter = m_extensionsSupportedByPlugins.value(extension);150 getSoundSourceFunc getter = m_extensionsSupportedByPlugins.value(extension);
144 if (getter)151 if (getter)
@@ -368,6 +375,9 @@
368#ifdef __COREAUDIO__375#ifdef __COREAUDIO__
369 supportedFileExtensions.append(SoundSourceCoreAudio::supportedFileExtensions());376 supportedFileExtensions.append(SoundSourceCoreAudio::supportedFileExtensions());
370#endif377#endif
378#ifdef __MODPLUG__
379 supportedFileExtensions.append(SoundSourceModPlug::supportedFileExtensions());
380#endif
371 supportedFileExtensions.append(m_extensionsSupportedByPlugins.keys());381 supportedFileExtensions.append(m_extensionsSupportedByPlugins.keys());
372382
373 return supportedFileExtensions;383 return supportedFileExtensions;