Added missing files because for some reason, they weren't imported at initial port...
git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@7 0778d3d1-df1d-0410-868b-ea421aaaa00d
This commit is contained in:
150
src/core/about_dialog.cpp
Normal file
150
src/core/about_dialog.cpp
Normal file
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* about_dialog.cpp - implementation of about-dialog
|
||||
*
|
||||
* Linux MultiMedia Studio
|
||||
* Copyright (c) 2004-2005 Tobias Doerffel <tobydox@users.sourceforge.net>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "qt3support.h"
|
||||
|
||||
#ifdef QT4
|
||||
|
||||
#include <QTextEdit>
|
||||
#include <QTabWidget>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QResizeEvent>
|
||||
|
||||
#else
|
||||
|
||||
#include <qtextedit.h>
|
||||
#include <qtabwidget.h>
|
||||
#include <qlabel.h>
|
||||
#include <qpushbutton.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "about_dialog.h"
|
||||
#include "embed.h"
|
||||
|
||||
|
||||
|
||||
|
||||
aboutDialog::aboutDialog() :
|
||||
QDialog()
|
||||
{
|
||||
setWindowTitle( tr( "About LMMS..." ) );
|
||||
|
||||
m_iconLbl = new QLabel( this );
|
||||
m_iconLbl->setPixmap( embed::getIconPixmap( "icon" ) );
|
||||
m_iconLbl->setGeometry( 10, 10, 64, 64 );
|
||||
|
||||
m_appNameLbl = new QLabel( tr( "Linux MultiMedia Studio %1"
|
||||
).arg( VERSION ), this );
|
||||
m_appNameLbl->setGeometry( 80, 30, 240, 20 );
|
||||
|
||||
m_aboutTabs = new QTabWidget( this );
|
||||
|
||||
QLabel * about_lbl = new QLabel( tr( "LMMS - A powerful "
|
||||
"synthesizer-studio\n\n"
|
||||
"Copyright (c) 2004-2005 "
|
||||
"LMMS-Developers\n\n"
|
||||
"http://lmms.sourceforge.net" )
|
||||
#ifndef QT4
|
||||
, m_aboutTabs
|
||||
#endif
|
||||
);
|
||||
about_lbl->setAlignment( Qt::AlignVCenter | Qt::AlignLeft );
|
||||
about_lbl->setIndent( 30 );
|
||||
|
||||
|
||||
QTextEdit * authors_lbl = new QTextEdit();
|
||||
authors_lbl->setPlainText( embed::getText( "AUTHORS" ) );
|
||||
authors_lbl->setReadOnly( TRUE );
|
||||
authors_lbl->setLineWrapMode( QTextEdit::NoWrap );
|
||||
|
||||
QTextEdit * translation_lbl = new QTextEdit();
|
||||
translation_lbl->setPlainText( tr( "Current language not translated."
|
||||
"\n\nIf you're interested in "
|
||||
"translating LMMS in another "
|
||||
"language or want to improve "
|
||||
"existing translations, you're "
|
||||
"welcome to help us! Just "
|
||||
"contact the maintainer!" ) );
|
||||
translation_lbl->setReadOnly( TRUE );
|
||||
|
||||
|
||||
QTextEdit * copying_lbl = new QTextEdit();
|
||||
copying_lbl->setPlainText( embed::getText( "COPYING" ) );
|
||||
copying_lbl->setReadOnly( TRUE );
|
||||
copying_lbl->setLineWrapMode( QTextEdit::NoWrap );
|
||||
|
||||
|
||||
m_aboutTabs->addTab( about_lbl, tr( "About" ) );
|
||||
m_aboutTabs->addTab( authors_lbl, tr( "Authors" ) );
|
||||
m_aboutTabs->addTab( translation_lbl, tr( "Translation" ) );
|
||||
m_aboutTabs->addTab( copying_lbl, tr( "License" ) );
|
||||
|
||||
m_okBtn = new QPushButton( tr( "Close" ), this );
|
||||
connect( m_okBtn, SIGNAL( clicked() ), this, SLOT( accept() ) );
|
||||
|
||||
resize( 400, 390 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
aboutDialog::~aboutDialog()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void aboutDialog::keyPressEvent( QKeyEvent * _ke )
|
||||
{
|
||||
if( _ke->key() == Qt::Key_Escape )
|
||||
{
|
||||
accept();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void aboutDialog::resizeEvent( QResizeEvent * _re )
|
||||
{
|
||||
m_aboutTabs->setGeometry( 10, 90, _re->size().width() - 20,
|
||||
_re->size().height() - 140 );
|
||||
m_okBtn->setGeometry( _re->size().width() - 110,
|
||||
_re->size().height() - 40, 100, 30 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#include "about_dialog.moc"
|
||||
|
||||
762
src/core/arp_and_chords_tab_widget.cpp
Normal file
762
src/core/arp_and_chords_tab_widget.cpp
Normal file
@@ -0,0 +1,762 @@
|
||||
/*
|
||||
* arp_and_chords_tab_widget.cpp - widget for use in arp/chord-tab of
|
||||
* channel-window
|
||||
*
|
||||
* Linux MultiMedia Studio
|
||||
* Copyright (c) 2004-2005 Tobias Doerffel <tobydox@users.sourceforge.net>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "qt3support.h"
|
||||
|
||||
#ifdef QT4
|
||||
|
||||
#include <Qt/QtXml>
|
||||
#include <QButtonGroup>
|
||||
#include <QLabel>
|
||||
#include <QComboBox>
|
||||
|
||||
#else
|
||||
|
||||
#include <qbuttongroup.h>
|
||||
#include <qdom.h>
|
||||
#include <qlabel.h>
|
||||
#include <qcombobox.h>
|
||||
|
||||
#define setChecked setOn
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "arp_and_chords_tab_widget.h"
|
||||
#include "embed.h"
|
||||
#include "note_play_handle.h"
|
||||
#include "song_editor.h"
|
||||
#include "group_box.h"
|
||||
#include "pixmap_button.h"
|
||||
#include "knob.h"
|
||||
#include "tooltip.h"
|
||||
|
||||
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
arpAndChordsTabWidget::chord arpAndChordsTabWidget::s_chords[] =
|
||||
{
|
||||
// thanks to the FL-team for this chords *lol* ;-) took me at least 3
|
||||
// hours to get them all out of FL-arpeggiator...
|
||||
|
||||
{ arpAndChordsTabWidget::tr( "octave" ), { 0, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Major" ), { 0, 4, 7, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Majb5" ), { 0, 4, 6, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "minor" ), { 0, 3, 7, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "minb5" ), { 0, 3, 6, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "sus2" ), { 0, 2, 7, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "sus4" ), { 0, 5, 7, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "aug" ), { 0, 4, 8, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "augsus4" ), { 0, 5, 8, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "tri" ), { 0, 3, 6, 9, -1 } },
|
||||
|
||||
{ arpAndChordsTabWidget::tr( "6" ), { 0, 4, 7, 9, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "6sus4" ), { 0, 5, 7, 9, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "6add9" ), { 0, 4, 7, 12, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "m6" ), { 0, 3, 7, 9, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "m6add9" ), { 0, 3, 7, 9, 14, -1 } },
|
||||
|
||||
{ arpAndChordsTabWidget::tr( "7" ), { 0, 4, 7, 10, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "7sus4" ), { 0, 5, 7, 10, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "7#5" ), { 0, 4, 8, 10, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "7b5" ), { 0, 4, 6, 10, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "7#9" ), { 0, 4, 7, 10, 13, 18, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "7b9" ), { 0, 4, 7, 10, 13, 16, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "7#5#9" ), { 0, 4, 8, 12, 14, 19, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "7#5b9" ), { 0, 4, 8, 12, 14, 17, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "7b5b9" ), { 0, 4, 6, 10, 12, 15, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "7add11" ), { 0, 4, 7, 10, 17, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "7add13" ), { 0, 4, 7, 10, 21, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "7#11" ), { 0, 4, 7, 10, 18, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Maj7" ), { 0, 4, 7, 11, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Maj7b5" ), { 0, 4, 6, 11, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Maj7#5" ), { 0, 4, 8, 11, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Maj7#11" ), { 0, 4, 7, 11, 18, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Maj7add13" ), { 0, 4, 7, 11, 21, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "m7" ), { 0, 3, 7, 10, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "m7b5" ), { 0, 3, 6, 10, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "m7b9" ), { 0, 3, 7, 10, 13, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "m7add11" ), { 0, 3, 7, 10, 17, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "m7add13" ), { 0, 3, 7, 10, 21, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "m-Maj7" ), { 0, 3, 7, 11, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "m-Maj7add11" ), { 0, 3, 7, 11, 17, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "m-Maj7add13" ), { 0, 3, 7, 11, 21, -1 } },
|
||||
|
||||
{ arpAndChordsTabWidget::tr( "9" ), { 0, 4, 7, 10, 14, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "9sus4" ), { 0, 5, 7, 10, 14, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "add9" ), { 0, 4, 7, 14, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "9#5" ), { 0, 4, 8, 10, 14, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "9b5" ), { 0, 4, 6, 10, 14, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "9#11" ), { 0, 4, 7, 10, 14, 18, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "9b13" ), { 0, 4, 7, 10, 14, 20, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Maj9" ), { 0, 4, 7, 11, 14, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Maj9sus4" ), { 0, 5, 7, 11, 15, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Maj9#5" ), { 0, 4, 8, 11, 14, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Maj9#11" ), { 0, 4, 7, 11, 14, 18, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "m9" ), { 0, 3, 7, 10, 14, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "madd9" ), { 0, 3, 7, 14, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "m9b5" ), { 0, 3, 6, 10, 14, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "m9-Maj7" ), { 0, 3, 7, 11, 14, -1 } },
|
||||
|
||||
{ arpAndChordsTabWidget::tr( "11" ), { 0, 4, 7, 10, 14, 17, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "11b9" ), { 0, 4, 7, 10, 13, 17, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Maj11" ), { 0, 4, 7, 11, 14, 17, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "m11" ), { 0, 3, 7, 10, 14, 17, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "m-Maj11" ), { 0, 3, 7, 11, 14, 17, -1 } },
|
||||
|
||||
{ arpAndChordsTabWidget::tr( "13" ), { 0, 4, 7, 10, 14, 21, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "13#9" ), { 0, 4, 7, 10, 15, 21, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "13b9" ), { 0, 4, 7, 10, 13, 21, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "13b5b9" ), { 0, 4, 6, 10, 13, 21, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Maj13" ), { 0, 4, 7, 11, 14, 21, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "m13" ), { 0, 3, 7, 10, 14, 21, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "m-Maj13" ), { 0, 3, 7, 11, 14, 21, -1 } },
|
||||
|
||||
{ arpAndChordsTabWidget::tr( "Major" ), { 0, 2, 4, 5, 7, 9, 11, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Harmonic minor" ), { 0, 2, 3, 5, 7, 8,
|
||||
11, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Melodic minor" ), { 0, 2, 3, 5, 7, 9,
|
||||
11, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Whole tone" ), { 0, 2, 4, 6, 8, 10,
|
||||
-1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Diminished" ), { 0, 2, 3, 5, 6, 8, 9,
|
||||
11, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Major pentatonic" ), { 0, 2, 4, 7, 10,
|
||||
-1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Minor pentatonic" ), { 0, 3, 5, 7, 10,
|
||||
-1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Jap in sen" ), { 0, 1, 5, 7, 10, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Major bebop" ), { 0, 2, 4, 5, 7, 8, 9,
|
||||
11, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Dominant bebop" ), { 0, 2, 4, 5, 7, 9,
|
||||
10, 11, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Blues" ), { 0, 3, 5, 6, 7, 10, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Arabic" ), { 0, 1, 4, 5, 7, 8, 11, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Enigmatic" ), { 0, 1, 4, 6, 8, 10, 11,
|
||||
-1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Neopolitan" ), { 0, 1, 3, 5, 7, 9, 11,
|
||||
-1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Neopolitan minor" ), { 0, 1, 3, 5, 7, 9,
|
||||
11, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Hungarian minor" ), { 0, 2, 3, 6, 7, 9,
|
||||
11, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Dorian" ), { 0, 2, 3, 5, 7, 9, 10, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Phrygolydian" ), { 0, 1, 3, 5, 7, 8, 10,
|
||||
-1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Lydian" ), { 0, 2, 4, 6, 7, 9, 11, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Mixolydian" ), { 0, 2, 4, 5, 7, 9, 10,
|
||||
-1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Aeolian" ), { 0, 2, 3, 5, 7, 8, 10,
|
||||
-1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Locrian" ), { 0, 1, 3, 5, 6, 8, 10,
|
||||
-1 } },
|
||||
|
||||
{ "", { -1, -1 } }
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
const int CHORDS_GROUPBOX_X = 5;
|
||||
const int CHORDS_GROUPBOX_Y = 5;
|
||||
const int CHORDS_GROUPBOX_WIDTH = 240;
|
||||
const int CHORDS_GROUPBOX_HEIGHT = 65;
|
||||
const int ARP_GROUPBOX_X = CHORDS_GROUPBOX_X;
|
||||
const int ARP_GROUPBOX_Y = 10 + CHORDS_GROUPBOX_Y + CHORDS_GROUPBOX_HEIGHT;
|
||||
const int ARP_GROUPBOX_WIDTH = CHORDS_GROUPBOX_WIDTH;
|
||||
const int ARP_GROUPBOX_HEIGHT = 180 - ARP_GROUPBOX_Y;
|
||||
|
||||
|
||||
|
||||
arpAndChordsTabWidget::arpAndChordsTabWidget( channelTrack * _channel_track,
|
||||
QWidget * _parent ) :
|
||||
QWidget( _parent ),
|
||||
settings(),
|
||||
m_arpDirection( UP ),
|
||||
m_channelTrack( _channel_track )
|
||||
{
|
||||
m_chordsGroupBox = new groupBox( tr( "CHORDS" ), this );
|
||||
m_chordsGroupBox->setGeometry( CHORDS_GROUPBOX_X, CHORDS_GROUPBOX_Y,
|
||||
CHORDS_GROUPBOX_WIDTH,
|
||||
CHORDS_GROUPBOX_HEIGHT );
|
||||
|
||||
m_chordsComboBox = new QComboBox( m_chordsGroupBox );
|
||||
m_chordsComboBox->setFont( pointSize<9>( m_chordsComboBox->font() ) );
|
||||
m_chordsComboBox->setGeometry( 10, 25, 100, 22 );
|
||||
|
||||
for( int i = 0; s_chords[i].interval[0] != -1; ++i )
|
||||
{
|
||||
m_chordsComboBox->addItem( tr( s_chords[i].name
|
||||
#ifdef QT4
|
||||
.toAscii().constData()
|
||||
#endif
|
||||
) );
|
||||
}
|
||||
|
||||
m_chordRangeKnob = new knob( knobBright_26, m_chordsGroupBox,
|
||||
tr( "Chord range" ) );
|
||||
m_chordRangeKnob->setLabel( tr( "RANGE" ) );
|
||||
m_chordRangeKnob->setRange( 1.0, 9.0, 1.0 );
|
||||
m_chordRangeKnob->setValue( 1.0, TRUE );
|
||||
m_chordRangeKnob->move( 123, 23 );
|
||||
m_chordRangeKnob->setHintText( tr( "Chord range:" ) + " ", " " +
|
||||
tr( "octave(s)" ) );
|
||||
#ifdef QT4
|
||||
m_chordRangeKnob->setWhatsThis(
|
||||
#else
|
||||
QWhatsThis::add( m_chordRangeKnob,
|
||||
#endif
|
||||
tr( "Use this knob for setting the chord range in octaves. "
|
||||
"The selected chord will be played within specified "
|
||||
"amount of octaves." ) );
|
||||
|
||||
|
||||
|
||||
|
||||
m_arpGroupBox = new groupBox( tr( "ARPEGGIO" ), this );
|
||||
m_arpGroupBox->setGeometry( ARP_GROUPBOX_X, ARP_GROUPBOX_Y,
|
||||
ARP_GROUPBOX_WIDTH,
|
||||
ARP_GROUPBOX_HEIGHT );
|
||||
|
||||
#ifdef QT4
|
||||
m_arpGroupBox->setWhatsThis(
|
||||
#else
|
||||
QWhatsThis::add( m_arpGroupBox,
|
||||
#endif
|
||||
tr( "An arpeggio is a type of playing (especially plucked) "
|
||||
"instruments, which makes the music much livelier. "
|
||||
"The strings of such instruments (e.g. harps) are "
|
||||
"plucked like chords, the only difference is, that "
|
||||
"this is done in a sequential order, so the notes are "
|
||||
"not played at the same time. Typical arpeggios are "
|
||||
"major or minor triads. But there're a lot of other "
|
||||
"possible chords, you can select." ) );
|
||||
m_arpComboBox = new QComboBox( m_arpGroupBox );
|
||||
m_arpComboBox->setFont( pointSize<9>( m_arpComboBox->font() ) );
|
||||
m_arpComboBox->setGeometry( 10, 25, 100, 22 );
|
||||
|
||||
for( int i = 0; s_chords[i].interval[0] != -1; ++i )
|
||||
{
|
||||
m_arpComboBox->addItem( tr( s_chords[i].name
|
||||
#ifdef QT4
|
||||
.toAscii().constData()
|
||||
#endif
|
||||
) );
|
||||
}
|
||||
m_arpRangeKnob = new knob( knobBright_26, m_arpGroupBox,
|
||||
tr( "Arpeggio range" ) );
|
||||
m_arpRangeKnob->setLabel( tr( "RANGE" ) );
|
||||
m_arpRangeKnob->setRange( 1.0, 9.0, 1.0 );
|
||||
m_arpRangeKnob->setValue( 1.0, TRUE );
|
||||
m_arpRangeKnob->move( 124, 24 );
|
||||
m_arpRangeKnob->setHintText( tr( "Arpeggio range:" ) + " ", " " +
|
||||
tr( "octave(s)" ) );
|
||||
#ifdef QT4
|
||||
m_arpRangeKnob->setWhatsThis(
|
||||
#else
|
||||
QWhatsThis::add( m_arpRangeKnob,
|
||||
#endif
|
||||
tr( "Use this knob for setting the arpeggio range in octaves. "
|
||||
"The selected arpeggio will be played within specified "
|
||||
"amount of octaves." ) );
|
||||
|
||||
m_arpTimeKnob = new knob( knobBright_26, m_arpGroupBox,
|
||||
tr( "Arpeggio time" ) );
|
||||
m_arpTimeKnob->setLabel( tr( "TIME" ) );
|
||||
m_arpTimeKnob->setRange( 10.0, 1000.0, 1.0 );
|
||||
m_arpTimeKnob->setValue( 100.0, TRUE );
|
||||
m_arpTimeKnob->move( 164, 24 );
|
||||
m_arpTimeKnob->setHintText( tr( "Arpeggio time:" ) + " ", " " +
|
||||
tr( "ms" ) );
|
||||
#ifdef QT4
|
||||
m_arpTimeKnob->setWhatsThis(
|
||||
#else
|
||||
QWhatsThis::add( m_arpTimeKnob,
|
||||
#endif
|
||||
tr( "Use this knob for setting the arpeggio time in "
|
||||
"milliseconds. The arpeggio time specifies how long "
|
||||
"each arpeggio-tone should be played." ) );
|
||||
|
||||
m_arpGateKnob = new knob( knobBright_26, m_arpGroupBox,
|
||||
tr( "Arpeggio gate" ) );
|
||||
m_arpGateKnob->setLabel( tr( "GATE" ) );
|
||||
m_arpGateKnob->setRange( 1.0, 200.0, 1.0 );
|
||||
m_arpGateKnob->setValue( 100.0, TRUE );
|
||||
m_arpGateKnob->move( 204, 24 );
|
||||
m_arpGateKnob->setHintText( tr( "Arpeggio gate:" ) + " ", tr( "%" ) );
|
||||
#ifdef QT4
|
||||
m_arpGateKnob->setWhatsThis(
|
||||
#else
|
||||
QWhatsThis::add( m_arpGateKnob,
|
||||
#endif
|
||||
tr( "Use this knob for setting the arpeggio gate. The "
|
||||
"arpeggio gate specifies the percent of a whole "
|
||||
"arpeggio-tone that should be played. With this you "
|
||||
"can make cool staccato-arpeggios." ) );
|
||||
|
||||
m_arpDirectionLbl = new QLabel( tr( "DIRECTION:" ), m_arpGroupBox );
|
||||
m_arpDirectionLbl->setGeometry( 10, 70, 64, 8 );
|
||||
m_arpDirectionLbl->setFont( pointSize<6>( m_arpDirectionLbl->font() ) );
|
||||
|
||||
|
||||
/* m_arpOffBtn = new pixmapButton( m_arpGroupBox );
|
||||
m_arpOffBtn->move( 10, 87 );
|
||||
m_arpOffBtn->setActiveGraphic( embed::getIconPixmap( "arp_off_on" ) );
|
||||
m_arpOffBtn->setInactiveGraphic( embed::getIconPixmap(
|
||||
"arp_off_off" ) );
|
||||
#ifdef QT4
|
||||
m_arpOffBtn->setChecked( TRUE );
|
||||
#else
|
||||
m_arpOffBtn->setOn( TRUE );
|
||||
#endif
|
||||
#ifndef QT4
|
||||
m_arpOffBtn->setBackgroundMode( Qt::PaletteBackground );
|
||||
#endif
|
||||
#ifdef QT4
|
||||
m_arpOffBtn->setToolTip(
|
||||
#else
|
||||
toolTip::add( m_arpOffBtn,
|
||||
#endif
|
||||
tr( "arpeggio direction = none = no arpeggio" ) );
|
||||
connect( m_arpOffBtn, SIGNAL( toggled( bool ) ), this,
|
||||
SLOT( arpOffToggled( bool ) ) );*/
|
||||
|
||||
|
||||
m_arpUpBtn = new pixmapButton( m_arpGroupBox );
|
||||
m_arpUpBtn->move( 80, 70 );
|
||||
m_arpUpBtn->setActiveGraphic( embed::getIconPixmap( "arp_up_on" ) );
|
||||
m_arpUpBtn->setInactiveGraphic( embed::getIconPixmap( "arp_up_off" ) );
|
||||
#ifdef QT4
|
||||
m_arpUpBtn->setChecked( TRUE );
|
||||
#else
|
||||
m_arpUpBtn->setOn( TRUE );
|
||||
#endif
|
||||
#ifndef QT4
|
||||
m_arpUpBtn->setBackgroundMode( Qt::PaletteBackground );
|
||||
#endif
|
||||
toolTip::add( m_arpUpBtn, tr( "arpeggio direction = up" ) );
|
||||
connect( m_arpUpBtn, SIGNAL( toggled( bool ) ), this,
|
||||
SLOT( arpUpToggled( bool ) ) );
|
||||
|
||||
m_arpDownBtn = new pixmapButton( m_arpGroupBox );
|
||||
m_arpDownBtn->move( 100, 70 );
|
||||
m_arpDownBtn->setActiveGraphic( embed::getIconPixmap( "arp_down_on" ) );
|
||||
m_arpDownBtn->setInactiveGraphic( embed::getIconPixmap(
|
||||
"arp_down_off" ) );
|
||||
#ifndef QT4
|
||||
m_arpDownBtn->setBackgroundMode( Qt::PaletteBackground );
|
||||
#endif
|
||||
toolTip::add( m_arpDownBtn, tr( "arpeggio direction = down" ) );
|
||||
connect( m_arpDownBtn, SIGNAL( toggled( bool ) ), this,
|
||||
SLOT( arpDownToggled( bool ) ) );
|
||||
|
||||
m_arpUpAndDownBtn = new pixmapButton( m_arpGroupBox );
|
||||
m_arpUpAndDownBtn->move( 120, 70 );
|
||||
m_arpUpAndDownBtn->setActiveGraphic( embed::getIconPixmap(
|
||||
"arp_up_and_down_on" ) );
|
||||
m_arpUpAndDownBtn->setInactiveGraphic( embed::getIconPixmap(
|
||||
"arp_up_and_down_off" ) );
|
||||
#ifndef QT4
|
||||
m_arpUpAndDownBtn->setBackgroundMode( Qt::PaletteBackground );
|
||||
#endif
|
||||
toolTip::add( m_arpUpAndDownBtn,
|
||||
tr( "arpeggio direction = up and down" ) );
|
||||
connect( m_arpUpAndDownBtn, SIGNAL( toggled( bool ) ), this,
|
||||
SLOT( arpUpAndDownToggled( bool ) ) );
|
||||
|
||||
m_arpRandomBtn = new pixmapButton( m_arpGroupBox );
|
||||
m_arpRandomBtn->move( 140, 70 );
|
||||
m_arpRandomBtn->setActiveGraphic( embed::getIconPixmap(
|
||||
"arp_random_on" ) );
|
||||
m_arpRandomBtn->setInactiveGraphic( embed::getIconPixmap(
|
||||
"arp_random_off" ) );
|
||||
#ifndef QT4
|
||||
m_arpRandomBtn->setBackgroundMode( Qt::PaletteBackground );
|
||||
#endif
|
||||
toolTip::add( m_arpRandomBtn, tr( "arpeggio direction = random" ) );
|
||||
connect( m_arpRandomBtn, SIGNAL( toggled( bool ) ), this,
|
||||
SLOT( arpRandomToggled( bool ) ) );
|
||||
|
||||
QButtonGroup * m_arpDirections_group = new QButtonGroup( this );
|
||||
// m_arpDirections_group->addButton( m_arpOffBtn );
|
||||
m_arpDirections_group->addButton( m_arpUpBtn );
|
||||
m_arpDirections_group->addButton( m_arpDownBtn );
|
||||
m_arpDirections_group->addButton( m_arpUpAndDownBtn );
|
||||
m_arpDirections_group->addButton( m_arpRandomBtn );
|
||||
m_arpDirections_group->setExclusive( TRUE );
|
||||
#ifndef QT4
|
||||
m_arpDirections_group->hide();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
arpAndChordsTabWidget::~arpAndChordsTabWidget()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void arpAndChordsTabWidget::processNote( notePlayHandle * _n )
|
||||
{
|
||||
const int base_note_key = _n->key();
|
||||
// we add chord-subnotes to note if either note is a base-note and
|
||||
// arpeggio is not used or note is part of an arpeggio
|
||||
// at the same time we only add sub-notes if nothing of the note was
|
||||
// played yet, because otherwise we would add chord-subnotes every
|
||||
// time an audio-buffer is rendered...
|
||||
if( ( ( _n->baseNote() && m_arpGroupBox->isActive() == FALSE ) ||
|
||||
_n->arpNote() ) &&
|
||||
_n->totalFramesPlayed() == 0 &&
|
||||
m_chordsGroupBox->isActive() == TRUE )
|
||||
{
|
||||
// then insert sub-notes for chord
|
||||
#ifdef QT4
|
||||
const int selected_chord = m_chordsComboBox->currentIndex();
|
||||
#else
|
||||
const int selected_chord = m_chordsComboBox->currentItem();
|
||||
#endif
|
||||
for( int octave_cnt = 0;
|
||||
octave_cnt < m_chordRangeKnob->value(); ++octave_cnt )
|
||||
{
|
||||
const int sub_note_key_base = base_note_key +
|
||||
octave_cnt * NOTES_PER_OCTAVE;
|
||||
// if octave_cnt == 1 we're in the first octave and
|
||||
// the base-note is already done, so we don't have to
|
||||
// create it in the following loop, then we loop until
|
||||
// there's a -1 in the interval-array
|
||||
for( int i = ( octave_cnt == 0 ) ? 1 : 0;
|
||||
s_chords[selected_chord].interval[i] != -1;
|
||||
++i )
|
||||
{
|
||||
// add interval to sub-note-key
|
||||
const int sub_note_key = sub_note_key_base +
|
||||
(int) s_chords[
|
||||
selected_chord].interval[i];
|
||||
// maybe we're out of range -> let's get outta
|
||||
// here!
|
||||
if( sub_note_key > NOTES_PER_OCTAVE*OCTAVES )
|
||||
{
|
||||
break;
|
||||
}
|
||||
// create copy of base-note
|
||||
note note_copy( 0, 0, (tones)( sub_note_key %
|
||||
NOTES_PER_OCTAVE ),
|
||||
(octaves)( sub_note_key /
|
||||
NOTES_PER_OCTAVE ),
|
||||
_n->getVolume(),
|
||||
_n->getPanning() );
|
||||
// duplicate note-play-handle, only note is
|
||||
// different
|
||||
notePlayHandle * note_play_handle =
|
||||
new notePlayHandle(
|
||||
_n->getChannelTrack(),
|
||||
_n->framesAhead(),
|
||||
_n->frames(), ¬e_copy );
|
||||
// add sub-note to base-note, now all stuff is
|
||||
// done by notePlayHandle::play_note()
|
||||
_n->addSubNote( note_play_handle );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// now follows code for arpeggio
|
||||
|
||||
if( _n->baseNote() == FALSE || m_arpDirection == OFF ||
|
||||
!m_arpGroupBox->isActive() ||
|
||||
( _n->released() && _n->releaseFramesDone() >=
|
||||
_n->actualReleaseFramesToDo() ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
#ifdef QT4
|
||||
const int selected_arp = m_arpComboBox->currentIndex();
|
||||
#else
|
||||
const int selected_arp = m_arpComboBox->currentItem();
|
||||
#endif
|
||||
|
||||
const int cur_chord_size = getChordSize( s_chords[selected_arp] );
|
||||
const int total_range = (int)( cur_chord_size *
|
||||
m_arpRangeKnob->value() );
|
||||
// number of frames that every note should be played
|
||||
const Uint32 arp_frames = (Uint32)( m_arpTimeKnob->value() / 1000.0f *
|
||||
mixer::inst()->sampleRate() );
|
||||
const Uint32 gated_frames = (Uint32)( m_arpGateKnob->value() *
|
||||
arp_frames / 100.0f );
|
||||
// used for calculating remaining frames for arp-note, we have to add
|
||||
// arp_frames-1, otherwise the first arp-note will not be setup
|
||||
// correctly... -> arp_frames frames silence at the start of every note!
|
||||
int cur_frame = _n->totalFramesPlayed() + arp_frames - 1;
|
||||
// used for loop
|
||||
Uint32 frames_processed = 0;
|
||||
// len for all arp-notes (depending on arp-time)
|
||||
|
||||
while( frames_processed < mixer::inst()->framesPerAudioBuffer() )
|
||||
{
|
||||
const Uint32 remaining_frames_for_cur_arp = arp_frames -
|
||||
( cur_frame % arp_frames );
|
||||
// does current arp-note fill whole audio-buffer?
|
||||
if( remaining_frames_for_cur_arp >=
|
||||
mixer::inst()->framesPerAudioBuffer() )
|
||||
{
|
||||
// then we don't have to do something!
|
||||
break;
|
||||
}
|
||||
|
||||
frames_processed += remaining_frames_for_cur_arp;
|
||||
|
||||
// init with zero
|
||||
int cur_arp_idx = 0;
|
||||
|
||||
// process according to arpeggio-direction...
|
||||
if( m_arpDirection == UP )
|
||||
{
|
||||
cur_arp_idx = ( cur_frame / arp_frames ) % total_range;
|
||||
}
|
||||
else if( m_arpDirection == DOWN )
|
||||
{
|
||||
cur_arp_idx = total_range - ( cur_frame / arp_frames ) %
|
||||
total_range - 1;
|
||||
}
|
||||
else if( m_arpDirection == UP_AND_DOWN && total_range > 1 )
|
||||
{
|
||||
// imagine, we had to play the arp once up and then
|
||||
// once down -> makes 2 * total_range possible notes...
|
||||
// because we don't play the lower and upper notes
|
||||
// twice, we have to subtract 2
|
||||
cur_arp_idx = ( cur_frame / arp_frames ) %
|
||||
( total_range * 2 - 2 );
|
||||
// if greater than total_range, we have to play down...
|
||||
// looks like the code for arp_dir==DOWN... :)
|
||||
if( cur_arp_idx >= total_range )
|
||||
{
|
||||
cur_arp_idx = total_range - cur_arp_idx %
|
||||
( total_range - 1 ) - 1;
|
||||
}
|
||||
}
|
||||
else if( m_arpDirection == RANDOM )
|
||||
{
|
||||
// just pick a random chord-index
|
||||
cur_arp_idx = (int)( total_range * ( (float) rand() /
|
||||
(float) RAND_MAX ) );
|
||||
}
|
||||
|
||||
// now calculate final key for our arp-note
|
||||
const int sub_note_key = base_note_key + (cur_arp_idx /
|
||||
cur_chord_size ) *
|
||||
NOTES_PER_OCTAVE +
|
||||
s_chords[selected_arp].interval[cur_arp_idx % cur_chord_size];
|
||||
|
||||
// range-checking
|
||||
if( sub_note_key >= NOTES_PER_OCTAVE * OCTAVES ||
|
||||
sub_note_key < 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
float vol_level = 1.0f;
|
||||
if( _n->released() )
|
||||
{
|
||||
vol_level = _n->volumeLevel( cur_frame + gated_frames );
|
||||
}
|
||||
|
||||
// create new arp-note
|
||||
note new_note( midiTime( 0 ), midiTime( 0 ),
|
||||
static_cast<tones>( sub_note_key %
|
||||
NOTES_PER_OCTAVE ),
|
||||
static_cast<octaves>( sub_note_key /
|
||||
NOTES_PER_OCTAVE ),
|
||||
static_cast<volume>( _n->getVolume() *
|
||||
vol_level ),
|
||||
_n->getPanning() );
|
||||
|
||||
// duplicate note-play-handle, only ptr to note is different
|
||||
// and is_arp_note=TRUE
|
||||
notePlayHandle * note_play_handle = new notePlayHandle(
|
||||
_n->getChannelTrack(),
|
||||
_n->framesAhead() +
|
||||
frames_processed,
|
||||
gated_frames,
|
||||
&new_note,
|
||||
TRUE );
|
||||
|
||||
// add sub-note to base-note, now all stuff is done by
|
||||
// notePlayHandle::play_note()
|
||||
_n->addSubNote( note_play_handle );
|
||||
|
||||
// update counters
|
||||
frames_processed += arp_frames;
|
||||
cur_frame += arp_frames;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void arpAndChordsTabWidget::saveSettings( QDomDocument & _doc,
|
||||
QDomElement & _parent )
|
||||
{
|
||||
QDomElement elw_de = _doc.createElement( nodeName() );
|
||||
elw_de.setAttribute( "chorddisabled", QString::number(
|
||||
!m_chordsGroupBox->isActive() ) );
|
||||
#ifdef QT4
|
||||
elw_de.setAttribute( "chord", QString::number(
|
||||
m_chordsComboBox->currentIndex() ) );
|
||||
#else
|
||||
elw_de.setAttribute( "chord", QString::number(
|
||||
m_chordsComboBox->currentItem() ) );
|
||||
#endif
|
||||
elw_de.setAttribute( "chordrange", QString::number(
|
||||
m_chordRangeKnob->value() ) );
|
||||
|
||||
elw_de.setAttribute( "arpdisabled", QString::number(
|
||||
!m_arpGroupBox->isActive() ) );
|
||||
#ifdef QT4
|
||||
elw_de.setAttribute( "arp", QString::number(
|
||||
m_arpComboBox->currentIndex() ) );
|
||||
#else
|
||||
elw_de.setAttribute( "arp", QString::number(
|
||||
m_arpComboBox->currentItem() ) );
|
||||
#endif
|
||||
elw_de.setAttribute( "arprange", QString::number(
|
||||
m_arpRangeKnob->value() ) );
|
||||
elw_de.setAttribute( "arptime", QString::number(
|
||||
m_arpTimeKnob->value() ) );
|
||||
elw_de.setAttribute( "arpgate", QString::number(
|
||||
m_arpGateKnob->value() ) );
|
||||
elw_de.setAttribute( "arpdir", QString::number(
|
||||
m_arpDirection ) );
|
||||
|
||||
_parent.appendChild( elw_de );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void arpAndChordsTabWidget::loadSettings( const QDomElement & _this )
|
||||
{
|
||||
m_chordsGroupBox->setState( !_this.attribute
|
||||
( "chorddisabled" ).toInt() );
|
||||
#ifdef QT4
|
||||
m_chordsComboBox->setCurrentIndex( _this.attribute( "chord" ).toInt() );
|
||||
#else
|
||||
m_chordsComboBox->setCurrentItem( _this.attribute( "chord" ).toInt() );
|
||||
#endif
|
||||
m_chordRangeKnob->setValue( _this.attribute( "chordrange" ).toFloat() );
|
||||
#ifdef QT4
|
||||
m_arpComboBox->setCurrentIndex( _this.attribute( "arp" ).toInt() );
|
||||
#else
|
||||
m_arpComboBox->setCurrentItem( _this.attribute( "arp" ).toInt() );
|
||||
#endif
|
||||
m_arpRangeKnob->setValue( _this.attribute( "arprange" ).toFloat() );
|
||||
m_arpTimeKnob->setValue( _this.attribute( "arptime" ).toFloat() );
|
||||
m_arpGateKnob->setValue( _this.attribute( "arpgate" ).toFloat() );
|
||||
m_arpDirection = static_cast<arpDirections>(
|
||||
_this.attribute( "arpdir" ).toInt() );
|
||||
|
||||
m_arpGroupBox->setState( m_arpDirection != OFF &&
|
||||
!_this.attribute( "arpdisabled" ).toInt() );
|
||||
switch( m_arpDirection )
|
||||
{
|
||||
case DOWN:
|
||||
m_arpDownBtn->setChecked( TRUE );
|
||||
break;
|
||||
case UP_AND_DOWN:
|
||||
m_arpUpAndDownBtn->setChecked( TRUE );
|
||||
break;
|
||||
case RANDOM:
|
||||
m_arpRandomBtn->setChecked( TRUE );
|
||||
break;
|
||||
case UP:
|
||||
default:
|
||||
m_arpUpBtn->setChecked( TRUE );
|
||||
m_arpDirection = UP;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void arpAndChordsTabWidget::arpUpToggled( bool _on )
|
||||
{
|
||||
if( _on )
|
||||
{
|
||||
m_arpDirection = UP;
|
||||
}
|
||||
songEditor::inst()->setModified();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void arpAndChordsTabWidget::arpDownToggled( bool _on )
|
||||
{
|
||||
if( _on )
|
||||
{
|
||||
m_arpDirection = DOWN;
|
||||
}
|
||||
songEditor::inst()->setModified();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void arpAndChordsTabWidget::arpUpAndDownToggled( bool _on )
|
||||
{
|
||||
if( _on )
|
||||
{
|
||||
m_arpDirection = UP_AND_DOWN;
|
||||
}
|
||||
songEditor::inst()->setModified();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void arpAndChordsTabWidget::arpRandomToggled( bool _on )
|
||||
{
|
||||
if( _on )
|
||||
{
|
||||
m_arpDirection = RANDOM;
|
||||
}
|
||||
songEditor::inst()->setModified();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#undef setChecked
|
||||
|
||||
#include "arp_and_chords_tab_widget.moc"
|
||||
|
||||
457
src/core/bb_editor.cpp
Normal file
457
src/core/bb_editor.cpp
Normal file
@@ -0,0 +1,457 @@
|
||||
/*
|
||||
* bb_editor.cpp - basic main-window for editing of beats and basslines
|
||||
*
|
||||
* Linux MultiMedia Studio
|
||||
* Copyright (c) 2004-2005 Tobias Doerffel <tobydox@users.sourceforge.net>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "qt3support.h"
|
||||
|
||||
#ifdef QT4
|
||||
|
||||
#include <QPainter>
|
||||
#include <QKeyEvent>
|
||||
#include <QCloseEvent>
|
||||
|
||||
#else
|
||||
|
||||
#include <qpainter.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "bb_editor.h"
|
||||
#include "song_editor.h"
|
||||
#include "embed.h"
|
||||
#include "pixmap_button.h"
|
||||
#include "track_container.h"
|
||||
#include "bb_track.h"
|
||||
#include "name_label.h"
|
||||
#include "templates.h"
|
||||
#include "debug.h"
|
||||
#include "spc_bg_hndl_widget.h"
|
||||
#include "tooltip.h"
|
||||
|
||||
|
||||
|
||||
const int BBE_PPT = 192;
|
||||
|
||||
|
||||
|
||||
bbEditor * bbEditor::s_instanceOfMe = NULL;
|
||||
QPixmap * bbEditor::s_titleArtwork = NULL;
|
||||
|
||||
|
||||
|
||||
bbEditor::bbEditor() :
|
||||
trackContainer()
|
||||
{
|
||||
setWindowIcon( embed::getIconPixmap( "bb_track" ) );
|
||||
setWindowTitle( tr( "Beat+Bassline Editor" ) );
|
||||
setMinimumWidth( TRACK_OP_WIDTH + DEFAULT_SETTINGS_WIDGET_WIDTH +
|
||||
BBE_PPT + 2 * TCO_BORDER_WIDTH );
|
||||
setGeometry( 10, 340, minimumWidth(), 300 );
|
||||
show();
|
||||
|
||||
if( s_titleArtwork == NULL )
|
||||
{
|
||||
s_titleArtwork = new QPixmap( embed::getIconPixmap(
|
||||
"bb_editor_title_artwork" ) );
|
||||
}
|
||||
|
||||
containerWidget()->move( 0, 47 );
|
||||
setPixelsPerTact( BBE_PPT );
|
||||
updateBackground();
|
||||
|
||||
m_playButton = new pixmapButton( this );
|
||||
m_playButton->move( 96, 7 );
|
||||
m_playButton->setCheckable( FALSE );
|
||||
m_playButton->setActiveGraphic( embed::getIconPixmap( "play" ) );
|
||||
m_playButton->setInactiveGraphic( embed::getIconPixmap( "play" ) );
|
||||
m_playButton->setBgGraphic( specialBgHandlingWidget::getBackground(
|
||||
m_playButton ) );
|
||||
connect( m_playButton, SIGNAL( clicked() ), this, SLOT( play() ) );
|
||||
|
||||
m_stopButton = new pixmapButton( this );
|
||||
m_stopButton->move( 136, 7 );
|
||||
m_stopButton->setCheckable( FALSE );
|
||||
m_stopButton->setActiveGraphic( embed::getIconPixmap( "stop" ) );
|
||||
m_stopButton->setInactiveGraphic( embed::getIconPixmap( "stop" ) );
|
||||
m_stopButton->setBgGraphic( specialBgHandlingWidget::getBackground(
|
||||
m_playButton ) );
|
||||
connect( m_stopButton, SIGNAL( clicked() ), this, SLOT( stop() ) );
|
||||
|
||||
|
||||
toolTip::add( m_playButton,
|
||||
tr( "Play/pause current beat/bassline (Space)" ) );
|
||||
toolTip::add( m_stopButton,
|
||||
tr( "Stop playing of current beat/bassline (Space)" ) );
|
||||
#ifdef QT4
|
||||
m_playButton->setWhatsThis(
|
||||
#else
|
||||
QWhatsThis::add( m_playButton,
|
||||
#endif
|
||||
tr( "Click here, if you want to play the current "
|
||||
"beat/bassline. The beat/bassline is automatically "
|
||||
"looped when its end is reached." ) );
|
||||
#ifdef QT4
|
||||
m_stopButton->setWhatsThis(
|
||||
#else
|
||||
QWhatsThis::add( m_stopButton,
|
||||
#endif
|
||||
tr( "Click here, if you want to stop playing of current "
|
||||
"beat/bassline." ) );
|
||||
|
||||
#ifndef QT4
|
||||
setBackgroundMode( Qt::NoBackground );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bbEditor::~bbEditor()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
csize bbEditor::currentBB( void ) const
|
||||
{
|
||||
return( static_cast<csize>( currentPosition().getTact() ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbEditor::setCurrentBB( csize _bb )
|
||||
{
|
||||
// first make sure, all channels have a TCO at current BB
|
||||
createTCOsForBB( _bb );
|
||||
|
||||
realignTracks();
|
||||
|
||||
// now update all track-labels (the current one has to become white,
|
||||
// the others green)
|
||||
for( csize i = 0; i < bbEditor::inst()->numOfBBs(); ++i )
|
||||
{
|
||||
bbTrack::findBBTrack( i )->trackLabel()->update();
|
||||
}
|
||||
|
||||
emit positionChanged( m_currentPosition = midiTime( _bb, 0 ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
tact bbEditor::lengthOfBB( csize _bb )
|
||||
{
|
||||
midiTime max_length;
|
||||
|
||||
trackVector tv = tracks();
|
||||
for( trackVector::iterator it = tv.begin(); it != tv.end(); ++it )
|
||||
{
|
||||
trackContentObject * tco = ( *it )->getTCO( _bb );
|
||||
#ifdef LMMS_DEBUG
|
||||
assert( tco != NULL );
|
||||
#endif
|
||||
max_length = tMax( max_length, tco->length() );
|
||||
}
|
||||
if( max_length.getTact64th() == 0 )
|
||||
{
|
||||
return( max_length.getTact() );
|
||||
}
|
||||
|
||||
return( max_length.getTact() + 1 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool FASTCALL bbEditor::play( midiTime _start, Uint32 _start_frame,
|
||||
Uint32 _frames, Uint32 _frame_base,
|
||||
Sint16 _tco_num )
|
||||
{
|
||||
bool played_a_note = FALSE;
|
||||
if( lengthOfBB( _tco_num ) <= 0 )
|
||||
{
|
||||
return( played_a_note );
|
||||
}
|
||||
|
||||
_start = ( _start.getTact() % lengthOfBB( _tco_num ) ) * 64 +
|
||||
_start.getTact64th();
|
||||
trackVector tv = tracks();
|
||||
for( trackVector::iterator it = tv.begin(); it != tv.end(); ++it )
|
||||
{
|
||||
if( ( *it )->play( _start, _start_frame, _frames, _frame_base,
|
||||
_tco_num ) == TRUE )
|
||||
{
|
||||
played_a_note = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return( played_a_note );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
csize bbEditor::numOfBBs( void ) const
|
||||
{
|
||||
return( songEditor::inst()->countTracks( track::BB_TRACK ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbEditor::removeBB( csize _bb )
|
||||
{
|
||||
trackVector tv = tracks();
|
||||
for( trackVector::iterator it = tv.begin(); it != tv.end(); ++it )
|
||||
{
|
||||
( *it )->removeTCO( _bb );
|
||||
( *it )->getTrackContentWidget()->removeTact( _bb * 64 );
|
||||
}
|
||||
/* if( _bb == currentBB() && numOfBBs() > 0 )
|
||||
{*/
|
||||
if( _bb > 0)
|
||||
{
|
||||
setCurrentBB( _bb - 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
setCurrentBB( 0 );
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
|
||||
// close-handler for bb-editor-window because closing of bb-editor isn't allowed
|
||||
// instead of closing it's being hidden
|
||||
void bbEditor::closeEvent( QCloseEvent * _ce )
|
||||
{
|
||||
_ce->ignore();
|
||||
hide();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*void bbEditor::paintEvent( QPaintEvent * )
|
||||
{
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
|
||||
void bbEditor::keyPressEvent( QKeyEvent * _ke )
|
||||
{
|
||||
if ( _ke->key() == Qt::Key_Space )
|
||||
{
|
||||
if( songEditor::inst()->playing() )
|
||||
{
|
||||
stop ();
|
||||
}
|
||||
else
|
||||
{
|
||||
play ();
|
||||
}
|
||||
}
|
||||
else if ( _ke->key() == Qt::Key_Plus )
|
||||
{
|
||||
if( currentBB() + 1 < numOfBBs() )
|
||||
{
|
||||
setCurrentBB( currentBB() + 1 );
|
||||
}
|
||||
}
|
||||
else if ( _ke->key() == Qt::Key_Minus )
|
||||
{
|
||||
if( currentBB() > 0 )
|
||||
{
|
||||
setCurrentBB( currentBB() - 1 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// ignore event and pass to parent-widget
|
||||
_ke->ignore();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbEditor::wheelEvent( QWheelEvent * _we )
|
||||
{
|
||||
lmmsMainWin::inst()->workspace()->wheelEvent( _we );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbEditor::resizeEvent( QResizeEvent * _re )
|
||||
{
|
||||
updateBackground();
|
||||
setPixelsPerTact( width() - ( TRACK_OP_WIDTH +
|
||||
DEFAULT_SETTINGS_WIDGET_WIDTH + 2 *
|
||||
TCO_BORDER_WIDTH ) );
|
||||
trackContainer::resizeEvent( _re );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbEditor::updateBackground( void )
|
||||
{
|
||||
QPixmap draw_pm( size() );
|
||||
#ifdef QT4
|
||||
draw_pm.fill( containerWidget()->palette().brush(
|
||||
containerWidget()->backgroundRole() ).color() );
|
||||
#else
|
||||
draw_pm.fill( containerWidget()->paletteBackgroundColor() );
|
||||
#endif
|
||||
|
||||
QPainter p( &draw_pm );
|
||||
|
||||
p.fillRect( 0, 0, width(), s_titleArtwork->height(),
|
||||
QColor( 74, 125, 213 ) );
|
||||
p.drawPixmap( 0, 0, *s_titleArtwork );
|
||||
#ifdef QT4
|
||||
QPalette pal = palette();
|
||||
pal.setBrush( backgroundRole(), QBrush( draw_pm ) );
|
||||
setPalette( pal );
|
||||
#else
|
||||
setErasePixmap( draw_pm );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
void bbEditor::play( void )
|
||||
{
|
||||
if( songEditor::inst()->playing() )
|
||||
{
|
||||
if( songEditor::inst()->playMode() != songEditor::PLAY_BB )
|
||||
{
|
||||
songEditor::inst()->stop();
|
||||
songEditor::inst()->playBB();
|
||||
m_playButton->setInactiveGraphic(
|
||||
embed::getIconPixmap( "pause" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
songEditor::inst()->pause();
|
||||
m_playButton->setInactiveGraphic(
|
||||
embed::getIconPixmap("play") );
|
||||
}
|
||||
}
|
||||
else if( songEditor::inst()->paused() )
|
||||
{
|
||||
songEditor::inst()->resumeFromPause();
|
||||
m_playButton->setInactiveGraphic(
|
||||
embed::getIconPixmap( "pause" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_playButton->setInactiveGraphic(
|
||||
embed::getIconPixmap( "pause" ) );
|
||||
songEditor::inst()->playBB();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbEditor::stop( void )
|
||||
{
|
||||
songEditor::inst()->stop();
|
||||
m_playButton->setInactiveGraphic( embed::getIconPixmap( "play" ) );
|
||||
m_playButton->update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void bbEditor::saveSettings( QDomDocument & _doc, QDomElement & _parent )
|
||||
{
|
||||
trackContainer::saveSettings( _doc, _parent );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbEditor::loadSettings( const QDomElement & _this )
|
||||
{
|
||||
trackContainer::loadSettings( _this );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbEditor::updateAfterTrackAdd( void )
|
||||
{
|
||||
// make sure, new track(s) have TCOs for every beat/bassline
|
||||
for( csize i = 0; i < tMax<csize>( 1, numOfBBs() ); ++i )
|
||||
{
|
||||
createTCOsForBB( i );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbEditor::createTCOsForBB( csize _bb )
|
||||
{
|
||||
trackVector tv = tracks();
|
||||
for( trackVector::iterator it = tv.begin(); it != tv.end(); ++it )
|
||||
{
|
||||
while( ( *it )->numOfTCOs() < _bb+1 )
|
||||
{
|
||||
midiTime position = midiTime( ( *it )->numOfTCOs(), 0 );
|
||||
trackContentObject * tco = ( *it )->addTCO(
|
||||
( *it )->createTCO( position ) );
|
||||
tco->movePosition( position );
|
||||
tco->changeLength( midiTime( 1, 0 ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbEditor::swapBB( csize _bb1, csize _bb2 )
|
||||
{
|
||||
trackVector tv = tracks();
|
||||
for( trackVector::iterator it = tv.begin(); it != tv.end(); ++it )
|
||||
{
|
||||
( *it )->swapPositionOfTCOs( _bb1, _bb2 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#include "bb_editor.moc"
|
||||
|
||||
884
src/core/config_mgr.cpp
Normal file
884
src/core/config_mgr.cpp
Normal file
@@ -0,0 +1,884 @@
|
||||
/*
|
||||
* config_mgr.cpp - implementation of class configManager
|
||||
*
|
||||
* Linux MultiMedia Studio
|
||||
* Copyright (c) 2004-2005 Tobias Doerffel <tobydox@users.sourceforge.net>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "qt3support.h"
|
||||
|
||||
#ifdef QT4
|
||||
|
||||
#include <QDir>
|
||||
#include <Qt/QtXml>
|
||||
#include <QFile>
|
||||
#include <QMessageBox>
|
||||
#include <QLabel>
|
||||
#include <QLayout>
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
#include <QFileDialog>
|
||||
#include <QRadioButton>
|
||||
#include <QButtonGroup>
|
||||
#include <QApplication>
|
||||
|
||||
#else
|
||||
|
||||
#include <qdir.h>
|
||||
#include <qdom.h>
|
||||
#include <qfile.h>
|
||||
#include <qmessagebox.h>
|
||||
#include <qlabel.h>
|
||||
#include <qlayout.h>
|
||||
#include <qlineedit.h>
|
||||
#include <qpushbutton.h>
|
||||
#include <qfiledialog.h>
|
||||
#include <qbuttongroup.h>
|
||||
#include <qradiobutton.h>
|
||||
#include <qapplication.h>
|
||||
|
||||
#ifndef __USE_XOPEN_EXTENDED
|
||||
#define __USE_XOPEN_EXTENDED
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "config_mgr.h"
|
||||
#include "embed.h"
|
||||
#include "templates.h"
|
||||
|
||||
|
||||
|
||||
void mkPath( const QString & _path )
|
||||
{
|
||||
#ifdef QT4
|
||||
// simple clean solution with Qt4...
|
||||
QDir().mkpath( _path );
|
||||
#else
|
||||
// ...but Qt3 needs additional code...
|
||||
QDir d( _path );
|
||||
vlist<QString> dirs;
|
||||
dirs.push_front( _path );
|
||||
QString dir = _path;
|
||||
while( !QDir( dir ).exists() )
|
||||
{
|
||||
dir = dir.section( '/', 0, -2 );
|
||||
dirs.push_front( dir );
|
||||
}
|
||||
while( !dirs.isEmpty() )
|
||||
{
|
||||
d.mkdir( dirs.front() );
|
||||
d.setPath( dirs.front() );
|
||||
dirs.erase( dirs.begin() );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void linkFile( const QString & _src, const QString & _dst )
|
||||
{
|
||||
#ifdef QT4
|
||||
// simple clean solution with Qt4...
|
||||
QFile::link( _src, _dst );
|
||||
#else
|
||||
// ...but Qt3 needs additional (unportable) code...
|
||||
symlink( _src.ascii(), _dst.ascii() );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void copyFile( const QString & _src, const QString & _dst )
|
||||
{
|
||||
#ifdef QT4
|
||||
// simple clean solution with Qt4...
|
||||
QFile::copy( _src, _dst );
|
||||
#else
|
||||
// ...but Qt3 needs additional code...
|
||||
QFile in( _src );
|
||||
QFile out( _dst );
|
||||
in.open( IO_ReadOnly );
|
||||
out.open( IO_WriteOnly );
|
||||
char buffer[1024];
|
||||
while( !in.atEnd() )
|
||||
{
|
||||
Q_LONG read = in.readBlock( buffer, 1024 );
|
||||
if( read == -1 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
if( out.writeBlock( buffer, read ) == -1 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
configManager * configManager::s_instanceOfMe = NULL;
|
||||
|
||||
|
||||
configManager::configManager( void ) :
|
||||
QDialog(),
|
||||
#ifdef QT4
|
||||
m_lmmsRcFile( QDir::home().absolutePath() + "/.lmmsrc.xml" ),
|
||||
m_lmmsWorkingDir( QDir::home().absolutePath() + "/lmms" ),
|
||||
#else
|
||||
m_lmmsRcFile( QDir::home().absPath() + "/.lmmsrc.xml" ),
|
||||
m_lmmsWorkingDir( QDir::home().absPath() + "/lmms" ),
|
||||
#endif
|
||||
#if QT_VERSION >= 0x030200
|
||||
m_lmmsDataDir( qApp->applicationDirPath().section( '/', 0, -2 ) +
|
||||
"/share/lmms/" ),
|
||||
#else
|
||||
// hardcode since qt 3.0 doesn't know something like
|
||||
// applicationDirPath and implmeneting own function would be senseless
|
||||
// since real support for qt 3.0 is senseless too ;-)
|
||||
m_lmmsDataDir( "/usr/share/lmms" ),
|
||||
#endif
|
||||
m_currentPage( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
configManager::~configManager()
|
||||
{
|
||||
saveConfigFile();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void configManager::createWidgets( void )
|
||||
{
|
||||
m_mainLayout = new QHBoxLayout( this );
|
||||
m_mainLayout->setSpacing( 10 );
|
||||
m_mainLayout->addSpacing( 8 );
|
||||
#ifdef QT4
|
||||
setLayout( m_mainLayout );
|
||||
#endif
|
||||
|
||||
m_contentWidget = new QWidget( this );
|
||||
m_contentLayout = new QVBoxLayout( m_contentWidget );
|
||||
m_contentLayout->setSpacing( 10 );
|
||||
m_contentLayout->addSpacing( 8 );
|
||||
#ifdef QT4
|
||||
m_contentWidget->setLayout( m_contentLayout );
|
||||
#endif
|
||||
m_mainLayout->addWidget( m_contentWidget );
|
||||
m_mainLayout->addSpacing( 8 );
|
||||
|
||||
// wizard-init
|
||||
m_hbar = new QFrame( m_contentWidget );
|
||||
m_hbar->setFrameStyle( QFrame::Sunken + QFrame::HLine );
|
||||
m_hbar->setFixedHeight( 4 );
|
||||
m_title = new QLabel( m_contentWidget );
|
||||
m_title->setFixedHeight( 16 );
|
||||
QFont f = m_title->font();
|
||||
f.setBold( TRUE );
|
||||
m_title->setFont( pointSize<12>( f ) );
|
||||
|
||||
|
||||
QWidget * button_widget = new QWidget( m_contentWidget );
|
||||
m_buttonLayout = new QHBoxLayout( button_widget );
|
||||
m_buttonLayout->addStretch( 1 );
|
||||
|
||||
m_cancelButton = new QPushButton( tr( "&Cancel" ), button_widget );
|
||||
m_backButton = new QPushButton( tr( "< &Back" ), button_widget );
|
||||
m_nextButton = new QPushButton( tr( "&Next >" ), button_widget );
|
||||
m_finishButton = new QPushButton( tr( "&Finish" ), button_widget );
|
||||
|
||||
connect( m_cancelButton, SIGNAL( clicked() ), this, SLOT( reject() ) );
|
||||
connect( m_backButton, SIGNAL( clicked() ), this,
|
||||
SLOT( backButtonClicked() ) );
|
||||
connect( m_nextButton, SIGNAL( clicked() ), this,
|
||||
SLOT( nextButtonClicked() ) );
|
||||
connect( m_finishButton, SIGNAL( clicked() ), this,
|
||||
SLOT( accept() ) );
|
||||
m_buttonLayout->addWidget( m_cancelButton );
|
||||
m_buttonLayout->addWidget( m_backButton );
|
||||
m_buttonLayout->addWidget( m_nextButton );
|
||||
m_buttonLayout->addWidget( m_finishButton );
|
||||
m_buttonLayout->addSpacing( 15 );
|
||||
|
||||
m_contentLayout->addWidget( m_title );
|
||||
m_contentLayout->addWidget( m_hbar );
|
||||
m_contentLayout->addWidget( button_widget );
|
||||
m_contentLayout->addSpacing( 8 );
|
||||
|
||||
// wizard-setup
|
||||
setWindowTitle( tr( "Setup LMMS" ) );
|
||||
setWindowIcon( embed::getIconPixmap( "wizard" ) );
|
||||
|
||||
m_pageIntro = new QWidget( m_contentWidget );
|
||||
QHBoxLayout * intro_layout = new QHBoxLayout( m_pageIntro );
|
||||
intro_layout->setSpacing( 15 );
|
||||
|
||||
QLabel * intro_logo_lbl = new QLabel( m_pageIntro );
|
||||
intro_logo_lbl->setPixmap( embed::getIconPixmap( "wizard_intro" ) );
|
||||
intro_logo_lbl->setFrameStyle( QFrame::Panel | QFrame::Sunken );
|
||||
intro_logo_lbl->setFixedSize( 240, 300 );
|
||||
|
||||
QLabel * intro_txt_lbl = new QLabel( tr( "LMMS needs to be setup in "
|
||||
"order to run properly. "
|
||||
"This wizard will help you to "
|
||||
"setup your personal LMMS-"
|
||||
"installation.\n\n"
|
||||
"If you're unsure what to do "
|
||||
"at a step, just click on "
|
||||
"'Next'. LMMS will "
|
||||
"automatically select the best "
|
||||
"options for you.\n\n\n"
|
||||
"Now click on 'Next' to get to "
|
||||
"the next page." ),
|
||||
m_pageIntro );
|
||||
#ifdef QT4
|
||||
intro_txt_lbl->setWordWrap( TRUE );
|
||||
#else
|
||||
intro_txt_lbl->setAlignment( intro_txt_lbl->alignment() | WordBreak );
|
||||
#endif
|
||||
|
||||
intro_layout->addWidget( intro_logo_lbl );
|
||||
intro_layout->addWidget( intro_txt_lbl );
|
||||
|
||||
|
||||
m_pageWorkingDir = new QWidget( m_contentWidget );
|
||||
QHBoxLayout * workingdir_layout = new QHBoxLayout( m_pageWorkingDir );
|
||||
workingdir_layout->setSpacing( 15 );
|
||||
|
||||
QLabel * workingdir_logo_lbl = new QLabel( m_pageWorkingDir );
|
||||
workingdir_logo_lbl->setPixmap( embed::getIconPixmap(
|
||||
"wizard_workingdir" ) );
|
||||
workingdir_logo_lbl->setFrameStyle( QFrame::Panel | QFrame::Sunken );
|
||||
workingdir_logo_lbl->setFixedSize( 240, 300 );
|
||||
|
||||
QWidget * workingdir_content = new QWidget( m_pageWorkingDir );
|
||||
QVBoxLayout * workingdir_content_layout = new QVBoxLayout(
|
||||
workingdir_content );
|
||||
|
||||
QLabel * workingdir_txt_lbl = new QLabel(
|
||||
tr( "When working with LMMS there needs to "
|
||||
"be a working-directory.\nThis "
|
||||
"directory is used for storing your "
|
||||
"projects, presets, samples etc.\n\n\n"
|
||||
"Please select a directory:" ),
|
||||
workingdir_content );
|
||||
#ifdef QT4
|
||||
workingdir_txt_lbl->setWordWrap( TRUE );
|
||||
#else
|
||||
workingdir_txt_lbl->setAlignment( workingdir_txt_lbl->alignment() |
|
||||
WordBreak );
|
||||
#endif
|
||||
|
||||
QWidget * workingdir_input_fields = new QWidget( workingdir_content );
|
||||
QHBoxLayout * workingdir_input_fields_layout = new QHBoxLayout(
|
||||
workingdir_input_fields );
|
||||
workingdir_input_fields_layout->setSpacing( 10 );
|
||||
|
||||
m_wdLineEdit = new QLineEdit( m_lmmsWorkingDir,
|
||||
workingdir_input_fields );
|
||||
connect( m_wdLineEdit, SIGNAL( textChanged( const QString & ) ), this,
|
||||
SLOT( setWorkingDir( const QString & ) ) );
|
||||
|
||||
QPushButton * workingdir_select_btn = new QPushButton(
|
||||
embed::getIconPixmap( "project_open" ), "",
|
||||
workingdir_input_fields );
|
||||
workingdir_select_btn->setFixedSize( 24, 24 );
|
||||
connect( workingdir_select_btn, SIGNAL( clicked() ), this,
|
||||
SLOT( openWorkingDir() ) );
|
||||
|
||||
workingdir_input_fields_layout->addWidget( m_wdLineEdit );
|
||||
workingdir_input_fields_layout->addWidget( workingdir_select_btn );
|
||||
|
||||
workingdir_content_layout->addWidget( workingdir_txt_lbl );
|
||||
workingdir_content_layout->addWidget( workingdir_input_fields );
|
||||
|
||||
workingdir_layout->addWidget( workingdir_logo_lbl );
|
||||
workingdir_layout->addWidget( workingdir_content );
|
||||
|
||||
|
||||
|
||||
// page for files-management
|
||||
m_pageFiles = new QWidget( m_contentWidget );
|
||||
QHBoxLayout * files_layout = new QHBoxLayout( m_pageFiles );
|
||||
files_layout->setSpacing( 15 );
|
||||
|
||||
QWidget * files_content = new QWidget( m_pageFiles );
|
||||
QVBoxLayout * files_content_layout = new QVBoxLayout( files_content );
|
||||
files_content_layout->setSpacing( 10 );
|
||||
|
||||
QLabel * files_logo_lbl = new QLabel( m_pageFiles );
|
||||
files_logo_lbl->setPixmap( embed::getIconPixmap( "wizard_files" ) );
|
||||
files_logo_lbl->setFrameStyle( QFrame::Panel | QFrame::Sunken );
|
||||
files_logo_lbl->setFixedSize( 240, 300 );
|
||||
|
||||
QLabel * files_txt_lbl = new QLabel(
|
||||
tr( "For using the ready presets and samples of "
|
||||
"LMMS and enjoying the demo-songs the "
|
||||
"according files have to be copied or "
|
||||
"linked into your LMMS-working-"
|
||||
"directory.\nWhen copying files, you "
|
||||
"can modify them, but they need "
|
||||
"additional space in your working-"
|
||||
"directory. If you link files, you "
|
||||
"cannot modify them, but they need "
|
||||
"no extra space. So it's recommended "
|
||||
"to copy presets and demo-projects "
|
||||
"and link samples, which are bigger "
|
||||
"in size.\n" ), files_content );
|
||||
#ifdef QT4
|
||||
files_txt_lbl->setWordWrap( TRUE );
|
||||
#else
|
||||
files_txt_lbl->setAlignment( files_txt_lbl->alignment() | WordBreak );
|
||||
#endif
|
||||
|
||||
|
||||
QWidget * samples_widget = new QWidget( files_content );
|
||||
QHBoxLayout * samples_layout = new QHBoxLayout( samples_widget );
|
||||
samples_layout->setSpacing( 5 );
|
||||
QLabel * samples_pic_lbl = new QLabel( samples_widget );
|
||||
samples_pic_lbl->setPixmap( embed::getIconPixmap( "sound_file" ) );
|
||||
QLabel * samples_txt_lbl = new QLabel( tr( "samples:" ),
|
||||
samples_widget );
|
||||
samples_txt_lbl->setFixedWidth( 144 );
|
||||
|
||||
QButtonGroup * samples_bg = new QButtonGroup( samples_widget );
|
||||
#ifndef QT4
|
||||
samples_bg->hide();
|
||||
#endif
|
||||
m_samplesCopyRB = new QRadioButton( tr( "copy" ), samples_widget );
|
||||
QRadioButton * samples_link_rb = new QRadioButton( tr( "link" ),
|
||||
samples_widget );
|
||||
samples_link_rb->setChecked( TRUE );
|
||||
samples_bg->addButton( m_samplesCopyRB );
|
||||
samples_bg->addButton( samples_link_rb );
|
||||
|
||||
samples_layout->addWidget( samples_pic_lbl );
|
||||
samples_layout->addWidget( samples_txt_lbl );
|
||||
samples_layout->addWidget( m_samplesCopyRB );
|
||||
samples_layout->addSpacing( 15 );
|
||||
samples_layout->addWidget( samples_link_rb );
|
||||
samples_layout->addStretch( 400 );
|
||||
|
||||
|
||||
|
||||
QWidget * presets_widget = new QWidget( files_content );
|
||||
QHBoxLayout * presets_layout = new QHBoxLayout( presets_widget );
|
||||
presets_layout->setSpacing( 5 );
|
||||
QLabel * presets_pic_lbl = new QLabel( presets_widget );
|
||||
presets_pic_lbl->setPixmap( embed::getIconPixmap( "preset_file" ) );
|
||||
QLabel * presets_txt_lbl = new QLabel( tr( "presets:" ),
|
||||
presets_widget );
|
||||
presets_txt_lbl->setFixedWidth( 144 );
|
||||
|
||||
QButtonGroup * presets_bg = new QButtonGroup( presets_widget );
|
||||
#ifndef QT4
|
||||
presets_bg->hide();
|
||||
#endif
|
||||
m_presetsCopyRB = new QRadioButton( tr( "copy" ), presets_widget );
|
||||
m_presetsCopyRB->setChecked( TRUE );
|
||||
QRadioButton * presets_link_rb = new QRadioButton( tr( "link" ),
|
||||
presets_widget );
|
||||
presets_bg->addButton( m_presetsCopyRB );
|
||||
presets_bg->addButton( presets_link_rb );
|
||||
|
||||
presets_layout->addWidget( presets_pic_lbl );
|
||||
presets_layout->addWidget( presets_txt_lbl );
|
||||
presets_layout->addWidget( m_presetsCopyRB );
|
||||
presets_layout->addSpacing( 15 );
|
||||
presets_layout->addWidget( presets_link_rb );
|
||||
presets_layout->addStretch( 400 );
|
||||
|
||||
|
||||
|
||||
QWidget * projects_widget = new QWidget( files_content );
|
||||
QHBoxLayout * projects_layout = new QHBoxLayout( projects_widget );
|
||||
projects_layout->setSpacing( 5 );
|
||||
QLabel * projects_pic_lbl = new QLabel( projects_widget );
|
||||
projects_pic_lbl->setPixmap( embed::getIconPixmap( "project_file" ) );
|
||||
QLabel * projects_txt_lbl = new QLabel( tr( "demo projects:" ),
|
||||
projects_widget );
|
||||
projects_txt_lbl->setFixedWidth( 144 );
|
||||
|
||||
QButtonGroup * projects_bg = new QButtonGroup( projects_widget );
|
||||
#ifndef QT4
|
||||
projects_bg->hide();
|
||||
#endif
|
||||
m_projectsCopyRB = new QRadioButton( tr( "copy" ), projects_widget );
|
||||
m_projectsCopyRB->setChecked( TRUE );
|
||||
QRadioButton * projects_link_rb = new QRadioButton( tr( "link" ),
|
||||
projects_widget );
|
||||
projects_bg->addButton( m_projectsCopyRB );
|
||||
projects_bg->addButton( projects_link_rb );
|
||||
|
||||
projects_layout->addWidget( projects_pic_lbl );
|
||||
projects_layout->addWidget( projects_txt_lbl );
|
||||
projects_layout->addWidget( m_projectsCopyRB );
|
||||
projects_layout->addSpacing( 15 );
|
||||
projects_layout->addWidget( projects_link_rb );
|
||||
projects_layout->addStretch( 400 );
|
||||
|
||||
|
||||
|
||||
|
||||
files_content_layout->addWidget( files_txt_lbl );
|
||||
files_content_layout->addWidget( samples_widget );
|
||||
files_content_layout->addWidget( presets_widget );
|
||||
files_content_layout->addWidget( projects_widget );
|
||||
|
||||
|
||||
files_layout->addWidget( files_logo_lbl );
|
||||
files_layout->addWidget( files_content );
|
||||
|
||||
|
||||
|
||||
addPage( m_pageIntro, tr( "Welcome to LMMS" ) );
|
||||
addPage( m_pageWorkingDir, tr( "Select working directory" ) );
|
||||
addPage( m_pageFiles, tr( "Copy or link files" ) );
|
||||
switchPage( static_cast<csize>( 0 ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void configManager::openWorkingDir( void )
|
||||
{
|
||||
#ifdef QT4
|
||||
QString new_dir = QFileDialog::getExistingDirectory( this,
|
||||
tr( "Choose LMMS-working-directory" ),
|
||||
m_lmmsWorkingDir );
|
||||
#else
|
||||
QString new_dir = QFileDialog::getExistingDirectory( m_lmmsWorkingDir,
|
||||
0, 0,
|
||||
tr( "Choose LMMS-working-directory" ),
|
||||
TRUE );
|
||||
#endif
|
||||
if( new_dir != QString::null )
|
||||
{
|
||||
m_wdLineEdit->setText( new_dir );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void configManager::setWorkingDir( const QString & _wd )
|
||||
{
|
||||
m_lmmsWorkingDir = _wd;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void configManager::accept( void )
|
||||
{
|
||||
if( m_lmmsWorkingDir.right( 1 ) != "/" )
|
||||
{
|
||||
m_lmmsWorkingDir += '/';
|
||||
}
|
||||
if( !QDir( m_lmmsWorkingDir ).exists() )
|
||||
{
|
||||
if( QMessageBox::
|
||||
#if QT_VERSION >= 0x030200
|
||||
question
|
||||
#else
|
||||
information
|
||||
#endif
|
||||
( 0, tr( "Directory not existing" ),
|
||||
tr( "The directory you "
|
||||
"specified does not "
|
||||
"exist. Create it?" ),
|
||||
QMessageBox::Yes, QMessageBox::No )
|
||||
== QMessageBox::Yes )
|
||||
{
|
||||
mkPath( m_lmmsWorkingDir );
|
||||
}
|
||||
else
|
||||
{
|
||||
switchPage( m_pageWorkingDir );
|
||||
return;
|
||||
}
|
||||
}
|
||||
processFilesRecursively( m_lmmsDataDir + "samples/", m_lmmsWorkingDir +
|
||||
"samples/",
|
||||
m_samplesCopyRB->isChecked() ?
|
||||
©File :
|
||||
&linkFile );
|
||||
processFilesRecursively( m_lmmsDataDir + "presets/", m_lmmsWorkingDir +
|
||||
"presets/",
|
||||
m_presetsCopyRB->isChecked() ?
|
||||
©File :
|
||||
&linkFile );
|
||||
processFilesRecursively( m_lmmsDataDir + "projects/", m_lmmsWorkingDir +
|
||||
"projects/",
|
||||
m_projectsCopyRB->isChecked() ?
|
||||
©File :
|
||||
&linkFile );
|
||||
setValue( "paths", "workingdir", m_lmmsWorkingDir );
|
||||
|
||||
saveConfigFile();
|
||||
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void configManager::backButtonClicked( void )
|
||||
{
|
||||
switchPage( m_currentPage-1 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void configManager::nextButtonClicked( void )
|
||||
{
|
||||
switchPage( m_currentPage+1 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void configManager::switchPage( csize _pg )
|
||||
{
|
||||
if( m_currentPage >= 0 && m_currentPage < m_pages.size() )
|
||||
{
|
||||
m_pages[m_currentPage].first->hide();
|
||||
#ifdef QT4
|
||||
m_contentLayout->removeWidget( m_pages[m_currentPage].first );
|
||||
#else
|
||||
#if QT_VERSION >= 0x030100
|
||||
m_contentLayout->remove( m_pages[m_currentPage].first );
|
||||
#else
|
||||
m_pages[m_currentPage].first->hide();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
if( _pg < m_pages.size() )
|
||||
{
|
||||
QWidget * p = m_pages[_pg].first;
|
||||
m_contentLayout->insertWidget( 2, p );
|
||||
p->show();
|
||||
p->setFocus();
|
||||
m_title->setText( m_pages[_pg].second );
|
||||
m_currentPage = _pg;
|
||||
}
|
||||
m_backButton->setEnabled( _pg > 0 );
|
||||
if( _pg == m_pages.size() - 1 )
|
||||
{
|
||||
m_nextButton->setEnabled( FALSE );
|
||||
m_finishButton->setEnabled( TRUE );
|
||||
m_finishButton->setDefault( TRUE );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_nextButton->setEnabled( TRUE );
|
||||
m_nextButton->setDefault( TRUE );
|
||||
m_finishButton->setEnabled( FALSE );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void configManager::switchPage( QWidget * _pg )
|
||||
{
|
||||
for( csize i = 0; i < m_pages.size(); ++i )
|
||||
{
|
||||
if( m_pages[i].first == _pg )
|
||||
{
|
||||
switchPage( i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void configManager::addPage( QWidget * _w, const QString & _title )
|
||||
{
|
||||
_w->hide();
|
||||
m_pages.push_back( qMakePair( _w, _title ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
const QString & configManager::value( const QString & _class,
|
||||
const QString & _attribute ) const
|
||||
{
|
||||
if( m_settings.contains( _class ) )
|
||||
{
|
||||
for( stringPairVector::const_iterator it =
|
||||
m_settings[_class].begin();
|
||||
it != m_settings[_class].end(); ++it )
|
||||
{
|
||||
if( ( *it ).first == _attribute )
|
||||
{
|
||||
return( ( *it ).second );
|
||||
}
|
||||
}
|
||||
}
|
||||
static QString empty;
|
||||
return( empty );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void configManager::setValue( const QString & _class,
|
||||
const QString & _attribute,
|
||||
const QString & _value )
|
||||
{
|
||||
if( m_settings.contains( _class ) )
|
||||
{
|
||||
for( stringPairVector::iterator it = m_settings[_class].begin();
|
||||
it != m_settings[_class].end(); ++it )
|
||||
{
|
||||
if( ( *it ).first == _attribute )
|
||||
{
|
||||
( *it ).second = _value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// not in map yet, so we have to add it...
|
||||
m_settings[_class].push_back( qMakePair( _attribute, _value ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool configManager::loadConfigFile( void )
|
||||
{
|
||||
createWidgets();
|
||||
|
||||
// read the XML file and create DOM tree
|
||||
QFile cfg_file( m_lmmsRcFile );
|
||||
#ifdef QT4
|
||||
if( !cfg_file.open( QIODevice::ReadOnly ) )
|
||||
#else
|
||||
if( !cfg_file.open( IO_ReadOnly ) )
|
||||
#endif
|
||||
{
|
||||
#ifdef QT4
|
||||
if( !( exec() && cfg_file.open( QIODevice::ReadOnly ) ) )
|
||||
#else
|
||||
if( !( exec() && cfg_file.open( IO_ReadOnly ) ) )
|
||||
#endif
|
||||
{
|
||||
return( FALSE );
|
||||
}
|
||||
}
|
||||
QDomDocument dom_tree;
|
||||
if( !dom_tree.setContent( &cfg_file ) )
|
||||
{
|
||||
QMessageBox::critical( 0, tr( "Error in configuration-file" ),
|
||||
tr( "Error while parsing "
|
||||
"configuration-file %1.\n"
|
||||
"The setup-wizard will be "
|
||||
"shown for reconfiguring LMMS."
|
||||
).arg( m_lmmsRcFile ) );
|
||||
cfg_file.close();
|
||||
if( exec() )
|
||||
{
|
||||
return( loadConfigFile() );
|
||||
}
|
||||
else
|
||||
{
|
||||
return( FALSE );
|
||||
}
|
||||
}
|
||||
cfg_file.close();
|
||||
|
||||
|
||||
// get the head information from the DOM
|
||||
QDomElement root = dom_tree.documentElement();
|
||||
if( root.isElement() )
|
||||
{
|
||||
QString cfg_file_ver = root.toElement().attribute( "version" );
|
||||
if( ( cfg_file_ver.length() == 0 || cfg_file_ver != VERSION ) &&
|
||||
QMessageBox::
|
||||
#if QT_VERSION >= 0x030200
|
||||
question
|
||||
#else
|
||||
information
|
||||
#endif
|
||||
( 0, tr( "Version mismatches" ),
|
||||
tr( "Accordingly to the information in "
|
||||
"your LMMS-configuration-file "
|
||||
"you seem\nto have run a "
|
||||
"different (probably older) "
|
||||
"version of LMMS before.\n"
|
||||
"It is recommended to run the "
|
||||
"setup-wizard again to ensure "
|
||||
"that\nthe latest samples, "
|
||||
"presets, demo-projects etc. "
|
||||
"are installed in your\n"
|
||||
"LMMS-working-directory. "
|
||||
"Run the setup-wizard now?" ),
|
||||
QMessageBox::Yes, QMessageBox::No )
|
||||
== QMessageBox::Yes )
|
||||
{
|
||||
if( exec() )
|
||||
{
|
||||
return( loadConfigFile() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QDomNode node = root.firstChild();
|
||||
|
||||
// create the settings-map out of the DOM
|
||||
while( !node.isNull() )
|
||||
{
|
||||
if( node.isElement() && node.toElement().hasAttributes () )
|
||||
{
|
||||
stringPairVector attr;
|
||||
QDomNamedNodeMap node_attr =
|
||||
node.toElement().attributes();
|
||||
for( unsigned int i = 0; i < node_attr.count(); ++i )
|
||||
{
|
||||
QDomNode n = node_attr.item( i );
|
||||
if( n.isAttr() )
|
||||
{
|
||||
attr.push_back( qMakePair(
|
||||
n.toAttr().name(),
|
||||
n.toAttr().value() ) );
|
||||
}
|
||||
}
|
||||
m_settings[node.nodeName()] = attr;
|
||||
}
|
||||
node = node.nextSibling();
|
||||
}
|
||||
|
||||
m_lmmsWorkingDir = value( "paths", "workingdir" );
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void configManager::saveConfigFile( void )
|
||||
{
|
||||
QDomDocument doc( "lmms-config-file" );
|
||||
|
||||
QDomElement lmms_config = doc.createElement( "lmms" );
|
||||
lmms_config.setAttribute( "version", VERSION );
|
||||
doc.appendChild( lmms_config );
|
||||
|
||||
for( settingsMap::iterator it = m_settings.begin();
|
||||
it != m_settings.end(); ++it )
|
||||
{
|
||||
QDomElement n = doc.createElement( it.key() );
|
||||
for( stringPairVector::iterator it2 = ( *it ).begin();
|
||||
it2 != ( *it ).end(); ++it2 )
|
||||
{
|
||||
n.setAttribute( ( *it2 ).first, ( *it2 ).second );
|
||||
}
|
||||
lmms_config.appendChild( n );
|
||||
}
|
||||
|
||||
#if QT_VERSION >= 0x030100
|
||||
QString xml = "<?xml version=\"1.0\"?>\n" + doc.toString( 2 );
|
||||
#else
|
||||
QString xml = "<?xml version=\"1.0\"?>\n" + doc.toString();
|
||||
#endif
|
||||
|
||||
QFile outfile( m_lmmsRcFile );
|
||||
#ifdef QT4
|
||||
if( !outfile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
|
||||
#else
|
||||
if( !outfile.open( IO_WriteOnly | IO_Truncate ) )
|
||||
#endif
|
||||
{
|
||||
QMessageBox::critical( NULL, tr( "Could not save config-file" ),
|
||||
tr( "Could not save configuration "
|
||||
"file %1. You probably are not "
|
||||
"permitted to write to this "
|
||||
"file.\n"
|
||||
"Please make sure you have "
|
||||
"write-access to the file and "
|
||||
"try again." ).arg(
|
||||
m_lmmsRcFile ) );
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef QT4
|
||||
outfile.write( xml.toAscii().constData(), xml.length() );
|
||||
#else
|
||||
outfile.writeBlock( xml.ascii(), xml.length() );
|
||||
#endif
|
||||
outfile.close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void configManager::processFilesRecursively( const QString & _src_dir,
|
||||
const QString & _dst_dir,
|
||||
void( * _proc_func )( const QString & _src, const QString & _dst ) )
|
||||
{
|
||||
mkPath( _dst_dir );
|
||||
QStringList files = QDir( _src_dir ).entryList();
|
||||
for( QStringList::iterator it = files.begin(); it != files.end(); ++it )
|
||||
{
|
||||
if( ( *it )[0] == '.' )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if( QFileInfo( _src_dir + *it ).isFile() )
|
||||
{
|
||||
_proc_func( _src_dir + *it, _dst_dir + *it );
|
||||
}
|
||||
else if( QFileInfo( _src_dir + *it ).isDir () )
|
||||
{
|
||||
processFilesRecursively( _src_dir + *it + "/",
|
||||
_dst_dir + *it + "/",
|
||||
_proc_func );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#include "config_mgr.moc"
|
||||
|
||||
1118
src/core/envelope_and_lfo_widget.cpp
Normal file
1118
src/core/envelope_and_lfo_widget.cpp
Normal file
File diff suppressed because it is too large
Load Diff
631
src/core/envelope_tab_widget.cpp
Normal file
631
src/core/envelope_tab_widget.cpp
Normal file
@@ -0,0 +1,631 @@
|
||||
/*
|
||||
* envelope_tab_widget.cpp - widget for use in envelope/lfo/filter-tab of
|
||||
* channel-window
|
||||
*
|
||||
* Linux MultiMedia Studio
|
||||
* Copyright (c) 2004-2005 Tobias Doerffel <tobydox@users.sourceforge.net>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "qt3support.h"
|
||||
|
||||
#ifdef QT4
|
||||
|
||||
#include <QComboBox>
|
||||
#include <Qt/QtXml>
|
||||
#include <QWhatsThis>
|
||||
|
||||
#else
|
||||
|
||||
#include <qcombobox.h>
|
||||
#include <qdom.h>
|
||||
#include <qwhatsthis.h>
|
||||
|
||||
#define isChecked isOn
|
||||
#define setChecked setOn
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "envelope_tab_widget.h"
|
||||
#include "envelope_and_lfo_widget.h"
|
||||
#include "note_play_handle.h"
|
||||
#include "knob.h"
|
||||
#include "pixmap_button.h"
|
||||
#include "group_box.h"
|
||||
#include "tab_widget.h"
|
||||
#include "embed.h"
|
||||
#include "templates.h"
|
||||
|
||||
|
||||
const int TARGETS_TABWIDGET_X = 4;
|
||||
const int TARGETS_TABWIDGET_Y = 5;
|
||||
const int TARGETS_TABWIDGET_WIDTH = 240;
|
||||
const int TARGETS_TABWIDGET_HEIGTH = 175;
|
||||
|
||||
const int FILTER_GROUPBOX_X = TARGETS_TABWIDGET_X;
|
||||
const int FILTER_GROUPBOX_Y = TARGETS_TABWIDGET_Y+TARGETS_TABWIDGET_HEIGTH+5;
|
||||
const int FILTER_GROUPBOX_WIDTH = TARGETS_TABWIDGET_WIDTH;
|
||||
const int FILTER_GROUPBOX_HEIGHT = 245-FILTER_GROUPBOX_Y;
|
||||
|
||||
const float CUT_FREQ_MULTIPLIER = 6000.0f;
|
||||
const float RES_MULTIPLIER = 2.0f;
|
||||
const float RES_PRECISION = 1000.0f;
|
||||
|
||||
|
||||
// names for env- and lfo-targets - first is name being displayed to user
|
||||
// and second one is used internally, e.g. for saving/restoring settings
|
||||
const QString targetNames[envelopeTabWidget::TARGET_COUNT][2] =
|
||||
{
|
||||
{ envelopeTabWidget::tr( "VOLUME" ), "vol" },
|
||||
/* envelopeTabWidget::tr( "Pan" ),
|
||||
envelopeTabWidget::tr( "Pitch" ),*/
|
||||
{ envelopeTabWidget::tr( "CUTOFF" ), "cut" },
|
||||
{ envelopeTabWidget::tr( "Q/RESO" ), "res" }
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
envelopeTabWidget::envelopeTabWidget( channelTrack * _channel_track,
|
||||
QWidget * _parent ) :
|
||||
QWidget( _parent ),
|
||||
settings(),
|
||||
m_channelTrack( _channel_track )
|
||||
{
|
||||
|
||||
m_targetsTabWidget = new tabWidget( tr( "TARGET" ), this );
|
||||
m_targetsTabWidget->setGeometry( TARGETS_TABWIDGET_X,
|
||||
TARGETS_TABWIDGET_Y,
|
||||
TARGETS_TABWIDGET_WIDTH,
|
||||
TARGETS_TABWIDGET_HEIGTH );
|
||||
#ifdef QT4
|
||||
m_targetsTabWidget->setWhatsThis(
|
||||
#else
|
||||
QWhatsThis::add( m_targetsTabWidget,
|
||||
#endif
|
||||
tr( "These tabs contain envelopes. They're very important for "
|
||||
"modifying a sound, for not saying that they're almost "
|
||||
"always neccessary for substractive synthesis. For "
|
||||
"example if you have a volume-envelope, you can set "
|
||||
"when the sound should have which volume-level. "
|
||||
"Maybe you want to create some soft strings. Then your "
|
||||
"sound has to fade in and out very softly. This can be "
|
||||
"done by setting a large attack- and release-time. "
|
||||
"It's the same for other envelope-targets like "
|
||||
"panning, cutoff-frequency of used filter and so on. "
|
||||
"Just monkey around with it! You can really make cool "
|
||||
"sounds out of a saw-wave with just some "
|
||||
"envelopes...!" ) );
|
||||
|
||||
for( int i = 0; i < TARGET_COUNT; ++i )
|
||||
{
|
||||
float value_for_zero_amount = 0.0;
|
||||
if( i == VOLUME )
|
||||
{
|
||||
value_for_zero_amount = 1.0;
|
||||
}
|
||||
m_envLFOWidgets[i] = new envelopeAndLFOWidget(
|
||||
value_for_zero_amount, m_targetsTabWidget );
|
||||
m_targetsTabWidget->addTab( m_envLFOWidgets[i],
|
||||
tr( targetNames[i][0]
|
||||
#ifdef QT4
|
||||
.toAscii().constData()
|
||||
#endif
|
||||
) );
|
||||
/*
|
||||
#ifdef QT4
|
||||
.toAscii().constData()
|
||||
#endif
|
||||
) );*/
|
||||
}
|
||||
|
||||
|
||||
m_filterGroupBox = new groupBox( tr( "FILTER" ), this );
|
||||
m_filterGroupBox->setGeometry( FILTER_GROUPBOX_X, FILTER_GROUPBOX_Y,
|
||||
FILTER_GROUPBOX_WIDTH,
|
||||
FILTER_GROUPBOX_HEIGHT );
|
||||
|
||||
m_filterComboBox = new QComboBox( m_filterGroupBox );
|
||||
m_filterComboBox->setGeometry( 20, 20, 100, 22 );
|
||||
m_filterComboBox->setFont( pointSize<8>( m_filterComboBox->font() ) );
|
||||
|
||||
|
||||
m_filterComboBox->addItem( tr( "LowPass" ) );
|
||||
m_filterComboBox->addItem( tr( "HiPass" ) );
|
||||
m_filterComboBox->addItem( tr( "BandPass csg" ) );
|
||||
m_filterComboBox->addItem( tr( "BandPass czpg" ) );
|
||||
m_filterComboBox->addItem( tr( "Notch" ) );
|
||||
m_filterComboBox->addItem( tr( "Allpass" ) );
|
||||
m_filterComboBox->addItem( tr( "Moog" ) );
|
||||
m_filterComboBox->addItem( tr( "2x LowPass" ) );
|
||||
m_filterComboBox->addItem( tr( "2x Moog" ) );
|
||||
|
||||
#ifdef QT4
|
||||
m_filterComboBox->setWhatsThis(
|
||||
#else
|
||||
QWhatsThis::add( m_filterComboBox,
|
||||
#endif
|
||||
tr( "Here you can select the built-in filter you want to use "
|
||||
"in this channel. Filters are very important for "
|
||||
"changing the characteristics of a sound." ) );
|
||||
|
||||
|
||||
m_filterCutKnob = new knob( knobBright_26, m_filterGroupBox, tr(
|
||||
"cutoff-frequency" ) );
|
||||
m_filterCutKnob->setLabel( tr( "CUTOFF" ) );
|
||||
m_filterCutKnob->setRange( 0.0, 16000.0, 1.0 );
|
||||
m_filterCutKnob->move( 140, 18 );
|
||||
m_filterCutKnob->setValue( 16000.0, TRUE );
|
||||
m_filterCutKnob->setHintText( tr( "cutoff-frequency:" ) + " ", " " +
|
||||
tr( "Hz" ) );
|
||||
#ifdef QT4
|
||||
m_filterCutKnob->setWhatsThis(
|
||||
#else
|
||||
QWhatsThis::add( m_filterCutKnob,
|
||||
#endif
|
||||
tr( "Use this knob for setting the cutoff-frequency for the "
|
||||
"selected filter. The cutoff-frequency specifies the "
|
||||
"frequency for cutting the signal by a filter. For "
|
||||
"example a lowpass-filter cuts all frequencies above "
|
||||
"the cutoff-frequency. A highpass-filter cuts all "
|
||||
"frequencies below cutoff-frequency and so on..." ) );
|
||||
|
||||
m_filterResKnob = new knob( knobBright_26, m_filterGroupBox, tr(
|
||||
"Q/Resonance" ) );
|
||||
m_filterResKnob->setLabel( tr( "Q/RESO" ) );
|
||||
m_filterResKnob->setRange( 0.01, 10.0, 0.01 );
|
||||
m_filterResKnob->move( 190, 18 );
|
||||
m_filterResKnob->setValue( 0.5, TRUE );
|
||||
m_filterResKnob->setHintText( tr( "Q/Resonance:" ) + " ", "" );
|
||||
#ifdef QT4
|
||||
m_filterResKnob->setWhatsThis(
|
||||
#else
|
||||
QWhatsThis::add( m_filterResKnob,
|
||||
#endif
|
||||
tr( "Use this knob for setting Q/Resonance for the selected "
|
||||
"filter. Q/Resonance tells the filter, how much it "
|
||||
"should amplify frequencies near Cutoff-frequency." ) );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
envelopeTabWidget::~envelopeTabWidget()
|
||||
{
|
||||
delete m_targetsTabWidget;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
float FASTCALL envelopeTabWidget::volumeLevel( notePlayHandle * _n,
|
||||
Uint32 _frame )
|
||||
{
|
||||
Uint32 release_begin = _frame - _n->releaseFramesDone() +
|
||||
_n->framesBeforeRelease();
|
||||
|
||||
if( _n->released() == FALSE )
|
||||
{
|
||||
release_begin += mixer::inst()->framesPerAudioBuffer();
|
||||
}
|
||||
|
||||
return( m_envLFOWidgets[VOLUME]->level( _frame, release_begin, 0 ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void envelopeTabWidget::processAudioBuffer( sampleFrame * _ab, Uint32 _frames,
|
||||
notePlayHandle * _n )
|
||||
{
|
||||
Uint32 total_frames = _n->totalFramesPlayed();
|
||||
Uint32 release_begin = total_frames - _n->releaseFramesDone() +
|
||||
_n->framesBeforeRelease();
|
||||
|
||||
if( _n->released() == FALSE )
|
||||
{
|
||||
release_begin += mixer::inst()->framesPerAudioBuffer();
|
||||
}
|
||||
|
||||
// because of optimizations, there's special code for several cases:
|
||||
// - volume-, cut- and res-lfo/envelope active
|
||||
// - volume- and cut-lfo/envelope active
|
||||
// - volume- and res-lfo/envelope active
|
||||
// - cut-lfo/envelope active
|
||||
// - res-lfo/envelope active
|
||||
// - volume-lfo/envelope active
|
||||
// - no lfo/envelope active but filter is used
|
||||
// now there's a lot of similar code but I didn't found a way to
|
||||
// generalize it yet... may be later we could do that
|
||||
// by using preprocessor and macro-expansion... (like in oscillator.cpp)
|
||||
|
||||
// only use filter, if it is really needed
|
||||
|
||||
if( _n->m_filter == NULL )
|
||||
{
|
||||
_n->m_filter = new basicFilters<>(
|
||||
mixer::inst()->sampleRate() );
|
||||
}
|
||||
|
||||
if( /*m_filterState->isChecked()*/ m_filterGroupBox->isActive() )
|
||||
{
|
||||
int old_filter_cut = 0;
|
||||
int old_filter_res = 0;
|
||||
|
||||
basicFilters<>::filterTypes filter = static_cast<basicFilters<>::filterTypes>( m_filterComboBox->
|
||||
#ifdef QT4
|
||||
currentIndex()
|
||||
#else
|
||||
currentItem()
|
||||
#endif
|
||||
);
|
||||
|
||||
if( m_envLFOWidgets[VOLUME]->used() &&
|
||||
m_envLFOWidgets[CUT]->used() &&
|
||||
m_envLFOWidgets[RES]->used() )
|
||||
{
|
||||
for( Uint32 frame = 0; frame < _frames;
|
||||
++frame, ++total_frames )
|
||||
{
|
||||
float new_cut_val = m_envLFOWidgets[CUT]->level( total_frames, release_begin, frame );
|
||||
new_cut_val = envelopeAndLFOWidget::expKnobVal( new_cut_val ) * CUT_FREQ_MULTIPLIER +
|
||||
m_filterCutKnob->value();
|
||||
|
||||
float new_res_val = m_filterResKnob->value() + RES_MULTIPLIER *
|
||||
m_envLFOWidgets[RES]->level( total_frames, release_begin, frame );
|
||||
|
||||
if( static_cast<int>( new_cut_val ) != old_filter_cut ||
|
||||
static_cast<int>( new_res_val*RES_PRECISION ) != old_filter_res )
|
||||
{
|
||||
_n->m_filter->calcFilterCoeffs( filter, new_cut_val, new_res_val );
|
||||
old_filter_cut = static_cast<int>( new_cut_val );
|
||||
old_filter_res = static_cast<int>( new_res_val*RES_PRECISION );
|
||||
}
|
||||
|
||||
float vol_level = m_envLFOWidgets[VOLUME]->level( total_frames, release_begin, frame );
|
||||
vol_level = vol_level*vol_level;
|
||||
|
||||
for( Uint8 chnl = 0; chnl < DEFAULT_CHANNELS; ++chnl )
|
||||
{
|
||||
_ab[frame][chnl] = vol_level * _n->m_filter->update( _ab[frame][chnl], chnl );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( m_envLFOWidgets[VOLUME]->used() && m_envLFOWidgets[CUT]->used() )
|
||||
{
|
||||
for( Uint32 frame = 0; frame < _frames; ++frame, ++total_frames )
|
||||
{
|
||||
float new_cut_val = m_envLFOWidgets[CUT]->level( total_frames, release_begin, frame );
|
||||
new_cut_val = envelopeAndLFOWidget::expKnobVal( new_cut_val ) * CUT_FREQ_MULTIPLIER +
|
||||
m_filterCutKnob->value();
|
||||
|
||||
if( static_cast<int>( new_cut_val ) != old_filter_cut )
|
||||
{
|
||||
_n->m_filter->calcFilterCoeffs( filter, new_cut_val, m_filterResKnob->value() );
|
||||
old_filter_cut = static_cast<int>( new_cut_val );
|
||||
}
|
||||
|
||||
float vol_level = m_envLFOWidgets[VOLUME]->level( total_frames, release_begin, frame );
|
||||
vol_level = vol_level*vol_level;
|
||||
|
||||
for( Uint8 chnl = 0; chnl < DEFAULT_CHANNELS; ++chnl )
|
||||
{
|
||||
_ab[frame][chnl] = vol_level * _n->m_filter->update( _ab[frame][chnl], chnl );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( m_envLFOWidgets[VOLUME]->used() && m_envLFOWidgets[RES]->used() )
|
||||
{
|
||||
|
||||
for( Uint32 frame = 0; frame < _frames; ++frame, ++total_frames )
|
||||
{
|
||||
float new_res_val = m_filterResKnob->value() + RES_MULTIPLIER *
|
||||
m_envLFOWidgets[RES]->level( total_frames, release_begin, frame );
|
||||
|
||||
if( static_cast<int>( new_res_val*RES_PRECISION ) != old_filter_res )
|
||||
{
|
||||
_n->m_filter->calcFilterCoeffs( filter, m_filterCutKnob->value(), new_res_val );
|
||||
old_filter_res = static_cast<int>( new_res_val*RES_PRECISION );
|
||||
}
|
||||
|
||||
float vol_level = m_envLFOWidgets[VOLUME]->level( total_frames, release_begin, frame );
|
||||
vol_level = vol_level*vol_level;
|
||||
|
||||
for( Uint8 chnl = 0; chnl < DEFAULT_CHANNELS; ++chnl )
|
||||
{
|
||||
_ab[frame][chnl] = vol_level * _n->m_filter->update( _ab[frame][chnl], chnl );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else if( m_envLFOWidgets[CUT]->used() )
|
||||
{
|
||||
for( Uint32 frame = 0; frame < _frames; ++frame, ++total_frames )
|
||||
{
|
||||
float new_cut_val = m_envLFOWidgets[CUT]->level( total_frames, release_begin, frame );
|
||||
new_cut_val = envelopeAndLFOWidget::expKnobVal( new_cut_val ) * CUT_FREQ_MULTIPLIER +
|
||||
m_filterCutKnob->value();
|
||||
|
||||
if( static_cast<int>( new_cut_val ) != old_filter_cut )
|
||||
{
|
||||
_n->m_filter->calcFilterCoeffs( filter, new_cut_val, m_filterResKnob->value() );
|
||||
old_filter_cut = static_cast<int>( new_cut_val );
|
||||
}
|
||||
|
||||
for( Uint8 chnl = 0; chnl < DEFAULT_CHANNELS; ++chnl )
|
||||
{
|
||||
_ab[frame][chnl] = _n->m_filter->update( _ab[frame][chnl], chnl );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( m_envLFOWidgets[RES]->used() )
|
||||
{
|
||||
for( Uint32 frame = 0; frame < _frames; ++frame, ++total_frames )
|
||||
{
|
||||
float new_res_val = m_filterResKnob->value() + RES_MULTIPLIER *
|
||||
m_envLFOWidgets[RES]->level( total_frames, release_begin, frame );
|
||||
|
||||
if( static_cast<int>( new_res_val*RES_PRECISION ) != old_filter_res )
|
||||
{
|
||||
_n->m_filter->calcFilterCoeffs( filter, m_filterCutKnob->value(), new_res_val );
|
||||
old_filter_res = static_cast<int>( new_res_val*RES_PRECISION );
|
||||
}
|
||||
|
||||
for( Uint8 chnl = 0; chnl < DEFAULT_CHANNELS; ++chnl )
|
||||
{
|
||||
_ab[frame][chnl] = _n->m_filter->update( _ab[frame][chnl], chnl );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( m_envLFOWidgets[VOLUME]->used() )
|
||||
{
|
||||
_n->m_filter->calcFilterCoeffs( filter, m_filterCutKnob->value(), m_filterResKnob->value() );
|
||||
|
||||
for( Uint32 frame = 0; frame < _frames; ++frame, ++total_frames )
|
||||
{
|
||||
float vol_level = m_envLFOWidgets[VOLUME]->level( total_frames, release_begin, frame );
|
||||
vol_level = vol_level*vol_level;
|
||||
|
||||
for( Uint8 chnl = 0; chnl < DEFAULT_CHANNELS; ++chnl )
|
||||
{
|
||||
_ab[frame][chnl] = vol_level * _n->m_filter->update( _ab[frame][chnl], chnl );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_n->m_filter->calcFilterCoeffs( filter, m_filterCutKnob->value(), m_filterResKnob->value() );
|
||||
|
||||
for( Uint32 frame = 0; frame < _frames; ++frame, ++total_frames )
|
||||
{
|
||||
for( Uint8 chnl = 0; chnl < DEFAULT_CHANNELS; ++chnl )
|
||||
{
|
||||
_ab[frame][chnl] = _n->m_filter->update( _ab[frame][chnl], chnl );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( m_envLFOWidgets[VOLUME]->used() /*&& m_envLFOWidgets[PANNING]->used() == FALSE*/ )
|
||||
{
|
||||
// only use volume-envelope...
|
||||
for( Uint32 frame = 0; frame < _frames; ++frame, ++total_frames )
|
||||
{
|
||||
float vol_level = m_envLFOWidgets[VOLUME]->level( total_frames, release_begin, frame );
|
||||
vol_level = vol_level*vol_level;
|
||||
for( Uint8 chnl = 0; chnl < DEFAULT_CHANNELS; ++chnl )
|
||||
{
|
||||
_ab[frame][chnl] = vol_level * _ab[frame][chnl];
|
||||
}
|
||||
}
|
||||
}
|
||||
/* else if( m_envLFOWidgets[VOLUME]->used() == FALSE && m_envLFOWidgets[PANNING]->used() )
|
||||
{
|
||||
// only use panning-envelope...
|
||||
for( Uint32 frame = 0; frame < _frames; ++frame, ++total_frames )
|
||||
{
|
||||
float vol_level = m_envLFOWidgets[PANNING]->level( total_frames, release_begin, frame );
|
||||
vol_level = vol_level*vol_level;
|
||||
for( Uint8 chnl = 0; chnl < DEFAULT_CHANNELS; ++chnl )
|
||||
{
|
||||
_ab[frame][chnl] = vol_level * _ab[frame][chnl];
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Uint32 envelopeTabWidget::envFrames( void )
|
||||
{
|
||||
Uint32 ret_val = m_envLFOWidgets[VOLUME]->m_pahdFrames;
|
||||
|
||||
for( int i = VOLUME+1; i < TARGET_COUNT; ++i )
|
||||
{
|
||||
if( m_envLFOWidgets[i]->used() &&
|
||||
m_envLFOWidgets[i]->m_pahdFrames > ret_val )
|
||||
{
|
||||
ret_val = m_envLFOWidgets[i]->m_pahdFrames;
|
||||
}
|
||||
}
|
||||
return( ret_val );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Uint32 envelopeTabWidget::releaseFrames( void )
|
||||
{
|
||||
Uint32 ret_val = m_envLFOWidgets[VOLUME]->m_rFrames;
|
||||
for( int i = VOLUME+1; i < TARGET_COUNT; ++i )
|
||||
{
|
||||
if( m_envLFOWidgets[i]->used() &&
|
||||
m_envLFOWidgets[i]->m_rFrames > ret_val )
|
||||
{
|
||||
ret_val = m_envLFOWidgets[i]->m_rFrames;
|
||||
}
|
||||
}
|
||||
return( ret_val );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void envelopeTabWidget::saveSettings( QDomDocument & _doc,
|
||||
QDomElement & _parent )
|
||||
{
|
||||
QDomElement etw_de = _doc.createElement( nodeName() );
|
||||
#ifdef QT4
|
||||
etw_de.setAttribute( "ftype", QString::number(
|
||||
m_filterComboBox->currentIndex() ) );
|
||||
#else
|
||||
etw_de.setAttribute( "ftype", QString::number(
|
||||
m_filterComboBox->currentItem() ) );
|
||||
#endif
|
||||
etw_de.setAttribute( "fcut", QString::number(
|
||||
m_filterCutKnob->value() ) );
|
||||
etw_de.setAttribute( "fres", QString::number(
|
||||
m_filterResKnob->value() ) );
|
||||
etw_de.setAttribute( "fwet", QString::number(
|
||||
/*m_filterState->isChecked()*/
|
||||
m_filterGroupBox->isActive() ) );
|
||||
_parent.appendChild( etw_de );
|
||||
|
||||
for( int i = 0; i < TARGET_COUNT; ++i )
|
||||
{
|
||||
QDomElement target_de = _doc.createElement(
|
||||
m_envLFOWidgets[i]->nodeName() +
|
||||
targetNames[i][1].toLower() );
|
||||
m_envLFOWidgets[i]->saveSettings( _doc, target_de );
|
||||
etw_de.appendChild( target_de );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void envelopeTabWidget::loadSettings( const QDomElement & _this )
|
||||
{
|
||||
#ifdef QT4
|
||||
m_filterComboBox->setCurrentIndex( _this.attribute( "ftype" ).toInt() );
|
||||
#else
|
||||
m_filterComboBox->setCurrentItem( _this.attribute( "ftype" ).toInt() );
|
||||
#endif
|
||||
m_filterCutKnob->setValue( _this.attribute( "fcut" ).toFloat() );
|
||||
m_filterResKnob->setValue( _this.attribute( "fres" ).toFloat() );
|
||||
/* m_filterState->setChecked( _this.attribute( "fwet" ).toInt() );*/
|
||||
m_filterGroupBox->setState( _this.attribute( "fwet" ).toInt() );
|
||||
|
||||
QDomNode node = _this.firstChild();
|
||||
while( !node.isNull() )
|
||||
{
|
||||
if( node.isElement() )
|
||||
{
|
||||
for( int i = 0; i < TARGET_COUNT; ++i )
|
||||
{
|
||||
if( node.nodeName() ==
|
||||
m_envLFOWidgets[i]->nodeName() +
|
||||
targetNames[i][1].toLower() )
|
||||
{
|
||||
m_envLFOWidgets[i]->loadSettings(
|
||||
node.toElement() );
|
||||
}
|
||||
}
|
||||
}
|
||||
node = node.nextSibling();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#undef isChecked
|
||||
#undef setChecked
|
||||
|
||||
|
||||
#include "envelope_tab_widget.moc"
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
|
||||
const long double coeff[5][11]= {
|
||||
{
|
||||
///A
|
||||
8.11044e-06,
|
||||
8.943665402, -36.83889529, 92.01697887, -154.337906, 181.6233289,
|
||||
-151.8651235, 89.09614114, -35.10298511, 8.388101016, -0.923313471
|
||||
},
|
||||
{
|
||||
///E
|
||||
4.36215e-06,
|
||||
8.90438318, -36.55179099, 91.05750846, -152.422234, 179.1170248,
|
||||
-149.6496211,87.78352223, -34.60687431, 8.282228154, -0.914150747
|
||||
},
|
||||
{
|
||||
///I
|
||||
3.33819e-06,
|
||||
8.893102966, -36.49532826, 90.96543286, -152.4545478, 179.4835618,
|
||||
-150.315433, 88.43409371, -34.98612086, 8.407803364, -0.932568035
|
||||
},
|
||||
{
|
||||
///O
|
||||
1.13572e-06,
|
||||
8.994734087, -37.2084849, 93.22900521, -156.6929844, 184.596544,
|
||||
-154.3755513, 90.49663749, -35.58964535, 8.478996281, -0.929252233
|
||||
},
|
||||
{
|
||||
///U
|
||||
4.09431e-07,
|
||||
8.997322763, -37.20218544, 93.11385476, -156.2530937, 183.7080141,
|
||||
-153.2631681, 89.59539726, -35.12454591, 8.338655623, -0.910251753
|
||||
}
|
||||
};
|
||||
//-----------------------------------------------------------------------------
|
||||
static long double memory[10]={0,0,0,0,0,0,0,0,0,0};
|
||||
//------------------------------------------------------------------------------
|
||||
inline float formant_filter(float in, int vowelnum)
|
||||
{
|
||||
float res= (float) ( coeff[vowelnum][0] *in +
|
||||
coeff[vowelnum][1] *memory[0] +
|
||||
coeff[vowelnum][2] *memory[1] +
|
||||
coeff[vowelnum][3] *memory[2] +
|
||||
coeff[vowelnum][4] *memory[3] +
|
||||
coeff[vowelnum][5] *memory[4] +
|
||||
coeff[vowelnum][6] *memory[5] +
|
||||
coeff[vowelnum][7] *memory[6] +
|
||||
coeff[vowelnum][8] *memory[7] +
|
||||
coeff[vowelnum][9] *memory[8] +
|
||||
coeff[vowelnum][10] *memory[9] );
|
||||
|
||||
memory[9]= memory[8];
|
||||
memory[8]= memory[7];
|
||||
memory[7]= memory[6];
|
||||
memory[6]= memory[5];
|
||||
memory[5]= memory[4];
|
||||
memory[4]= memory[3];
|
||||
memory[3]= memory[2];
|
||||
memory[2]= memory[1];
|
||||
memory[1]= memory[0];
|
||||
memory[0]=(long double) res;
|
||||
return res;
|
||||
}
|
||||
|
||||
*/
|
||||
481
src/core/export_project_dialog.cpp
Normal file
481
src/core/export_project_dialog.cpp
Normal file
@@ -0,0 +1,481 @@
|
||||
/*
|
||||
* export_project_dialog.cpp - implementation of dialog for exporting project
|
||||
*
|
||||
* Linux MultiMedia Studio
|
||||
* Copyright (c) 2004-2005 Tobias Doerffel <tobydox@users.sourceforge.net>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "qt3support.h"
|
||||
|
||||
#ifdef QT4
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QProgressBar>
|
||||
#include <QComboBox>
|
||||
#include <QCheckBox>
|
||||
#include <QTimer>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QCloseEvent>
|
||||
|
||||
#else
|
||||
|
||||
#include <qfiledialog.h>
|
||||
#include <qmessagebox.h>
|
||||
#include <qprogressbar.h>
|
||||
#include <qcombobox.h>
|
||||
#include <qcheckbox.h>
|
||||
#include <qtimer.h>
|
||||
#include <qlabel.h>
|
||||
#include <qpushbutton.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "export_project_dialog.h"
|
||||
#include "song_editor.h"
|
||||
#include "embed.h"
|
||||
|
||||
#include "audio_file_wave.h"
|
||||
#include "audio_file_ogg.h"
|
||||
|
||||
|
||||
fileEncodeDevice fileEncodeDevices[] =
|
||||
{
|
||||
|
||||
{ WAVE_FILE, QT_TRANSLATE_NOOP( "exportProjectDialog",
|
||||
"Uncompressed Wave-File (*.wav)" ),
|
||||
".wav", &audioFileWave::getInst },
|
||||
#ifdef HAVE_VORBIS_CODEC_H
|
||||
{ OGG_FILE, QT_TRANSLATE_NOOP( "exportProjectDialog",
|
||||
"Compressed OGG-File (*.ogg)" ),
|
||||
".ogg", &audioFileOgg::getInst },
|
||||
#endif
|
||||
// ... insert your own file-encoder-infos here... may be one day the
|
||||
// user can add own encoders inside the program...
|
||||
|
||||
{ NULL_FILE, NULL, NULL, NULL }
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
const int LABEL_MARGIN = 6;
|
||||
const int LABEL_X = 10;
|
||||
const int LABEL_WIDTH = 48;
|
||||
const int TYPE_STUFF_Y = 10;
|
||||
const int TYPE_HEIGHT = 26;
|
||||
const int TYPE_COMBO_WIDTH = 256;
|
||||
const int KBPS_STUFF_Y = TYPE_STUFF_Y + TYPE_HEIGHT + LABEL_MARGIN + 6;
|
||||
const int KBPS_HEIGHT = TYPE_HEIGHT;
|
||||
const int KBPS_COMBO_WIDTH = 64;
|
||||
const int HQ_MODE_CB_Y = KBPS_STUFF_Y + KBPS_HEIGHT + LABEL_MARGIN;
|
||||
const int HQ_MODE_CB_HEIGHT = TYPE_HEIGHT;
|
||||
const int HQ_MODE_CB_WIDTH = 300;
|
||||
const int CTL_BUTTONS_Y = HQ_MODE_CB_Y + HQ_MODE_CB_HEIGHT + LABEL_MARGIN + 6;
|
||||
const int CTL_BUTTONS_HEIGHT = 30;
|
||||
const int CTL_BUTTONS_WIDTH = 120;
|
||||
const int HOURGLASS_X = LABEL_X;
|
||||
const int HOURGLASS_Y = 24;
|
||||
const int HOURGLASS_WIDTH = 44;
|
||||
const int HOURGLASS_HEIGHT = 56;
|
||||
|
||||
const int EPB_X = LABEL_X + 60;
|
||||
const int EPB_Y = HOURGLASS_Y;
|
||||
const int EPB_WIDTH = 260;
|
||||
const int EPB_HEIGHT = 24;
|
||||
const int CANCEL_X_WHILE_EXPORT = 136;
|
||||
const int CANCEL_Y_WHILE_EXPORT = EPB_Y + EPB_HEIGHT + 32;
|
||||
|
||||
|
||||
Sint16 exportProjectDialog::s_availableBitrates[] =
|
||||
{
|
||||
64,
|
||||
80,
|
||||
96,
|
||||
112,
|
||||
128,
|
||||
160,
|
||||
192,
|
||||
256,
|
||||
320,
|
||||
-1
|
||||
};
|
||||
|
||||
|
||||
// TODO: rewrite that crap using layouts!!
|
||||
|
||||
exportProjectDialog::exportProjectDialog( const QString & _file_name,
|
||||
QWidget * _parent ) :
|
||||
QDialog( _parent ),
|
||||
m_fileName( _file_name ),
|
||||
m_hourglassLbl( NULL ),
|
||||
m_exportProgressBar( NULL ),
|
||||
m_deleteFile( FALSE ),
|
||||
m_oldProgressVal( -1 )
|
||||
{
|
||||
#ifdef QT4
|
||||
m_fileType = getFileTypeFromExtension( "." +
|
||||
QFileInfo( _file_name
|
||||
).completeSuffix() );
|
||||
#else
|
||||
m_fileType = getFileTypeFromExtension( "." + QFileInfo( _file_name
|
||||
).extension() );
|
||||
#endif
|
||||
setWindowTitle( tr( "Export project to %1" ).arg(
|
||||
QFileInfo( _file_name ).fileName() ) );
|
||||
|
||||
// type-ui-stuff
|
||||
m_typeLbl = new QLabel( tr( "Type:" ), this );
|
||||
m_typeLbl->setGeometry( LABEL_X, TYPE_STUFF_Y, LABEL_WIDTH,
|
||||
TYPE_HEIGHT );
|
||||
|
||||
m_typeCombo = new QComboBox( this );
|
||||
m_typeCombo->setGeometry( LABEL_X + LABEL_WIDTH+LABEL_MARGIN,
|
||||
TYPE_STUFF_Y, TYPE_COMBO_WIDTH,
|
||||
TYPE_HEIGHT );
|
||||
connect( m_typeCombo, SIGNAL( activated( const QString & ) ), this,
|
||||
SLOT( changedType( const QString & ) ) );
|
||||
|
||||
int idx = 0;
|
||||
while( fileEncodeDevices[idx].m_fileType != NULL_FILE )
|
||||
{
|
||||
m_typeCombo->addItem(
|
||||
tr( fileEncodeDevices[idx].m_description ) );
|
||||
++idx;
|
||||
}
|
||||
#ifdef QT4
|
||||
m_typeCombo->setCurrentIndex( m_typeCombo->findText( tr(
|
||||
fileEncodeDevices[m_fileType].m_description ) ) );
|
||||
#else
|
||||
m_typeCombo->setCurrentText( tr(
|
||||
fileEncodeDevices[m_fileType].m_description ) );
|
||||
#endif
|
||||
|
||||
|
||||
// kbps-ui-stuff
|
||||
m_kbpsLbl = new QLabel( tr( "kbps:" ), this );
|
||||
m_kbpsLbl->setGeometry( LABEL_X, KBPS_STUFF_Y, LABEL_WIDTH,
|
||||
KBPS_HEIGHT );
|
||||
|
||||
m_kbpsCombo = new QComboBox( this );
|
||||
m_kbpsCombo->setGeometry( LABEL_X + LABEL_WIDTH + LABEL_MARGIN,
|
||||
KBPS_STUFF_Y, KBPS_COMBO_WIDTH,
|
||||
KBPS_HEIGHT );
|
||||
|
||||
idx = 0;
|
||||
while( s_availableBitrates[idx] != -1 )
|
||||
{
|
||||
m_kbpsCombo->addItem( QString::number(
|
||||
s_availableBitrates[idx] ) );
|
||||
++idx;
|
||||
}
|
||||
#ifdef QT4
|
||||
m_typeCombo->setCurrentIndex( m_typeCombo->findText(
|
||||
QString::number( 128 ) ) );
|
||||
#else
|
||||
m_kbpsCombo->setCurrentText( QString::number( 128 ) );
|
||||
#endif
|
||||
|
||||
|
||||
m_vbrCb = new QCheckBox( tr( "variable bitrate" ), this );
|
||||
m_vbrCb->setGeometry( LABEL_X + LABEL_WIDTH + 3 * LABEL_MARGIN +
|
||||
KBPS_COMBO_WIDTH, KBPS_STUFF_Y + 3, 190, 20 );
|
||||
m_vbrCb->setChecked( TRUE );
|
||||
|
||||
|
||||
m_hqmCb = new QCheckBox( tr( "use high-quality-mode (recommened)" ),
|
||||
this );
|
||||
m_hqmCb->setGeometry( LABEL_X, HQ_MODE_CB_Y + 3, HQ_MODE_CB_WIDTH,
|
||||
HQ_MODE_CB_HEIGHT );
|
||||
m_hqmCb->setChecked( TRUE );
|
||||
|
||||
|
||||
m_exportBtn = new QPushButton( embed::getIconPixmap( "apply" ),
|
||||
tr( "Export" ), this );
|
||||
m_exportBtn->setGeometry( LABEL_X + LABEL_WIDTH + LABEL_MARGIN,
|
||||
CTL_BUTTONS_Y, CTL_BUTTONS_WIDTH,
|
||||
CTL_BUTTONS_HEIGHT );
|
||||
connect( m_exportBtn, SIGNAL( clicked() ), this,
|
||||
SLOT( exportBtnClicked() ) );
|
||||
|
||||
m_cancelBtn = new QPushButton( embed::getIconPixmap( "cancel" ),
|
||||
tr( "Cancel" ), this );
|
||||
m_cancelBtn->setGeometry( LABEL_X + LABEL_WIDTH + 2 * LABEL_MARGIN +
|
||||
CTL_BUTTONS_WIDTH, CTL_BUTTONS_Y,
|
||||
CTL_BUTTONS_WIDTH, CTL_BUTTONS_HEIGHT );
|
||||
connect( m_cancelBtn, SIGNAL( clicked() ), this,
|
||||
SLOT( cancelBtnClicked() ) );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
exportProjectDialog::~exportProjectDialog()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// little help-function for getting file-type from a file-extension (only for
|
||||
// registered file-encoders)
|
||||
fileTypes exportProjectDialog::getFileTypeFromExtension( const QString & _ext )
|
||||
{
|
||||
int idx = 0;
|
||||
while( fileEncodeDevices[idx].m_fileType != NULL_FILE )
|
||||
{
|
||||
if( QString( fileEncodeDevices[idx].m_extension ) == _ext )
|
||||
{
|
||||
return( fileEncodeDevices[idx].m_fileType );
|
||||
}
|
||||
++idx;
|
||||
}
|
||||
|
||||
return( WAVE_FILE ); // default
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void exportProjectDialog::keyPressEvent( QKeyEvent * _ke )
|
||||
{
|
||||
if( _ke->key() == Qt::Key_Escape )
|
||||
{
|
||||
if( songEditor::inst()->exporting() == FALSE )
|
||||
{
|
||||
accept();
|
||||
}
|
||||
else
|
||||
{
|
||||
abortProjectExport();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void exportProjectDialog::closeEvent (QCloseEvent * _ce)
|
||||
{
|
||||
if( songEditor::inst()->exporting() == TRUE )
|
||||
{
|
||||
abortProjectExport();
|
||||
_ce->ignore();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void exportProjectDialog::changedType( const QString & _new_type )
|
||||
{
|
||||
int idx = 0;
|
||||
while( fileEncodeDevices[idx].m_fileType != NULL_FILE )
|
||||
{
|
||||
if( tr( fileEncodeDevices[idx].m_description ) == _new_type )
|
||||
{
|
||||
m_fileType = fileEncodeDevices[idx].m_fileType;
|
||||
break;
|
||||
}
|
||||
++idx;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void exportProjectDialog::exportBtnClicked( void )
|
||||
{
|
||||
int idx = 0;
|
||||
while( fileEncodeDevices[idx].m_fileType != NULL_FILE )
|
||||
{
|
||||
if( fileEncodeDevices[idx].m_fileType == m_fileType )
|
||||
{
|
||||
bool success_ful = FALSE;
|
||||
audioDevice * dev = fileEncodeDevices[idx].m_getDevInst(
|
||||
DEFAULT_SAMPLE_RATE,
|
||||
DEFAULT_CHANNELS,
|
||||
success_ful,
|
||||
m_fileName,
|
||||
m_vbrCb->isChecked(),
|
||||
m_kbpsCombo->currentText().toInt(),
|
||||
m_kbpsCombo->currentText().toInt() - 64,
|
||||
m_kbpsCombo->currentText().toInt() + 64
|
||||
);
|
||||
if( success_ful == FALSE )
|
||||
{
|
||||
QMessageBox::information( this,
|
||||
tr( "Export failed" ),
|
||||
tr( "The project-export failed, "
|
||||
"because the output-file/-"
|
||||
"device could not be opened.\n"
|
||||
"Make sure, you have write "
|
||||
"access to the selected "
|
||||
"file/device!" ),
|
||||
QMessageBox::Ok );
|
||||
return;
|
||||
}
|
||||
mixer::inst()->pause();
|
||||
mixer::inst()->setAudioDevice( dev,
|
||||
m_hqmCb->isChecked() );
|
||||
songEditor::inst()->startExport();
|
||||
mixer::inst()->play();
|
||||
break;
|
||||
}
|
||||
++idx;
|
||||
}
|
||||
|
||||
if( fileEncodeDevices[idx].m_fileType == NULL_FILE )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
setWindowTitle( tr( "Exporting project to %1" ).arg(
|
||||
QFileInfo( m_fileName ).fileName() ) );
|
||||
|
||||
delete m_typeLbl;
|
||||
delete m_typeCombo;
|
||||
delete m_kbpsLbl;
|
||||
delete m_kbpsCombo;
|
||||
delete m_vbrCb;
|
||||
delete m_hqmCb;
|
||||
delete m_exportBtn;
|
||||
|
||||
m_exportProgressBar = new QProgressBar( this );
|
||||
m_exportProgressBar->setGeometry( EPB_X, EPB_Y, EPB_WIDTH, EPB_HEIGHT );
|
||||
#ifdef QT4
|
||||
m_exportProgressBar->setMaximum( 100 );
|
||||
#else
|
||||
m_exportProgressBar->setTotalSteps( 100 );
|
||||
#endif
|
||||
m_exportProgressBar->show();
|
||||
|
||||
m_hourglassLbl = new QLabel( this );
|
||||
m_hourglassLbl->setPixmap( embed::getIconPixmap( "hourglass" ) );
|
||||
m_hourglassLbl->setGeometry( HOURGLASS_X, HOURGLASS_Y,
|
||||
HOURGLASS_WIDTH, HOURGLASS_HEIGHT );
|
||||
m_hourglassLbl->show();
|
||||
|
||||
m_cancelBtn->move( CANCEL_X_WHILE_EXPORT, CANCEL_Y_WHILE_EXPORT );
|
||||
|
||||
m_progressBarUpdateTimer = new QTimer( this );
|
||||
connect( m_progressBarUpdateTimer, SIGNAL( timeout() ), this,
|
||||
SLOT( redrawProgressBar() ) );
|
||||
m_progressBarUpdateTimer->start( 100 );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void exportProjectDialog::cancelBtnClicked( void )
|
||||
{
|
||||
// is song-export-thread active?
|
||||
if( songEditor::inst()->exporting() == TRUE )
|
||||
{
|
||||
// then dispose abort of export
|
||||
abortProjectExport();
|
||||
return;
|
||||
}
|
||||
|
||||
// if the user aborted export-process, the file has to be deleted
|
||||
if( m_deleteFile )
|
||||
{
|
||||
QFile( m_fileName ).remove();
|
||||
}
|
||||
|
||||
// restore window-title
|
||||
lmmsMainWin::inst()->resetWindowTitle();
|
||||
|
||||
// let's close us...
|
||||
accept();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// called whenever there's a reason for aborting song-export (like user-input)
|
||||
void exportProjectDialog::abortProjectExport( void )
|
||||
{
|
||||
mixer::inst()->pause();
|
||||
m_deleteFile = TRUE;
|
||||
|
||||
finishProjectExport();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void exportProjectDialog::finishProjectExport( void )
|
||||
{
|
||||
m_progressBarUpdateTimer->stop();
|
||||
delete m_progressBarUpdateTimer;
|
||||
|
||||
mixer::inst()->restoreAudioDevice();
|
||||
songEditor::inst()->stopExport();
|
||||
|
||||
mixer::inst()->play();
|
||||
|
||||
// this method does the final cleanup...
|
||||
cancelBtnClicked();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void exportProjectDialog::redrawProgressBar( void )
|
||||
{
|
||||
if( m_progressVal != m_oldProgressVal )
|
||||
{
|
||||
#ifdef QT4
|
||||
m_exportProgressBar->setValue( m_progressVal );
|
||||
#else
|
||||
m_exportProgressBar->setProgress( m_progressVal );
|
||||
#endif
|
||||
// update lmms-main-win-caption
|
||||
lmmsMainWin::inst()->setWindowTitle( tr( "Rendering:" ) + " " +
|
||||
QString::number( m_progressVal ) + "%" );
|
||||
m_oldProgressVal = m_progressVal;
|
||||
}
|
||||
|
||||
if( songEditor::inst()->exportDone() == TRUE ||
|
||||
songEditor::inst()->exporting() == FALSE )
|
||||
{
|
||||
finishProjectExport();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void exportProjectDialog::updateProgressBar( int _new_val )
|
||||
{
|
||||
m_progressVal = _new_val;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#include "export_project_dialog.moc"
|
||||
|
||||
168
src/core/main.cpp
Normal file
168
src/core/main.cpp
Normal file
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* main.cpp - just main.cpp which is starting up app...
|
||||
*
|
||||
* Linux MultiMedia Studio
|
||||
* Copyright (c) 2004-2005 Tobias Doerffel <tobydox@users.sourceforge.net>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "qt3support.h"
|
||||
|
||||
#ifdef QT4
|
||||
|
||||
#include <QApplication>
|
||||
#include <QLocale>
|
||||
#include <QSplashScreen>
|
||||
|
||||
#else
|
||||
|
||||
#include <qapplication.h>
|
||||
#include <qtextcodec.h>
|
||||
#if QT_VERSION >= 0x030200
|
||||
#include <qsplashscreen.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#include "lmms_main_win.h"
|
||||
#include "embed.h"
|
||||
#include "config_mgr.h"
|
||||
#include "export_project_dialog.h"
|
||||
#include "song_editor.h"
|
||||
#include "templates.h"
|
||||
|
||||
|
||||
#if QT_VERSION >= 0x030100
|
||||
int splash_alignment_flags = Qt::AlignTop | Qt::AlignLeft;
|
||||
#endif
|
||||
|
||||
QString file_to_load;
|
||||
QString file_to_render;
|
||||
|
||||
|
||||
int main( int argc, char * * argv )
|
||||
{
|
||||
QApplication app( argc, argv );
|
||||
|
||||
for( int i = 1; i < app.argc(); ++i )
|
||||
{
|
||||
if( QString( app.argv()[i] ) == "--version" ||
|
||||
QString( app.argv()[i] ) == "-v" )
|
||||
{
|
||||
printf( "\n%s\n\n"
|
||||
"This program is free software; you can redistribute it and/or\n"
|
||||
"modify it under the terms of the GNU General Public\n"
|
||||
"License as published by the Free Software Foundation; either\n"
|
||||
"version 2 of the License, or (at your option) any later version.\n\n",
|
||||
PACKAGE_STRING );
|
||||
return( 0 );
|
||||
}
|
||||
else if( app.argc() > i &&
|
||||
( QString( app.argv()[i] ) == "--render" ||
|
||||
QString( app.argv()[i] ) == "-r" ) )
|
||||
{
|
||||
file_to_load = QString( app.argv()[i+1] );
|
||||
file_to_render = QString( app.argv()[i+1] ) + ".wav";
|
||||
}
|
||||
else
|
||||
{
|
||||
file_to_load = app.argv()[i];
|
||||
}
|
||||
}
|
||||
|
||||
QString pos =
|
||||
#ifdef QT4
|
||||
QLocale::system().name().left( 2 );
|
||||
#else
|
||||
QString( QTextCodec::locale() ).section( '_', 0, 0 );
|
||||
#endif
|
||||
// load translation for Qt-widgets/-dialogs
|
||||
embed::loadTranslation( QString( "qt_" ) + pos );
|
||||
// load actual translation for LMMS
|
||||
embed::loadTranslation( pos );
|
||||
|
||||
#ifdef QT4
|
||||
app.setFont( pointSize<10>( app.font() ) );
|
||||
#endif
|
||||
|
||||
|
||||
if( !configManager::inst()->loadConfigFile() )
|
||||
{
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
QPalette pal = app.palette();
|
||||
#ifdef QT4
|
||||
pal.setColor( QPalette::Background, QColor( 128, 128, 128 ) );
|
||||
pal.setColor( QPalette::Foreground, QColor( 240, 240, 240 ) );
|
||||
pal.setColor( QPalette::Base, QColor( 128, 128, 128 ) );
|
||||
pal.setColor( QPalette::Text, QColor( 224, 224, 224 ) );
|
||||
pal.setColor( QPalette::Button, QColor( 160, 160, 160 ) );
|
||||
pal.setColor( QPalette::ButtonText, QColor( 255, 255, 255 ) );
|
||||
pal.setColor( QPalette::Highlight, QColor( 255, 224, 224 ) );
|
||||
pal.setColor( QPalette::HighlightedText, QColor( 0, 0, 0 ) );
|
||||
#else
|
||||
pal.setColor( QColorGroup::Background, QColor( 128, 128, 128 ) );
|
||||
pal.setColor( QColorGroup::Foreground, QColor( 240, 240, 240 ) );
|
||||
pal.setColor( QColorGroup::Base, QColor( 128, 128, 128 ) );
|
||||
pal.setColor( QColorGroup::Text, QColor( 224, 224, 224 ) );
|
||||
pal.setColor( QColorGroup::Button, QColor( 160, 160, 160 ) );
|
||||
pal.setColor( QColorGroup::ButtonText, QColor( 255, 255, 255 ) );
|
||||
pal.setColor( QColorGroup::Highlight, QColor( 224, 224, 224 ) );
|
||||
pal.setColor( QColorGroup::HighlightedText, QColor( 0, 0, 0 ) );
|
||||
#endif
|
||||
app.setPalette( pal );
|
||||
|
||||
|
||||
#if QT_VERSION >= 0x030200
|
||||
// init splash screen
|
||||
QPixmap splash = embed::getIconPixmap( "splash" );
|
||||
lmmsMainWin::s_splashScreen = new QSplashScreen( splash );
|
||||
lmmsMainWin::s_splashScreen->show();
|
||||
|
||||
lmmsMainWin::s_splashScreen->showMessage( lmmsMainWin::tr(
|
||||
"Setting up main-"
|
||||
"window and "
|
||||
"workspace..." ),
|
||||
splash_alignment_flags,
|
||||
Qt::white );
|
||||
#endif
|
||||
|
||||
#ifndef QT4
|
||||
app.setMainWidget( lmmsMainWin::inst() );
|
||||
#endif
|
||||
lmmsMainWin::inst()->showMaximized();
|
||||
|
||||
|
||||
#if QT_VERSION >= 0x030200
|
||||
delete lmmsMainWin::s_splashScreen;
|
||||
lmmsMainWin::s_splashScreen = NULL;
|
||||
#endif
|
||||
if( file_to_render != "" )
|
||||
{
|
||||
exportProjectDialog * e = new exportProjectDialog(
|
||||
file_to_render,
|
||||
lmmsMainWin::inst() );
|
||||
songEditor::inst()->setExportProjectDialog( e );
|
||||
e->show();
|
||||
e->exportBtnClicked();
|
||||
}
|
||||
return( app.exec() );
|
||||
}
|
||||
|
||||
698
src/core/mixer.cpp
Normal file
698
src/core/mixer.cpp
Normal file
@@ -0,0 +1,698 @@
|
||||
/*
|
||||
* mixer.cpp - audio-device-independent mixer for LMMS
|
||||
*
|
||||
* Linux MultiMedia Studio
|
||||
* Copyright (c) 2004-2005 Tobias Doerffel <tobydox@users.sourceforge.net>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "mixer.h"
|
||||
#include "play_handle.h"
|
||||
#include "song_editor.h"
|
||||
#include "templates.h"
|
||||
#include "envelope_and_lfo_widget.h"
|
||||
#include "buffer_allocator.h"
|
||||
#include "debug.h"
|
||||
#include "config_mgr.h"
|
||||
|
||||
#include "audio_device.h"
|
||||
#include "midi_device.h"
|
||||
|
||||
// platform-specific audio-interface-classes
|
||||
#include "audio_alsa.h"
|
||||
#include "audio_jack.h"
|
||||
#include "audio_oss.h"
|
||||
#include "audio_sdl.h"
|
||||
#include "audio_dummy.h"
|
||||
|
||||
// platform-specific midi-interface-classes
|
||||
#include "midi_alsa_raw.h"
|
||||
#include "midi_oss.h"
|
||||
#include "midi_dummy.h"
|
||||
|
||||
|
||||
|
||||
Uint32 SAMPLE_RATES[QUALITY_LEVELS] = { 44100, 88200 } ;
|
||||
|
||||
mixer * mixer::s_instanceOfMe = NULL;
|
||||
|
||||
|
||||
mixer::mixer() :
|
||||
#ifndef QT4
|
||||
QObject(),
|
||||
#endif
|
||||
QThread(),
|
||||
m_silence(),
|
||||
#ifndef DISABLE_SURROUND
|
||||
m_surroundSilence(),
|
||||
#endif
|
||||
m_framesPerAudioBuffer( DEFAULT_BUFFER_SIZE ),
|
||||
m_buffer1( NULL ),
|
||||
m_buffer2( NULL ),
|
||||
m_curBuf( NULL ),
|
||||
m_nextBuf( NULL ),
|
||||
m_discardCurBuf( FALSE ),
|
||||
m_qualityLevel( DEFAULT_QUALITY_LEVEL ),
|
||||
m_masterOutput( 1.0f ),
|
||||
m_quit( FALSE ),
|
||||
m_audioDev( NULL ),
|
||||
m_oldAudioDev( NULL )
|
||||
{
|
||||
// small hack because code calling mixer::inst() is called out of ctor
|
||||
s_instanceOfMe = this;
|
||||
|
||||
if( configManager::inst()->value( "mixer", "framesperaudiobuffer"
|
||||
).toInt() >= 32 )
|
||||
{
|
||||
m_framesPerAudioBuffer = configManager::inst()->value( "mixer",
|
||||
"framesperaudiobuffer" ).toInt();
|
||||
}
|
||||
else
|
||||
{
|
||||
configManager::inst()->setValue( "mixer",
|
||||
"framesperaudiobuffer",
|
||||
QString::number( m_framesPerAudioBuffer ) );
|
||||
}
|
||||
|
||||
m_buffer1 = bufferAllocator::alloc<surroundSampleFrame>(
|
||||
m_framesPerAudioBuffer );
|
||||
m_buffer2 = bufferAllocator::alloc<surroundSampleFrame>(
|
||||
m_framesPerAudioBuffer );
|
||||
|
||||
m_curBuf = m_buffer1;
|
||||
m_nextBuf = m_buffer2;
|
||||
|
||||
|
||||
m_audioDev = tryAudioDevices();
|
||||
m_midiDev = tryMIDIDevices();
|
||||
|
||||
|
||||
for( int i = 0; i < MAX_SAMPLE_PACKETS; ++i )
|
||||
{
|
||||
m_samplePackets[i].m_buffer = NULL;
|
||||
m_samplePackets[i].m_state = samplePacket::UNUSED;
|
||||
}
|
||||
|
||||
m_silence = bufferAllocator::alloc<sampleFrame>(
|
||||
m_framesPerAudioBuffer );
|
||||
m_surroundSilence = bufferAllocator::alloc<surroundSampleFrame>(
|
||||
m_framesPerAudioBuffer );
|
||||
|
||||
for( Uint32 frame = 0; frame < m_framesPerAudioBuffer; ++frame )
|
||||
{
|
||||
for( Uint8 chnl = 0; chnl < DEFAULT_CHANNELS; ++chnl )
|
||||
{
|
||||
m_silence[frame][chnl] = 0.0f;
|
||||
}
|
||||
#ifndef DISABLE_SURROUND
|
||||
for( Uint8 chnl = 0; chnl < SURROUND_CHANNELS; ++chnl )
|
||||
{
|
||||
m_surroundSilence[frame][chnl] = 0.0f;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// now clear our two output-buffers before using them...
|
||||
clearAudioBuffer( m_buffer1, m_framesPerAudioBuffer );
|
||||
clearAudioBuffer( m_buffer2, m_framesPerAudioBuffer );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
mixer::~mixer()
|
||||
{
|
||||
delete m_audioDev;
|
||||
|
||||
bufferAllocator::free( m_buffer1 );
|
||||
bufferAllocator::free( m_buffer2 );
|
||||
|
||||
for( int i = 0; i < MAX_SAMPLE_PACKETS; ++i )
|
||||
{
|
||||
if( m_samplePackets[i].m_state != samplePacket::UNUSED )
|
||||
{
|
||||
bufferAllocator::free( m_samplePackets[i].m_buffer );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void mixer::quitThread( void )
|
||||
{
|
||||
// make sure there're no mutexes locked anymore...
|
||||
m_safetySyncMutex.unlock();
|
||||
m_devMutex.unlock();
|
||||
|
||||
// now tell mixer-thread to quit
|
||||
m_quit = TRUE;
|
||||
|
||||
wait( 1000 );
|
||||
terminate();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void mixer::run( void )
|
||||
{
|
||||
|
||||
while( m_quit == FALSE )
|
||||
{
|
||||
|
||||
// remove all play-handles that have to be deleted and delete
|
||||
// them if they still exist...
|
||||
// maybe this algorithm could be optimized...
|
||||
while( !m_playHandlesToRemove.isEmpty() )
|
||||
{
|
||||
playHandleVector::iterator it = m_playHandles.begin();
|
||||
|
||||
while( it != m_playHandles.end() )
|
||||
{
|
||||
if( *it == m_playHandlesToRemove.first() )
|
||||
{
|
||||
m_playHandles.erase( it );
|
||||
delete m_playHandlesToRemove.first();
|
||||
break;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
m_playHandlesToRemove.erase(
|
||||
m_playHandlesToRemove.begin() );
|
||||
|
||||
}
|
||||
|
||||
// now we have to make sure no other thread does anything bad
|
||||
// while we're acting...
|
||||
m_safetySyncMutex.lock();
|
||||
|
||||
/* following code is faster but unstable since using iterators
|
||||
while deleting from vector is dangerous and often leads to
|
||||
undefined results...
|
||||
|
||||
playHandleVector::iterator it = m_playHandles.begin();
|
||||
while( it != m_playHandles.end() )
|
||||
{
|
||||
if( ( *it )->done() )
|
||||
{
|
||||
// delete all play-handles which have
|
||||
// played completely now
|
||||
delete *it;
|
||||
m_playHandles.erase( it );
|
||||
}
|
||||
else
|
||||
{
|
||||
// play all uncompletely-played play-handles...
|
||||
( *it )->play();
|
||||
++it;
|
||||
}
|
||||
}*/
|
||||
csize idx = 0;
|
||||
while( idx < m_playHandles.size() )
|
||||
{
|
||||
register playHandle * n = m_playHandles[idx];
|
||||
if( n->done() )
|
||||
{
|
||||
// delete all play-handles which have
|
||||
// played completely now
|
||||
delete n;
|
||||
m_playHandles.erase( m_playHandles.begin() +
|
||||
idx );
|
||||
}
|
||||
else
|
||||
{
|
||||
// play all uncompletely-played play-handles...
|
||||
n->play();
|
||||
++idx;
|
||||
}
|
||||
}
|
||||
|
||||
songEditor::inst()->processNextBuffer();
|
||||
|
||||
// check for samples-packets that have to be mixed in
|
||||
// the current audio-buffer
|
||||
for( int i = 0; i < MAX_SAMPLE_PACKETS; ++i )
|
||||
{
|
||||
if( m_samplePackets[i].m_state == samplePacket::READY )
|
||||
{
|
||||
if( m_samplePackets[i].m_framesAhead <=
|
||||
m_framesPerAudioBuffer )
|
||||
{
|
||||
// found one! mix it...
|
||||
mixSamplePacket( &m_samplePackets[i] );
|
||||
// now this audio-sample can be used
|
||||
// again
|
||||
bufferAllocator::free(
|
||||
m_samplePackets[i].m_buffer );
|
||||
m_samplePackets[i].m_state =
|
||||
samplePacket::UNUSED;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_samplePackets[i].m_framesAhead -=
|
||||
m_framesPerAudioBuffer;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( !m_discardCurBuf )
|
||||
{
|
||||
m_devMutex.lock();
|
||||
// write actual data to our current output-device
|
||||
// (blocking!)
|
||||
m_audioDev->writeBuffer( m_curBuf,
|
||||
m_framesPerAudioBuffer,
|
||||
SAMPLE_RATES[m_qualityLevel],
|
||||
m_masterOutput );
|
||||
m_devMutex.unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_discardCurBuf = FALSE;
|
||||
}
|
||||
|
||||
emit nextAudioBuffer( m_curBuf, m_framesPerAudioBuffer );
|
||||
|
||||
|
||||
m_safetySyncMutex.unlock();
|
||||
|
||||
|
||||
// clear last audio-buffer
|
||||
clearAudioBuffer( m_curBuf, m_framesPerAudioBuffer );
|
||||
|
||||
// now swap the buffers... current buffer becomes next (last)
|
||||
// buffer and the next buffer becomes current (first) buffer
|
||||
qSwap( m_curBuf, m_nextBuf );
|
||||
|
||||
// and trigger LFOs
|
||||
envelopeAndLFOWidget::triggerLFO();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// removes all play-handles. this is neccessary, when the song is stopped ->
|
||||
// all remaining notes etc. would be played until their end
|
||||
void mixer::clear( void )
|
||||
{
|
||||
m_midiDev->noteOffAll();
|
||||
for( playHandleVector::iterator it = m_playHandles.begin();
|
||||
it != m_playHandles.end(); ++it )
|
||||
{
|
||||
m_playHandlesToRemove.push_back( *it );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FASTCALL mixer::clearAudioBuffer( sampleFrame * _ab, Uint32 _frames )
|
||||
{
|
||||
if( _frames == m_framesPerAudioBuffer )
|
||||
{
|
||||
memcpy( _ab, m_silence, m_framesPerAudioBuffer *
|
||||
BYTES_PER_FRAME );
|
||||
}
|
||||
else
|
||||
{
|
||||
for( Uint32 frame = 0; frame < _frames; ++frame )
|
||||
{
|
||||
for( Uint8 ch = 0; ch < DEFAULT_CHANNELS; ++ch )
|
||||
{
|
||||
_ab[frame][ch] = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifndef DISABLE_SURROUND
|
||||
void FASTCALL mixer::clearAudioBuffer( surroundSampleFrame * _ab,
|
||||
Uint32 _frames )
|
||||
{
|
||||
if( _frames == m_framesPerAudioBuffer )
|
||||
{
|
||||
memcpy( _ab, m_surroundSilence, m_framesPerAudioBuffer *
|
||||
BYTES_PER_SURROUND_FRAME );
|
||||
}
|
||||
else
|
||||
{
|
||||
for( Uint32 frame = 0; frame < _frames; ++frame )
|
||||
{
|
||||
for( Uint8 ch = 0; ch < DEFAULT_CHANNELS; ++ch )
|
||||
{
|
||||
_ab[frame][ch] = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void FASTCALL mixer::addBuffer( sampleFrame * _buf, Uint32 _frames,
|
||||
Uint32 _frames_ahead,
|
||||
volumeVector & _volume_vector )
|
||||
{
|
||||
#ifdef LMMS_DEBUG
|
||||
bool success = FALSE;
|
||||
#endif
|
||||
for ( Uint16 i = 0; i < MAX_SAMPLE_PACKETS; ++i )
|
||||
{
|
||||
if( m_samplePackets[i].m_state == samplePacket::UNUSED )
|
||||
{
|
||||
m_samplePackets[i].m_state = samplePacket::FILLING;
|
||||
m_samplePackets[i].m_frames = _frames;//m_framesPerAudioBuffer;
|
||||
m_samplePackets[i].m_framesDone = 0;
|
||||
m_samplePackets[i].m_framesAhead = _frames_ahead;
|
||||
|
||||
m_samplePackets[i].m_buffer =
|
||||
bufferAllocator::alloc<surroundSampleFrame>(
|
||||
m_framesPerAudioBuffer );
|
||||
// now we have to make a surround-buffer out of a
|
||||
// stereo-buffer (could be done more easily if there
|
||||
// would be no volume-vector...)
|
||||
for( Uint32 frame = 0; frame < _frames/*m_framesPerAudioBuffer*/;
|
||||
++frame )
|
||||
{
|
||||
for( Uint8 chnl = 0; chnl < SURROUND_CHANNELS;
|
||||
++chnl )
|
||||
{
|
||||
m_samplePackets[i].m_buffer[frame][chnl] =
|
||||
_buf[frame][chnl%DEFAULT_CHANNELS] *
|
||||
_volume_vector.vol[chnl];
|
||||
}
|
||||
}
|
||||
|
||||
m_samplePackets[i].m_state = samplePacket::READY;
|
||||
#ifdef LMMS_DEBUG
|
||||
success = TRUE;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifdef LMMS_DEBUG
|
||||
if( success == FALSE )
|
||||
{
|
||||
qWarning( "No sample-packets left in mixer::addBuffer(...)!\n" );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void mixer::setHighQuality( bool _hq_on )
|
||||
{
|
||||
m_safetySyncMutex.lock();
|
||||
|
||||
// delete (= close) our audio-device
|
||||
delete m_audioDev;
|
||||
|
||||
// set new quality-level...
|
||||
if( _hq_on == TRUE )
|
||||
{
|
||||
m_qualityLevel = HIGH_QUALITY_LEVEL;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_qualityLevel = DEFAULT_QUALITY_LEVEL;
|
||||
}
|
||||
// and re-open device
|
||||
m_audioDev = tryAudioDevices();
|
||||
|
||||
m_safetySyncMutex.unlock();
|
||||
|
||||
emit( sampleRateChanged() );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FASTCALL mixer::setAudioDevice( audioDevice * _dev, bool _hq )
|
||||
{
|
||||
|
||||
m_devMutex.lock();
|
||||
|
||||
m_oldAudioDev = m_audioDev;
|
||||
|
||||
if( _dev == NULL )
|
||||
{
|
||||
printf( "param _dev == NULL in mixer::setAudioDevice(...). "
|
||||
"Trying any working audio-device\n" );
|
||||
m_audioDev = tryAudioDevices();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_audioDev = _dev;
|
||||
}
|
||||
|
||||
m_qualityLevel = _hq ? 1 : 0;
|
||||
emit sampleRateChanged();
|
||||
|
||||
m_devMutex.unlock();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void mixer::restoreAudioDevice( void )
|
||||
{
|
||||
m_devMutex.lock();
|
||||
|
||||
if( m_oldAudioDev != NULL )
|
||||
{
|
||||
delete m_audioDev;
|
||||
m_audioDev = m_oldAudioDev;
|
||||
for( Uint8 qli = 0; qli < QUALITY_LEVELS; ++qli )
|
||||
{
|
||||
if( SAMPLE_RATES[qli] == m_audioDev->sampleRate() )
|
||||
{
|
||||
m_qualityLevel = qli;
|
||||
emit sampleRateChanged();
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_oldAudioDev = NULL;
|
||||
m_discardCurBuf = TRUE;
|
||||
}
|
||||
|
||||
m_devMutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void mixer::checkValidityOfPlayHandles( void )
|
||||
{
|
||||
playHandleVector::iterator it = m_playHandles.begin();
|
||||
while( it != m_playHandles.end() )
|
||||
{
|
||||
( *it )->checkValidity();
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FASTCALL mixer::mixSamplePacket( samplePacket * _sp )
|
||||
{
|
||||
Uint32 start_frame = _sp->m_framesAhead % m_framesPerAudioBuffer;
|
||||
Uint32 end_frame = start_frame + _sp->m_frames;//m_framesPerAudioBuffer;
|
||||
|
||||
if( end_frame <= m_framesPerAudioBuffer )
|
||||
{
|
||||
for( Uint32 frame = start_frame; frame < end_frame; ++frame )
|
||||
{
|
||||
for( Uint8 chnl = 0; chnl < SURROUND_CHANNELS; ++chnl )
|
||||
{
|
||||
m_curBuf[frame][chnl] +=
|
||||
_sp->m_buffer[frame-start_frame][chnl];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( Uint32 frame = start_frame; frame <
|
||||
m_framesPerAudioBuffer; ++frame )
|
||||
{
|
||||
for( Uint8 chnl = 0; chnl < SURROUND_CHANNELS; ++chnl )
|
||||
{
|
||||
m_curBuf[frame][chnl] +=
|
||||
_sp->m_buffer[frame-start_frame][chnl];
|
||||
}
|
||||
}
|
||||
|
||||
Uint32 frames_done = m_framesPerAudioBuffer - start_frame;
|
||||
end_frame = tMin( end_frame -= m_framesPerAudioBuffer,
|
||||
m_framesPerAudioBuffer );
|
||||
|
||||
for( Uint32 frame = 0; frame < end_frame; ++frame )
|
||||
{
|
||||
for( Uint8 chnl = 0; chnl < SURROUND_CHANNELS; ++chnl )
|
||||
{
|
||||
m_nextBuf[frame][chnl] +=
|
||||
_sp->m_buffer[frames_done+frame][chnl];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
audioDevice * mixer::tryAudioDevices( void )
|
||||
{
|
||||
//m_discardCurBuf = TRUE;
|
||||
|
||||
bool success_ful = FALSE;
|
||||
audioDevice * dev = NULL;
|
||||
QString dev_name = configManager::inst()->value( "mixer", "audiodev" );
|
||||
|
||||
#ifdef OSS_SUPPORT
|
||||
if( dev_name == audioOSS::name() || dev_name == "" )
|
||||
{
|
||||
dev = new audioOSS( SAMPLE_RATES[DEFAULT_QUALITY_LEVEL],
|
||||
success_ful );
|
||||
if( success_ful )
|
||||
{
|
||||
m_audioDevName = audioOSS::name();
|
||||
return( dev );
|
||||
}
|
||||
delete dev;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ALSA_SUPPORT
|
||||
if( dev_name == audioALSA::name() || dev_name == "" )
|
||||
{
|
||||
dev = new audioALSA( SAMPLE_RATES[DEFAULT_QUALITY_LEVEL],
|
||||
success_ful );
|
||||
if( success_ful )
|
||||
{
|
||||
m_audioDevName = audioALSA::name();
|
||||
return( dev );
|
||||
}
|
||||
delete dev;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef JACK_SUPPORT
|
||||
if( dev_name == audioJACK::name() || dev_name == "" )
|
||||
{
|
||||
dev = new audioJACK( SAMPLE_RATES[DEFAULT_QUALITY_LEVEL],
|
||||
success_ful );
|
||||
if( success_ful )
|
||||
{
|
||||
m_audioDevName = audioJACK::name();
|
||||
return( dev );
|
||||
}
|
||||
delete dev;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef SDL_AUDIO_SUPPORT
|
||||
if( dev_name == audioSDL::name() || dev_name == "" )
|
||||
{
|
||||
dev = new audioSDL( SAMPLE_RATES[DEFAULT_QUALITY_LEVEL],
|
||||
success_ful );
|
||||
if( success_ful )
|
||||
{
|
||||
m_audioDevName = audioSDL::name();
|
||||
return( dev );
|
||||
}
|
||||
delete dev;
|
||||
}
|
||||
#endif
|
||||
|
||||
// add more device-classes here...
|
||||
//dev = new audioXXXX( SAMPLE_RATES[m_qualityLevel], success_ful );
|
||||
//if( sucess_ful )
|
||||
//{
|
||||
// return( dev );
|
||||
//}
|
||||
//delete dev
|
||||
|
||||
printf( "No audio-driver working - falling back to dummy-audio-"
|
||||
"driver\nYou can render your songs and listen to the output "
|
||||
"files...\n" );
|
||||
|
||||
m_audioDevName = audioDummy::name();
|
||||
|
||||
return( new audioDummy( SAMPLE_RATES[m_qualityLevel], success_ful ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
midiDevice * mixer::tryMIDIDevices( void )
|
||||
{
|
||||
QString dev_name = configManager::inst()->value( "mixer", "mididev" );
|
||||
|
||||
#ifdef ALSA_SUPPORT
|
||||
if( dev_name == midiALSARaw::name() || dev_name == "" )
|
||||
{
|
||||
midiALSARaw * malsa = new midiALSARaw();
|
||||
if( malsa->isRunning() )
|
||||
{
|
||||
m_midiDevName = midiALSARaw::name();
|
||||
return( malsa );
|
||||
}
|
||||
delete malsa;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef OSS_SUPPORT
|
||||
if( dev_name == midiOSS::name() || dev_name == "" )
|
||||
{
|
||||
midiOSS * moss = new midiOSS();
|
||||
if( moss->isRunning() )
|
||||
{
|
||||
m_midiDevName = midiOSS::name();
|
||||
return( moss );
|
||||
}
|
||||
delete moss;
|
||||
}
|
||||
#endif
|
||||
|
||||
printf( "Couldn't open a MIDI-device, neither with ALSA nor with "
|
||||
"OSS. Will use dummy-MIDI-device.\n" );
|
||||
|
||||
m_midiDevName = midiDummy::name();
|
||||
|
||||
return( new midiDummy() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
#include "mixer.moc"
|
||||
|
||||
153
src/core/name_label.cpp
Normal file
153
src/core/name_label.cpp
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* name_label.cpp - implementation of class nameLabel, a label which
|
||||
* is renamable by double-clicking it
|
||||
*
|
||||
* Linux MultiMedia Studio
|
||||
* Copyright (c) 2004-2005 Tobias Doerffel <tobydox@users.sourceforge.net>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "qt3support.h"
|
||||
|
||||
#ifdef QT4
|
||||
|
||||
#include <QPainter>
|
||||
#include <QMouseEvent>
|
||||
|
||||
#else
|
||||
|
||||
#include <qpainter.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "name_label.h"
|
||||
#include "rename_dialog.h"
|
||||
#include "bb_editor.h"
|
||||
#include "bb_track.h"
|
||||
#include "templates.h"
|
||||
|
||||
#include "name_label.moc"
|
||||
|
||||
|
||||
nameLabel::nameLabel( const QString & _initial_name, QWidget * _parent,
|
||||
const QPixmap & _pm ) :
|
||||
QLabel( _initial_name, _parent ),
|
||||
m_pm( _pm )
|
||||
{
|
||||
#ifndef QT4
|
||||
setBackgroundMode( Qt::NoBackground );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
nameLabel::~nameLabel()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
const QPixmap * nameLabel::pixmap( void ) const
|
||||
{
|
||||
return( &m_pm );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void nameLabel::setPixmap( const QPixmap & _pm )
|
||||
{
|
||||
m_pm = _pm;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void nameLabel::rename( void )
|
||||
{
|
||||
QString txt = text();
|
||||
renameDialog rename_dlg( txt );
|
||||
rename_dlg.exec();
|
||||
if( txt != text() )
|
||||
{
|
||||
setText( txt );
|
||||
emit nameChanged( txt );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void nameLabel::paintEvent( QPaintEvent * )
|
||||
{
|
||||
#ifdef QT4
|
||||
QPainter p( this );
|
||||
#else
|
||||
QPixmap draw_pm( rect().size() );
|
||||
draw_pm.fill( this, rect().topLeft() );
|
||||
|
||||
QPainter p( &draw_pm, this );
|
||||
#endif
|
||||
p.setFont( pointSize<8>( p.font() ) );
|
||||
|
||||
QFontMetrics fm( font() );
|
||||
|
||||
p.drawPixmap( 4, ( height() - m_pm.height() ) / 2, m_pm );
|
||||
p.setPen( QColor( 0, 224, 0 ) );
|
||||
bbTrack * bbt = bbTrack::findBBTrack( bbEditor::inst()->currentBB() );
|
||||
if( bbt != NULL && bbt->getTrackSettingsWidget() ==
|
||||
dynamic_cast<trackSettingsWidget *>( parentWidget() ) )
|
||||
{
|
||||
p.setPen( QColor( 255, 255, 255 ) );
|
||||
}
|
||||
p.drawText( m_pm.width() + 8, height() / 2 + fm.height() / 2 - 4,
|
||||
text() );
|
||||
|
||||
#ifndef QT4
|
||||
// and blit all the drawn stuff on the screen...
|
||||
bitBlt( this, rect().topLeft(), &draw_pm );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void nameLabel::mousePressEvent( QMouseEvent * _me )
|
||||
{
|
||||
|
||||
if( _me->button() == Qt::RightButton )
|
||||
{
|
||||
rename();
|
||||
}
|
||||
else
|
||||
{
|
||||
emit clicked();
|
||||
//QLabel::mousePressEvent( _me );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void nameLabel::mouseDoubleClickEvent( QMouseEvent * _me )
|
||||
{
|
||||
rename();
|
||||
}
|
||||
189
src/core/note.cpp
Normal file
189
src/core/note.cpp
Normal file
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* note.cpp - implementation of class note
|
||||
*
|
||||
* Linux MultiMedia Studio
|
||||
* Copyright (c) 2004-2005 Tobias Doerffel <tobydox@users.sourceforge.net>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "qt3support.h"
|
||||
|
||||
#ifdef QT4
|
||||
|
||||
#include <Qt/QtXml>
|
||||
|
||||
#else
|
||||
|
||||
#include <qdom.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "debug.h"
|
||||
#include "note.h"
|
||||
#include "templates.h"
|
||||
|
||||
|
||||
|
||||
note::note( const midiTime & _length, const midiTime & _pos, tones _tone,
|
||||
octaves _octave, volume _volume, panning _panning ) :
|
||||
m_tone( C ),
|
||||
m_octave( DEFAULT_OCTAVE ),
|
||||
m_volume( DEFAULT_VOLUME ),
|
||||
m_panning( DEFAULT_PANNING ),
|
||||
m_length( _length ),
|
||||
m_pos( _pos )
|
||||
{
|
||||
setTone( _tone );
|
||||
setOctave( _octave );
|
||||
setVolume( _volume );
|
||||
setPanning( _panning );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
note::~note()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void note::setLength( const midiTime & _length )
|
||||
{
|
||||
m_length = _length;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void note::setPos( const midiTime & _pos )
|
||||
{
|
||||
m_pos = _pos;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void note::setTone( tones _tone )
|
||||
{
|
||||
if( _tone >= C && _tone <= H )
|
||||
{
|
||||
m_tone = _tone;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tone = tLimit( _tone, C, H );
|
||||
#ifdef LMMS_DEBUG
|
||||
printf ( "Tone out of range (note::setTone)\n" );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void note::setOctave( octaves _octave )
|
||||
{
|
||||
if( _octave >= MIN_OCTAVE && _octave <= MAX_OCTAVE )
|
||||
{
|
||||
m_octave = _octave;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_octave = tLimit( _octave, MIN_OCTAVE, MAX_OCTAVE );
|
||||
#ifdef LMMS_DEBUG
|
||||
printf( "Octave out of range (note::setOctave)\n" );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void note::setKey( int _key )
|
||||
{
|
||||
setTone( static_cast<tones>( _key % NOTES_PER_OCTAVE ) );
|
||||
setOctave( static_cast<octaves>( _key / NOTES_PER_OCTAVE ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void note::setVolume( volume _volume )
|
||||
{
|
||||
if( _volume <= MAX_VOLUME )
|
||||
{
|
||||
m_volume = _volume;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_volume = tMin( _volume, MAX_VOLUME );
|
||||
#ifdef LMMS_DEBUG
|
||||
printf( "Volume out of range (note::setVolume)\n" );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void note::setPanning( panning _panning )
|
||||
{
|
||||
if( _panning >= PANNING_LEFT && _panning <= PANNING_RIGHT )
|
||||
{
|
||||
m_panning = _panning;
|
||||
}
|
||||
#ifdef LMMS_DEBUG
|
||||
else
|
||||
{
|
||||
printf ("Paning out of range (note::set_panning)\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void note::saveSettings( QDomDocument & _doc, QDomElement & _parent )
|
||||
{
|
||||
QDomElement note_de = _doc.createElement( "note" );
|
||||
note_de.setAttribute( "tone", QString::number( m_tone ) );
|
||||
note_de.setAttribute( "oct", QString::number( m_octave ) );
|
||||
note_de.setAttribute( "vol", QString::number( m_volume ) );
|
||||
note_de.setAttribute( "pan", QString::number( m_panning ) );
|
||||
note_de.setAttribute( "len", QString::number( m_length ) );
|
||||
note_de.setAttribute( "pos", QString::number( m_pos ) );
|
||||
_parent.appendChild( note_de );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void note::loadSettings( const QDomElement & _this )
|
||||
{
|
||||
m_tone = static_cast<tones>( _this.attribute( "tone" ).toInt() );
|
||||
m_octave = static_cast<octaves>( _this.attribute( "oct" ).toInt() );
|
||||
m_volume = _this.attribute( "vol" ).toInt();
|
||||
m_panning = _this.attribute( "pan" ).toInt();
|
||||
m_length = _this.attribute( "len" ).toInt();
|
||||
m_pos = _this.attribute( "pos" ).toInt();
|
||||
}
|
||||
|
||||
259
src/core/note_play_handle.cpp
Normal file
259
src/core/note_play_handle.cpp
Normal file
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* note_play_handle.cpp - implementation of class notePlayHandle, part of
|
||||
* play-engine
|
||||
*
|
||||
* Linux MultiMedia Studio
|
||||
* Copyright (c) 2004-2005 Tobias Doerffel <tobydox@users.sourceforge.net>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <qmap.h>
|
||||
|
||||
#include "note_play_handle.h"
|
||||
#include "channel_track.h"
|
||||
#include "envelope_tab_widget.h"
|
||||
|
||||
|
||||
notePlayHandle::notePlayHandle( channelTrack * _chnl_trk, Uint32 _frames_ahead,
|
||||
Uint32 _frames, note * n, bool _arp_note ) :
|
||||
playHandle(),
|
||||
note( *n ),
|
||||
m_pluginData( NULL ),
|
||||
m_filter( NULL ),
|
||||
m_channelTrack( _chnl_trk ),
|
||||
m_frames( 0 ),
|
||||
m_framesAhead( _frames_ahead ),
|
||||
m_totalFramesPlayed( 0 ),
|
||||
m_framesBeforeRelease( 0 ),
|
||||
m_releaseFramesToDo( 0 ),
|
||||
m_releaseFramesDone( 0 ),
|
||||
m_released( FALSE ),
|
||||
m_baseNote( TRUE ),
|
||||
m_arpNote( _arp_note ),
|
||||
m_muted( FALSE )
|
||||
{
|
||||
setFrames( _frames );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
notePlayHandle::~notePlayHandle()
|
||||
{
|
||||
if( m_channelTrack != NULL )
|
||||
{
|
||||
m_channelTrack->deleteNotePluginData( this );
|
||||
}
|
||||
|
||||
for( notePlayHandleVector::iterator it = m_subNotes.begin();
|
||||
it != m_subNotes.end(); ++it )
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
m_subNotes.clear();
|
||||
|
||||
delete m_filter;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void notePlayHandle::play( void )
|
||||
{
|
||||
if( m_muted == TRUE || m_channelTrack == NULL )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_released == FALSE &&
|
||||
m_totalFramesPlayed + mixer::inst()->framesPerAudioBuffer() >=
|
||||
m_frames )
|
||||
{
|
||||
noteOff( m_frames - m_totalFramesPlayed );
|
||||
}
|
||||
|
||||
// play note!
|
||||
m_channelTrack->playNote( this );
|
||||
|
||||
if( m_released == TRUE )
|
||||
{
|
||||
Uint32 todo = mixer::inst()->framesPerAudioBuffer();
|
||||
// if this note is base-note for arpeggio, always set
|
||||
// m_releaseFramesToDo to bigger value than m_releaseFramesDone
|
||||
// because we do not allow notePlayHandle::done() to be true
|
||||
// until all sub-notes are completely played and no new ones
|
||||
// are inserted by arpAndChordsTabWidget::processNote()
|
||||
if( arpBaseNote() == TRUE )
|
||||
{
|
||||
m_releaseFramesToDo = m_releaseFramesDone + 2 *
|
||||
mixer::inst()->framesPerAudioBuffer();
|
||||
}
|
||||
// look whether we have frames left to be done before release
|
||||
if( m_framesBeforeRelease )
|
||||
{
|
||||
// yes, then look whether these samples can be played
|
||||
// within one audio-buffer
|
||||
if( m_framesBeforeRelease <=
|
||||
mixer::inst()->framesPerAudioBuffer() )
|
||||
{
|
||||
// yes, then we did less releaseFramesDone
|
||||
todo -= m_framesBeforeRelease;
|
||||
m_framesBeforeRelease = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// no, then just decrese framesBeforeRelease
|
||||
// and wait for next loop... (we're not in
|
||||
// release-phase yet)
|
||||
todo = 0;
|
||||
m_framesBeforeRelease -=
|
||||
mixer::inst()->framesPerAudioBuffer();
|
||||
}
|
||||
}
|
||||
// look whether we're in release-phase
|
||||
if( todo && m_releaseFramesDone < m_releaseFramesToDo )
|
||||
{
|
||||
// check whether we have to do more frames in current
|
||||
// loop than left in current loop
|
||||
if( m_releaseFramesToDo - m_releaseFramesDone >= todo )
|
||||
{
|
||||
// yes, then increase number of release-frames
|
||||
// done
|
||||
m_releaseFramesDone += todo;
|
||||
}
|
||||
else
|
||||
{
|
||||
// no, we did all in this loop!
|
||||
m_releaseFramesDone = m_releaseFramesToDo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// play sub-notes (e.g. chords)
|
||||
for( notePlayHandleVector::iterator it = m_subNotes.begin();
|
||||
it != m_subNotes.end(); )
|
||||
{
|
||||
( *it )->play();
|
||||
if( ( *it )->done() )
|
||||
{
|
||||
delete *it;
|
||||
m_subNotes.erase( it );
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
// if this note is a base-note and there're no more sub-notes left we
|
||||
// can set m_releaseFramesDone to m_releaseFramesToDo so that
|
||||
// notePlayHandle::done() returns true and also this base-note is
|
||||
// removed from mixer's active note vector
|
||||
if( arpBaseNote() == TRUE && m_subNotes.size() == 0 )
|
||||
{
|
||||
m_releaseFramesDone = m_releaseFramesToDo;
|
||||
}
|
||||
|
||||
// update internal data
|
||||
m_totalFramesPlayed += mixer::inst()->framesPerAudioBuffer();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void notePlayHandle::checkValidity( void )
|
||||
{
|
||||
if( m_channelTrack != NULL &&
|
||||
m_channelTrack->trackType() == track::NULL_TRACK )
|
||||
{
|
||||
m_channelTrack = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void notePlayHandle::noteOff( Uint32 _s )
|
||||
{
|
||||
// first note-off all sub-notes
|
||||
for( notePlayHandleVector::iterator it = m_subNotes.begin();
|
||||
it != m_subNotes.end(); ++it )
|
||||
{
|
||||
( *it )->noteOff( _s );
|
||||
}
|
||||
|
||||
// then set some variables indicating release-state
|
||||
m_framesBeforeRelease = _s;
|
||||
if( m_channelTrack != NULL )
|
||||
{
|
||||
m_releaseFramesToDo =
|
||||
m_channelTrack->m_envWidget->releaseFrames();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_releaseFramesToDo = 0;
|
||||
}
|
||||
|
||||
m_released = TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Uint32 notePlayHandle::actualReleaseFramesToDo( void ) const
|
||||
{
|
||||
return( ( m_channelTrack != NULL ) ?
|
||||
m_channelTrack->m_envWidget->releaseFrames() : 0 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void notePlayHandle::setFrames( Uint32 _frames )
|
||||
{
|
||||
m_frames = _frames;
|
||||
if( m_frames == 0 && m_channelTrack != NULL )
|
||||
{
|
||||
m_frames = m_channelTrack->beatLen( this );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
float notePlayHandle::volumeLevel( Uint32 _frame )
|
||||
{
|
||||
return( ( m_channelTrack != NULL ) ?
|
||||
m_channelTrack->m_envWidget->volumeLevel( this, _frame ) : 0 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void notePlayHandle::mute( void )
|
||||
{
|
||||
// mute all sub-notes
|
||||
for( notePlayHandleVector::iterator it = m_subNotes.begin();
|
||||
it != m_subNotes.end(); ++it )
|
||||
{
|
||||
( *it )->mute();
|
||||
}
|
||||
m_muted = TRUE;
|
||||
}
|
||||
|
||||
2350
src/core/piano_roll.cpp
Normal file
2350
src/core/piano_roll.cpp
Normal file
File diff suppressed because it is too large
Load Diff
619
src/core/piano_widget.cpp
Normal file
619
src/core/piano_widget.cpp
Normal file
@@ -0,0 +1,619 @@
|
||||
/*
|
||||
* piano_widget.cpp - implementation of piano-widget used in channel-window
|
||||
* for testing channel
|
||||
*
|
||||
* Linux MultiMedia Studio
|
||||
* Copyright (c) 2004-2005 Tobias Doerffel <tobydox@users.sourceforge.net>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "qt3support.h"
|
||||
|
||||
#ifdef QT4
|
||||
|
||||
#include <QPainter>
|
||||
#include <QMouseEvent>
|
||||
#include <QKeyEvent>
|
||||
|
||||
#else
|
||||
|
||||
#include <qpainter.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "piano_widget.h"
|
||||
#include "channel_track.h"
|
||||
#include "note_play_handle.h"
|
||||
#include "embed.h"
|
||||
|
||||
|
||||
const keyTypes KEY_ORDER[] =
|
||||
{
|
||||
// C CIS D DIS E F
|
||||
WHITE_KEY, BLACK_KEY, WHITE_KEY, BLACK_KEY, WHITE_KEY, WHITE_KEY,
|
||||
// FIS G GIS A B H
|
||||
BLACK_KEY, WHITE_KEY, BLACK_KEY, WHITE_KEY, BLACK_KEY, WHITE_KEY
|
||||
} ;
|
||||
|
||||
|
||||
tones WHITE_KEYS[] =
|
||||
{
|
||||
C, D, E, F, G, A, H
|
||||
} ;
|
||||
|
||||
|
||||
QPixmap * pianoWidget::s_whiteKeyPm = NULL;
|
||||
QPixmap * pianoWidget::s_blackKeyPm = NULL;
|
||||
QPixmap * pianoWidget::s_whiteKeyPressedPm = NULL;
|
||||
QPixmap * pianoWidget::s_blackKeyPressedPm = NULL;
|
||||
|
||||
|
||||
const int PIANO_BASE = 11;
|
||||
const int WHITE_KEY_WIDTH = 10;
|
||||
const int BLACK_KEY_WIDTH = 8;
|
||||
const int WHITE_KEY_HEIGHT = 57;
|
||||
const int BLACK_KEY_HEIGHT = 38;
|
||||
const int LABEL_TEXT_SIZE = 7;
|
||||
|
||||
|
||||
pianoWidget::pianoWidget (channelTrack * _parent ) :
|
||||
QWidget( _parent ),
|
||||
m_channelTrack( _parent ),
|
||||
m_startTone( C ),
|
||||
m_startOctave( OCTAVE_3 )
|
||||
{
|
||||
#ifdef QT4
|
||||
setFocusPolicy( Qt::StrongFocus );
|
||||
#else
|
||||
setFocusPolicy( StrongFocus );
|
||||
#endif
|
||||
|
||||
if( s_whiteKeyPm == NULL )
|
||||
{
|
||||
s_whiteKeyPm = new QPixmap( embed::getIconPixmap(
|
||||
"white_key" ) );
|
||||
}
|
||||
if( s_blackKeyPm == NULL )
|
||||
{
|
||||
s_blackKeyPm = new QPixmap( embed::getIconPixmap(
|
||||
"black_key" ) );
|
||||
}
|
||||
if( s_whiteKeyPressedPm == NULL )
|
||||
{
|
||||
s_whiteKeyPressedPm = new QPixmap( embed::getIconPixmap(
|
||||
"white_key_pressed" ) );
|
||||
}
|
||||
if ( s_blackKeyPressedPm == NULL )
|
||||
{
|
||||
s_blackKeyPressedPm = new QPixmap( embed::getIconPixmap(
|
||||
"black_key_pressed" ) );
|
||||
}
|
||||
|
||||
#ifdef QT4
|
||||
m_pianoScroll = new QScrollBar( Qt::Horizontal, this );
|
||||
m_pianoScroll->setRange( 0, WHITE_KEYS_PER_OCTAVE * ( OCTAVES - 3 ) -
|
||||
4 );
|
||||
m_pianoScroll->setSingleStep( 1 );
|
||||
m_pianoScroll->setPageStep( 20 );
|
||||
m_pianoScroll->setValue( OCTAVE_3*WHITE_KEYS_PER_OCTAVE );
|
||||
#else
|
||||
// create scrollbar below piano-widget...
|
||||
m_pianoScroll = new QScrollBar( 0, WHITE_KEYS_PER_OCTAVE *
|
||||
( OCTAVES - 3 ) - 4, 1, 20,
|
||||
OCTAVE_3 * WHITE_KEYS_PER_OCTAVE,
|
||||
Qt::Horizontal, this );
|
||||
#endif
|
||||
m_pianoScroll->setGeometry( 0, PIANO_BASE+WHITE_KEY_HEIGHT, 250, 16 );
|
||||
// ...and connect it to this widget...
|
||||
connect( m_pianoScroll, SIGNAL( valueChanged( int ) ), this,
|
||||
SLOT( pianoScrolled( int ) ) );
|
||||
|
||||
#ifndef QT4
|
||||
// set background-mode for flicker-free redraw
|
||||
setBackgroundMode( Qt::NoBackground );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
pianoWidget::~pianoWidget()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// gets the key from the given mouse-position
|
||||
int pianoWidget::getKeyFromMouse( const QPoint & _p )
|
||||
{
|
||||
|
||||
int key_num = (int)( (float) _p.x() / (float) WHITE_KEY_WIDTH );
|
||||
|
||||
for( int i = 0; i <= key_num; ++i )
|
||||
{
|
||||
if( KEY_ORDER[( m_startOctave * NOTES_PER_OCTAVE +
|
||||
m_startTone +i ) % NOTES_PER_OCTAVE] ==
|
||||
BLACK_KEY )
|
||||
{
|
||||
++key_num;
|
||||
}
|
||||
}
|
||||
|
||||
key_num += m_startOctave * NOTES_PER_OCTAVE + m_startTone;
|
||||
|
||||
// is it a black key?
|
||||
if( _p.y() < PIANO_BASE + BLACK_KEY_HEIGHT )
|
||||
{
|
||||
// then do extra checking whether the mouse-cursor is over
|
||||
// a black key
|
||||
if( key_num > 0 &&
|
||||
KEY_ORDER[( key_num - 1 ) % NOTES_PER_OCTAVE] ==
|
||||
BLACK_KEY &&
|
||||
_p.x() % WHITE_KEY_WIDTH <= ( WHITE_KEY_WIDTH / 2 ) -
|
||||
( BLACK_KEY_WIDTH / 2 ) )
|
||||
{
|
||||
--key_num;
|
||||
}
|
||||
if( key_num < NOTES_PER_OCTAVE * OCTAVES - 1 &&
|
||||
KEY_ORDER[( key_num + 1 ) % NOTES_PER_OCTAVE] ==
|
||||
BLACK_KEY &&
|
||||
_p.x() % WHITE_KEY_WIDTH >=
|
||||
( WHITE_KEY_WIDTH - BLACK_KEY_WIDTH / 2 ) )
|
||||
{
|
||||
++key_num;
|
||||
}
|
||||
}
|
||||
|
||||
// some range-checking-stuff
|
||||
key_num = tLimit( key_num, 0, NOTES_PER_OCTAVE * OCTAVES - 1 );
|
||||
|
||||
return( m_lastKey = key_num );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// handler for scrolling-event
|
||||
void pianoWidget::pianoScrolled( int _new_pos )
|
||||
{
|
||||
m_startTone = WHITE_KEYS[_new_pos % WHITE_KEYS_PER_OCTAVE];
|
||||
m_startOctave = (octaves)( _new_pos / WHITE_KEYS_PER_OCTAVE );
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// handler for mouse-click-event
|
||||
void pianoWidget::mousePressEvent( QMouseEvent * _me )
|
||||
{
|
||||
if( _me->button() == Qt::LeftButton )
|
||||
{
|
||||
// get pressed key
|
||||
int key_num = getKeyFromMouse( _me->pos() );
|
||||
if( _me->pos().y() > PIANO_BASE )
|
||||
{
|
||||
int y_diff = _me->pos().y() - PIANO_BASE;
|
||||
volume vol = (volume)( ( float ) y_diff /
|
||||
( ( KEY_ORDER[key_num % NOTES_PER_OCTAVE] ==
|
||||
WHITE_KEY ) ?
|
||||
WHITE_KEY_HEIGHT : BLACK_KEY_HEIGHT ) *
|
||||
(float) DEFAULT_VOLUME);
|
||||
if( y_diff < 0 )
|
||||
{
|
||||
vol = 0;
|
||||
}
|
||||
else if( y_diff > ( ( KEY_ORDER[key_num %
|
||||
NOTES_PER_OCTAVE] ==
|
||||
WHITE_KEY ) ?
|
||||
WHITE_KEY_HEIGHT : BLACK_KEY_HEIGHT ) )
|
||||
{
|
||||
vol = DEFAULT_VOLUME;
|
||||
}
|
||||
// set note on
|
||||
m_channelTrack->processInEvent(
|
||||
midiEvent( NOTE_ON, 0, key_num, vol ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_channelTrack->setBaseTone( static_cast<tones>(
|
||||
key_num % NOTES_PER_OCTAVE ) );
|
||||
m_channelTrack->setBaseOctave( static_cast<octaves>(
|
||||
key_num / NOTES_PER_OCTAVE ) );
|
||||
}
|
||||
|
||||
// and let the user see that he pressed a key... :)
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// handler for mouse-release-event
|
||||
void pianoWidget::mouseReleaseEvent( QMouseEvent * _me )
|
||||
{
|
||||
int released_key = getKeyFromMouse( _me->pos() );
|
||||
|
||||
m_channelTrack->processInEvent(
|
||||
midiEvent ( NOTE_OFF, 0, released_key ) );
|
||||
|
||||
// and let the user see that he released a key... :)
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// handler for mouse-move-event
|
||||
void pianoWidget::mouseMoveEvent( QMouseEvent * _me )
|
||||
{
|
||||
// save current last-key-var
|
||||
int released_key = m_lastKey;
|
||||
int key_num = getKeyFromMouse( _me->pos() );
|
||||
int y_diff = _me->pos().y() - PIANO_BASE;
|
||||
volume vol = (volume)( (float) y_diff /
|
||||
( ( KEY_ORDER[key_num % NOTES_PER_OCTAVE] == WHITE_KEY ) ?
|
||||
WHITE_KEY_HEIGHT : BLACK_KEY_HEIGHT ) *
|
||||
(float)DEFAULT_VOLUME );
|
||||
// maybe the user moved the mouse-cursor above or under the
|
||||
// piano-widget while holding left button so check that and
|
||||
// correct volume if necessary
|
||||
if( y_diff < 0 )
|
||||
{
|
||||
vol = 0;
|
||||
}
|
||||
else if( y_diff >
|
||||
( ( KEY_ORDER[key_num % NOTES_PER_OCTAVE] == WHITE_KEY ) ?
|
||||
WHITE_KEY_HEIGHT : BLACK_KEY_HEIGHT ) )
|
||||
{
|
||||
vol = DEFAULT_VOLUME;
|
||||
}
|
||||
|
||||
// is the calculated key different from current key? (could be the
|
||||
// user just moved the cursor one pixel left but on the same key)
|
||||
if( key_num != released_key )
|
||||
{
|
||||
m_channelTrack->processInEvent(
|
||||
midiEvent( NOTE_OFF, 0, released_key ) );
|
||||
#ifdef QT4
|
||||
if( _me->buttons() & Qt::LeftButton )
|
||||
#else
|
||||
if( _me->state() == Qt::LeftButton )
|
||||
#endif
|
||||
{
|
||||
if( _me->pos().y() > PIANO_BASE )
|
||||
{
|
||||
m_channelTrack->processInEvent(
|
||||
midiEvent( NOTE_ON, 0, key_num, vol ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_channelTrack->setBaseTone( (tones)
|
||||
( key_num % NOTES_PER_OCTAVE ) );
|
||||
m_channelTrack->setBaseOctave( (octaves)
|
||||
( key_num / NOTES_PER_OCTAVE ) );
|
||||
}
|
||||
}
|
||||
// and let the user see that he pressed a key... :)
|
||||
update();
|
||||
}
|
||||
else if( m_channelTrack->keyPressed( key_num ) == TRUE )
|
||||
{
|
||||
m_channelTrack->noteForKey( key_num )->setVolume( vol );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int pianoWidget::getKeyFromKeyboard( int _k ) const
|
||||
{
|
||||
switch( _k )
|
||||
{
|
||||
case Qt::Key_Y: return( 0 );
|
||||
case Qt::Key_S: return( 1 );
|
||||
case Qt::Key_X: return( 2 );
|
||||
case Qt::Key_D: return( 3 );
|
||||
case Qt::Key_C: return( 4 );
|
||||
case Qt::Key_V: return( 5 );
|
||||
case Qt::Key_G: return( 6 );
|
||||
case Qt::Key_B: return( 7 );
|
||||
case Qt::Key_H: return( 8 );
|
||||
case Qt::Key_N: return( 9 );
|
||||
case Qt::Key_J: return( 10 );
|
||||
case Qt::Key_M: return( 11 );
|
||||
case Qt::Key_Q: return( 12 );
|
||||
case Qt::Key_2: return( 13 );
|
||||
case Qt::Key_W: return( 14 );
|
||||
case Qt::Key_3: return( 15 );
|
||||
case Qt::Key_E: return( 16 );
|
||||
case Qt::Key_R: return( 17 );
|
||||
case Qt::Key_5: return( 18 );
|
||||
case Qt::Key_T: return( 19 );
|
||||
case Qt::Key_6: return( 20 );
|
||||
case Qt::Key_Z: return( 21 );
|
||||
case Qt::Key_7: return( 22 );
|
||||
case Qt::Key_U: return( 23 );
|
||||
case Qt::Key_I: return( 24 );
|
||||
case Qt::Key_9: return( 25 );
|
||||
case Qt::Key_O: return( 26 );
|
||||
case Qt::Key_0: return( 27 );
|
||||
case Qt::Key_P: return( 28 );
|
||||
}
|
||||
|
||||
return( -100 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void pianoWidget::keyPressEvent( QKeyEvent * _ke )
|
||||
{
|
||||
int key_num = getKeyFromKeyboard( _ke->key() ) +
|
||||
( DEFAULT_OCTAVE - 1 ) * NOTES_PER_OCTAVE;
|
||||
|
||||
if( _ke->isAutoRepeat() == FALSE && key_num > -1 )
|
||||
{
|
||||
m_channelTrack->processInEvent(
|
||||
midiEvent( NOTE_ON, 0, key_num, DEFAULT_VOLUME ) );
|
||||
update();
|
||||
}
|
||||
else
|
||||
{
|
||||
_ke->ignore();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void pianoWidget::keyReleaseEvent( QKeyEvent * _ke )
|
||||
{
|
||||
int key_num = getKeyFromKeyboard( _ke->key() ) +
|
||||
( DEFAULT_OCTAVE - 1 ) * NOTES_PER_OCTAVE;
|
||||
if( _ke->isAutoRepeat() == FALSE && key_num > -1 )
|
||||
{
|
||||
m_channelTrack->processInEvent(
|
||||
midiEvent( NOTE_OFF, 0, key_num ) );
|
||||
update();
|
||||
}
|
||||
else
|
||||
{
|
||||
_ke->ignore();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void pianoWidget::focusInEvent( QFocusEvent * )
|
||||
{
|
||||
mixer::inst()->getMIDIDevice()->setChannelTrack( m_channelTrack );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void pianoWidget::focusOutEvent( QFocusEvent * )
|
||||
{
|
||||
// if we loose focus, we HAVE to note off all "running" notes because
|
||||
// we don't receive key-release-events anymore and so the notes would
|
||||
// hang otherwise
|
||||
for( int i = 0; i < NOTES_PER_OCTAVE * OCTAVES; ++i )
|
||||
{
|
||||
if( m_channelTrack->keyPressed( i ) )
|
||||
{
|
||||
m_channelTrack->processInEvent(
|
||||
midiEvent( NOTE_OFF, 0, i ) );
|
||||
}
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int pianoWidget::getKeyX( int _key_num )
|
||||
{
|
||||
int k = m_startOctave*NOTES_PER_OCTAVE + m_startTone;
|
||||
if( _key_num < k )
|
||||
{
|
||||
return( ( _key_num - k ) * WHITE_KEY_WIDTH / 2 );
|
||||
}
|
||||
|
||||
int x = 0;
|
||||
int white_cnt = 0;
|
||||
|
||||
while( k <= _key_num )
|
||||
{
|
||||
if( KEY_ORDER[k % NOTES_PER_OCTAVE] == WHITE_KEY )
|
||||
{
|
||||
++white_cnt;
|
||||
if( white_cnt > 1 )
|
||||
{
|
||||
x += WHITE_KEY_WIDTH;
|
||||
}
|
||||
else
|
||||
{
|
||||
x += WHITE_KEY_WIDTH/2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
white_cnt = 0;
|
||||
x += WHITE_KEY_WIDTH/2;
|
||||
}
|
||||
++k;
|
||||
}
|
||||
|
||||
x -= WHITE_KEY_WIDTH / 2;
|
||||
|
||||
return( x );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void pianoWidget::paintEvent( QPaintEvent * )
|
||||
{
|
||||
#ifdef QT4
|
||||
QPainter p( this );
|
||||
#else
|
||||
// create pixmap for whole widget
|
||||
QPixmap pm( rect().size() );//width(), PIANO_BASE+WHITE_KEY_HEIGHT);
|
||||
// and a painter for it
|
||||
QPainter p( &pm, this );
|
||||
#endif
|
||||
|
||||
// set smaller font for printing number of every octave
|
||||
p.setFont( pointSize<LABEL_TEXT_SIZE>( p.font() ) );
|
||||
|
||||
|
||||
// draw blue bar above the actual keyboard (there will be the labels
|
||||
// for all C's)
|
||||
p.fillRect( QRect( 0, 1, width(), PIANO_BASE-2 ),
|
||||
QColor( 0x00, 0x00, 0xFF ) );
|
||||
|
||||
// draw stuff above the actual keyboard
|
||||
p.setPen( QColor( 0x00, 0x00, 0x00 ) );
|
||||
p.drawLine( 0, 0, width(), 0 );
|
||||
p.drawLine( 0, PIANO_BASE-1, width(), PIANO_BASE-1 );
|
||||
|
||||
p.setPen( QColor ( 0xFF, 0xFF, 0xFF ) );
|
||||
|
||||
int base_key = m_channelTrack->baseTone() +
|
||||
m_channelTrack->baseOctave() * NOTES_PER_OCTAVE;
|
||||
if( KEY_ORDER[base_key % NOTES_PER_OCTAVE] == WHITE_KEY )
|
||||
{
|
||||
p.fillRect( QRect( getKeyX( base_key ), 1, WHITE_KEY_WIDTH-1,
|
||||
PIANO_BASE-2 ),
|
||||
QColor( 0xFF, 0xBB, 0x00 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
p.fillRect( QRect( getKeyX( base_key ) + 1, 1,
|
||||
BLACK_KEY_WIDTH - 1, PIANO_BASE - 2 ),
|
||||
QColor( 0xFF, 0xBB, 0x00 ) );
|
||||
}
|
||||
|
||||
|
||||
int cur_key = m_startOctave*NOTES_PER_OCTAVE + m_startTone;
|
||||
|
||||
// draw all white keys...
|
||||
for( int x = 0; x < width(); )
|
||||
{
|
||||
while( KEY_ORDER[cur_key%NOTES_PER_OCTAVE] != WHITE_KEY )
|
||||
{
|
||||
++cur_key;
|
||||
}
|
||||
|
||||
// draw pressed or not pressed key, depending on state of
|
||||
// current key
|
||||
if( m_channelTrack->keyPressed( cur_key ) == TRUE )
|
||||
{
|
||||
p.drawPixmap( x, PIANO_BASE, *s_whiteKeyPressedPm );
|
||||
}
|
||||
else
|
||||
{
|
||||
p.drawPixmap( x, PIANO_BASE, *s_whiteKeyPm );
|
||||
}
|
||||
|
||||
x += WHITE_KEY_WIDTH;
|
||||
|
||||
if( (tones) (cur_key%NOTES_PER_OCTAVE) == C )
|
||||
{
|
||||
// label key of note C with "C" and number of current
|
||||
// octave
|
||||
p.drawText( x - WHITE_KEY_WIDTH, LABEL_TEXT_SIZE + 2,
|
||||
QString( "C" ) + QString::number(
|
||||
cur_key / NOTES_PER_OCTAVE, 10 ) );
|
||||
}
|
||||
++cur_key;
|
||||
}
|
||||
|
||||
|
||||
// reset all values, because now we're going to draw all black keys
|
||||
cur_key = m_startOctave*NOTES_PER_OCTAVE + m_startTone;
|
||||
int white_cnt = 0;
|
||||
|
||||
int s_key = m_startOctave*NOTES_PER_OCTAVE+m_startTone;
|
||||
if( s_key > 0 &&
|
||||
KEY_ORDER[(tones)( --s_key ) % NOTES_PER_OCTAVE] == BLACK_KEY )
|
||||
{
|
||||
if( m_channelTrack->keyPressed( s_key ) == TRUE )
|
||||
{
|
||||
p.drawPixmap( 0 - WHITE_KEY_WIDTH / 2, PIANO_BASE,
|
||||
*s_blackKeyPressedPm );
|
||||
}
|
||||
else
|
||||
{
|
||||
p.drawPixmap( 0 - WHITE_KEY_WIDTH / 2, PIANO_BASE,
|
||||
*s_blackKeyPm );
|
||||
}
|
||||
}
|
||||
|
||||
// now draw all black keys...
|
||||
for( int x = 0; x < width(); )
|
||||
{
|
||||
if( KEY_ORDER[cur_key%NOTES_PER_OCTAVE] == BLACK_KEY )
|
||||
{
|
||||
// draw pressed or not pressed key, depending on
|
||||
// state of current key
|
||||
if( m_channelTrack->keyPressed( cur_key ) == TRUE )
|
||||
{
|
||||
p.drawPixmap( x + WHITE_KEY_WIDTH / 2,
|
||||
PIANO_BASE,
|
||||
*s_blackKeyPressedPm );
|
||||
}
|
||||
else
|
||||
{
|
||||
p.drawPixmap( x + WHITE_KEY_WIDTH / 2,
|
||||
PIANO_BASE, *s_blackKeyPm );
|
||||
}
|
||||
x += WHITE_KEY_WIDTH;
|
||||
white_cnt = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// simple workaround for increasing x if there were two
|
||||
// white keys (e.g. between E and F)
|
||||
++white_cnt;
|
||||
if( white_cnt > 1 )
|
||||
{
|
||||
x += WHITE_KEY_WIDTH;
|
||||
}
|
||||
}
|
||||
++cur_key;
|
||||
}
|
||||
#ifndef QT4
|
||||
// blit drawn pixmap to actual widget
|
||||
bitBlt( this, rect().topLeft(), &pm );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
#include "piano_widget.moc"
|
||||
|
||||
179
src/core/preset_preview_play_handle.cpp
Normal file
179
src/core/preset_preview_play_handle.cpp
Normal file
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* preset_preview_play_handle.cpp - implementation of class
|
||||
* presetPreviewPlayHandle
|
||||
*
|
||||
* Linux MultiMedia Studio
|
||||
* Copyright (c) 2004-2005 Tobias Doerffel <tobydox@users.sourceforge.net>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qt3support.h"
|
||||
|
||||
#ifdef QT4
|
||||
|
||||
#include <QMutex>
|
||||
#include <QMutexLocker>
|
||||
|
||||
#else
|
||||
|
||||
#include <qmutex.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#include "preset_preview_play_handle.h"
|
||||
#include "note_play_handle.h"
|
||||
#include "channel_track.h"
|
||||
#include "track_container.h"
|
||||
#include "mmp.h"
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
// invisible track-container which is needed as parents for preview-channels
|
||||
class blindTrackContainer : public trackContainer
|
||||
{
|
||||
public:
|
||||
static inline blindTrackContainer * inst( void )
|
||||
{
|
||||
if( s_instanceOfMe == NULL )
|
||||
{
|
||||
s_instanceOfMe = new blindTrackContainer();
|
||||
}
|
||||
return( s_instanceOfMe );
|
||||
}
|
||||
|
||||
// implement pure-virtual functions...
|
||||
virtual inline bool fixedTCOs( void ) const
|
||||
{
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
virtual inline QString nodeName( void ) const
|
||||
{
|
||||
return( "blindtc" );
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
blindTrackContainer( void ) :
|
||||
trackContainer()
|
||||
{
|
||||
hide();
|
||||
}
|
||||
~blindTrackContainer()
|
||||
{
|
||||
}
|
||||
|
||||
static blindTrackContainer * s_instanceOfMe;
|
||||
|
||||
friend void presetPreviewPlayHandle::cleanUp( void );
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
blindTrackContainer * blindTrackContainer::s_instanceOfMe = NULL;
|
||||
|
||||
channelTrack * presetPreviewPlayHandle::s_globalChannelTrack = NULL;
|
||||
notePlayHandle * presetPreviewPlayHandle::s_globalPreviewNote = NULL;
|
||||
QMutex * presetPreviewPlayHandle::s_globalDataMutex = NULL;
|
||||
|
||||
|
||||
presetPreviewPlayHandle::presetPreviewPlayHandle(
|
||||
const QString & _preset_file ) :
|
||||
playHandle(),
|
||||
m_previewNote( NULL )
|
||||
{
|
||||
if( s_globalDataMutex == NULL )
|
||||
{
|
||||
s_globalDataMutex = new QMutex;
|
||||
}
|
||||
|
||||
s_globalDataMutex->lock();
|
||||
|
||||
if( s_globalPreviewNote != NULL )
|
||||
{
|
||||
s_globalPreviewNote->mute();
|
||||
}
|
||||
|
||||
|
||||
multimediaProject mmp( _preset_file );
|
||||
if( s_globalChannelTrack == NULL )
|
||||
{
|
||||
track * t = track::createTrack( track::CHANNEL_TRACK,
|
||||
blindTrackContainer::inst() );
|
||||
s_globalChannelTrack = dynamic_cast<channelTrack *>( t );
|
||||
#ifdef LMMS_DEBUG
|
||||
assert( s_globalChannelTrack != NULL );
|
||||
#endif
|
||||
}
|
||||
s_globalChannelTrack->loadTrackSpecificSettings( mmp.content().
|
||||
firstChild().
|
||||
toElement() );
|
||||
// create temporary note
|
||||
note n( 0, 0, static_cast<tones>( A ),
|
||||
static_cast<octaves>( DEFAULT_OCTAVE-1 ), 100 );
|
||||
// create note-play-handle for it
|
||||
m_previewNote = new notePlayHandle( s_globalChannelTrack, 0, ~0, &n );
|
||||
//m_previewNote->setFrames( mixer::inst()->sampleRate() );
|
||||
|
||||
|
||||
s_globalPreviewNote = m_previewNote;
|
||||
|
||||
s_globalDataMutex->unlock();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
presetPreviewPlayHandle::~presetPreviewPlayHandle()
|
||||
{
|
||||
s_globalDataMutex->lock();
|
||||
if( m_previewNote->muted() == FALSE )
|
||||
{
|
||||
s_globalPreviewNote = NULL;
|
||||
}
|
||||
delete m_previewNote;
|
||||
s_globalDataMutex->unlock();
|
||||
//blindTrackContainer::inst()->removeTrack( m_channelTrack );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void presetPreviewPlayHandle::cleanUp( void )
|
||||
{
|
||||
delete blindTrackContainer::inst();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void presetPreviewPlayHandle::play( void )
|
||||
{
|
||||
m_previewNote->play();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool presetPreviewPlayHandle::done( void ) const
|
||||
{
|
||||
return( m_previewNote->muted() );
|
||||
}
|
||||
|
||||
106
src/core/sample_play_handle.cpp
Normal file
106
src/core/sample_play_handle.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* sample_play_handle.cpp - implementation of class samplePlayHandle
|
||||
*
|
||||
* Linux MultiMedia Studio
|
||||
* Copyright (c) 2004-2005 Tobias Doerffel <tobydox@users.sourceforge.net>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "qt3support.h"
|
||||
#ifndef QT4
|
||||
#include <qpair.h>
|
||||
#endif
|
||||
|
||||
#include "sample_play_handle.h"
|
||||
#include "sample_buffer.h"
|
||||
#include "buffer_allocator.h"
|
||||
|
||||
|
||||
samplePlayHandle::samplePlayHandle( const QString & _sample_file ) :
|
||||
playHandle(),
|
||||
m_sampleBuffer( new sampleBuffer( _sample_file ) ),
|
||||
m_ownSampleBuffer( TRUE ),
|
||||
m_doneMayReturnTrue( TRUE ),
|
||||
m_frame( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
samplePlayHandle::samplePlayHandle( sampleBuffer * _sample_buffer ) :
|
||||
playHandle(),
|
||||
m_sampleBuffer( _sample_buffer ),
|
||||
m_ownSampleBuffer( FALSE ),
|
||||
m_doneMayReturnTrue( TRUE ),
|
||||
m_frame( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
samplePlayHandle::~samplePlayHandle()
|
||||
{
|
||||
if( m_ownSampleBuffer == TRUE )
|
||||
{
|
||||
delete m_sampleBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void samplePlayHandle::play( void )
|
||||
{
|
||||
if( framesDone() >= totalFrames() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
sampleFrame * buf = bufferAllocator::alloc<sampleFrame>(
|
||||
mixer::inst()->framesPerAudioBuffer() *
|
||||
DEFAULT_CHANNELS );
|
||||
volumeVector v = { 1.0f, 1.0f
|
||||
#ifndef DISABLE_SURROUND
|
||||
, 1.0f, 1.0f
|
||||
#endif
|
||||
} ;
|
||||
m_sampleBuffer->play( buf, m_frame );
|
||||
mixer::inst()->addBuffer( buf, mixer::inst()->framesPerAudioBuffer(),
|
||||
0, v );
|
||||
|
||||
bufferAllocator::free( buf );
|
||||
|
||||
m_frame += mixer::inst()->framesPerAudioBuffer();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool samplePlayHandle::done( void ) const
|
||||
{
|
||||
return( framesDone() >= totalFrames() && m_doneMayReturnTrue == TRUE );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Uint32 samplePlayHandle::totalFrames( void ) const
|
||||
{
|
||||
return( m_sampleBuffer->endFrame() - m_sampleBuffer->startFrame() );
|
||||
}
|
||||
|
||||
592
src/core/setup_dialog.cpp
Normal file
592
src/core/setup_dialog.cpp
Normal file
@@ -0,0 +1,592 @@
|
||||
/*
|
||||
* setup_dialog.cpp - dialog for setting up LMMS
|
||||
*
|
||||
* Linux MultiMedia Studio
|
||||
* Copyright (c) 2004-2005 Tobias Doerffel <tobydox@users.sourceforge.net>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "qt3support.h"
|
||||
|
||||
#ifdef QT4
|
||||
|
||||
#include <QLayout>
|
||||
#include <QLabel>
|
||||
#include <QSlider>
|
||||
#include <QWhatsThis>
|
||||
#include <QComboBox>
|
||||
#include <QMessageBox>
|
||||
|
||||
#else
|
||||
|
||||
#include <qlayout.h>
|
||||
#include <qlabel.h>
|
||||
#include <qslider.h>
|
||||
#include <qwhatsthis.h>
|
||||
#include <qcombobox.h>
|
||||
#include <qmessagebox.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "setup_dialog.h"
|
||||
#include "tab_bar.h"
|
||||
#include "tab_button.h"
|
||||
#include "tab_widget.h"
|
||||
#include "templates.h"
|
||||
#include "mixer.h"
|
||||
#include "config_mgr.h"
|
||||
#include "embed.h"
|
||||
#include "debug.h"
|
||||
#include "tooltip.h"
|
||||
#include "led_checkbox.h"
|
||||
|
||||
|
||||
// platform-specific audio-interface-classes
|
||||
#include "audio_alsa.h"
|
||||
#include "audio_jack.h"
|
||||
#include "audio_oss.h"
|
||||
#include "audio_sdl.h"
|
||||
#include "audio_dummy.h"
|
||||
|
||||
// platform-specific midi-interface-classes
|
||||
#include "midi_alsa_raw.h"
|
||||
#include "midi_oss.h"
|
||||
#include "midi_dummy.h"
|
||||
|
||||
|
||||
|
||||
inline void labelWidget( QWidget * _w, const QString & _txt )
|
||||
{
|
||||
QLabel * title = new QLabel( _txt, _w );
|
||||
QFont f = title->font();
|
||||
f.setBold( TRUE );
|
||||
title->setFont( pointSize<12>( f ) );
|
||||
|
||||
#ifdef LMMS_DEBUG
|
||||
assert( dynamic_cast<QBoxLayout *>( _w->layout() ) != NULL );
|
||||
#endif
|
||||
dynamic_cast<QBoxLayout *>( _w->layout() )->addSpacing( 5 );
|
||||
dynamic_cast<QBoxLayout *>( _w->layout() )->addWidget( title );
|
||||
dynamic_cast<QBoxLayout *>( _w->layout() )->addSpacing( 10 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
setupDialog::setupDialog( configTabs _tab_to_open ) :
|
||||
QDialog(),
|
||||
m_bufferSize( mixer::inst()->framesPerAudioBuffer() ),
|
||||
m_disableToolTips( configManager::inst()->value( "tooltips",
|
||||
"disabled" ).toInt() ),
|
||||
m_classicalKnobUsability( configManager::inst()->value( "knobs",
|
||||
"classicalusability" ).toInt() )
|
||||
{
|
||||
setWindowIcon( embed::getIconPixmap( "setup_general" ) );
|
||||
setWindowTitle( tr( "Setup LMMS" ) );
|
||||
|
||||
QVBoxLayout * vlayout = new QVBoxLayout( this );
|
||||
QWidget * settings = new QWidget( this );
|
||||
QHBoxLayout * hlayout = new QHBoxLayout( settings );
|
||||
|
||||
m_tabBar = new tabBar( settings, QBoxLayout::TopToBottom );
|
||||
m_tabBar->setExclusive( TRUE );
|
||||
m_tabBar->setFixedWidth( 72 );
|
||||
|
||||
QWidget * ws = new QWidget( settings );
|
||||
ws->setFixedSize( 360, 200 );
|
||||
|
||||
QWidget * general = new QWidget( ws );
|
||||
general->setFixedSize( 360, 200 );
|
||||
QVBoxLayout * gen_layout = new QVBoxLayout( general );
|
||||
labelWidget( general, tr( "General settings" ) );
|
||||
|
||||
tabWidget * bufsize_tw = new tabWidget( tr( "BUFFER SIZE" ), general );
|
||||
bufsize_tw->setFixedHeight( 80 );
|
||||
|
||||
m_bufSizeSlider = new QSlider( Qt::Horizontal, bufsize_tw );
|
||||
#ifdef QT4
|
||||
m_bufSizeSlider->setRange( 1, 256 );
|
||||
m_bufSizeSlider->setTickPosition( QSlider::TicksBelow );
|
||||
#else
|
||||
m_bufSizeSlider->setMinimum( 1 );
|
||||
m_bufSizeSlider->setMaximum( 256 );
|
||||
m_bufSizeSlider->setLineStep( 4 );
|
||||
m_bufSizeSlider->setTickmarks( QSlider::Below );
|
||||
#endif
|
||||
m_bufSizeSlider->setPageStep( 4 );
|
||||
m_bufSizeSlider->setTickInterval( 8 );
|
||||
m_bufSizeSlider->setGeometry( 10, 16, 340, 18 );
|
||||
m_bufSizeSlider->setValue( m_bufferSize / 64 );
|
||||
|
||||
connect( m_bufSizeSlider, SIGNAL( valueChanged( int ) ), this,
|
||||
SLOT( setBufferSize( int ) ) );
|
||||
|
||||
m_bufSizeLbl = new QLabel( bufsize_tw );
|
||||
m_bufSizeLbl->setGeometry( 10, 40, 200, 24 );
|
||||
setBufferSize( m_bufSizeSlider->value() );
|
||||
|
||||
QPushButton * bufsize_reset_btn = new QPushButton(
|
||||
embed::getIconPixmap( "reload" ), "", bufsize_tw );
|
||||
bufsize_reset_btn->setGeometry( 290, 40, 28, 28 );
|
||||
connect( bufsize_reset_btn, SIGNAL( clicked() ), this,
|
||||
SLOT( resetBufSize() ) );
|
||||
toolTip::add( bufsize_reset_btn, tr( "Reset to default-value" ) );
|
||||
|
||||
QPushButton * bufsize_help_btn = new QPushButton(
|
||||
embed::getIconPixmap( "help" ), "", bufsize_tw );
|
||||
bufsize_help_btn->setGeometry( 320, 40, 28, 28 );
|
||||
connect( bufsize_help_btn, SIGNAL( clicked() ), this,
|
||||
SLOT( displayBufSizeHelp() ) );
|
||||
|
||||
|
||||
tabWidget * misc_tw = new tabWidget( tr( "MISC" ), general );
|
||||
misc_tw->setFixedHeight( 60 );
|
||||
|
||||
ledCheckBox * disable_tooltips = new ledCheckBox(
|
||||
tr( "Disable tooltips (no spurious "
|
||||
"interrupts while playing)" ),
|
||||
misc_tw );
|
||||
disable_tooltips->move( 10, 18 );
|
||||
disable_tooltips->setChecked( m_disableToolTips );
|
||||
connect( disable_tooltips, SIGNAL( toggled( bool ) ),
|
||||
this, SLOT( toggleToolTips( bool ) ) );
|
||||
|
||||
ledCheckBox * classical_knob_usability = new ledCheckBox(
|
||||
tr( "Classical knob usability (move "
|
||||
"cursor around knob to change "
|
||||
"value)" ),
|
||||
misc_tw );
|
||||
classical_knob_usability->move( 10, 36 );
|
||||
classical_knob_usability->setChecked( m_classicalKnobUsability );
|
||||
connect( classical_knob_usability, SIGNAL( toggled( bool ) ),
|
||||
this, SLOT( toggleKnobUsability( bool ) ) );
|
||||
|
||||
|
||||
gen_layout->addWidget( bufsize_tw );
|
||||
gen_layout->addSpacing( 10 );
|
||||
gen_layout->addWidget( misc_tw );
|
||||
gen_layout->addStretch();
|
||||
|
||||
|
||||
|
||||
|
||||
QWidget * audio = new QWidget( ws );
|
||||
audio->setFixedSize( 360, 200 );
|
||||
QVBoxLayout * audio_layout = new QVBoxLayout( audio );
|
||||
labelWidget( audio, tr( "Audio settings" ) );
|
||||
|
||||
tabWidget * audioiface_tw = new tabWidget( tr( "AUDIO INTERFACE" ),
|
||||
audio );
|
||||
audioiface_tw->setFixedHeight( 60 );
|
||||
|
||||
m_audioInterfaces = new QComboBox( audioiface_tw );
|
||||
m_audioInterfaces->setGeometry( 10, 20, 240, 22 );
|
||||
|
||||
|
||||
QPushButton * audio_help_btn = new QPushButton(
|
||||
embed::getIconPixmap( "help" ), "", audioiface_tw );
|
||||
audio_help_btn->setGeometry( 320, 20, 28, 28 );
|
||||
connect( audio_help_btn, SIGNAL( clicked() ), this,
|
||||
SLOT( displayAudioHelp() ) );
|
||||
|
||||
|
||||
// create ifaces-settings-widget
|
||||
QWidget * asw = new QWidget( audio );
|
||||
asw->setFixedHeight( 60 );
|
||||
#ifndef QT4
|
||||
asw->setBackgroundMode( NoBackground );
|
||||
#endif
|
||||
|
||||
QHBoxLayout * asw_layout = new QHBoxLayout( asw );
|
||||
//asw_layout->setAutoAdd( TRUE );
|
||||
|
||||
#ifdef JACK_SUPPORT
|
||||
m_audioIfaceSetupWidgets[audioJACK::name()] =
|
||||
new audioJACK::setupWidget( asw );
|
||||
#endif
|
||||
|
||||
#ifdef ALSA_SUPPORT
|
||||
m_audioIfaceSetupWidgets[audioALSA::name()] =
|
||||
new audioALSA::setupWidget( asw );
|
||||
#endif
|
||||
|
||||
#ifdef SDL_AUDIO_SUPPORT
|
||||
m_audioIfaceSetupWidgets[audioSDL::name()] =
|
||||
new audioSDL::setupWidget( asw );
|
||||
#endif
|
||||
|
||||
#ifdef OSS_SUPPORT
|
||||
m_audioIfaceSetupWidgets[audioOSS::name()] =
|
||||
new audioOSS::setupWidget( asw );
|
||||
#endif
|
||||
m_audioIfaceSetupWidgets[audioDummy::name()] =
|
||||
new audioDummy::setupWidget( asw );
|
||||
|
||||
|
||||
for( aswMap::iterator it = m_audioIfaceSetupWidgets.begin();
|
||||
it != m_audioIfaceSetupWidgets.end(); ++it )
|
||||
{
|
||||
#ifdef QT4
|
||||
it.value()->hide();
|
||||
asw_layout->addWidget( it.value() );
|
||||
#else
|
||||
it.data()->hide();
|
||||
asw_layout->addWidget( it.data() );
|
||||
#endif
|
||||
m_audioInterfaces->addItem( it.key() );
|
||||
}
|
||||
#ifdef QT4
|
||||
m_audioInterfaces->setCurrentIndex( m_audioInterfaces->findText(
|
||||
mixer::inst()->audioDevName() ) );
|
||||
#else
|
||||
m_audioInterfaces->setCurrentText( mixer::inst()->audioDevName() );
|
||||
#endif
|
||||
m_audioIfaceSetupWidgets[mixer::inst()->audioDevName()]->show();
|
||||
|
||||
connect( m_audioInterfaces, SIGNAL( activated( const QString & ) ),
|
||||
this, SLOT( audioInterfaceChanged( const QString & ) ) );
|
||||
|
||||
|
||||
audio_layout->addWidget( audioiface_tw );
|
||||
audio_layout->addSpacing( 20 );
|
||||
audio_layout->addWidget( asw );
|
||||
audio_layout->addStretch();
|
||||
|
||||
|
||||
|
||||
|
||||
QWidget * midi = new QWidget( ws );
|
||||
QVBoxLayout * midi_layout = new QVBoxLayout( midi );
|
||||
labelWidget( midi, tr( "MIDI settings" ) );
|
||||
|
||||
tabWidget * midiiface_tw = new tabWidget( tr( "MIDI INTERFACE" ),
|
||||
midi );
|
||||
midiiface_tw->setFixedHeight( 60 );
|
||||
|
||||
m_midiInterfaces = new QComboBox( midiiface_tw );
|
||||
m_midiInterfaces->setGeometry( 10, 20, 240, 22 );
|
||||
|
||||
|
||||
QPushButton * midi_help_btn = new QPushButton(
|
||||
embed::getIconPixmap( "help" ), "", midiiface_tw );
|
||||
midi_help_btn->setGeometry( 320, 20, 28, 28 );
|
||||
connect( midi_help_btn, SIGNAL( clicked() ), this,
|
||||
SLOT( displayMIDIHelp() ) );
|
||||
|
||||
|
||||
// create ifaces-settings-widget
|
||||
QWidget * msw = new QWidget( midi );
|
||||
msw->setFixedHeight( 60 );
|
||||
#ifndef QT4
|
||||
msw->setBackgroundMode( NoBackground );
|
||||
#endif
|
||||
|
||||
QHBoxLayout * msw_layout = new QHBoxLayout( msw );
|
||||
//msw_layout->setAutoAdd( TRUE );
|
||||
|
||||
#ifdef ALSA_SUPPORT
|
||||
m_midiIfaceSetupWidgets[midiALSARaw::name()] =
|
||||
new midiALSARaw::setupWidget( msw );
|
||||
#endif
|
||||
|
||||
#ifdef OSS_SUPPORT
|
||||
m_midiIfaceSetupWidgets[midiOSS::name()] =
|
||||
new midiOSS::setupWidget( msw );
|
||||
#endif
|
||||
m_midiIfaceSetupWidgets[midiDummy::name()] =
|
||||
new midiDummy::setupWidget( msw );
|
||||
|
||||
|
||||
for( mswMap::iterator it = m_midiIfaceSetupWidgets.begin();
|
||||
it != m_midiIfaceSetupWidgets.end(); ++it )
|
||||
{
|
||||
#ifdef QT4
|
||||
it.value()->hide();
|
||||
msw_layout->addWidget( it.value() );
|
||||
#else
|
||||
msw_layout->addWidget( it.data() );
|
||||
it.data()->hide();
|
||||
#endif
|
||||
m_midiInterfaces->addItem( it.key() );
|
||||
}
|
||||
|
||||
#ifdef QT4
|
||||
m_midiInterfaces->setCurrentIndex( m_midiInterfaces->findText(
|
||||
mixer::inst()->midiDevName() ) );
|
||||
#else
|
||||
m_midiInterfaces->setCurrentText( mixer::inst()->midiDevName() );
|
||||
#endif
|
||||
m_midiIfaceSetupWidgets[mixer::inst()->midiDevName()]->show();
|
||||
|
||||
connect( m_midiInterfaces, SIGNAL( activated( const QString & ) ),
|
||||
this, SLOT( midiInterfaceChanged( const QString & ) ) );
|
||||
|
||||
|
||||
midi_layout->addWidget( midiiface_tw );
|
||||
midi_layout->addSpacing( 20 );
|
||||
midi_layout->addWidget( msw );
|
||||
midi_layout->addStretch();
|
||||
|
||||
|
||||
#ifndef QT
|
||||
#define setIcon setPixmap
|
||||
#endif
|
||||
|
||||
m_tabBar->addTab( general, tr( "General settings" ), 0, FALSE, TRUE
|
||||
)->setIcon( embed::getIconPixmap( "setup_general" ) );
|
||||
m_tabBar->addTab( audio, tr( "Audio settings" ), 1, FALSE, TRUE
|
||||
)->setIcon( embed::getIconPixmap( "setup_audio" ) );
|
||||
m_tabBar->addTab( midi, tr( "MIDI settings" ), 2, TRUE, TRUE
|
||||
)->setIcon( embed::getIconPixmap( "setup_midi" ) );
|
||||
|
||||
#undef setIcon
|
||||
|
||||
m_tabBar->setActiveTab( _tab_to_open );
|
||||
|
||||
hlayout->addWidget( m_tabBar );
|
||||
hlayout->addSpacing( 10 );
|
||||
hlayout->addWidget( ws );
|
||||
hlayout->addSpacing( 10 );
|
||||
hlayout->addStretch();
|
||||
|
||||
QWidget * buttons = new QWidget( this );
|
||||
QHBoxLayout * btn_layout = new QHBoxLayout( buttons );
|
||||
QPushButton * ok_btn = new QPushButton( embed::getIconPixmap( "apply" ),
|
||||
tr( "OK" ), buttons );
|
||||
connect( ok_btn, SIGNAL( clicked() ), this, SLOT( accept() ) );
|
||||
|
||||
QPushButton * cancel_btn = new QPushButton( embed::getIconPixmap(
|
||||
"cancel" ),
|
||||
tr( "Cancel" ),
|
||||
buttons );
|
||||
connect( cancel_btn, SIGNAL( clicked() ), this, SLOT( reject() ) );
|
||||
|
||||
btn_layout->addStretch();
|
||||
btn_layout->addSpacing( 10 );
|
||||
btn_layout->addWidget( ok_btn );
|
||||
btn_layout->addSpacing( 10 );
|
||||
btn_layout->addWidget( cancel_btn );
|
||||
btn_layout->addSpacing( 10 );
|
||||
|
||||
vlayout->addWidget( settings );
|
||||
vlayout->addSpacing( 10 );
|
||||
vlayout->addWidget( buttons );
|
||||
vlayout->addSpacing( 10 );
|
||||
vlayout->addStretch();
|
||||
|
||||
show();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
setupDialog::~setupDialog()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void setupDialog::accept( void )
|
||||
{
|
||||
configManager::inst()->setValue( "mixer", "framesperaudiobuffer",
|
||||
QString::number( m_bufferSize ) );
|
||||
configManager::inst()->setValue( "mixer", "audiodev",
|
||||
m_audioInterfaces->currentText() );
|
||||
configManager::inst()->setValue( "mixer", "mididev",
|
||||
m_midiInterfaces->currentText() );
|
||||
configManager::inst()->setValue( "tooltips", "disabled",
|
||||
QString::number( m_disableToolTips ) );
|
||||
configManager::inst()->setValue( "knobs", "classicalusability",
|
||||
QString::number( m_classicalKnobUsability ) );
|
||||
// tell all audio-settings-widget to save their settings
|
||||
for( aswMap::iterator it = m_audioIfaceSetupWidgets.begin();
|
||||
it != m_audioIfaceSetupWidgets.end(); ++it )
|
||||
{
|
||||
#ifdef QT4
|
||||
it.value()->saveSettings();
|
||||
#else
|
||||
it.data()->saveSettings();
|
||||
#endif
|
||||
}
|
||||
// tell all MIDI-settings-widget to save their settings
|
||||
for( mswMap::iterator it = m_midiIfaceSetupWidgets.begin();
|
||||
it != m_midiIfaceSetupWidgets.end(); ++it )
|
||||
{
|
||||
#ifdef QT4
|
||||
it.value()->saveSettings();
|
||||
#else
|
||||
it.data()->saveSettings();
|
||||
#endif
|
||||
}
|
||||
|
||||
configManager::inst()->saveConfigFile();
|
||||
|
||||
QDialog::accept();
|
||||
QMessageBox::information( NULL, tr( "Restart LMMS" ),
|
||||
tr( "Please note that most changes "
|
||||
"won't take effect until "
|
||||
"you restart LMMS!" ),
|
||||
QMessageBox::Ok );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void setupDialog::setBufferSize( int _value )
|
||||
{
|
||||
if( m_bufSizeSlider->value() != _value )
|
||||
{
|
||||
m_bufSizeSlider->setValue( _value );
|
||||
}
|
||||
|
||||
m_bufferSize = _value * 64;
|
||||
m_bufSizeLbl->setText( tr( "FRAMES: %1\nLATENCY: %2 ms" ).arg(
|
||||
m_bufferSize ).arg(
|
||||
1000.0f * m_bufferSize /
|
||||
mixer::inst()->sampleRate(),
|
||||
0, 'f', 1 ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void setupDialog::resetBufSize( void )
|
||||
{
|
||||
setBufferSize( DEFAULT_BUFFER_SIZE / 64 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void setupDialog::displayBufSizeHelp( void )
|
||||
{
|
||||
#ifdef QT4
|
||||
QWhatsThis::showText( QCursor::pos(),
|
||||
#else
|
||||
QWhatsThis::display(
|
||||
#endif
|
||||
tr( "Here you can setup the internal buffer-size "
|
||||
"used by LMMS. Smaller values result "
|
||||
"in a lower latency but also may cause "
|
||||
"unusable sound or bad performance, "
|
||||
"especially on older computers or "
|
||||
"systems with a non-realtime "
|
||||
"kernel." ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void setupDialog::audioInterfaceChanged( const QString & _iface )
|
||||
{
|
||||
for( aswMap::iterator it = m_audioIfaceSetupWidgets.begin();
|
||||
it != m_audioIfaceSetupWidgets.end(); ++it )
|
||||
{
|
||||
#ifdef QT4
|
||||
it.value()->hide();
|
||||
#else
|
||||
it.data()->hide();
|
||||
#endif
|
||||
}
|
||||
|
||||
m_audioIfaceSetupWidgets[_iface]->show();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void setupDialog::displayAudioHelp( void )
|
||||
{
|
||||
#ifdef QT4
|
||||
QWhatsThis::showText( QCursor::pos(),
|
||||
#else
|
||||
QWhatsThis::display(
|
||||
#endif
|
||||
tr( "Here you can select your preferred "
|
||||
"audio-interface. Depending on the "
|
||||
"configuration of your system during "
|
||||
"compilation time you can choose "
|
||||
"between ALSA, JACK, OSS and more. "
|
||||
"Below you see a box which offers "
|
||||
"controls to setup the selected "
|
||||
"audio-interface." ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void setupDialog::midiInterfaceChanged( const QString & _iface )
|
||||
{
|
||||
for( mswMap::iterator it = m_midiIfaceSetupWidgets.begin();
|
||||
it != m_midiIfaceSetupWidgets.end(); ++it )
|
||||
{
|
||||
#ifdef QT4
|
||||
it.value()->hide();
|
||||
#else
|
||||
it.data()->hide();
|
||||
#endif
|
||||
}
|
||||
|
||||
m_midiIfaceSetupWidgets[_iface]->show();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void setupDialog::displayMIDIHelp( void )
|
||||
{
|
||||
#ifdef QT4
|
||||
QWhatsThis::showText( QCursor::pos(),
|
||||
#else
|
||||
QWhatsThis::display(
|
||||
#endif
|
||||
tr( "Here you can select your preferred "
|
||||
"MIDI-interface. Depending on the "
|
||||
"configuration of your system during "
|
||||
"compilation time you can choose "
|
||||
"between ALSA, OSS and more. "
|
||||
"Below you see a box which offers "
|
||||
"controls to setup the selected "
|
||||
"MIDI-interface." ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void setupDialog::toggleToolTips( bool _disabled )
|
||||
{
|
||||
m_disableToolTips = _disabled;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void setupDialog::toggleKnobUsability( bool _classical )
|
||||
{
|
||||
m_classicalKnobUsability = _classical;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#include "setup_dialog.moc"
|
||||
|
||||
1695
src/core/song_editor.cpp
Normal file
1695
src/core/song_editor.cpp
Normal file
File diff suppressed because it is too large
Load Diff
242
src/core/surround_area.cpp
Normal file
242
src/core/surround_area.cpp
Normal file
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* surround_area.cpp - a widget for setting position of a channel +
|
||||
* calculation of volume for each speaker
|
||||
*
|
||||
* Linux MultiMedia Studio
|
||||
* Copyright (c) 2004-2005 Tobias Doerffel <tobydox@users.sourceforge.net>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "qt3support.h"
|
||||
|
||||
#ifdef QT4
|
||||
|
||||
#include <QApplication>
|
||||
#include <QPainter>
|
||||
#include <QCursor>
|
||||
#include <QMouseEvent>
|
||||
#include <QImage>
|
||||
|
||||
#else
|
||||
|
||||
#include <qapplication.h>
|
||||
#include <qpainter.h>
|
||||
#include <qcursor.h>
|
||||
#include <qimage.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "surround_area.h"
|
||||
#include "embed.h"
|
||||
#include "templates.h"
|
||||
#include "tooltip.h"
|
||||
|
||||
|
||||
|
||||
const QPoint surroundArea::s_defaultSpeakerPositions[SURROUND_CHANNELS] =
|
||||
{
|
||||
QPoint( -SURROUND_AREA_SIZE, -SURROUND_AREA_SIZE ),
|
||||
QPoint( SURROUND_AREA_SIZE, -SURROUND_AREA_SIZE)
|
||||
#ifndef DISABLE_SURROUND
|
||||
,
|
||||
QPoint( -SURROUND_AREA_SIZE, SURROUND_AREA_SIZE ),
|
||||
QPoint( SURROUND_AREA_SIZE, SURROUND_AREA_SIZE )
|
||||
#endif
|
||||
} ;
|
||||
|
||||
QPixmap * surroundArea::s_backgroundArtwork = NULL;
|
||||
|
||||
|
||||
|
||||
|
||||
surroundArea::surroundArea( QWidget * _parent ) :
|
||||
QWidget( _parent ),
|
||||
m_sndSrcPos( QPoint() )
|
||||
{
|
||||
if( s_backgroundArtwork == NULL )
|
||||
{
|
||||
s_backgroundArtwork = new QPixmap( embed::getIconPixmap(
|
||||
"surround_area" ) );
|
||||
}
|
||||
|
||||
setFixedSize( s_backgroundArtwork->width(),
|
||||
s_backgroundArtwork->height() );
|
||||
#ifndef QT4
|
||||
setBackgroundMode( Qt::NoBackground );
|
||||
#endif
|
||||
toolTip::add( this,
|
||||
tr( "click to where this channel should be audible" ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
surroundArea::~surroundArea()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
volumeVector surroundArea::getVolumeVector( float _v_scale ) const
|
||||
{
|
||||
volumeVector v;
|
||||
for( Uint8 chnl = 0; chnl < SURROUND_CHANNELS; ++chnl )
|
||||
{
|
||||
v.vol[chnl] = getVolume( s_defaultSpeakerPositions[chnl],
|
||||
_v_scale );
|
||||
}
|
||||
|
||||
return( v );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void surroundArea::setValue( const QPoint & _p )
|
||||
{
|
||||
if( tLimit( _p.x(), -SURROUND_AREA_SIZE, SURROUND_AREA_SIZE ) !=
|
||||
_p.x() ||
|
||||
tLimit( _p.y(), -SURROUND_AREA_SIZE, SURROUND_AREA_SIZE ) != _p.y() )
|
||||
{
|
||||
m_sndSrcPos = QPoint( 0, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sndSrcPos = _p;
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
FASTCALL float surroundArea::getVolume( const QPoint & _speaker_pos,
|
||||
float _v_scale ) const
|
||||
{
|
||||
const int x = _speaker_pos.x() - m_sndSrcPos.x();
|
||||
const int y = _speaker_pos.y() - m_sndSrcPos.y();
|
||||
const float new_vol = 2.0f - sqrt( x*x + y*y ) *
|
||||
( 1.0f / SURROUND_AREA_SIZE );
|
||||
|
||||
return( tLimit( new_vol, 0.0f, 1.0f ) * _v_scale );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void surroundArea::paintEvent( QPaintEvent * )
|
||||
{
|
||||
#ifdef QT4
|
||||
QPainter p( this );
|
||||
if( s_backgroundArtwork->size() != size() )
|
||||
{
|
||||
p.drawPixmap( 0, 0, *s_backgroundArtwork );
|
||||
}
|
||||
else
|
||||
{
|
||||
p.drawPixmap( 0, 0, s_backgroundArtwork->scaled(
|
||||
width(), height(),
|
||||
Qt::IgnoreAspectRatio,
|
||||
Qt::SmoothTransformation ) );
|
||||
}
|
||||
#else
|
||||
QPixmap pm;
|
||||
if( s_backgroundArtwork->size() != size() )
|
||||
{
|
||||
pm.convertFromImage(
|
||||
s_backgroundArtwork->convertToImage().smoothScale(
|
||||
width(), height() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
pm = *s_backgroundArtwork;
|
||||
}
|
||||
QPainter p( &pm );
|
||||
#endif
|
||||
const int x = ( width() + m_sndSrcPos.x() * ( width() - 4 ) /
|
||||
SURROUND_AREA_SIZE ) / 2;
|
||||
const int y = ( height() + m_sndSrcPos.y() * ( height() - 4 ) /
|
||||
SURROUND_AREA_SIZE ) / 2;
|
||||
p.setPen( QColor( 64, 255, 64 ) );
|
||||
p.drawPoint( x, y - 1 );
|
||||
p.drawPoint( x - 1, y );
|
||||
p.drawPoint( x, y );
|
||||
p.drawPoint( x + 1, y );
|
||||
p.drawPoint( x, y + 1 );
|
||||
|
||||
#ifndef QT4
|
||||
// blit drawn pixmap to actual widget
|
||||
bitBlt( this, rect().topLeft(), &pm );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void surroundArea::mousePressEvent( QMouseEvent * _me )
|
||||
{
|
||||
const int w = width();//s_backgroundArtwork->width();
|
||||
const int h = height();//s_backgroundArtwork->height();
|
||||
if( _me->x() > 1 && _me->x() < w-1 && _me->y() > 1 && _me->y() < h-1 )
|
||||
{
|
||||
m_sndSrcPos.setX( ( _me->x() * 2 - w ) * SURROUND_AREA_SIZE /
|
||||
( w - 4 ) );
|
||||
m_sndSrcPos.setY( ( _me->y() * 2 - h ) * SURROUND_AREA_SIZE /
|
||||
( h - 4 ) );
|
||||
update();
|
||||
if( _me->button() != Qt::NoButton )
|
||||
{
|
||||
QApplication::setOverrideCursor( Qt::BlankCursor );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int x = tLimit( _me->x(), 2, w - 2 );
|
||||
int y = tLimit( _me->y(), 2, h - 2 );
|
||||
QCursor::setPos( mapToGlobal( QPoint( x, y ) ) );
|
||||
}
|
||||
|
||||
emit valueChanged( m_sndSrcPos );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void surroundArea::mouseMoveEvent( QMouseEvent * _me )
|
||||
{
|
||||
mousePressEvent( _me );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void surroundArea::mouseReleaseEvent( QMouseEvent * )
|
||||
{
|
||||
QApplication::restoreOverrideCursor();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#include "surround_area.moc"
|
||||
|
||||
328
src/core/timeline.cpp
Normal file
328
src/core/timeline.cpp
Normal file
@@ -0,0 +1,328 @@
|
||||
/*
|
||||
* playpos_marker.cpp - class timeLine, representing a time-line with
|
||||
* position marker
|
||||
*
|
||||
* Linux MultiMedia Studio
|
||||
* Copyright (c) 2004-2005 Tobias Doerffel <tobydox@users.sourceforge.net>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "qt3support.h"
|
||||
|
||||
#ifdef QT4
|
||||
|
||||
#include <QPainter>
|
||||
#include <QApplication>
|
||||
#include <QMouseEvent>
|
||||
|
||||
#else
|
||||
|
||||
#include <qpainter.h>
|
||||
#include <qapplication.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "timeline.h"
|
||||
#include "nstate_button.h"
|
||||
#include "embed.h"
|
||||
#include "templates.h"
|
||||
|
||||
|
||||
|
||||
QPixmap * timeLine::s_timeLinePixmap = NULL;
|
||||
QPixmap * timeLine::s_posMarkerPixmap = NULL;
|
||||
QPixmap * timeLine::s_loopPointPixmap = NULL;
|
||||
|
||||
|
||||
timeLine::timeLine( const int _xoff, const int _yoff, const float _ppt,
|
||||
songEditor::playPos & _pos, const midiTime & _begin,
|
||||
QWidget * _parent ) :
|
||||
QWidget( _parent ),
|
||||
m_xOffset( _xoff ),
|
||||
m_posMarkerX( 0 ),
|
||||
m_ppt( _ppt ),
|
||||
m_pos( _pos ),
|
||||
m_begin( _begin ),
|
||||
m_savedPos( -1 ),
|
||||
m_action( NONE ),
|
||||
m_moveXOff( 0 )
|
||||
{
|
||||
m_loopPos[0] = 0;
|
||||
m_loopPos[1] = 64;
|
||||
|
||||
if( s_timeLinePixmap == NULL)
|
||||
{
|
||||
s_timeLinePixmap = new QPixmap( embed::getIconPixmap(
|
||||
"timeline" ) );
|
||||
}
|
||||
if( s_posMarkerPixmap == NULL)
|
||||
{
|
||||
s_posMarkerPixmap = new QPixmap( embed::getIconPixmap(
|
||||
"playpos_marker" ) );
|
||||
}
|
||||
if( s_loopPointPixmap == NULL)
|
||||
{
|
||||
s_loopPointPixmap = new QPixmap( embed::getIconPixmap(
|
||||
"loop_point" ) );
|
||||
}
|
||||
|
||||
move( 0, _yoff );
|
||||
setFixedHeight( s_timeLinePixmap->height() );
|
||||
|
||||
m_xOffset -= s_posMarkerPixmap->width() / 2;
|
||||
|
||||
|
||||
m_autoScroll = new nStateButton( this );
|
||||
m_autoScroll->move( 3, 3 );
|
||||
m_autoScroll->setGeneralToolTip( tr( "Enable/disable "
|
||||
"auto-scrolling" ) );
|
||||
m_autoScroll->addState( embed::getIconPixmap( "autoscroll_on" ) );
|
||||
m_autoScroll->addState( embed::getIconPixmap( "autoscroll_off" ) );
|
||||
|
||||
m_loopPoints = new nStateButton( this );
|
||||
m_loopPoints->move( 20, 3 );
|
||||
m_loopPoints->setGeneralToolTip( tr( "Enable/disable loop-points" ) );
|
||||
m_loopPoints->addState( embed::getIconPixmap( "loop_points_off" ) );
|
||||
m_loopPoints->addState( embed::getIconPixmap( "loop_points_on" ) );
|
||||
connect( m_loopPoints, SIGNAL( stateChanged( int ) ), this,
|
||||
SLOT( toggleLoopPoints( int ) ) );
|
||||
|
||||
m_behaviourAtStop = new nStateButton( this );
|
||||
m_behaviourAtStop ->move( 37, 3 );
|
||||
m_behaviourAtStop ->addState( embed::getIconPixmap( "back_to_zero" ),
|
||||
tr( "After stopping go back to begin" )
|
||||
);
|
||||
m_behaviourAtStop ->addState( embed::getIconPixmap(
|
||||
"back_to_start" ),
|
||||
tr( "After stopping go back to "
|
||||
"position at which playing was "
|
||||
"started" ) );
|
||||
m_behaviourAtStop ->addState( embed::getIconPixmap(
|
||||
"keep_stop_position" ),
|
||||
tr( "After stopping keep position" ) );
|
||||
|
||||
#ifndef QT4
|
||||
setBackgroundMode( Qt::NoBackground );
|
||||
#endif
|
||||
|
||||
m_pos.m_timeLine = this;
|
||||
|
||||
updatePosition();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
timeLine::~timeLine()
|
||||
{
|
||||
m_pos.m_timeLine = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
timeLine::behaviourAtStopStates timeLine::behaviourAtStop( void ) const
|
||||
{
|
||||
return( static_cast<behaviourAtStopStates>(
|
||||
m_behaviourAtStop->state() ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool timeLine::loopPointsEnabled( void ) const
|
||||
{
|
||||
return( m_loopPoints->state() == LOOP_POINTS_ENABLED );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void timeLine::updatePosition( const midiTime & )
|
||||
{
|
||||
const int new_x = markerX( m_pos );
|
||||
|
||||
if( new_x != m_posMarkerX )
|
||||
{
|
||||
m_posMarkerX = new_x;
|
||||
#ifndef QT4
|
||||
qApp->lock();
|
||||
#endif
|
||||
update();
|
||||
#ifndef QT4
|
||||
qApp->unlock();
|
||||
#endif
|
||||
if( m_autoScroll->state() == AUTOSCROLL_ENABLED )
|
||||
{
|
||||
emit positionChanged( m_pos );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void timeLine::toggleLoopPoints( int _n )
|
||||
{
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void timeLine::paintEvent( QPaintEvent * )
|
||||
{
|
||||
#ifdef QT4
|
||||
QPainter p( this );
|
||||
#else
|
||||
QPixmap draw_pm( rect().size() );
|
||||
|
||||
QPainter p( &draw_pm, this );
|
||||
#endif
|
||||
|
||||
for( int x = 0; x < width(); x += s_timeLinePixmap->width() )
|
||||
{
|
||||
p.drawPixmap( x, 0, *s_timeLinePixmap );
|
||||
}
|
||||
p.setClipRect( m_xOffset, 0, width() - m_xOffset, height() );
|
||||
p.setPen( QColor( 0, 0, 0 ) );
|
||||
|
||||
if( m_loopPoints->state() == LOOP_POINTS_ENABLED )
|
||||
{
|
||||
p.drawPixmap( markerX( m_loopPos[0] ), 7,
|
||||
*s_loopPointPixmap );
|
||||
p.drawPixmap( markerX( m_loopPos[1] ), 7,
|
||||
*s_loopPointPixmap );
|
||||
}
|
||||
|
||||
|
||||
tact tact_num = m_begin.getTact();
|
||||
int x = m_xOffset + s_posMarkerPixmap->width() / 2 -
|
||||
( ( static_cast<Sint32>( m_begin * m_ppt ) / 64 ) %
|
||||
static_cast<int>( m_ppt ) );
|
||||
|
||||
for( int i = 0; x + i * m_ppt < width(); ++i )
|
||||
{
|
||||
++tact_num;
|
||||
if( ( tact_num - 1 ) %
|
||||
tMax( 1, static_cast<int>( 64.0f / m_ppt ) ) == 0 )
|
||||
{
|
||||
p.drawText( x + static_cast<int>( i * m_ppt ), 16,
|
||||
QString::number( tact_num ) );
|
||||
}
|
||||
}
|
||||
|
||||
p.drawPixmap( m_posMarkerX, 4, *s_posMarkerPixmap );
|
||||
|
||||
#ifndef QT4
|
||||
// and blit all the drawn stuff on the screen...
|
||||
bitBlt( this, rect().topLeft(), &draw_pm );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void timeLine::mousePressEvent( QMouseEvent * _me )
|
||||
{
|
||||
if( _me->x() < m_xOffset )
|
||||
{
|
||||
return;
|
||||
}
|
||||
if( _me->button() == Qt::RightButton )
|
||||
{
|
||||
if( m_loopPoints->state() != LOOP_POINTS_ENABLED )
|
||||
{
|
||||
return;
|
||||
}
|
||||
if( _me->x() >= markerX( loopBegin() ) &&
|
||||
_me->x() <= markerX( loopBegin() ) +
|
||||
s_loopPointPixmap->width() )
|
||||
{
|
||||
m_action = MOVE_LOOP_BEGIN;
|
||||
m_moveXOff = s_loopPointPixmap->width() / 2;
|
||||
}
|
||||
else if( _me->x() >= markerX( loopEnd() ) &&
|
||||
_me->x() <= markerX( loopEnd() ) +
|
||||
s_loopPointPixmap->width() )
|
||||
{
|
||||
m_action = MOVE_LOOP_END;
|
||||
m_moveXOff = s_loopPointPixmap->width() / 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_action = MOVE_POS_MARKER;
|
||||
if( _me->x() - m_xOffset < s_posMarkerPixmap->width() )
|
||||
{
|
||||
m_moveXOff = _me->x() - m_xOffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_moveXOff = s_posMarkerPixmap->width() / 2;
|
||||
}
|
||||
}
|
||||
mouseMoveEvent( _me );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void timeLine::mouseMoveEvent( QMouseEvent * _me )
|
||||
{
|
||||
const midiTime t = m_begin + static_cast<Sint32>( tMax( _me->x() -
|
||||
m_xOffset - m_moveXOff, 0 ) * 64 / m_ppt );
|
||||
switch( m_action )
|
||||
{
|
||||
case MOVE_POS_MARKER:
|
||||
m_pos.setTact( t.getTact() );
|
||||
m_pos.setTact64th( t.getTact64th() );
|
||||
m_pos.setCurrentFrame( 0 );
|
||||
updatePosition();
|
||||
break;
|
||||
|
||||
case MOVE_LOOP_BEGIN:
|
||||
m_loopPos[0] = t;
|
||||
update();
|
||||
break;
|
||||
|
||||
case MOVE_LOOP_END:
|
||||
m_loopPos[1] = t;
|
||||
update();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void timeLine::mouseReleaseEvent( QMouseEvent * _me )
|
||||
{
|
||||
m_action = NONE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#include "timeline.moc"
|
||||
|
||||
1087
src/core/track.cpp
Normal file
1087
src/core/track.cpp
Normal file
File diff suppressed because it is too large
Load Diff
391
src/core/track_container.cpp
Normal file
391
src/core/track_container.cpp
Normal file
@@ -0,0 +1,391 @@
|
||||
/*
|
||||
* track_container.cpp - implementation of base-class for all track-containers
|
||||
* like Song-Editor, BB-Editor...
|
||||
*
|
||||
* Linux MultiMedia Studio
|
||||
* Copyright (c) 2004-2005 Tobias Doerffel <tobydox@users.sourceforge.net>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "qt3support.h"
|
||||
|
||||
#ifdef QT4
|
||||
|
||||
#include <Qt/QtXml>
|
||||
#include <QApplication>
|
||||
#include <QProgressDialog>
|
||||
|
||||
#else
|
||||
|
||||
#include <qdom.h>
|
||||
#include <qapplication.h>
|
||||
#include <qprogressdialog.h>
|
||||
|
||||
#define setValue setProgress
|
||||
#define value progress
|
||||
#define maximum totalSteps
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "track_container.h"
|
||||
#include "track.h"
|
||||
#include "templates.h"
|
||||
#include "bb_track.h"
|
||||
#include "lmms_main_win.h"
|
||||
#include "mixer.h"
|
||||
|
||||
|
||||
|
||||
const Uint16 DEFAULT_PIXELS_PER_TACT = 16;
|
||||
|
||||
|
||||
trackContainer::trackContainer() :
|
||||
QMainWindow( lmmsMainWin::inst()->workspace()
|
||||
#ifndef QT4
|
||||
, 0, Qt::WStyle_Title
|
||||
#endif
|
||||
),
|
||||
settings(),
|
||||
m_currentPosition( 0, 0 ),
|
||||
m_ppt( DEFAULT_PIXELS_PER_TACT )
|
||||
{
|
||||
#ifdef QT4
|
||||
lmmsMainWin::inst()->workspace()->addWindow( this );
|
||||
#endif
|
||||
|
||||
m_scrollArea = new QScrollArea( this );
|
||||
m_scrollArea->setFrameStyle( QFrame::NoFrame );
|
||||
m_scrollArea->setHorizontalScrollBarPolicy(
|
||||
#ifdef QT4
|
||||
Qt::ScrollBarAlwaysOff
|
||||
#else
|
||||
QScrollArea::AlwaysOff
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
trackContainer::~trackContainer()
|
||||
{
|
||||
while( m_trackWidgets.size() )
|
||||
{
|
||||
removeTrack( m_trackWidgets.front()->getTrack() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void trackContainer::saveSettings( QDomDocument & _doc, QDomElement & _parent )
|
||||
{
|
||||
QDomElement tc_de = _doc.createElement( "trackcontainer" );
|
||||
tc_de.setAttribute( "type", nodeName() );
|
||||
_parent.appendChild( tc_de );
|
||||
|
||||
// save settings of each track
|
||||
for( trackWidgetVector::iterator it = m_trackWidgets.begin();
|
||||
it != m_trackWidgets.end(); ++it )
|
||||
{
|
||||
( *it )->getTrack()->saveSettings( _doc, tc_de );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void trackContainer::loadSettings( const QDomElement & _this )
|
||||
{
|
||||
static QProgressDialog * pd = NULL;
|
||||
bool was_null = ( pd == NULL );
|
||||
int start_val = 0;
|
||||
if( pd == NULL )
|
||||
{
|
||||
#ifdef QT4
|
||||
pd = new QProgressDialog( tr( "Loading project..." ),
|
||||
tr( "Cancel" ), 0,
|
||||
_this.childNodes().count() );
|
||||
#else
|
||||
pd = new QProgressDialog( tr( "Loading project..." ),
|
||||
tr( "Cancel" ),
|
||||
_this.childNodes().count(),
|
||||
0, 0, TRUE );
|
||||
#endif
|
||||
pd->setWindowTitle( tr( "Please wait..." ) );
|
||||
pd->show();
|
||||
}
|
||||
else
|
||||
{
|
||||
start_val = pd->value();
|
||||
#ifdef QT4
|
||||
pd->setMaximum( pd->maximum() + _this.childNodes().count() );
|
||||
#else
|
||||
pd->setTotalSteps( pd->maximum() + _this.childNodes().count() );
|
||||
#endif
|
||||
}
|
||||
|
||||
QDomNode node = _this.firstChild();
|
||||
while( !node.isNull() )
|
||||
{
|
||||
pd->setValue( pd->value() + 1 );
|
||||
#ifdef QT4
|
||||
qApp->processEvents( QEventLoop::AllEvents, 100 );
|
||||
#else
|
||||
qApp->processEvents( 100 );
|
||||
#endif
|
||||
|
||||
if( pd->wasCanceled() )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if( node.isElement() )
|
||||
{
|
||||
track::createTrack( node.toElement(), this );
|
||||
}
|
||||
node = node.nextSibling();
|
||||
}
|
||||
|
||||
pd->setValue( start_val + _this.childNodes().count() );
|
||||
|
||||
if( was_null )
|
||||
{
|
||||
delete pd;
|
||||
pd = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void trackContainer::cloneTrack( track * _track )
|
||||
{
|
||||
track::cloneTrack( _track );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void trackContainer::addTrack( track * _track )
|
||||
{
|
||||
m_trackWidgets.push_back( _track->getTrackWidget() );
|
||||
#ifndef QT4
|
||||
m_scrollArea->addChild( _track->getTrackWidget() );
|
||||
#endif
|
||||
connect( this, SIGNAL( positionChanged( const midiTime & ) ),
|
||||
_track->getTrackWidget(),
|
||||
SLOT( changePosition( const midiTime & ) ) );
|
||||
realignTracks();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void trackContainer::removeTrack( track * _track )
|
||||
{
|
||||
trackWidgetVector::iterator it = qFind( m_trackWidgets.begin(),
|
||||
m_trackWidgets.end(), _track->getTrackWidget() );
|
||||
if( it != m_trackWidgets.end() )
|
||||
{
|
||||
mixer::inst()->pause();
|
||||
#ifndef QT4
|
||||
m_scrollArea->removeChild( _track->getTrackWidget() );
|
||||
#endif
|
||||
m_trackWidgets.erase( it );
|
||||
|
||||
delete _track;
|
||||
|
||||
mixer::inst()->play();
|
||||
|
||||
realignTracks();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void trackContainer::moveTrackUp( track * _track )
|
||||
{
|
||||
for( trackWidgetVector::iterator it = m_trackWidgets.begin();
|
||||
it != m_trackWidgets.end(); ++it )
|
||||
{
|
||||
if( *it == _track->getTrackWidget() &&
|
||||
it > m_trackWidgets.begin() )
|
||||
{
|
||||
bbTrack::swapBBTracks( ( *it )->getTrack(),
|
||||
( *( it - 1 ) )->getTrack() );
|
||||
qSwap( *it, *( it - 1 ) );
|
||||
realignTracks();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void trackContainer::moveTrackDown( track * _track )
|
||||
{
|
||||
for( trackWidgetVector::iterator it = m_trackWidgets.begin();
|
||||
it != m_trackWidgets.end(); ++it )
|
||||
{
|
||||
if( *it == _track->getTrackWidget() &&
|
||||
it + 1 < m_trackWidgets.end() )
|
||||
{
|
||||
bbTrack::swapBBTracks( ( *it )->getTrack(),
|
||||
( *( it + 1 ) )->getTrack() );
|
||||
qSwap( *it, *( it + 1 ) );
|
||||
realignTracks();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void trackContainer::updateAfterTrackAdd( void )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void trackContainer::realignTracks( bool _complete_update )
|
||||
{
|
||||
int y = 0;
|
||||
for( trackWidgetVector::iterator it = m_trackWidgets.begin();
|
||||
it != m_trackWidgets.end(); ++it )
|
||||
{
|
||||
if( _complete_update )
|
||||
{
|
||||
( *it )->hide();
|
||||
}
|
||||
( *it )->show();
|
||||
#ifdef QT4
|
||||
( *it )->move( 0, y );
|
||||
#else
|
||||
m_scrollArea->moveChild( *it, 0, y );
|
||||
#endif
|
||||
( *it )->resize( width(), ( *it )->height() );
|
||||
( *it )->changePosition( m_currentPosition );
|
||||
y += ( *it )->height();
|
||||
}
|
||||
#ifndef QT4
|
||||
m_scrollArea->resizeContents( m_scrollArea->parentWidget()->width(),
|
||||
y );
|
||||
#endif
|
||||
updateScrollArea();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
unsigned int trackContainer::countTracks( track::trackTypes _tt ) const
|
||||
{
|
||||
unsigned int cnt = 0;
|
||||
for( trackWidgetVector::const_iterator it = m_trackWidgets.begin();
|
||||
it != m_trackWidgets.end(); ++it )
|
||||
{
|
||||
if( ( *it )->getTrack()->trackType() == _tt ||
|
||||
_tt == track::TOTAL_TRACK_TYPES )
|
||||
{
|
||||
++cnt;
|
||||
}
|
||||
}
|
||||
return( cnt );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void trackContainer::setMutedOfAllTracks( bool _muted )
|
||||
{
|
||||
for( trackWidgetVector::iterator it = m_trackWidgets.begin();
|
||||
it != m_trackWidgets.end(); ++it )
|
||||
{
|
||||
( *it )->setMuted( _muted );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
constTrackVector trackContainer::tracks( void ) const
|
||||
{
|
||||
constTrackVector tracks;
|
||||
for( trackWidgetVector::const_iterator it = m_trackWidgets.begin();
|
||||
it != m_trackWidgets.end(); ++it )
|
||||
{
|
||||
tracks.push_back( ( *it )->getTrack() );
|
||||
}
|
||||
return( tracks );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
trackVector trackContainer::tracks( void )
|
||||
{
|
||||
trackVector tracks;
|
||||
for( trackWidgetVector::iterator it = m_trackWidgets.begin();
|
||||
it != m_trackWidgets.end(); ++it )
|
||||
{
|
||||
tracks.push_back( ( *it )->getTrack() );
|
||||
}
|
||||
return( tracks );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void trackContainer::setPixelsPerTact( Uint16 _ppt )
|
||||
{
|
||||
m_ppt = _ppt;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void trackContainer::resizeEvent( QResizeEvent * )
|
||||
{
|
||||
realignTracks();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void trackContainer::updateScrollArea( void )
|
||||
{
|
||||
m_scrollArea->resize( tMax( m_scrollArea->parentWidget()->width() -
|
||||
m_scrollArea->x()-2, 0 ),
|
||||
tMax( m_scrollArea->parentWidget()->height() -
|
||||
m_scrollArea->y() - 2, 0 ) );
|
||||
//m_scrollArea->updateContents();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#include "track_container.moc"
|
||||
|
||||
#undef setValue
|
||||
#undef value
|
||||
#undef maximum
|
||||
Reference in New Issue
Block a user