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:
Tobias Doerffel
2005-09-27 12:58:19 +00:00
parent 4c7832a975
commit 3a2536e269
22 changed files with 13539 additions and 0 deletions

150
src/core/about_dialog.cpp Normal file
View 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"

View 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(), &note_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
View 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
View 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() ?
&copyFile :
&linkFile );
processFilesRecursively( m_lmmsDataDir + "presets/", m_lmmsWorkingDir +
"presets/",
m_presetsCopyRB->isChecked() ?
&copyFile :
&linkFile );
processFilesRecursively( m_lmmsDataDir + "projects/", m_lmmsWorkingDir +
"projects/",
m_projectsCopyRB->isChecked() ?
&copyFile :
&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"

File diff suppressed because it is too large Load Diff

View 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;
}
*/

View 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
View 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
View 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
View 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
View 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();
}

View 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

File diff suppressed because it is too large Load Diff

619
src/core/piano_widget.cpp Normal file
View 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"

View 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() );
}

View 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
View 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

File diff suppressed because it is too large Load Diff

242
src/core/surround_area.cpp Normal file
View 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
View 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

File diff suppressed because it is too large Load Diff

View 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