Initial revision
git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@3 0778d3d1-df1d-0410-868b-ea421aaaa00d
This commit is contained in:
439
src/audio/audio_alsa.cpp
Normal file
439
src/audio/audio_alsa.cpp
Normal file
@@ -0,0 +1,439 @@
|
||||
/*
|
||||
* audio_alsa.cpp - device-class that implements ALSA-PCM-output
|
||||
*
|
||||
* 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 <QLineEdit>
|
||||
#include <QLabel>
|
||||
|
||||
#else
|
||||
|
||||
#include <qpair.h>
|
||||
#include <qlineedit.h>
|
||||
#include <qlabel.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "audio_alsa.h"
|
||||
|
||||
|
||||
#ifdef ALSA_SUPPORT
|
||||
|
||||
#include "endian_handling.h"
|
||||
#include "buffer_allocator.h"
|
||||
#include "config_mgr.h"
|
||||
#include "lcd_spinbox.h"
|
||||
#include "templates.h"
|
||||
|
||||
|
||||
|
||||
audioALSA::audioALSA( Uint32 _sample_rate, bool & _success_ful ) :
|
||||
audioDevice( _sample_rate, tLimit<int>( configManager::inst()->value(
|
||||
"audioalsa", "channels" ).toInt(),
|
||||
DEFAULT_CHANNELS, SURROUND_CHANNELS ) ),
|
||||
m_handle( NULL ),
|
||||
m_hwParams( NULL ),
|
||||
m_swParams( NULL ),
|
||||
m_littleEndian( isLittleEndian() )
|
||||
{
|
||||
_success_ful = FALSE;
|
||||
|
||||
int err;
|
||||
|
||||
if( ( err = snd_pcm_open( &m_handle,
|
||||
#ifdef QT4
|
||||
probeDevice().toAscii().constData(),
|
||||
#else
|
||||
probeDevice().ascii(),
|
||||
#endif
|
||||
SND_PCM_STREAM_PLAYBACK,
|
||||
SND_PCM_NONBLOCK ) ) < 0 )
|
||||
{
|
||||
printf( "Playback open error: %s\n", snd_strerror( err ) );
|
||||
return;
|
||||
}
|
||||
|
||||
snd_pcm_hw_params_alloca( &m_hwParams );
|
||||
snd_pcm_sw_params_alloca( &m_swParams );
|
||||
|
||||
if( ( err = setHWParams( _sample_rate, channels(),
|
||||
SND_PCM_ACCESS_RW_INTERLEAVED ) ) < 0 )
|
||||
{
|
||||
printf( "Setting of hwparams failed: %s\n",
|
||||
snd_strerror( err ) );
|
||||
return;
|
||||
}
|
||||
if( ( err = setSWParams() ) < 0 )
|
||||
{
|
||||
printf( "Setting of swparams failed: %s\n",
|
||||
snd_strerror( err ) );
|
||||
return;
|
||||
}
|
||||
|
||||
_success_ful = TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
audioALSA::~audioALSA()
|
||||
{
|
||||
if( m_handle != NULL )
|
||||
{
|
||||
snd_pcm_close( m_handle );
|
||||
}
|
||||
// the following code doesn't work and leads to a crash...
|
||||
/* if( m_hwParams != NULL )
|
||||
{
|
||||
snd_pcm_hw_params_free( m_hwParams );
|
||||
}
|
||||
|
||||
if( m_swParams != NULL )
|
||||
{
|
||||
snd_pcm_sw_params_free( m_swParams );
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
QString audioALSA::probeDevice( void )
|
||||
{
|
||||
QString dev = configManager::inst()->value( "audioalsa", "device" );
|
||||
if( dev == "" )
|
||||
{
|
||||
if( getenv( "AUDIODEV" ) != NULL )
|
||||
{
|
||||
return( getenv( "AUDIODEV" ) );
|
||||
}
|
||||
return( "default" );
|
||||
}
|
||||
return( dev );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int audioALSA::handleError( int _err )
|
||||
{
|
||||
if( _err == -EPIPE )
|
||||
{
|
||||
// under-run
|
||||
_err = snd_pcm_prepare( m_handle );
|
||||
if( _err < 0 )
|
||||
printf( "Can't recovery from underrun, prepare "
|
||||
"failed: %s\n", snd_strerror( _err ) );
|
||||
return ( 0 );
|
||||
}
|
||||
else if( _err == -ESTRPIPE )
|
||||
{
|
||||
while( ( _err = snd_pcm_resume( m_handle ) ) == -EAGAIN )
|
||||
{
|
||||
sleep( 1 ); // wait until the suspend flag
|
||||
// is released
|
||||
}
|
||||
|
||||
if( _err < 0 )
|
||||
{
|
||||
_err = snd_pcm_prepare( m_handle );
|
||||
if( _err < 0 )
|
||||
printf( "Can't recovery from suspend, prepare "
|
||||
"failed: %s\n", snd_strerror( _err ) );
|
||||
}
|
||||
return ( 0 );
|
||||
}
|
||||
return( _err );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void audioALSA::writeBufferToDev( surroundSampleFrame * _ab, Uint32 _frames,
|
||||
float _master_output )
|
||||
{
|
||||
outputSampleType * outbuf = bufferAllocator::alloc<outputSampleType>(
|
||||
_frames * channels() );
|
||||
bufferAllocator::autoCleaner<> ac( outbuf );
|
||||
|
||||
convertToS16( _ab, _frames, _master_output, outbuf,
|
||||
m_littleEndian != isLittleEndian() );
|
||||
|
||||
Uint32 frame = 0;
|
||||
|
||||
while( frame < _frames )
|
||||
{
|
||||
int err = snd_pcm_writei( m_handle, outbuf, _frames );
|
||||
|
||||
if( err == -EAGAIN )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if( err < 0 )
|
||||
{
|
||||
if( handleError( err ) < 0 )
|
||||
{
|
||||
printf( "Write error: %s\n",
|
||||
snd_strerror( err ) );
|
||||
return;
|
||||
}
|
||||
break; // skip this buffer
|
||||
}
|
||||
outbuf += err * channels();
|
||||
frame += err;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int audioALSA::setHWParams( Uint32 _sample_rate, Uint32 _channels,
|
||||
snd_pcm_access_t _access )
|
||||
{
|
||||
int err, dir;
|
||||
|
||||
// choose all parameters
|
||||
if( ( err = snd_pcm_hw_params_any( m_handle, m_hwParams ) ) < 0 )
|
||||
{
|
||||
printf( "Broken configuration for playback: no configurations "
|
||||
"available: %s\n", snd_strerror( err ) );
|
||||
return( err );
|
||||
}
|
||||
|
||||
// set the interleaved read/write format
|
||||
if( ( err = snd_pcm_hw_params_set_access( m_handle, m_hwParams,
|
||||
_access ) ) < 0 )
|
||||
{
|
||||
printf( "Access type not available for playback: %s\n",
|
||||
snd_strerror( err ) );
|
||||
return( err );
|
||||
}
|
||||
|
||||
// set the sample format
|
||||
if( ( snd_pcm_hw_params_set_format( m_handle, m_hwParams,
|
||||
SND_PCM_FORMAT_S16_LE ) ) < 0 )
|
||||
{
|
||||
if( ( snd_pcm_hw_params_set_format( m_handle, m_hwParams,
|
||||
SND_PCM_FORMAT_S16_BE ) ) < 0 )
|
||||
{
|
||||
printf( "Neither little- nor big-endian available for "
|
||||
"playback: %s\n", snd_strerror( err ) );
|
||||
return( err );
|
||||
}
|
||||
m_littleEndian = FALSE;
|
||||
}
|
||||
|
||||
// set the count of channels
|
||||
if( ( err = snd_pcm_hw_params_set_channels( m_handle, m_hwParams,
|
||||
_channels ) ) < 0 )
|
||||
{
|
||||
printf( "Channel count (%i) not available for playbacks: %s\n"
|
||||
"(Does your soundcard not support surround?)\n",
|
||||
_channels, snd_strerror( err ) );
|
||||
return( err );
|
||||
}
|
||||
|
||||
// set the sample rate
|
||||
if( ( err = snd_pcm_hw_params_set_rate( m_handle, m_hwParams,
|
||||
_sample_rate, 0 ) ) < 0 )
|
||||
{
|
||||
int q = 0;
|
||||
if( sampleRate() == SAMPLE_RATES[1] )
|
||||
{
|
||||
q = 1;
|
||||
}
|
||||
if( sampleRate() == 44100 || sampleRate() == 88200 )
|
||||
{
|
||||
SAMPLE_RATES[0] = 48000;
|
||||
SAMPLE_RATES[1] = 96000;
|
||||
}
|
||||
else
|
||||
{
|
||||
SAMPLE_RATES[0] = 44100;
|
||||
SAMPLE_RATES[1] = 82000;
|
||||
}
|
||||
setSampleRate( SAMPLE_RATES[q] );
|
||||
if( ( err = snd_pcm_hw_params_set_rate( m_handle, m_hwParams,
|
||||
SAMPLE_RATES[q], 0 ) ) < 0 )
|
||||
{
|
||||
printf( "Could not set sample rate: %s\n",
|
||||
snd_strerror( err ) );
|
||||
return( err );
|
||||
}
|
||||
}
|
||||
|
||||
m_periodSize = mixer::inst()->framesPerAudioBuffer();
|
||||
m_bufferSize = m_periodSize * 8;
|
||||
dir = 0;
|
||||
err = snd_pcm_hw_params_set_period_size_near( m_handle, m_hwParams,
|
||||
&m_periodSize, &dir );
|
||||
if( err < 0 )
|
||||
{
|
||||
printf( "Unable to set period size %lu for playback: %s\n",
|
||||
m_periodSize, snd_strerror( err ) );
|
||||
return( err );
|
||||
}
|
||||
dir = 0;
|
||||
err = snd_pcm_hw_params_get_period_size( m_hwParams, &m_periodSize,
|
||||
&dir );
|
||||
if( err < 0 )
|
||||
{
|
||||
printf( "Unable to get period size for playback: %s\n",
|
||||
snd_strerror( err ) );
|
||||
}
|
||||
|
||||
dir = 0;
|
||||
err = snd_pcm_hw_params_set_buffer_size_near( m_handle, m_hwParams,
|
||||
&m_bufferSize );
|
||||
if( err < 0 )
|
||||
{
|
||||
printf( "Unable to set buffer size %lu for playback: %s\n",
|
||||
m_bufferSize, snd_strerror( err ) );
|
||||
return ( err );
|
||||
}
|
||||
err = snd_pcm_hw_params_get_buffer_size( m_hwParams, &m_bufferSize );
|
||||
|
||||
if( 2 * m_periodSize > m_bufferSize )
|
||||
{
|
||||
printf( "buffer to small, could not use\n" );
|
||||
return ( err );
|
||||
}
|
||||
|
||||
|
||||
// write the parameters to device
|
||||
err = snd_pcm_hw_params( m_handle, m_hwParams );
|
||||
if( err < 0 )
|
||||
{
|
||||
printf( "Unable to set hw params for playback: %s\n",
|
||||
snd_strerror( err ) );
|
||||
return ( err );
|
||||
}
|
||||
|
||||
return ( 0 ); // all ok
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int audioALSA::setSWParams( void )
|
||||
{
|
||||
int err;
|
||||
|
||||
// get the current swparams
|
||||
if( ( err = snd_pcm_sw_params_current( m_handle, m_swParams ) ) < 0 )
|
||||
{
|
||||
printf( "Unable to determine current swparams for playback: %s"
|
||||
"\n", snd_strerror( err ) );
|
||||
return( err );
|
||||
}
|
||||
|
||||
// start the transfer when a period is full
|
||||
if( ( err = snd_pcm_sw_params_set_start_threshold( m_handle,
|
||||
m_swParams, m_periodSize ) ) < 0 )
|
||||
{
|
||||
printf( "Unable to set start threshold mode for playback: %s\n",
|
||||
snd_strerror( err ) );
|
||||
return( err );
|
||||
}
|
||||
|
||||
// allow the transfer when at least m_periodSize samples can be
|
||||
// processed
|
||||
if( ( err = snd_pcm_sw_params_set_avail_min( m_handle, m_swParams,
|
||||
m_periodSize ) ) < 0 )
|
||||
{
|
||||
printf( "Unable to set avail min for playback: %s\n",
|
||||
snd_strerror( err ) );
|
||||
return( err );
|
||||
}
|
||||
|
||||
// align all transfers to 1 sample
|
||||
if( ( err = snd_pcm_sw_params_set_xfer_align( m_handle,
|
||||
m_swParams, 1 ) ) < 0 )
|
||||
{
|
||||
printf( "Unable to set transfer align for playback: %s\n",
|
||||
snd_strerror( err ) );
|
||||
return( err );
|
||||
}
|
||||
|
||||
// write the parameters to the playback device
|
||||
if( ( err = snd_pcm_sw_params( m_handle, m_swParams ) ) < 0 )
|
||||
{
|
||||
printf( "Unable to set sw params for playback: %s\n",
|
||||
snd_strerror( err ) );
|
||||
return( err );
|
||||
}
|
||||
|
||||
return( 0 ); // all ok
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
audioALSA::setupWidget::setupWidget( QWidget * _parent ) :
|
||||
audioDevice::setupWidget( audioALSA::name(), _parent )
|
||||
{
|
||||
m_device = new QLineEdit( audioALSA::probeDevice(), this );
|
||||
m_device->setGeometry( 10, 20, 160, 20 );
|
||||
|
||||
QLabel * dev_lbl = new QLabel( tr( "DEVICE" ), this );
|
||||
dev_lbl->setFont( pointSize<6>( dev_lbl->font() ) );
|
||||
dev_lbl->setGeometry( 10, 40, 160, 10 );
|
||||
|
||||
m_channels = new lcdSpinBox( DEFAULT_CHANNELS, SURROUND_CHANNELS, 1,
|
||||
this );
|
||||
m_channels->setStep( 2 );
|
||||
m_channels->setLabel( tr( "CHANNELS" ) );
|
||||
m_channels->setValue( configManager::inst()->value( "audioalsa",
|
||||
"channels" ).toInt() );
|
||||
m_channels->move( 180, 20 );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
audioALSA::setupWidget::~setupWidget()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void audioALSA::setupWidget::saveSettings( void )
|
||||
{
|
||||
configManager::inst()->setValue( "audioalsa", "device",
|
||||
m_device->text() );
|
||||
configManager::inst()->setValue( "audioalsa", "channels",
|
||||
QString::number( m_channels->value() ) );
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
290
src/audio/audio_device.cpp
Normal file
290
src/audio/audio_device.cpp
Normal file
@@ -0,0 +1,290 @@
|
||||
/*
|
||||
* audio_device.cpp - base-class for audio-devices used by LMMS-mixer
|
||||
*
|
||||
* 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 <cstring>
|
||||
|
||||
|
||||
#include "audio_device.h"
|
||||
#include "buffer_allocator.h"
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
|
||||
audioDevice::audioDevice( Uint32 _sample_rate, Uint8 _channels ) :
|
||||
m_sampleRate( _sample_rate ),
|
||||
m_channels( _channels )
|
||||
{
|
||||
#ifdef HAVE_SAMPLERATE_H
|
||||
int error;
|
||||
if( ( m_srcState = src_new(
|
||||
#ifdef HQ_SINC
|
||||
SRC_SINC_BEST_QUALITY,
|
||||
#else
|
||||
SRC_SINC_FASTEST,
|
||||
#endif
|
||||
SURROUND_CHANNELS, &error ) ) == NULL )
|
||||
{
|
||||
printf( "Error: src_new() failed in audio_device.cpp!\n" );
|
||||
}
|
||||
m_srcData.end_of_input = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
audioDevice::~audioDevice()
|
||||
{
|
||||
#ifdef HAVE_SAMPLERATE_H
|
||||
src_delete( m_srcState );
|
||||
#endif
|
||||
unlock();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void audioDevice::writeBuffer( surroundSampleFrame * _ab, Uint32 _frames,
|
||||
Uint32 _src_sample_rate, float _master_output )
|
||||
{
|
||||
// make sure, no other thread is accessing device
|
||||
lock();
|
||||
// now were save to access the device
|
||||
if( _src_sample_rate != m_sampleRate )
|
||||
{
|
||||
surroundSampleFrame * temp =
|
||||
bufferAllocator::alloc<surroundSampleFrame>(
|
||||
_frames * channels() );
|
||||
resample( _ab, _frames, temp, _src_sample_rate, m_sampleRate );
|
||||
writeBufferToDev( temp, _frames * m_sampleRate /
|
||||
_src_sample_rate, _master_output );
|
||||
bufferAllocator::free( temp );
|
||||
}
|
||||
else
|
||||
{
|
||||
writeBufferToDev( _ab, _frames, _master_output );
|
||||
}
|
||||
// release lock
|
||||
unlock();
|
||||
}
|
||||
|
||||
|
||||
#ifndef HAVE_SAMPLERATE_H
|
||||
const Uint8 LP_FILTER_TAPS = 24;
|
||||
const float LP_FILTER_COEFFS[LP_FILTER_TAPS] =
|
||||
{
|
||||
+0.000511851442,
|
||||
-0.001446936402,
|
||||
-0.005058312516,
|
||||
-0.002347181570,
|
||||
+0.011236146012,
|
||||
+0.020351310667,
|
||||
-0.000479735368,
|
||||
-0.045333228189
|
||||
-0.055186434405,
|
||||
+0.032962246498,
|
||||
+0.202439670159,
|
||||
+0.342350604673,
|
||||
+0.342350604673,
|
||||
+0.202439670159,
|
||||
+0.032962246498,
|
||||
-0.055186434405,
|
||||
-0.045333228189
|
||||
-0.000479735368,
|
||||
+0.020351310667,
|
||||
+0.011236146012,
|
||||
-0.002347181570,
|
||||
-0.005058312516,
|
||||
-0.001446936402,
|
||||
+0.000511851442
|
||||
} ;
|
||||
#endif
|
||||
|
||||
|
||||
void FASTCALL audioDevice::resample( surroundSampleFrame * _src, Uint32 _frames,
|
||||
surroundSampleFrame * _dst,
|
||||
Uint32 _src_sr, Uint32 _dst_sr )
|
||||
{
|
||||
#ifdef HAVE_SAMPLERATE_H
|
||||
if( m_srcState == NULL )
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_srcData.input_frames = _frames;
|
||||
m_srcData.output_frames = _frames;
|
||||
m_srcData.data_in = _src[0];
|
||||
m_srcData.data_out = _dst[0];
|
||||
m_srcData.src_ratio = (float) _dst_sr / _src_sr;
|
||||
|
||||
int error;
|
||||
if( ( error = src_process( m_srcState, &m_srcData ) ) )
|
||||
{
|
||||
printf( "audioDevice::resample(): error while resampling: %s\n",
|
||||
src_strerror( error ) );
|
||||
}
|
||||
#else
|
||||
if( _src_sr == 2*SAMPLE_RATES[DEFAULT_QUALITY_LEVEL] )
|
||||
{
|
||||
// we use a simple N-tap FIR-Filter with
|
||||
// precalculated/-designed LP-Coeffs
|
||||
static surroundSampleFrame lp_hist[LP_FILTER_TAPS] =
|
||||
{
|
||||
#ifndef DISABLE_SURROUND
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f }
|
||||
#else
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f }
|
||||
#endif
|
||||
} ;
|
||||
static Uint8 oldest = 0;
|
||||
|
||||
for( Uint32 frame = 0; frame < _frames; ++frame )
|
||||
{
|
||||
for( Uint8 chnl = 0; chnl < SURROUND_CHANNELS; ++chnl )
|
||||
{
|
||||
lp_hist[oldest][chnl] = _src[frame][chnl];
|
||||
if( frame % 2==0 )
|
||||
{
|
||||
_dst[frame/2][chnl] = 0.0f;
|
||||
for( Uint8 tap = 0;
|
||||
tap < LP_FILTER_TAPS; ++tap )
|
||||
{
|
||||
_dst[frame / 2][chnl] +=
|
||||
LP_FILTER_COEFFS[tap] * lp_hist[( oldest + tap ) % LP_FILTER_TAPS][chnl];
|
||||
}
|
||||
}
|
||||
}
|
||||
oldest = ( oldest + 1 ) % LP_FILTER_TAPS;
|
||||
}
|
||||
}
|
||||
else if( _src_sr == SAMPLE_RATES[DEFAULT_QUALITY_LEVEL] / 2 )
|
||||
{
|
||||
printf( "No resampling for given sample-rates implemented!\n"
|
||||
"Consider installing libsamplerate and recompile "
|
||||
"LMMS!\n" );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int FASTCALL audioDevice::convertToS16( surroundSampleFrame * _ab,
|
||||
Uint32 _frames, float _master_output,
|
||||
outputSampleType * _output_buffer,
|
||||
bool _convert_endian )
|
||||
{
|
||||
for( Uint32 frame = 0; frame < _frames; ++frame )
|
||||
{
|
||||
for( Uint8 chnl = 0; chnl < channels(); ++chnl )
|
||||
{
|
||||
( _output_buffer + frame * channels() )[chnl] =
|
||||
static_cast<outputSampleType>(
|
||||
mixer::clip( _ab[frame][chnl] *
|
||||
_master_output ) *
|
||||
OUTPUT_SAMPLE_MULTIPLIER );
|
||||
}
|
||||
}
|
||||
if( _convert_endian )
|
||||
{
|
||||
for( Uint32 frame = 0; frame < _frames; ++frame )
|
||||
{
|
||||
for( Uint8 chnl = 0; chnl < channels(); ++chnl )
|
||||
{
|
||||
Sint8 * ptr = reinterpret_cast<Sint8 *>(
|
||||
_output_buffer +
|
||||
frame * channels() +
|
||||
chnl );
|
||||
*(outputSampleType *)ptr =
|
||||
( ( outputSampleType )*ptr << 8
|
||||
) |
|
||||
( ( outputSampleType ) *
|
||||
( ptr+1 ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
return( _frames * channels() * BYTES_PER_OUTPUT_SAMPLE );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FASTCALL audioDevice::clearS16Buffer( outputSampleType * _outbuf,
|
||||
Uint32 _frames )
|
||||
{
|
||||
#ifdef LMMS_DEBUG
|
||||
assert( _outbuf != NULL );
|
||||
#endif
|
||||
memset( _outbuf, 0, _frames * channels() * BYTES_PER_OUTPUT_SAMPLE );
|
||||
}
|
||||
|
||||
103
src/audio/audio_file_device.cpp
Normal file
103
src/audio/audio_file_device.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* audio_file_device.cpp - base-class for audio-device-classes which write
|
||||
* their output into a file
|
||||
*
|
||||
* 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 <QMessageBox>
|
||||
|
||||
#else
|
||||
|
||||
#include <qmessagebox.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "audio_file_device.h"
|
||||
#include "export_project_dialog.h"
|
||||
|
||||
|
||||
audioFileDevice::audioFileDevice( Uint32 _sample_rate, Uint8 _channels,
|
||||
const QString & _file,
|
||||
bool _use_vbr,
|
||||
Uint16 _nom_bitrate,
|
||||
Uint16 _min_bitrate,
|
||||
Uint16 _max_bitrate ) :
|
||||
audioDevice( _sample_rate, _channels),
|
||||
m_outputFile( _file ),
|
||||
m_useVbr( _use_vbr ),
|
||||
m_nomBitrate( _nom_bitrate ),
|
||||
m_minBitrate( _min_bitrate ),
|
||||
m_maxBitrate( _max_bitrate )
|
||||
{
|
||||
#ifdef QT4
|
||||
if( m_outputFile.open( QFile::WriteOnly | QFile::Truncate ) == FALSE )
|
||||
#else
|
||||
if( m_outputFile.open( IO_WriteOnly | IO_Truncate ) == FALSE )
|
||||
#endif
|
||||
{
|
||||
QMessageBox::critical( NULL,
|
||||
exportProjectDialog::tr( "Could not open file" ),
|
||||
exportProjectDialog::tr( "Could not open file %1 "
|
||||
"for writing.\nPlease make "
|
||||
"sure you have write-"
|
||||
"permission to the file and "
|
||||
"the directory containing the "
|
||||
"file and try again!" ).arg(
|
||||
_file ),
|
||||
QMessageBox::Ok,
|
||||
QMessageBox::NoButton );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
audioFileDevice::~audioFileDevice()
|
||||
{
|
||||
m_outputFile.close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int audioFileDevice::writeData( const void * _data, int _len )
|
||||
{
|
||||
#ifdef QT4
|
||||
return( m_outputFile.write( (const char *)_data, _len ) );
|
||||
#else
|
||||
return( m_outputFile.writeBlock( (const char *)_data, _len ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void audioFileDevice::seekToBegin( void )
|
||||
{
|
||||
m_outputFile.seek( 0 );
|
||||
}
|
||||
|
||||
267
src/audio/audio_file_ogg.cpp
Normal file
267
src/audio/audio_file_ogg.cpp
Normal file
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
* audio_file_ogg.cpp - Audio-device which encodes wave-stream and writes it
|
||||
* into an OGG-file. This is used for song-export.
|
||||
*
|
||||
* This file is based on encode.c from vorbis-tools-source, for more information
|
||||
* see below.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* OggEnc
|
||||
**
|
||||
** This program is distributed under the GNU General Public License, version 2.
|
||||
** A copy of this license is included with this source.
|
||||
**
|
||||
** Copyright 2000-2002, Michael Smith <msmith@labyrinth.net.au>
|
||||
**
|
||||
** Portions from Vorbize, (c) Kenneth Arnold <kcarnold@yahoo.com>
|
||||
** and libvorbis examples, (c) Monty <monty@xiph.org>
|
||||
**/
|
||||
|
||||
|
||||
#include <qpair.h>
|
||||
|
||||
#include "audio_file_ogg.h"
|
||||
|
||||
#ifdef HAVE_VORBIS_CODEC_H
|
||||
|
||||
|
||||
#include <vorbis/vorbisenc.h>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
audioFileOgg::audioFileOgg( Uint32 _sample_rate, Uint32 _channels,
|
||||
bool & _success_ful, const QString & _file,
|
||||
bool _use_vbr, Uint16 _nom_bitrate,
|
||||
Uint16 _min_bitrate, Uint16 _max_bitrate ) :
|
||||
audioFileDevice( _sample_rate, _channels, _file, _use_vbr,
|
||||
_nom_bitrate, _min_bitrate, _max_bitrate )
|
||||
{
|
||||
_success_ful = startEncoding();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
audioFileOgg::~audioFileOgg()
|
||||
{
|
||||
finishEncoding();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
inline int audioFileOgg::writePage( void )
|
||||
{
|
||||
int written = writeData( m_og.header, m_og.header_len );
|
||||
written += writeData( m_og.body, m_og.body_len );
|
||||
return( written );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool audioFileOgg::startEncoding( void )
|
||||
{
|
||||
vorbis_comment vc;
|
||||
char * comments = "Cool=This song was written with Linux "
|
||||
"MultiMedia Studio";
|
||||
int comment_length = strlen( comments );
|
||||
|
||||
vc.user_comments = &comments;
|
||||
vc.comment_lengths = &comment_length;
|
||||
vc.comments = 1;
|
||||
vc.vendor = NULL;
|
||||
|
||||
m_channels = channels();
|
||||
// vbr enabled?
|
||||
if( useVBR() == 0 )
|
||||
{
|
||||
m_managed = -1; // we don't want vbr
|
||||
m_minBitrate = nominalBitrate(); // min for vbr
|
||||
m_maxBitrate = nominalBitrate(); // max for vbr
|
||||
}
|
||||
else
|
||||
{
|
||||
m_managed = 0; // let's use vbr
|
||||
m_minBitrate = minBitrate(); // min for vbr
|
||||
m_maxBitrate = maxBitrate(); // max for vbr
|
||||
}
|
||||
|
||||
m_bitrate = nominalBitrate(); // nominal bitrate
|
||||
m_rate = sampleRate(); // default-samplerate
|
||||
m_serialNo = 0; // track-num?
|
||||
m_comments = &vc; // comments for ogg-file
|
||||
|
||||
// Have vorbisenc choose a mode for us
|
||||
vorbis_info_init( &m_vi );
|
||||
|
||||
if( vorbis_encode_setup_managed( &m_vi, m_channels, m_rate,
|
||||
( m_maxBitrate > 0 )? m_maxBitrate * 1000 : -1,
|
||||
m_bitrate * 1000,
|
||||
( m_minBitrate > 0 )? m_minBitrate * 1000 : -1 ) )
|
||||
{
|
||||
printf( "Mode initialization failed: invalid parameters for "
|
||||
"bitrate\n" );
|
||||
vorbis_info_clear( &m_vi );
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
if( m_managed && m_bitrate < 0 )
|
||||
{
|
||||
vorbis_encode_ctl( &m_vi, OV_ECTL_RATEMANAGE_AVG, NULL );
|
||||
}
|
||||
else if( !m_managed )
|
||||
{
|
||||
// Turn off management entirely (if it was turned on).
|
||||
vorbis_encode_ctl( &m_vi, OV_ECTL_RATEMANAGE_SET, NULL );
|
||||
}
|
||||
|
||||
vorbis_encode_setup_init( &m_vi );
|
||||
|
||||
// Now, set up the analysis engine, stream encoder, and other
|
||||
// preparation before the encoding begins.
|
||||
vorbis_analysis_init( &m_vd, &m_vi );
|
||||
vorbis_block_init( &m_vd, &m_vb );
|
||||
|
||||
ogg_stream_init( &m_os, m_serialNo );
|
||||
|
||||
// Now, build the three header packets and send through to the stream
|
||||
// output stage (but defer actual file output until the main encode
|
||||
// loop)
|
||||
|
||||
ogg_packet header_main;
|
||||
ogg_packet header_comments;
|
||||
ogg_packet header_codebooks;
|
||||
int result;
|
||||
|
||||
// Build the packets
|
||||
vorbis_analysis_headerout( &m_vd, m_comments, &header_main,
|
||||
&header_comments, &header_codebooks );
|
||||
|
||||
// And stream them out
|
||||
ogg_stream_packetin( &m_os, &header_main );
|
||||
ogg_stream_packetin( &m_os, &header_comments );
|
||||
ogg_stream_packetin( &m_os, &header_codebooks );
|
||||
|
||||
while( ( result = ogg_stream_flush( &m_os, &m_og ) ) )
|
||||
{
|
||||
if( !result )
|
||||
{
|
||||
break;
|
||||
}
|
||||
int ret = writePage();
|
||||
if( ret != m_og.header_len + m_og.body_len )
|
||||
{
|
||||
// clean up
|
||||
finishEncoding();
|
||||
return( FALSE );
|
||||
}
|
||||
}
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FASTCALL audioFileOgg::writeBufferToDev( surroundSampleFrame * _ab,
|
||||
Uint32 _frames,
|
||||
float _master_output )
|
||||
{
|
||||
int eos = 0;
|
||||
|
||||
float * * buffer = vorbis_analysis_buffer( &m_vd, _frames *
|
||||
BYTES_PER_SAMPLE *
|
||||
channels() );
|
||||
for( Uint32 frame = 0; frame < _frames; ++frame )
|
||||
{
|
||||
for( Uint8 chnl = 0; chnl < channels(); ++chnl )
|
||||
{
|
||||
buffer[chnl][frame] = _ab[frame][chnl] * _master_output;
|
||||
}
|
||||
}
|
||||
|
||||
vorbis_analysis_wrote( &m_vd, _frames );
|
||||
|
||||
// While we can get enough data from the library to analyse,
|
||||
// one block at a time...
|
||||
while( vorbis_analysis_blockout( &m_vd, &m_vb ) == 1 )
|
||||
{
|
||||
// Do the main analysis, creating a packet
|
||||
vorbis_analysis( &m_vb, NULL );
|
||||
vorbis_bitrate_addblock( &m_vb );
|
||||
|
||||
while( vorbis_bitrate_flushpacket( &m_vd, &m_op ) )
|
||||
{
|
||||
// Add packet to bitstream
|
||||
ogg_stream_packetin( &m_os, &m_op );
|
||||
|
||||
// If we've gone over a page boundary, we can do
|
||||
// actual output, so do so (for however many pages
|
||||
// are available)
|
||||
while( !eos )
|
||||
{
|
||||
int result = ogg_stream_pageout( &m_os,
|
||||
&m_og );
|
||||
if( !result )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
int ret = writePage();
|
||||
if( ret != m_og.header_len +
|
||||
m_og.body_len )
|
||||
{
|
||||
printf( "failed writing to "
|
||||
"outstream\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
if( ogg_page_eos( &m_og ) )
|
||||
{
|
||||
eos = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void audioFileOgg::finishEncoding( void )
|
||||
{
|
||||
// just for flushing buffers...
|
||||
writeBufferToDev( NULL, 0, 0.0f );
|
||||
|
||||
// clean up
|
||||
ogg_stream_clear( &m_os );
|
||||
|
||||
vorbis_block_clear( &m_vb );
|
||||
vorbis_dsp_clear( &m_vd );
|
||||
vorbis_info_clear( &m_vi );
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
118
src/audio/audio_file_wave.cpp
Normal file
118
src/audio/audio_file_wave.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* audio_file_wave.cpp - Audio-device which encodes wave-stream and writes it
|
||||
* into a WAVE-file. This is used for song-export.
|
||||
*
|
||||
* 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 "audio_file_wave.h"
|
||||
#include "endian_handling.h"
|
||||
#include "buffer_allocator.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
|
||||
audioFileWave::audioFileWave( Uint32 _sample_rate, Uint32 _channels,
|
||||
bool & _success_ful, const QString & _file,
|
||||
bool _use_vbr, Uint16 _nom_bitrate,
|
||||
Uint16 _min_bitrate, Uint16 _max_bitrate ) :
|
||||
audioFileDevice( _sample_rate, _channels, _file, _use_vbr,
|
||||
_nom_bitrate, _min_bitrate, _max_bitrate )
|
||||
{
|
||||
_success_ful = startEncoding();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
audioFileWave::~audioFileWave()
|
||||
{
|
||||
finishEncoding();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool audioFileWave::startEncoding( void )
|
||||
{
|
||||
if( outputFileOpened() == FALSE )
|
||||
{
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
m_bytesWritten = 0;
|
||||
|
||||
memcpy( m_waveFileHeader.riff_id, "RIFF", 4 );
|
||||
m_waveFileHeader.total_bytes = swap32IfBE( 0 );
|
||||
memcpy( m_waveFileHeader.wave_fmt_str, "WAVEfmt ", 8 );
|
||||
m_waveFileHeader.bitrate_1 =
|
||||
m_waveFileHeader.bitrate_2 =
|
||||
swap16IfBE( BYTES_PER_OUTPUT_SAMPLE * 8 );
|
||||
m_waveFileHeader.uncompressed = swap16IfBE( 1 );
|
||||
m_waveFileHeader.channels = swap16IfBE( channels() );
|
||||
m_waveFileHeader.sample_rate = swap32IfBE( sampleRate() );
|
||||
m_waveFileHeader.bytes_per_second = swap32IfBE( sampleRate() *
|
||||
BYTES_PER_OUTPUT_SAMPLE *
|
||||
channels() );
|
||||
m_waveFileHeader.block_alignment = swap16IfBE( BYTES_PER_OUTPUT_SAMPLE *
|
||||
channels() );
|
||||
memcpy ( m_waveFileHeader.data_chunk_id, "data", 4 );
|
||||
m_waveFileHeader.data_bytes = swap32IfBE( 0 );
|
||||
|
||||
writeData( &m_waveFileHeader, sizeof( m_waveFileHeader ) );
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FASTCALL audioFileWave::writeBufferToDev( surroundSampleFrame * _ab,
|
||||
Uint32 _frames,
|
||||
float _master_output )
|
||||
{
|
||||
outputSampleType * outbuf = bufferAllocator::alloc<outputSampleType>(
|
||||
_frames * channels() );
|
||||
int bytes = convertToS16( _ab, _frames, _master_output, outbuf,
|
||||
!isLittleEndian() );
|
||||
writeData( outbuf, bytes );
|
||||
|
||||
bufferAllocator::free( outbuf );
|
||||
|
||||
m_bytesWritten += bytes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void audioFileWave::finishEncoding( void )
|
||||
{
|
||||
seekToBegin();
|
||||
|
||||
m_waveFileHeader.total_bytes = m_bytesWritten+36;
|
||||
m_waveFileHeader.data_bytes = m_bytesWritten;
|
||||
|
||||
// write header again, because total-bytes-field and data-bytes-field
|
||||
// have to be updated...
|
||||
writeData( &m_waveFileHeader, sizeof( m_waveFileHeader ) );
|
||||
}
|
||||
|
||||
379
src/audio/audio_jack.cpp
Normal file
379
src/audio/audio_jack.cpp
Normal file
@@ -0,0 +1,379 @@
|
||||
/*
|
||||
* audio_jack.cpp - support for JACK-transport
|
||||
*
|
||||
* 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 "audio_jack.h"
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
// for usleep
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef JACK_SUPPORT
|
||||
|
||||
#ifdef QT4
|
||||
|
||||
#include <QLineEdit>
|
||||
#include <QLabel>
|
||||
|
||||
#else
|
||||
|
||||
#include <qlineedit.h>
|
||||
#include <qlabel.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#include "debug.h"
|
||||
#include "templates.h"
|
||||
#include "buffer_allocator.h"
|
||||
#include "config_mgr.h"
|
||||
#include "lcd_spinbox.h"
|
||||
|
||||
|
||||
audioJACK::audioJACK( Uint32 _sample_rate, bool & _success_ful ) :
|
||||
audioDevice( _sample_rate, tLimit<int>( configManager::inst()->value(
|
||||
"audiojack", "channels" ).toInt(),
|
||||
DEFAULT_CHANNELS, SURROUND_CHANNELS ) ),
|
||||
m_framesDoneInCurBuf( 0 ),
|
||||
m_frameSync( 0 ),
|
||||
m_jackBufSize( 0 ),
|
||||
m_bufMutex()
|
||||
{
|
||||
_success_ful = FALSE;
|
||||
|
||||
QString client_name = configManager::inst()->value( "audiojack",
|
||||
"clientname" );
|
||||
if( client_name == "" )
|
||||
{
|
||||
client_name = "lmms";
|
||||
}
|
||||
|
||||
#ifndef OLD_JACK
|
||||
const char * server_name = NULL;
|
||||
jack_status_t status;
|
||||
m_client = jack_client_open( client_name.
|
||||
#ifdef QT4
|
||||
toAscii().constData(),
|
||||
#else
|
||||
ascii(),
|
||||
#endif
|
||||
JackNullOption, &status,
|
||||
server_name );
|
||||
if( m_client == NULL )
|
||||
{
|
||||
printf( "jack_client_open() failed with status %d\n", status );
|
||||
if( status & JackServerFailed )
|
||||
{
|
||||
printf( "Could not connect to JACK server.\n" );
|
||||
}
|
||||
return;
|
||||
}
|
||||
if( status & JackNameNotUnique )
|
||||
{
|
||||
printf( "there's already a client with name '%s', so unique "
|
||||
"name '%s' was assigned\n", client_name.
|
||||
#ifdef QT4
|
||||
toAscii().constData(),
|
||||
#else
|
||||
ascii(),
|
||||
#endif
|
||||
jack_get_client_name( m_client ) );
|
||||
}
|
||||
#else
|
||||
m_client = jack_client_new( client_name.
|
||||
#ifdef QT4
|
||||
toAscii().constData()
|
||||
#else
|
||||
ascii()
|
||||
#endif
|
||||
);
|
||||
#endif
|
||||
|
||||
// set process-callback
|
||||
jack_set_process_callback( m_client, processCallback, this );
|
||||
|
||||
// we need to know about buffer-size changes to know how long to block
|
||||
// in writeToDev()-method
|
||||
jack_set_buffer_size_callback( m_client, bufSizeCallback, this );
|
||||
|
||||
// set shutdown-callback
|
||||
//jack_on_shutdown( m_client, shutdown, this );
|
||||
|
||||
m_jackBufSize = jack_get_buffer_size( m_client );
|
||||
|
||||
|
||||
if( jack_get_sample_rate( m_client ) != sampleRate() )
|
||||
{
|
||||
SAMPLE_RATES[0] = jack_get_sample_rate( m_client );
|
||||
SAMPLE_RATES[1] = 2 * SAMPLE_RATES[0];
|
||||
setSampleRate( SAMPLE_RATES[0] );
|
||||
}
|
||||
|
||||
for( Uint8 ch = 0; ch < channels(); ++ch )
|
||||
{
|
||||
QString name = QString( "master_out_" ) +
|
||||
( ( ch % 2 ) ? "R" : "L" ) +
|
||||
QString::number( ch / 2 + 1 );
|
||||
m_outputPorts.push_back( jack_port_register( m_client,
|
||||
#ifdef QT4
|
||||
name.toAscii().constData(),
|
||||
#else
|
||||
name.ascii(),
|
||||
#endif
|
||||
JACK_DEFAULT_AUDIO_TYPE,
|
||||
JackPortIsOutput, 0 ) );
|
||||
if( m_outputPorts.back() == NULL )
|
||||
{
|
||||
printf( "no more JACK-ports available!\n" );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( jack_activate( m_client ) )
|
||||
{
|
||||
printf( "cannot activate client\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
const char * * ports = jack_get_ports( m_client, NULL, NULL,
|
||||
JackPortIsPhysical |
|
||||
JackPortIsInput );
|
||||
if( ports == NULL )
|
||||
{
|
||||
printf( "no physical playback ports. you'll have to do "
|
||||
"connections at your own!\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
for( Uint8 ch = 0; ch < channels(); ++ch )
|
||||
{
|
||||
if( jack_connect( m_client, jack_port_name(
|
||||
m_outputPorts[ch] ),
|
||||
ports[ch] ) )
|
||||
{
|
||||
printf( "cannot connect output ports. you'll "
|
||||
"have to do connections at your own!\n"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free( ports );
|
||||
|
||||
_success_ful = TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
audioJACK::~audioJACK()
|
||||
{
|
||||
jack_deactivate( m_client );
|
||||
jack_client_close( m_client );
|
||||
|
||||
while( m_bufferSets.size() )
|
||||
{
|
||||
while( m_bufferSets.front().size() )
|
||||
{
|
||||
bufferAllocator::free(
|
||||
m_bufferSets.front().front().buf );
|
||||
m_bufferSets.front().erase(
|
||||
m_bufferSets.front().begin() );
|
||||
}
|
||||
m_bufferSets.erase( m_bufferSets.begin() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void audioJACK::writeBufferToDev( surroundSampleFrame * _ab, Uint32 _frames,
|
||||
float _master_output )
|
||||
{
|
||||
m_bufMutex.lock();
|
||||
|
||||
vvector<bufset> bufs;
|
||||
for( Uint8 chnl = 0; chnl < channels(); ++chnl )
|
||||
{
|
||||
sampleType * buf = bufferAllocator::alloc<sampleType>(
|
||||
_frames );
|
||||
for( Uint32 frame = 0; frame < _frames; ++frame )
|
||||
{
|
||||
buf[frame] = _ab[frame][chnl] * _master_output;
|
||||
}
|
||||
bufset b = { buf, _frames } ;
|
||||
bufs.push_back( b );
|
||||
}
|
||||
m_bufferSets.push_back( bufs );
|
||||
m_frameSync += _frames;
|
||||
|
||||
m_bufMutex.unlock();
|
||||
|
||||
// now wait until data has been collected by processCallback()
|
||||
while( m_frameSync > m_jackBufSize )
|
||||
{
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#ifdef HAVE_USLEEP
|
||||
// just wait and give cpu-time to other processes
|
||||
usleep( 500 );
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int audioJACK::processCallback( jack_nframes_t _nframes, void * _udata )
|
||||
{
|
||||
audioJACK * _this = static_cast<audioJACK *>( _udata );
|
||||
|
||||
#ifdef LMMS_DEBUG
|
||||
assert( _this != NULL );
|
||||
#endif
|
||||
jack_transport_state_t ts = jack_transport_query( _this->m_client,
|
||||
NULL );
|
||||
if( ts != JackTransportRolling )
|
||||
{
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
vvector<jack_default_audio_sample_t *> outbufs( _this->channels(),
|
||||
NULL );
|
||||
Uint8 ch = 0;
|
||||
for( vvector<jack_default_audio_sample_t *>::iterator it =
|
||||
outbufs.begin(); it != outbufs.end(); ++it, ++ch )
|
||||
{
|
||||
*it = (jack_default_audio_sample_t *) jack_port_get_buffer(
|
||||
_this->m_outputPorts[ch], _nframes );
|
||||
}
|
||||
|
||||
_this->m_bufMutex.lock();
|
||||
|
||||
jack_nframes_t done = 0;
|
||||
while( done < _nframes )
|
||||
{
|
||||
if( _this->m_bufferSets.size() == 0 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
jack_nframes_t todo = tMin( _nframes - done,
|
||||
_this->m_bufferSets.front()[0].frames -
|
||||
_this->m_framesDoneInCurBuf );
|
||||
for( Uint8 ch = 0; ch < _this->channels(); ++ch )
|
||||
{
|
||||
memcpy( outbufs[ch] + done,
|
||||
_this->m_bufferSets.front()[ch].buf +
|
||||
_this->m_framesDoneInCurBuf,
|
||||
sizeof( jack_default_audio_sample_t ) *
|
||||
todo );
|
||||
}
|
||||
_this->m_framesDoneInCurBuf += todo;
|
||||
if( _this->m_framesDoneInCurBuf >=
|
||||
_this->m_bufferSets.front()[0].frames )
|
||||
{
|
||||
for( Uint8 ch = 0; ch < _this->channels(); ++ch )
|
||||
{
|
||||
bufferAllocator::free(
|
||||
_this->m_bufferSets.front()[ch].buf );
|
||||
}
|
||||
_this->m_bufferSets.erase(
|
||||
_this->m_bufferSets.begin() );
|
||||
_this->m_framesDoneInCurBuf = 0;
|
||||
}
|
||||
done += todo;
|
||||
_this->m_frameSync -= todo;
|
||||
}
|
||||
_this->m_bufMutex.unlock();
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int audioJACK::bufSizeCallback( jack_nframes_t _nframes, void * _udata )
|
||||
{
|
||||
audioJACK * _this = static_cast<audioJACK *>( _udata );
|
||||
|
||||
#ifdef LMMS_DEBUG
|
||||
assert( _this != NULL );
|
||||
#endif
|
||||
_this->m_jackBufSize = _nframes;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
audioJACK::setupWidget::setupWidget( QWidget * _parent ) :
|
||||
audioDevice::setupWidget( audioJACK::name(), _parent )
|
||||
{
|
||||
QString cn = configManager::inst()->value( "audiojack", "clientname" );
|
||||
if( cn == "" )
|
||||
{
|
||||
cn = "lmms";
|
||||
}
|
||||
m_clientName = new QLineEdit( cn, this );
|
||||
m_clientName->setGeometry( 10, 20, 160, 20 );
|
||||
|
||||
QLabel * cn_lbl = new QLabel( tr( "CLIENT-NAME" ), this );
|
||||
cn_lbl->setFont( pointSize<6>( cn_lbl->font() ) );
|
||||
cn_lbl->setGeometry( 10, 40, 160, 10 );
|
||||
|
||||
m_channels = new lcdSpinBox( DEFAULT_CHANNELS, SURROUND_CHANNELS, 1,
|
||||
this );
|
||||
m_channels->setStep( 2 );
|
||||
m_channels->setLabel( tr( "CHANNELS" ) );
|
||||
m_channels->setValue( configManager::inst()->value( "audiojack",
|
||||
"channels" ).toInt() );
|
||||
m_channels->move( 180, 20 );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
audioJACK::setupWidget::~setupWidget()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void audioJACK::setupWidget::saveSettings( void )
|
||||
{
|
||||
configManager::inst()->setValue( "audiojack", "clientname",
|
||||
m_clientName->text() );
|
||||
configManager::inst()->setValue( "audiojack", "channels",
|
||||
QString::number( m_channels->value() ) );
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
329
src/audio/audio_oss.cpp
Normal file
329
src/audio/audio_oss.cpp
Normal file
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
* audio_oss.cpp - device-class that implements OSS-PCM-output
|
||||
*
|
||||
* 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 <QFileInfo>
|
||||
#include <QLineEdit>
|
||||
#include <QLabel>
|
||||
|
||||
#else
|
||||
|
||||
#include <qfileinfo.h>
|
||||
#include <qlineedit.h>
|
||||
#include <qlabel.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "audio_oss.h"
|
||||
#include "buffer_allocator.h"
|
||||
#include "endian_handling.h"
|
||||
#include "lcd_spinbox.h"
|
||||
#include "templates.h"
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_IOCTL_H
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef OSS_USE_SOUNDCARD_H
|
||||
/* This is installed on some systems */
|
||||
#include <soundcard.h>
|
||||
#else
|
||||
/* This is recommended by OSS */
|
||||
#include <sys/soundcard.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "config_mgr.h"
|
||||
|
||||
|
||||
#ifndef _PATH_DEV_DSP
|
||||
#ifdef __OpenBSD__
|
||||
#define _PATH_DEV_DSP "/dev/audio"
|
||||
#else
|
||||
#define _PATH_DEV_DSP "/dev/dsp"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
audioOSS::audioOSS( Uint32 _sample_rate, bool & _success_ful ) :
|
||||
audioDevice( _sample_rate, tLimit<int>( configManager::inst()->value(
|
||||
"audiooss", "channels" ).toInt(),
|
||||
DEFAULT_CHANNELS, SURROUND_CHANNELS ) ),
|
||||
m_convertEndian( FALSE )
|
||||
{
|
||||
_success_ful = FALSE;
|
||||
|
||||
m_audioFD = open(
|
||||
#ifdef QT4
|
||||
probeDevice().toAscii().constData(),
|
||||
#else
|
||||
probeDevice().ascii(),
|
||||
#endif
|
||||
O_WRONLY, 0 );
|
||||
|
||||
if( m_audioFD == -1 )
|
||||
{
|
||||
printf( "audioOSS: failed opening audio-device\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Make the file descriptor use blocking writes with fcntl()
|
||||
if ( fcntl( m_audioFD, F_SETFL, fcntl( m_audioFD, F_GETFL ) &
|
||||
~O_NONBLOCK ) < 0 )
|
||||
{
|
||||
printf( "could not set audio blocking mode\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
int frag_spec;
|
||||
for( frag_spec = 0; static_cast<unsigned int>( 0x01 << frag_spec ) <
|
||||
mixer::inst()->framesPerAudioBuffer() * channels() *
|
||||
BYTES_PER_OUTPUT_SAMPLE;
|
||||
++frag_spec )
|
||||
{
|
||||
}
|
||||
|
||||
frag_spec |= 0x00020000; // two fragments, for low latency
|
||||
|
||||
if ( ioctl( m_audioFD, SNDCTL_DSP_SETFRAGMENT, &frag_spec ) < 0 )
|
||||
{
|
||||
perror( "SNDCTL_DSP_SETFRAGMENT" );
|
||||
printf( "Warning: Couldn't set audio fragment size\n" );
|
||||
}
|
||||
|
||||
unsigned int value;
|
||||
// Get a list of supported hardware formats
|
||||
if ( ioctl( m_audioFD, SNDCTL_DSP_GETFMTS, &value ) < 0 )
|
||||
{
|
||||
perror( "SNDCTL_DSP_GETFMTS" );
|
||||
printf( "Couldn't get audio format list\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the audio format
|
||||
if( value & AFMT_S16_LE )
|
||||
{
|
||||
value = AFMT_S16_LE;
|
||||
}
|
||||
else if( value & AFMT_S16_BE )
|
||||
{
|
||||
value = AFMT_S16_BE;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(" Soundcard doesn't support signed 16-bit-data\n");
|
||||
}
|
||||
if ( ioctl( m_audioFD, SNDCTL_DSP_SETFMT, &value ) < 0 )
|
||||
{
|
||||
perror( "SNDCTL_DSP_SETFMT" );
|
||||
printf( "Couldn't set audio format\n" );
|
||||
return;
|
||||
}
|
||||
if( ( isLittleEndian() && ( value == AFMT_S16_BE ) ) ||
|
||||
( !isLittleEndian() && ( value == AFMT_S16_LE ) ) )
|
||||
{
|
||||
m_convertEndian = TRUE;
|
||||
}
|
||||
|
||||
// Set the number of channels of output
|
||||
value = channels();
|
||||
if ( ioctl( m_audioFD, SNDCTL_DSP_CHANNELS, &value ) < 0 )
|
||||
{
|
||||
perror( "SNDCTL_DSP_CHANNELS" );
|
||||
printf( "Cannot set the number of channels\n" );
|
||||
return;
|
||||
}
|
||||
if( value != channels() )
|
||||
{
|
||||
printf( "Couldn't set number of channels\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the DSP frequency
|
||||
value = sampleRate();
|
||||
if ( ioctl( m_audioFD, SNDCTL_DSP_SPEED, &value ) < 0 )
|
||||
{
|
||||
perror( "SNDCTL_DSP_SPEED" );
|
||||
printf( "Couldn't set audio frequency\n" );
|
||||
return;
|
||||
}
|
||||
if( value != sampleRate() )
|
||||
{
|
||||
//printf( "Soundcard uses different sample-rate than LMMS "
|
||||
// "does!\n" );
|
||||
int q = 0;
|
||||
if( sampleRate() == SAMPLE_RATES[1] )
|
||||
{
|
||||
q = 1;
|
||||
}
|
||||
if( sampleRate() == 44100 || sampleRate() == 88200 )
|
||||
{
|
||||
SAMPLE_RATES[0] = 48000;
|
||||
SAMPLE_RATES[1] = 96000;
|
||||
}
|
||||
else
|
||||
{
|
||||
SAMPLE_RATES[0] = 44100;
|
||||
SAMPLE_RATES[1] = 82000;
|
||||
}
|
||||
setSampleRate( SAMPLE_RATES[q] );
|
||||
value = sampleRate();
|
||||
if ( ioctl( m_audioFD, SNDCTL_DSP_SPEED, &value ) < 0 )
|
||||
{
|
||||
perror( "SNDCTL_DSP_SPEED" );
|
||||
printf( "Couldn't set audio frequency\n" );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_success_ful = TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
audioOSS::~audioOSS()
|
||||
{
|
||||
close( m_audioFD );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
QString audioOSS::probeDevice( void )
|
||||
{
|
||||
QString dev = configManager::inst()->value( "audiooss", "device" );
|
||||
if( dev == "" )
|
||||
{
|
||||
char * adev = getenv( "AUDIODEV" ); // Is there a standard
|
||||
// variable name?
|
||||
if( adev != NULL )
|
||||
{
|
||||
dev = adev;
|
||||
}
|
||||
else
|
||||
{
|
||||
dev = _PATH_DEV_DSP; // default device
|
||||
}
|
||||
}
|
||||
|
||||
// if the first open fails, look for other devices
|
||||
if ( QFileInfo( dev ).isWritable() == FALSE )
|
||||
{
|
||||
int instance = -1;
|
||||
while( 1 )
|
||||
{
|
||||
dev = _PATH_DEV_DSP + QString::number( ++instance );
|
||||
if( !QFileInfo( dev ).exists() )
|
||||
{
|
||||
dev = _PATH_DEV_DSP;
|
||||
break;
|
||||
}
|
||||
if( QFileInfo( dev ).isWritable() )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return( dev );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void audioOSS::writeBufferToDev( surroundSampleFrame * _ab, Uint32 _frames,
|
||||
float _master_output )
|
||||
{
|
||||
outputSampleType * outbuf = bufferAllocator::alloc<outputSampleType>(
|
||||
_frames * channels() );
|
||||
int bytes = convertToS16( _ab, _frames, _master_output, outbuf,
|
||||
m_convertEndian );
|
||||
write( m_audioFD, outbuf, bytes );
|
||||
|
||||
bufferAllocator::free( outbuf );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
audioOSS::setupWidget::setupWidget( QWidget * _parent ) :
|
||||
audioDevice::setupWidget( audioOSS::name(), _parent )
|
||||
{
|
||||
m_device = new QLineEdit( probeDevice(), this );
|
||||
m_device->setGeometry( 10, 20, 160, 20 );
|
||||
|
||||
QLabel * dev_lbl = new QLabel( tr( "DEVICE" ), this );
|
||||
dev_lbl->setFont( pointSize<6>( dev_lbl->font() ) );
|
||||
dev_lbl->setGeometry( 10, 40, 160, 10 );
|
||||
|
||||
m_channels = new lcdSpinBox( DEFAULT_CHANNELS, SURROUND_CHANNELS, 1,
|
||||
this );
|
||||
m_channels->setStep( 2 );
|
||||
m_channels->setLabel( tr( "CHANNELS" ) );
|
||||
m_channels->setValue( configManager::inst()->value( "audiooss",
|
||||
"channels" ).toInt() );
|
||||
m_channels->move( 180, 20 );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
audioOSS::setupWidget::~setupWidget()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void audioOSS::setupWidget::saveSettings( void )
|
||||
{
|
||||
configManager::inst()->setValue( "audiooss", "device",
|
||||
m_device->text() );
|
||||
configManager::inst()->setValue( "audiooss", "channels",
|
||||
QString::number( m_channels->value() ) );
|
||||
}
|
||||
|
||||
|
||||
112
src/audio/audio_sample_recorder.cpp
Normal file
112
src/audio/audio_sample_recorder.cpp
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* audio_sample_recorder.cpp - device-class that implements recording
|
||||
* surround-audio-buffers into RAM, maybe later
|
||||
* also harddisk
|
||||
*
|
||||
* 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 "audio_sample_recorder.h"
|
||||
#include "sample_buffer.h"
|
||||
#include "buffer_allocator.h"
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
|
||||
audioSampleRecorder::audioSampleRecorder( Uint32 _sample_rate, Uint32 _channels,
|
||||
bool & _success_ful ) :
|
||||
audioDevice( _sample_rate, _channels ),
|
||||
m_buffers()
|
||||
{
|
||||
_success_ful = TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
audioSampleRecorder::~audioSampleRecorder()
|
||||
{
|
||||
while( !m_buffers.isEmpty() )
|
||||
{
|
||||
bufferAllocator::free( m_buffers.front().first );
|
||||
m_buffers.erase( m_buffers.begin() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Uint32 audioSampleRecorder::framesRecorded( void ) const
|
||||
{
|
||||
Uint32 frames = 0;
|
||||
for( bufferVector::const_iterator it = m_buffers.begin();
|
||||
it != m_buffers.end(); ++it )
|
||||
{
|
||||
frames += it->second;
|
||||
}
|
||||
return( frames );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void audioSampleRecorder::createSampleBuffer( sampleBuffer * * _sample_buf )
|
||||
const
|
||||
{
|
||||
Uint32 frames = framesRecorded();
|
||||
// create buffer to store all recorded buffers in
|
||||
sampleFrame * data = bufferAllocator::alloc<sampleFrame>( frames );
|
||||
// make sure buffer is cleaned up properly at the end...
|
||||
bufferAllocator::autoCleaner<sampleFrame> ac( data );
|
||||
|
||||
#ifdef LMMS_DEBUG
|
||||
assert( data != NULL );
|
||||
#endif
|
||||
// now copy all buffers into big buffer
|
||||
for( bufferVector::const_iterator it = m_buffers.begin();
|
||||
it != m_buffers.end(); ++it )
|
||||
{
|
||||
memcpy( data, it->first, it->second * sizeof( sampleFrame ) );
|
||||
data += it->second;
|
||||
}
|
||||
// create according sample-buffer out of big buffer
|
||||
*_sample_buf = new sampleBuffer( ac.ptr(), frames );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void audioSampleRecorder::writeBufferToDev( surroundSampleFrame * _ab,
|
||||
Uint32 _frames, float )
|
||||
{
|
||||
sampleFrame * buf = bufferAllocator::alloc<sampleFrame>( _frames );
|
||||
for( Uint32 frame = 0; frame < _frames; ++frame )
|
||||
{
|
||||
for( Uint8 chnl = 0; chnl < DEFAULT_CHANNELS; ++chnl )
|
||||
{
|
||||
buf[frame][chnl] = _ab[frame][chnl];
|
||||
}
|
||||
}
|
||||
m_buffers.push_back( qMakePair( buf, _frames ) );
|
||||
}
|
||||
|
||||
|
||||
203
src/audio/audio_sdl.cpp
Normal file
203
src/audio/audio_sdl.cpp
Normal file
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* audio_sdl.cpp - device-class that performs PCM-output via SDL
|
||||
*
|
||||
* 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 "audio_sdl.h"
|
||||
|
||||
#ifdef SDL_AUDIO_SUPPORT
|
||||
|
||||
#ifdef QT4
|
||||
|
||||
#include <QLineEdit>
|
||||
#include <QLabel>
|
||||
|
||||
#else
|
||||
|
||||
#include <qlineedit.h>
|
||||
#include <qlabel.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "buffer_allocator.h"
|
||||
#include "debug.h"
|
||||
#include "config_mgr.h"
|
||||
#include "templates.h"
|
||||
|
||||
|
||||
|
||||
audioSDL::audioSDL( Uint32 _sample_rate, bool & _success_ful ) :
|
||||
audioDevice( _sample_rate, DEFAULT_CHANNELS ),
|
||||
m_buffer( bufferAllocator::alloc<outputSampleType>(
|
||||
mixer::inst()->framesPerAudioBuffer() *
|
||||
channels() ) ),
|
||||
m_bufMutex(),
|
||||
m_callbackMutex(),
|
||||
m_convertEndian( FALSE )
|
||||
{
|
||||
_success_ful = FALSE;
|
||||
|
||||
// if device is set, we set AUDIODEV-environment-variable, so that
|
||||
// SDL can evaluate and use it
|
||||
QString dev = configManager::inst()->value( "audiosdl", "device" );
|
||||
if( dev != "" )
|
||||
{
|
||||
putenv( const_cast<char *>( ( "AUDIODEV=" + dev ).
|
||||
#ifdef QT4
|
||||
toAscii().constData() ) );
|
||||
#else
|
||||
ascii() ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
if( SDL_Init( SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE ) < 0 )
|
||||
{
|
||||
printf( "Couldn't initialize SDL: %s\n", SDL_GetError() );
|
||||
return;
|
||||
}
|
||||
|
||||
m_audioHandle.freq = _sample_rate;
|
||||
m_audioHandle.format = AUDIO_S16SYS; // we want it in byte-order
|
||||
// of system, so we don't have
|
||||
// to convert the buffers
|
||||
m_audioHandle.channels = channels();
|
||||
m_audioHandle.samples = mixer::inst()->framesPerAudioBuffer();
|
||||
|
||||
m_audioHandle.callback = sdlAudioCallback;
|
||||
m_audioHandle.userdata = this;
|
||||
|
||||
SDL_AudioSpec actual;
|
||||
|
||||
// open the audio device, forcing the desired format
|
||||
if( SDL_OpenAudio( &m_audioHandle, &actual ) < 0 )
|
||||
{
|
||||
printf( "Couldn't open SDL-audio: %s\n", SDL_GetError() );
|
||||
return;
|
||||
}
|
||||
m_convertEndian = ( m_audioHandle.format != actual.format );
|
||||
|
||||
clearS16Buffer( m_buffer, m_audioHandle.samples );
|
||||
|
||||
// start playing
|
||||
SDL_PauseAudio( 0 );
|
||||
|
||||
_success_ful = TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
audioSDL::~audioSDL()
|
||||
{
|
||||
SDL_PauseAudio( 1 );
|
||||
SDL_CloseAudio();
|
||||
SDL_Quit();
|
||||
|
||||
m_bufMutex.lock();
|
||||
bufferAllocator::free( m_buffer );
|
||||
m_bufMutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void audioSDL::writeBufferToDev( surroundSampleFrame * _ab, Uint32 _frames,
|
||||
float _master_output )
|
||||
{
|
||||
m_bufMutex.lock();
|
||||
convertToS16( _ab, _frames, _master_output, m_buffer,
|
||||
m_convertEndian );
|
||||
m_bufMutex.unlock();
|
||||
// before returning make sure, callback was called, so we're synced
|
||||
// with it (otherwise it could be that (if there's not much to render)
|
||||
// this function is called several times although we had to wait until
|
||||
// we can proceed with next audio-output)
|
||||
m_callbackMutex.lock();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void audioSDL::sdlAudioCallback( void * _udata, Uint8 * _buf, int _len )
|
||||
{
|
||||
audioSDL * _this = static_cast<audioSDL *>( _udata );
|
||||
|
||||
#ifdef LMMS_DEBUG
|
||||
assert( _this != NULL );
|
||||
#endif
|
||||
|
||||
_this->m_bufMutex.lock();
|
||||
|
||||
// writeBufferToDev() prepared everything for us, so we just have
|
||||
// to do a memcpy() :-)
|
||||
memcpy( _buf, _this->m_buffer, _len );
|
||||
|
||||
// clear our output buffer, so that we don't output the same noise
|
||||
// when being called again without that writeBufferToDev() was called
|
||||
// (e.g. if there's too much to render)
|
||||
_this->clearS16Buffer( _this->m_buffer, _this->m_audioHandle.samples );
|
||||
|
||||
_this->m_bufMutex.unlock();
|
||||
|
||||
// we got our last buffer, so we let writeBufferToDev() return
|
||||
_this->m_callbackMutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
audioSDL::setupWidget::setupWidget( QWidget * _parent ) :
|
||||
audioDevice::setupWidget( audioSDL::name(), _parent )
|
||||
{
|
||||
QString dev = configManager::inst()->value( "audiosdl", "device" );
|
||||
m_device = new QLineEdit( dev, this );
|
||||
m_device->setGeometry( 10, 20, 160, 20 );
|
||||
|
||||
QLabel * dev_lbl = new QLabel( tr( "DEVICE" ), this );
|
||||
dev_lbl->setFont( pointSize<6>( dev_lbl->font() ) );
|
||||
dev_lbl->setGeometry( 10, 40, 160, 10 );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
audioSDL::setupWidget::~setupWidget()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void audioSDL::setupWidget::saveSettings( void )
|
||||
{
|
||||
configManager::inst()->setValue( "audiosdl", "device",
|
||||
m_device->text() );
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
197
src/lib/buffer_allocator.cpp
Normal file
197
src/lib/buffer_allocator.cpp
Normal file
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* buffer_allocator.cpp - namespace bufferAllocator providing routines for own
|
||||
* optimized memory-management for audio-buffers
|
||||
*
|
||||
* 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 <QList>
|
||||
#include <QMutex>
|
||||
|
||||
#else
|
||||
|
||||
#include <qpair.h>
|
||||
#include <qvaluelist.h>
|
||||
#include <qmutex.h>
|
||||
|
||||
#define qSort qHeapSort
|
||||
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include <cstring>
|
||||
|
||||
#include "buffer_allocator.h"
|
||||
#include "templates.h"
|
||||
#include "mixer.h"
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
struct bufDesc
|
||||
{
|
||||
bool free;
|
||||
char * origPtr;
|
||||
void * buf;
|
||||
Uint32 bytes;
|
||||
Uint32 timesUsed;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
inline bool operator<( const bufDesc & _bd1, const bufDesc & _bd2 )
|
||||
{
|
||||
return( _bd1.timesUsed < _bd2.timesUsed );
|
||||
}
|
||||
|
||||
#ifdef QT4
|
||||
|
||||
inline bool operator==( const bufDesc & _bd1, const bufDesc & _bd2 )
|
||||
{
|
||||
return( memcmp( &_bd1, &_bd2, sizeof( bufDesc ) ) == 0 );
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline bool operator!=( const bufDesc & _bd1, const bufDesc & _bd2 )
|
||||
{
|
||||
return( memcmp( &_bd1, &_bd2, sizeof( bufDesc ) ) != 0 );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static vlist<bufDesc> s_buffers;
|
||||
typedef vlist<bufDesc>::iterator bufIt;
|
||||
|
||||
QMutex s_buffersMutex;
|
||||
|
||||
|
||||
const int BUFFER_ALIGN = 16;
|
||||
const int BUFFER_ALIGN_MASK = BUFFER_ALIGN - 1;
|
||||
|
||||
|
||||
|
||||
void bufferAllocator::cleanUp( Uint16 _level )
|
||||
{
|
||||
// first insert all unused bufs into an array
|
||||
vvector<bufDesc> bufsToRemove;
|
||||
for( bufIt it = s_buffers.begin(); it != s_buffers.end(); ++it )
|
||||
{
|
||||
if( ( *it ).free )
|
||||
{
|
||||
bufsToRemove.push_back( *it );
|
||||
}
|
||||
}
|
||||
|
||||
// sort array by usage of each buffer
|
||||
// ( operator<(...) compares bufDesc::timesUsed )
|
||||
qSort( bufsToRemove );
|
||||
|
||||
const Uint16 todo = tMin<Uint16>( s_buffers.size() - _level,
|
||||
bufsToRemove.size() );
|
||||
|
||||
// now cleanup the first n elements of sorted array
|
||||
for( Uint16 i = 0; i < todo ; ++i )
|
||||
{
|
||||
delete[] bufsToRemove[i].origPtr;
|
||||
s_buffers.erase( qFind( s_buffers.begin(), s_buffers.end(),
|
||||
bufsToRemove[i] ) );
|
||||
}
|
||||
#ifdef LMMS_DEBUG
|
||||
//printf( "cleaned up %d buffers\n", todo );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bufferAllocator::free( void * _buf )
|
||||
{
|
||||
s_buffersMutex.lock();
|
||||
|
||||
// look for buffer
|
||||
for( bufIt it = s_buffers.begin(); it != s_buffers.end(); ++it )
|
||||
{
|
||||
if( !( *it ).free && ( *it ).buf == _buf )
|
||||
{
|
||||
++( *it ).timesUsed;
|
||||
( *it ).free = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// do clean-up if neccessary
|
||||
static Uint16 CLEANUP_LEVEL = static_cast<Uint16>( 512 / ( logf(
|
||||
mixer::inst()->framesPerAudioBuffer() ) /
|
||||
logf( 2 ) ) );
|
||||
if( s_buffers.size() > CLEANUP_LEVEL )
|
||||
{
|
||||
cleanUp( CLEANUP_LEVEL );
|
||||
}
|
||||
|
||||
s_buffersMutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void * bufferAllocator::allocBytes( Uint32 _bytes )
|
||||
{
|
||||
QMutexLocker ml( &s_buffersMutex );
|
||||
|
||||
bufIt free_buf = s_buffers.end();
|
||||
|
||||
// look whether there's a buffer matching to the one wanted and
|
||||
// find out the most used one (higher chances for being in CPU-cache)
|
||||
for( bufIt it = s_buffers.begin(); it != s_buffers.end(); ++it )
|
||||
{
|
||||
if( ( *it ).free && ( *it ).bytes == _bytes )
|
||||
{
|
||||
if( free_buf == s_buffers.end() ||
|
||||
( *it ).timesUsed > ( *free_buf ).timesUsed )
|
||||
{
|
||||
free_buf = it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( free_buf != s_buffers.end() )
|
||||
{
|
||||
( *free_buf ).free = FALSE;
|
||||
return( ( *free_buf ).buf );
|
||||
}
|
||||
|
||||
|
||||
// nothing so far, so we'll alloc a new (aligned) buf
|
||||
bufDesc d = { FALSE, new char[_bytes + BUFFER_ALIGN], NULL, _bytes, 0 };
|
||||
d.buf = (void *)( (size_t) d.origPtr + ( BUFFER_ALIGN -
|
||||
( (size_t) d.origPtr &
|
||||
BUFFER_ALIGN_MASK ) ) );
|
||||
s_buffers.push_back( d );
|
||||
return( d.buf );
|
||||
}
|
||||
|
||||
|
||||
|
||||
58
src/lib/clipboard.cpp
Normal file
58
src/lib/clipboard.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* clipboard.cpp - the clipboard for patterns, notes etc.
|
||||
*
|
||||
* 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 "clipboard.h"
|
||||
#include "settings.h"
|
||||
|
||||
|
||||
namespace clipboard
|
||||
{
|
||||
|
||||
map content;
|
||||
|
||||
|
||||
void copy( settings * _settings_object )
|
||||
{
|
||||
QDomDocument doc;
|
||||
QDomElement parent = doc.createElement( "clipboard" );
|
||||
_settings_object->saveSettings( doc, parent );
|
||||
content[_settings_object->nodeName()] =
|
||||
parent.firstChild().toElement();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
const QDomElement * getContent( const QString & _node_name )
|
||||
{
|
||||
if( content.find( _node_name ) != content.end() )
|
||||
{
|
||||
return( &content[_node_name] );
|
||||
}
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
123
src/lib/embed.cpp
Normal file
123
src/lib/embed.cpp
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* embed.cpp - misc stuff for using embedded resources (linked into binary)
|
||||
*
|
||||
* 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 <QTranslator>
|
||||
#include <QImage>
|
||||
|
||||
#else
|
||||
|
||||
#include <qapplication.h>
|
||||
#include <qtranslator.h>
|
||||
#include <qimage.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "embed.h"
|
||||
#include "config_mgr.h"
|
||||
|
||||
|
||||
namespace embed
|
||||
{
|
||||
|
||||
#include "embedded_resources.h"
|
||||
|
||||
|
||||
QPixmap getIconPixmap( const char * _name, int _w, int _h )
|
||||
{
|
||||
if( _w == -1 || _h == -1 )
|
||||
{
|
||||
QString name = QString( _name ) + ".png";
|
||||
#ifdef QT4
|
||||
const embedDesc & e = findEmbeddedData(
|
||||
name.toAscii().constData() );
|
||||
#else
|
||||
const embedDesc & e = findEmbeddedData( name.ascii() );
|
||||
#endif
|
||||
// not found?
|
||||
if( QString( e.name ) != name )
|
||||
{
|
||||
// then look whether icon is in data-dir
|
||||
QPixmap p( configManager::inst()->artworkDir() + name );
|
||||
if( p.isNull() )
|
||||
{
|
||||
p = QPixmap( 1, 1 );
|
||||
}
|
||||
return( p );
|
||||
}
|
||||
QPixmap p;
|
||||
p.loadFromData( e.data, e.size );
|
||||
return( p );
|
||||
}
|
||||
#ifdef QT4
|
||||
return( getIconPixmap( _name ).scaled( _w, _h, Qt::IgnoreAspectRatio,
|
||||
Qt::SmoothTransformation ) );
|
||||
#else
|
||||
return( getIconPixmap( _name ).convertToImage().smoothScale( _w, _h ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
QString getText( const char * _name )
|
||||
{
|
||||
const embedDesc & e = findEmbeddedData( _name );
|
||||
return( QString::fromLatin1( (const char *) e.data, e.size ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void loadTranslation( const QString & _tname )
|
||||
{
|
||||
#if QT_VERSION >= 0x030100
|
||||
QString name = _tname + ".qm";
|
||||
#ifdef QT4
|
||||
const embedDesc & e = findEmbeddedData( name.toAscii().constData() );
|
||||
#else
|
||||
const embedDesc & e = findEmbeddedData( name.ascii() );
|
||||
#endif
|
||||
QTranslator * t = new QTranslator( 0 );
|
||||
// not found?
|
||||
if( QString( e.name ) != name )
|
||||
{
|
||||
// then look whether translation is in data-dir
|
||||
t->load( name, configManager::inst()->localeDir() );
|
||||
}
|
||||
else
|
||||
{
|
||||
t->load( e.data, (int) e.size );
|
||||
}
|
||||
qApp->installTranslator( t );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
273
src/lib/mmp.cpp
Normal file
273
src/lib/mmp.cpp
Normal file
@@ -0,0 +1,273 @@
|
||||
/*
|
||||
* mmp.cpp - implementation of class multimediaProject
|
||||
*
|
||||
* 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 <QFile>
|
||||
#include <QMessageBox>
|
||||
|
||||
#else
|
||||
|
||||
#include <qfile.h>
|
||||
#include <qmessagebox.h>
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "mmp.h"
|
||||
#include "song_editor.h"
|
||||
|
||||
|
||||
|
||||
multimediaProject::typeDescStruct multimediaProject::s_types[multimediaProject::PROJ_TYPE_COUNT] =
|
||||
{
|
||||
{ multimediaProject::UNKNOWN, "unknown" },
|
||||
{ multimediaProject::SONG_PROJECT, "song" },
|
||||
{ multimediaProject::CHANNEL_SETTINGS, "channelsettings" },
|
||||
{ multimediaProject::EFFECT_SETTINGS, "effectsettings" },
|
||||
{ multimediaProject::VIDEO_PROJECT, "video" },
|
||||
{ multimediaProject::BURN_PROJECT, "burn" },
|
||||
{ multimediaProject::PLAYLIST, "playlist" }
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
multimediaProject::multimediaProject( projectTypes _project_type ) :
|
||||
QDomDocument( "multimedia-project" ),
|
||||
m_content(),
|
||||
m_head(),
|
||||
m_type( _project_type )
|
||||
{
|
||||
QDomElement root = createElement( "multimediaproject" );
|
||||
root.setAttribute( "version", MMP_VERSION_STRING );
|
||||
root.setAttribute( "type", typeName( _project_type ) );
|
||||
root.setAttribute( "creator", "Linux MultiMedia Studio (LMMS)" );
|
||||
root.setAttribute( "creatorversion", VERSION );
|
||||
appendChild( root );
|
||||
|
||||
m_head = createElement( "head" );
|
||||
root.appendChild( m_head );
|
||||
|
||||
m_content = createElement( typeName( _project_type ) );
|
||||
root.appendChild( m_content );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
multimediaProject::multimediaProject( const QString & _in_file_name ) :
|
||||
QDomDocument(),
|
||||
m_content(),
|
||||
m_head()
|
||||
{
|
||||
QFile in_file( _in_file_name );
|
||||
#ifdef QT4
|
||||
if( !in_file.open( QIODevice::ReadOnly ) )
|
||||
#else
|
||||
if( !in_file.open( IO_ReadOnly ) )
|
||||
#endif
|
||||
{
|
||||
QMessageBox::critical( NULL,
|
||||
songEditor::tr( "Could not open file" ),
|
||||
songEditor::tr( "Could not open "
|
||||
"file %1. You probably "
|
||||
"have no rights to "
|
||||
"read this file.\n"
|
||||
"Please make sure you "
|
||||
"have at least read-"
|
||||
"access to the file "
|
||||
"and try again."
|
||||
).arg( _in_file_name ) );
|
||||
return;
|
||||
}
|
||||
|
||||
QString error_msg;
|
||||
int line;
|
||||
int col;
|
||||
if( !setContent( &in_file, &error_msg, &line, &col ) )
|
||||
{
|
||||
QMessageBox::critical( NULL, songEditor::tr( "Error in "
|
||||
"multimedia-project" ),
|
||||
songEditor::tr( "The multimedia-"
|
||||
"project %1 seems to "
|
||||
"contain errors. LMMS "
|
||||
"will try its best "
|
||||
"to recover as much as "
|
||||
"possible data from "
|
||||
"this file."
|
||||
).arg( _in_file_name ) );
|
||||
return;
|
||||
}
|
||||
in_file.close();
|
||||
|
||||
|
||||
QDomElement root = documentElement();
|
||||
m_type = type( root.attribute( "type" ) );
|
||||
|
||||
QDomNode node = root.firstChild();
|
||||
while( !node.isNull() )
|
||||
{
|
||||
if( node.isElement() )
|
||||
{
|
||||
if( node.nodeName() == "head" )
|
||||
{
|
||||
m_head = node.toElement();
|
||||
}
|
||||
else if( node.nodeName() == typeName( m_type ) )
|
||||
{
|
||||
m_content = node.toElement();
|
||||
}
|
||||
}
|
||||
node = node.nextSibling();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
multimediaProject::~multimediaProject()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool multimediaProject::writeFile( const QString & _fn, bool _overwrite_check )
|
||||
{
|
||||
QString xml = "<?xml version=\"1.0\"?>\n" + toString(
|
||||
#if QT_VERSION >= 0x030100
|
||||
2
|
||||
#endif
|
||||
);
|
||||
QString fn = _fn;
|
||||
if( type() == CHANNEL_SETTINGS )
|
||||
{
|
||||
if( fn.section( '.', -2, -1 ) != "cs.xml" )
|
||||
{
|
||||
fn += ".cs.xml";
|
||||
}
|
||||
}
|
||||
else if( fn.section( '.',-1 ) != "xml" )
|
||||
{
|
||||
fn += ".xml";
|
||||
}
|
||||
|
||||
|
||||
QFile outfile( fn );
|
||||
if( _overwrite_check == TRUE &&
|
||||
outfile.exists() == TRUE &&
|
||||
QMessageBox::
|
||||
#if QT_VERSION >= 0x030200
|
||||
question
|
||||
#else
|
||||
information
|
||||
#endif
|
||||
( NULL,
|
||||
songEditor::tr( "File already exists" ),
|
||||
songEditor::tr( "The file %1 already "
|
||||
"exists.\nDo you want "
|
||||
"to overwrite it?"
|
||||
).arg( fn ),
|
||||
QMessageBox::Yes, QMessageBox::No )
|
||||
== QMessageBox::No )
|
||||
{
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
|
||||
#ifdef QT4
|
||||
if( !outfile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
|
||||
#else
|
||||
if( !outfile.open( IO_WriteOnly | IO_Truncate ) )
|
||||
#endif
|
||||
{
|
||||
QMessageBox::critical( NULL, songEditor::tr( "Could not write "
|
||||
"file" ),
|
||||
songEditor::tr( "Could not write file "
|
||||
"%1. You probably are "
|
||||
"not permitted to "
|
||||
"write to this file. "
|
||||
"Please make sure you "
|
||||
"have write-access to "
|
||||
"the file and try "
|
||||
"again."
|
||||
).arg( fn ) );
|
||||
return( FALSE );
|
||||
}
|
||||
#ifdef QT4
|
||||
outfile.write( xml.toAscii().constData(), xml.length() );
|
||||
#else
|
||||
outfile.writeBlock( xml.ascii(), xml.length() );
|
||||
#endif
|
||||
outfile.close();
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
multimediaProject::projectTypes multimediaProject::typeOfFile(
|
||||
const QString & _fn )
|
||||
{
|
||||
multimediaProject m( _fn );
|
||||
return( m.type() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
multimediaProject::projectTypes multimediaProject::type(
|
||||
const QString & _type_name )
|
||||
{
|
||||
for( int i = 0; i < PROJ_TYPE_COUNT; ++i )
|
||||
{
|
||||
if( s_types[i].m_name == _type_name )
|
||||
{
|
||||
return( static_cast<multimediaProject::projectTypes>(
|
||||
i ) );
|
||||
}
|
||||
}
|
||||
return( UNKNOWN );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
QString multimediaProject::typeName( projectTypes _project_type )
|
||||
{
|
||||
if( _project_type >= UNKNOWN && _project_type < PROJ_TYPE_COUNT )
|
||||
{
|
||||
return( s_types[_project_type].m_name );
|
||||
}
|
||||
return( s_types[UNKNOWN].m_name );
|
||||
}
|
||||
|
||||
259
src/lib/oscillator.cpp
Normal file
259
src/lib/oscillator.cpp
Normal file
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* oscillator.cpp - implementation of powerful oscillator-class
|
||||
*
|
||||
* 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 "oscillator.h"
|
||||
|
||||
|
||||
const sampleFrame zero_frame = { 0.0f, 0.0f };
|
||||
|
||||
|
||||
oscillator::oscillator( modulationAlgos _modulation_algo, float _freq,
|
||||
Sint16 _phase_offset, float _volume_factor,
|
||||
oscillator * _sub_osc ) :
|
||||
m_freq(_freq),
|
||||
m_volumeFactor(_volume_factor),
|
||||
m_phaseOffset(_phase_offset),
|
||||
m_subOsc(_sub_osc),
|
||||
m_userWaveData( &zero_frame ),
|
||||
m_userWaveFrames( 1 )
|
||||
{
|
||||
|
||||
if( m_subOsc != NULL )
|
||||
{
|
||||
switch( _modulation_algo )
|
||||
{
|
||||
case FREQ_MODULATION:
|
||||
m_callUpdate = &oscillator::updateFM;
|
||||
break;
|
||||
|
||||
case AMP_MODULATION:
|
||||
m_callUpdate = &oscillator::updateAM;
|
||||
break;
|
||||
|
||||
case MIX:
|
||||
m_callUpdate = &oscillator::updateMix;
|
||||
break;
|
||||
case SYNC:
|
||||
m_callUpdate = &oscillator::updateSync;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_callUpdate = &oscillator::updateNoSub;
|
||||
}
|
||||
|
||||
recalcOscCoeff();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// if we have no sub-osc, we can't do any modulation... just get our samples
|
||||
#define defineNoSubUpdateFor(x,getSampleFunction) \
|
||||
void x::updateNoSub( sampleFrame * _ab, Uint32 _frames, Uint8 _chnl ) \
|
||||
{ \
|
||||
for( Uint16 frame = 0; frame < _frames; ++frame ) \
|
||||
{ \
|
||||
_ab[frame][_chnl] = getSampleFunction( ++m_sample * \
|
||||
m_oscCoeff ) * m_volumeFactor; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
// do fm by using sub-osc as modulator
|
||||
#define defineFMUpdateFor(x,getSampleFunction) \
|
||||
void x::updateFM( sampleFrame * _ab, Uint32 _frames, Uint8 _chnl ) \
|
||||
{ \
|
||||
m_subOsc->update( _ab, _frames, _chnl ); \
|
||||
for( Uint16 frame = 0; frame < _frames; ++frame ) \
|
||||
{ \
|
||||
_ab[frame][_chnl] = getSampleFunction( ++m_sample * \
|
||||
m_oscCoeff + \
|
||||
_ab[frame][_chnl] ) * \
|
||||
m_volumeFactor; \
|
||||
/* following line is REAL FM */ \
|
||||
/* float new_freq = powf( 2.0, _ab[frame][_chnl] ); \
|
||||
_ab[frame][_chnl] = getSampleFunction( ++m_sample*((m_freq * \
|
||||
new_freq )/mixer::inst()->sampleRate() )) * m_volumeFactor; \
|
||||
_ab[frame][_chnl] = getSampleFunction( ++m_sample*(m_oscCoeff *\
|
||||
_ab[frame][_chnl] )) * m_volumeFactor;*/ \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
// do am by using sub-osc as modulator
|
||||
#define defineAMUpdateFor(x,getSampleFunction) \
|
||||
void x::updateAM( sampleFrame * _ab, Uint32 _frames, Uint8 _chnl ) \
|
||||
{ \
|
||||
m_subOsc->update( _ab, _frames, _chnl ); \
|
||||
for( Uint16 frame = 0; frame < _frames; ++frame ) \
|
||||
{ \
|
||||
_ab[frame][_chnl] *= getSampleFunction( ++m_sample * \
|
||||
m_oscCoeff ) * m_volumeFactor; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
// do mix by using sub-osc as mix-sample
|
||||
#define defineMixUpdateFor(x,getSampleFunction) \
|
||||
void x::updateMix( sampleFrame * _ab, Uint32 _frames, Uint8 _chnl ) \
|
||||
{ \
|
||||
m_subOsc->update( _ab, _frames, _chnl ); \
|
||||
for( Uint16 frame = 0; frame < _frames; ++frame ) \
|
||||
{ \
|
||||
_ab[frame][_chnl] += getSampleFunction( ++m_sample * \
|
||||
m_oscCoeff ) * m_volumeFactor; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
// sync with sub-osc (every time sub-osc starts new period, we also start new
|
||||
// period)
|
||||
#define defineSyncUpdateFor(x,getSampleFunction) \
|
||||
void x::updateSync( sampleFrame * _ab, Uint32 _frames, Uint8 _chnl ) \
|
||||
{ \
|
||||
for( Uint16 frame = 0; frame < _frames ; ++frame ) \
|
||||
{ \
|
||||
if( m_subOsc->syncOk() ) \
|
||||
{ \
|
||||
sync(); \
|
||||
} \
|
||||
_ab[frame][_chnl] = getSampleFunction( ++m_sample * \
|
||||
m_oscCoeff ) * m_volumeFactor; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define generateOscillatorCodeFor(x,getSampleFunction); \
|
||||
class x : public oscillator \
|
||||
{ \
|
||||
public: \
|
||||
x( modulationAlgos modulation_algo, float _freq, Sint16 _phase_offset, \
|
||||
float _volume_factor, oscillator * _sub_osc) : \
|
||||
oscillator (modulation_algo, _freq, _phase_offset, _volume_factor, \
|
||||
_sub_osc ) \
|
||||
{ \
|
||||
} \
|
||||
\
|
||||
protected: \
|
||||
void updateNoSub( sampleFrame * _ab, Uint32 _frames, \
|
||||
Uint8 _chnl ); \
|
||||
void updateFM( sampleFrame * _ab, Uint32 _frames, \
|
||||
Uint8 _chnl ); \
|
||||
void updateAM( sampleFrame * _ab, Uint32 _frames, \
|
||||
Uint8 _chnl ); \
|
||||
void updateMix( sampleFrame * _ab, Uint32 _frames, \
|
||||
Uint8 _chnl ); \
|
||||
void updateSync( sampleFrame * _ab, Uint32 _frames, \
|
||||
Uint8 _chnl ); \
|
||||
\
|
||||
} ; \
|
||||
\
|
||||
defineNoSubUpdateFor( x, getSampleFunction ) \
|
||||
defineFMUpdateFor( x, getSampleFunction ) \
|
||||
defineAMUpdateFor( x, getSampleFunction ) \
|
||||
defineMixUpdateFor( x, getSampleFunction ) \
|
||||
defineSyncUpdateFor( x, getSampleFunction )
|
||||
|
||||
|
||||
generateOscillatorCodeFor( sinWaveOsc, sinSample );
|
||||
generateOscillatorCodeFor( triangleWaveOsc, triangleSample );
|
||||
generateOscillatorCodeFor( sawWaveOsc, sawSample );
|
||||
generateOscillatorCodeFor( squareWaveOsc, squareSample );
|
||||
generateOscillatorCodeFor( moogSawWaveOsc, moogSawSample );
|
||||
generateOscillatorCodeFor( expWaveOsc, expSample );
|
||||
generateOscillatorCodeFor( noiseWaveOsc, noiseSample );
|
||||
generateOscillatorCodeFor( userWaveOsc, userWaveSample );
|
||||
|
||||
|
||||
|
||||
oscillator * FASTCALL oscillator::createNewOsc( waveShapes _wave_shape,
|
||||
modulationAlgos _modulation_algo,
|
||||
float _freq, Sint16 _phase_offset,
|
||||
float _volume_factor,
|
||||
oscillator * _sub_osc )
|
||||
{
|
||||
switch( _wave_shape )
|
||||
{
|
||||
case SIN_WAVE:
|
||||
return( new sinWaveOsc( _modulation_algo, _freq,
|
||||
_phase_offset, _volume_factor,
|
||||
_sub_osc ) );
|
||||
case TRIANGLE_WAVE:
|
||||
return( new triangleWaveOsc( _modulation_algo, _freq,
|
||||
_phase_offset, _volume_factor,
|
||||
_sub_osc ) );
|
||||
case SAW_WAVE:
|
||||
return( new sawWaveOsc( _modulation_algo, _freq,
|
||||
_phase_offset, _volume_factor,
|
||||
_sub_osc ) );
|
||||
case SQUARE_WAVE:
|
||||
return( new squareWaveOsc( _modulation_algo, _freq,
|
||||
_phase_offset, _volume_factor,
|
||||
_sub_osc ) );
|
||||
case MOOG_SAW_WAVE:
|
||||
return( new moogSawWaveOsc( _modulation_algo, _freq,
|
||||
_phase_offset, _volume_factor,
|
||||
_sub_osc ) );
|
||||
case EXP_WAVE:
|
||||
return( new expWaveOsc( _modulation_algo, _freq,
|
||||
_phase_offset, _volume_factor,
|
||||
_sub_osc ) );
|
||||
case WHITE_NOISE_WAVE:
|
||||
return( new noiseWaveOsc( _modulation_algo, _freq,
|
||||
_phase_offset, _volume_factor,
|
||||
_sub_osc ) );
|
||||
case USER_DEF_WAVE:
|
||||
return( new userWaveOsc( _modulation_algo, _freq,
|
||||
_phase_offset, _volume_factor,
|
||||
_sub_osc ) );
|
||||
default:
|
||||
return( new sinWaveOsc( _modulation_algo, _freq,
|
||||
_phase_offset, _volume_factor,
|
||||
_sub_osc ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// should be called every time phase-offset or frequency is changed...
|
||||
void oscillator::recalcOscCoeff( const float additional_phase_offset )
|
||||
{
|
||||
m_oscCoeff = m_freq / static_cast<float>( mixer::inst()->sampleRate() );
|
||||
|
||||
m_sample = static_cast<Uint32>( ( m_phaseOffset * ( 1.0f / 360.0f ) +
|
||||
additional_phase_offset ) *
|
||||
( mixer::inst()->sampleRate() /
|
||||
m_freq ) );
|
||||
// because we pre-increment m_sample in update-function, we should
|
||||
// decrement it here... (not possible when 0 because it is
|
||||
// unsigned - overflow!!!)
|
||||
if( m_sample > 0 )
|
||||
{
|
||||
--m_sample;
|
||||
}
|
||||
}
|
||||
1014
src/lib/sample_buffer.cpp
Normal file
1014
src/lib/sample_buffer.cpp
Normal file
File diff suppressed because it is too large
Load Diff
233
src/midi/midi_alsa_raw.cpp
Normal file
233
src/midi/midi_alsa_raw.cpp
Normal file
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* midi_alsa_raw.cpp - midi-device-driver for RawMIDI via ALSA
|
||||
*
|
||||
* 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 <QLineEdit>
|
||||
#include <QLabel>
|
||||
|
||||
#else
|
||||
|
||||
#include <qpair.h>
|
||||
#include <qlineedit.h>
|
||||
#include <qlabel.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "midi_alsa_raw.h"
|
||||
#include "config_mgr.h"
|
||||
#include "templates.h"
|
||||
|
||||
|
||||
#ifdef ALSA_SUPPORT
|
||||
|
||||
|
||||
midiALSARaw::midiALSARaw( channelTrack * _ct ) :
|
||||
midiDevice( _ct ),
|
||||
QThread(),
|
||||
m_inputp( &m_input ),
|
||||
m_outputp( &m_output ),
|
||||
m_quit( FALSE )
|
||||
{
|
||||
int err;
|
||||
if( ( err = snd_rawmidi_open( m_inputp, m_outputp,
|
||||
#ifdef QT4
|
||||
probeDevice().toAscii().constData(),
|
||||
#else
|
||||
probeDevice().ascii(),
|
||||
#endif
|
||||
0 ) ) < 0 )
|
||||
{
|
||||
printf( "cannot open MIDI-device: %s\n", snd_strerror( err ) );
|
||||
return;
|
||||
}
|
||||
|
||||
snd_rawmidi_read( m_input, NULL, 0 );
|
||||
|
||||
snd_rawmidi_nonblock( m_input, 1 );
|
||||
m_npfds = snd_rawmidi_poll_descriptors_count( m_input );
|
||||
m_pfds = new pollfd[m_npfds];
|
||||
snd_rawmidi_poll_descriptors( m_input, m_pfds, m_npfds );
|
||||
|
||||
start(
|
||||
#if QT_VERSION >= 0x030200
|
||||
QThread::LowPriority
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
midiALSARaw::~midiALSARaw()
|
||||
{
|
||||
if( running() )
|
||||
{
|
||||
m_quit = TRUE;
|
||||
wait( 500 );
|
||||
terminate();
|
||||
|
||||
snd_rawmidi_close( m_input );
|
||||
snd_rawmidi_close( m_output );
|
||||
delete[] m_pfds;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
QString midiALSARaw::probeDevice( void )
|
||||
{
|
||||
QString dev = configManager::inst()->value( "midialsa", "device" );
|
||||
if( dev == "" )
|
||||
{
|
||||
if( getenv( "MIDIDEV" ) != NULL )
|
||||
{
|
||||
return( getenv( "MIDIDEV" ) );
|
||||
}
|
||||
return( "default" );
|
||||
}
|
||||
return( dev );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void midiALSARaw::sendByte( Uint8 _c )
|
||||
{
|
||||
snd_rawmidi_write( m_output, &_c, sizeof( _c ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void midiALSARaw::run( void )
|
||||
{
|
||||
Uint8 buf[128];
|
||||
//int cnt = 0;
|
||||
while( m_quit == FALSE )
|
||||
{
|
||||
msleep( 5 ); // must do that, otherwise this thread takes
|
||||
// too much CPU-time, even with LowPriority...
|
||||
int err = poll( m_pfds, m_npfds, 10000 );
|
||||
if( err < 0 && errno == EINTR )
|
||||
{
|
||||
printf( "midiALSARaw::run(): Got EINTR while "
|
||||
"polling. Will stop polling MIDI-events from "
|
||||
"MIDI-port.\n" );
|
||||
break;
|
||||
}
|
||||
if( err < 0 )
|
||||
{
|
||||
printf( "poll failed: %s\nWill stop polling "
|
||||
"MIDI-events from MIDI-port.\n",
|
||||
strerror( errno ) );
|
||||
break;
|
||||
}
|
||||
if( err == 0 )
|
||||
{
|
||||
//printf( "there seems to be no active MIDI-device %d\n", ++cnt );
|
||||
continue;
|
||||
}
|
||||
unsigned short revents;
|
||||
if( ( err = snd_rawmidi_poll_descriptors_revents(
|
||||
m_input, m_pfds, m_npfds, &revents ) ) < 0 )
|
||||
{
|
||||
printf( "cannot get poll events: %s\nWill stop polling "
|
||||
"MIDI-events from MIDI-port.\n",
|
||||
snd_strerror( errno ) );
|
||||
break;
|
||||
}
|
||||
if( revents & ( POLLERR | POLLHUP ) )
|
||||
{
|
||||
printf( "POLLERR or POLLHUP\n" );
|
||||
break;
|
||||
}
|
||||
if( !( revents & POLLIN ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
err = snd_rawmidi_read( m_input, buf, sizeof( buf ) );
|
||||
if( err == -EAGAIN )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if( err < 0 )
|
||||
{
|
||||
printf( "cannot read from port \"%s\": %s\nWill stop "
|
||||
"polling MIDI-events from MIDI-port.\n",
|
||||
/*port_name*/"default", snd_strerror( err ) );
|
||||
break;
|
||||
}
|
||||
if( err == 0 )
|
||||
continue;
|
||||
for( int i = 0; i < err; ++i )
|
||||
{
|
||||
const midiEvent * midi_event = parseData( buf[i] );
|
||||
if( midi_event != NULL )
|
||||
{
|
||||
processInEvent( *midi_event );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
midiALSARaw::setupWidget::setupWidget( QWidget * _parent ) :
|
||||
midiDevice::setupWidget( midiALSARaw::name(), _parent )
|
||||
{
|
||||
m_device = new QLineEdit( midiALSARaw::probeDevice(), this );
|
||||
m_device->setGeometry( 10, 20, 160, 20 );
|
||||
|
||||
QLabel * dev_lbl = new QLabel( tr( "DEVICE" ), this );
|
||||
dev_lbl->setFont( pointSize<6>( dev_lbl->font() ) );
|
||||
dev_lbl->setGeometry( 10, 40, 160, 10 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
midiALSARaw::setupWidget::~setupWidget()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void midiALSARaw::setupWidget::saveSettings( void )
|
||||
{
|
||||
configManager::inst()->setValue( "midialsa", "device",
|
||||
m_device->text() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
222
src/midi/midi_mapper.cpp
Normal file
222
src/midi/midi_mapper.cpp
Normal file
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* midi_mapper.cpp - MIDI-mapper for any midiDevice
|
||||
*
|
||||
* 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 "midi_mapper.h"
|
||||
|
||||
#ifdef QT4
|
||||
|
||||
#include <QRegExp>
|
||||
|
||||
#else
|
||||
|
||||
#include <qregexp.h>
|
||||
|
||||
#define indexOf find
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
midiMapper::midiMapper( const QString & _map ) :
|
||||
m_drumsetChannel( 0 ),
|
||||
m_drumsetPatch( 0 )
|
||||
{
|
||||
// default mappings
|
||||
for( Uint8 i = 0; i < MIDI_PROGRAMS; ++i )
|
||||
{
|
||||
m_patchMap[i].first = i;
|
||||
}
|
||||
for( Uint8 i = 0; i < MIDI_KEYS; ++i )
|
||||
{
|
||||
m_drumsetKeyMap[i].first = i;
|
||||
}
|
||||
for( Uint8 i = 0; i < MIDI_CHANNELS; ++i )
|
||||
{
|
||||
m_channelMap[i] = i;
|
||||
}
|
||||
QFile map( _map );
|
||||
#ifdef QT4
|
||||
if( !map.open( QIODevice::ReadOnly ) )
|
||||
#else
|
||||
if( !map.open( IO_ReadOnly ) )
|
||||
#endif
|
||||
{
|
||||
return;
|
||||
}
|
||||
while( !map.atEnd() )
|
||||
{
|
||||
char buf[1024];
|
||||
int len = map.readLine( buf, sizeof( buf ) );
|
||||
if( len <= 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
QString line( buf );
|
||||
line.replace( '\n', "" );
|
||||
if( line.left( 6 ) == "DEFINE" )
|
||||
{
|
||||
if( line.section( ' ', 1, 1 ) == "PATCHMAP" )
|
||||
{
|
||||
readPatchMap( map );
|
||||
}
|
||||
else if( line.section( ' ', 1, 1 ) == "KEYMAP" &&
|
||||
line.section( ' ', 2, 2 ) ==
|
||||
"\"Drumset\"" )
|
||||
{
|
||||
readDrumsetKeyMap( map );
|
||||
}
|
||||
else if( line.section( ' ', 1, 1 ) == "CHANNELMAP" )
|
||||
{
|
||||
readChannelMap( map );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
midiMapper::~midiMapper()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void midiMapper::readPatchMap( QFile & _f )
|
||||
{
|
||||
Uint8 prog_idx = 0;
|
||||
|
||||
while( !_f.atEnd() && prog_idx < MIDI_PROGRAMS )
|
||||
{
|
||||
char buf[1024];
|
||||
int len = _f.readLine( buf, sizeof( buf ) );
|
||||
if( len <= 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
QString line( buf );
|
||||
line.replace( '\n', "" );
|
||||
if( line.left( 3 ) == "END" )
|
||||
{
|
||||
return;
|
||||
}
|
||||
if( QString( line ).replace( ' ', "" )[0] == '#' )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
m_patchMap[prog_idx].first = line.section( '=', 1, 1 ).toInt();
|
||||
m_patchMap[prog_idx].second = line.section( '=', 0, 0 ).
|
||||
replace( ' ', "" );
|
||||
++prog_idx;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void midiMapper::readDrumsetKeyMap( QFile & _f )
|
||||
{
|
||||
Uint8 key = 0;
|
||||
while( !_f.atEnd() )
|
||||
{
|
||||
char buf[1024];
|
||||
int len = _f.readLine( buf, sizeof( buf ) );
|
||||
if( len <= 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
QString line( buf );
|
||||
line.replace( '\n', "" );
|
||||
if( line.left( 3 ) == "END" )
|
||||
{
|
||||
return;
|
||||
}
|
||||
if( QString( line ).replace( ' ', "" )[0] == '#' )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if( line[4] != '=' )
|
||||
{
|
||||
m_drumsetKeyMap[key].first = line.section( '=', 1, 1 ).
|
||||
toInt();
|
||||
|
||||
m_drumsetKeyMap[key].second = line.mid( 4 ).
|
||||
section( '=', 0, 0 ).
|
||||
section( ' ', 1, 1 ).
|
||||
replace( ' ', "" );
|
||||
}
|
||||
++key;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void midiMapper::readChannelMap( QFile & _f )
|
||||
{
|
||||
while( !_f.atEnd() )
|
||||
{
|
||||
char buf[1024];
|
||||
int len = _f.readLine( buf, sizeof( buf ) );
|
||||
if( len <= 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
QString line( buf );
|
||||
line.replace( '\n', "" );
|
||||
if( line.left( 3 ) == "END" )
|
||||
{
|
||||
return;
|
||||
}
|
||||
if( QString( line ).replace( ' ', "" )[0] == '#' )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Uint8 ch = line.section( ' ', 0, 0 ).toInt();
|
||||
Uint8 mch = line.section( '=', 1, 1 ).mid( 1 ).
|
||||
section( ' ', 0, 0 ).
|
||||
toInt();
|
||||
if( ch < MIDI_CHANNELS && mch < MIDI_CHANNELS )
|
||||
{
|
||||
m_channelMap[ch] = mch;
|
||||
if( line.contains( QRegExp( "Keymap *\"Drumset\"" ) ) )
|
||||
{
|
||||
m_drumsetChannel = mch;
|
||||
int fp = line.indexOf( "ForcePatch" );
|
||||
if( fp != -1 )
|
||||
{
|
||||
m_drumsetPatch = line.mid( fp ).
|
||||
section( ' ', 1, 1 ).
|
||||
toInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#undef indexOf
|
||||
|
||||
164
src/midi/midi_oss.cpp
Normal file
164
src/midi/midi_oss.cpp
Normal file
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* midi_oss.cpp - simple midi-device-driver for OSS
|
||||
*
|
||||
* 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 <QLineEdit>
|
||||
#include <QLabel>
|
||||
|
||||
#else
|
||||
|
||||
#include <qmap.h>
|
||||
#include <qlineedit.h>
|
||||
#include <qlabel.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "midi_oss.h"
|
||||
#include "config_mgr.h"
|
||||
#include "templates.h"
|
||||
|
||||
|
||||
|
||||
midiOSS::midiOSS( channelTrack * _ct ) :
|
||||
midiDevice( _ct ),
|
||||
QThread(),
|
||||
m_midiDev( probeDevice() ),
|
||||
m_quit( FALSE )
|
||||
{
|
||||
// only start thread, if opening of MIDI-device is successful,
|
||||
// otherwise isRunning()==FALSE indicates error
|
||||
#ifdef QT4
|
||||
if( m_midiDev.open( QIODevice::ReadWrite ) ||
|
||||
m_midiDev.open( QIODevice::ReadOnly ) )
|
||||
#else
|
||||
if( m_midiDev.open( IO_ReadWrite ) || m_midiDev.open( IO_ReadOnly ) )
|
||||
#endif
|
||||
{
|
||||
start(
|
||||
#if QT_VERSION >= 0x030200
|
||||
QThread::LowPriority
|
||||
#endif
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
midiOSS::~midiOSS()
|
||||
{
|
||||
m_quit = TRUE;
|
||||
wait( 500 );
|
||||
terminate();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
QString midiOSS::probeDevice( void )
|
||||
{
|
||||
QString dev = configManager::inst()->value( "midioss", "device" );
|
||||
if( dev == "" )
|
||||
{
|
||||
if( getenv( "MIDIDEV" ) != NULL )
|
||||
{
|
||||
return( getenv( "MIDIDEV" ) );
|
||||
}
|
||||
return( "/dev/midi" );
|
||||
}
|
||||
return( dev );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void midiOSS::sendByte( Uint8 _c )
|
||||
{
|
||||
#ifdef QT4
|
||||
m_midiDev.putChar( _c );
|
||||
#else
|
||||
m_midiDev.putch( _c );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void midiOSS::run( void )
|
||||
{
|
||||
while( m_quit == FALSE )
|
||||
{
|
||||
#ifdef QT4
|
||||
char c;
|
||||
if( !m_midiDev.getChar( &c ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const midiEvent * midi_event = parseData( c );
|
||||
#else
|
||||
const midiEvent * midi_event = parseData( m_midiDev.getch() );
|
||||
#endif
|
||||
if( midi_event != NULL )
|
||||
{
|
||||
processInEvent( *midi_event );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
midiOSS::setupWidget::setupWidget( QWidget * _parent ) :
|
||||
midiDevice::setupWidget( midiOSS::name(), _parent )
|
||||
{
|
||||
m_device = new QLineEdit( midiOSS::probeDevice(), this );
|
||||
m_device->setGeometry( 10, 20, 160, 20 );
|
||||
|
||||
QLabel * dev_lbl = new QLabel( tr( "DEVICE" ), this );
|
||||
dev_lbl->setFont( pointSize<6>( dev_lbl->font() ) );
|
||||
dev_lbl->setGeometry( 10, 40, 160, 10 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
midiOSS::setupWidget::~setupWidget()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void midiOSS::setupWidget::saveSettings( void )
|
||||
{
|
||||
configManager::inst()->setValue( "midioss", "device",
|
||||
m_device->text() );
|
||||
}
|
||||
|
||||
|
||||
509
src/tracks/bb_track.cpp
Normal file
509
src/tracks/bb_track.cpp
Normal file
@@ -0,0 +1,509 @@
|
||||
/*
|
||||
* bb_track.cpp - implementation of class bbTrack
|
||||
*
|
||||
* 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 <QPainter>
|
||||
#include <QColorDialog>
|
||||
#include <QMenu>
|
||||
|
||||
#else
|
||||
|
||||
#include <qdom.h>
|
||||
#include <qpainter.h>
|
||||
#include <qcolordialog.h>
|
||||
#include <qpopupmenu.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "bb_track.h"
|
||||
#include "song_editor.h"
|
||||
#include "bb_editor.h"
|
||||
#include "templates.h"
|
||||
#include "name_label.h"
|
||||
#include "embed.h"
|
||||
#include "rename_dialog.h"
|
||||
|
||||
#include "bb_track.moc"
|
||||
|
||||
|
||||
QMap<bbTrack *, bbTrack::bbInfoStruct> bbTrack::s_bbNums;
|
||||
|
||||
|
||||
bbTCO::bbTCO( track * _track, const QColor & _c ) :
|
||||
trackContentObject( _track ),
|
||||
m_name( ( dynamic_cast<bbTrack *>( _track ) != NULL ) ?
|
||||
dynamic_cast<bbTrack *>( _track )->trackLabel()->text() :
|
||||
QString( "" ) ),
|
||||
m_color( _c.isValid() ? _c : QColor( 64, 128, 255 ) )
|
||||
{
|
||||
//setPaletteBackgroundColor( QColor( 64, 128, 255 ) );
|
||||
#ifndef QT4
|
||||
setBackgroundMode( Qt::NoBackground );
|
||||
#endif
|
||||
tact t = bbEditor::inst()->lengthOfBB(
|
||||
bbTrack::numOfBBTrack( getTrack() ) );
|
||||
if( t > 0 )
|
||||
{
|
||||
changeLength( midiTime( t, 0 ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bbTCO::~bbTCO()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTCO::movePosition( const midiTime & _pos )
|
||||
{
|
||||
// bb-playlist-entries are always aligned on tact-boundaries
|
||||
trackContentObject::movePosition( midiTime( _pos.getTact(), 0 ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTCO::changeLength( const midiTime & _length )
|
||||
{
|
||||
// the length of bb-playlist-entries is always a multiple of one tact
|
||||
trackContentObject::changeLength( midiTime( _length.getTact(), 0 ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTCO::constructContextMenu( QMenu * _cm )
|
||||
{
|
||||
#ifdef QT4
|
||||
QAction * a = new QAction( embed::getIconPixmap( "bb_track" ),
|
||||
tr( "Open in Beat+Bassline-Editor" ),
|
||||
_cm );
|
||||
_cm->insertAction( _cm->actions()[0], a );
|
||||
connect( a, SIGNAL( triggered( bool ) ), this,
|
||||
SLOT( openInBBEditor( bool ) ) );
|
||||
#else
|
||||
_cm->insertItem( embed::getIconPixmap( "bb_track" ),
|
||||
tr( "Open in Beat+Bassline-Editor" ),
|
||||
this, SLOT( openInBBEditor() ),
|
||||
0, -1, 0 );
|
||||
#endif
|
||||
#ifdef QT4
|
||||
_cm->insertSeparator( _cm->actions()[1] );
|
||||
#else
|
||||
_cm->insertSeparator( 1 );
|
||||
#endif
|
||||
#ifdef QT4
|
||||
_cm->addSeparator();
|
||||
#else
|
||||
_cm->insertSeparator();
|
||||
#endif
|
||||
_cm->addAction( embed::getIconPixmap( "reload" ), tr( "Reset name" ),
|
||||
this, SLOT( resetName() ) );
|
||||
_cm->addAction( embed::getIconPixmap( "rename" ), tr( "Change name" ),
|
||||
this, SLOT( changeName() ) );
|
||||
_cm->addAction( embed::getIconPixmap( "colorize" ),
|
||||
tr( "Change color" ), this, SLOT( changeColor() ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTCO::mouseDoubleClickEvent( QMouseEvent * )
|
||||
{
|
||||
openInBBEditor();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTCO::paintEvent( QPaintEvent * )
|
||||
{
|
||||
QColor col = m_color;
|
||||
if( getTrack()->muted() )
|
||||
{
|
||||
col = QColor( 160, 160, 160 );
|
||||
}
|
||||
#ifdef QT4
|
||||
QPainter p( this );
|
||||
// TODO: set according brush/pen for gradient!
|
||||
p.fillRect( rect(), col );
|
||||
#else
|
||||
// create pixmap for whole widget
|
||||
QPixmap pm( rect().size() );
|
||||
// and a painter for it
|
||||
QPainter p( &pm );
|
||||
|
||||
// COOL gradient ;-)
|
||||
for( int y = 0; y < height(); ++y )
|
||||
{
|
||||
p.setPen( col.light( 130 - y * 60 / height() ) );
|
||||
p.drawLine( 0, y, width(), y );
|
||||
}
|
||||
//pm.fill( col );
|
||||
#endif
|
||||
|
||||
tact t = bbEditor::inst()->lengthOfBB( bbTrack::numOfBBTrack(
|
||||
getTrack() ) );
|
||||
if( length().getTact() > 1 && t > 0 )
|
||||
{
|
||||
for( int x = TCO_BORDER_WIDTH + static_cast<int>( t *
|
||||
pixelsPerTact() ); x < width();
|
||||
x += static_cast<int>( t * pixelsPerTact() ) )
|
||||
{
|
||||
p.setPen( col.light( 80 ) );
|
||||
p.drawLine( x, 1, x, 5 );
|
||||
p.setPen( col.light( 120 ) );
|
||||
p.drawLine( x, height() - 6, x, height() - 2 );
|
||||
}
|
||||
}
|
||||
|
||||
p.setPen( col.dark() );
|
||||
p.drawRect( 0, 0, width(), height() );
|
||||
|
||||
p.setFont( pointSize<7>( p.font() ) );
|
||||
p.setPen( QColor( 0, 0, 0 ) );
|
||||
p.drawText( 2, QFontMetrics( p.font() ).height() - 1, m_name );
|
||||
|
||||
#ifndef QT4
|
||||
bitBlt( this, rect().topLeft(), &pm );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTCO::saveSettings( QDomDocument & _doc, QDomElement & _parent )
|
||||
{
|
||||
QDomElement bbtco_de = _doc.createElement( nodeName() );
|
||||
bbtco_de.setAttribute( "name", m_name );
|
||||
if( _parent.nodeName() == "clipboard" )
|
||||
{
|
||||
bbtco_de.setAttribute( "pos", QString::number( -1 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
bbtco_de.setAttribute( "pos",
|
||||
QString::number( startPosition() ) );
|
||||
}
|
||||
bbtco_de.setAttribute( "len", QString::number( length() ) );
|
||||
bbtco_de.setAttribute( "color", QString::number( m_color.rgb() ) );
|
||||
_parent.appendChild( bbtco_de );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTCO::loadSettings( const QDomElement & _this )
|
||||
{
|
||||
m_name = _this.attribute( "name" );
|
||||
if( _this.attribute( "pos" ).toInt() >= 0 )
|
||||
{
|
||||
movePosition( _this.attribute( "pos" ).toInt() );
|
||||
}
|
||||
changeLength( _this.attribute( "len" ).toInt() );
|
||||
if( _this.attribute( "color" ).toUInt() != 0 )
|
||||
{
|
||||
m_color.setRgb( _this.attribute( "color" ).toUInt() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTCO::openInBBEditor( bool )
|
||||
{
|
||||
bbEditor::inst()->setCurrentBB( bbTrack::numOfBBTrack( getTrack() ) );
|
||||
bbEditor::inst()->show();
|
||||
bbEditor::inst()->setFocus();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTCO::openInBBEditor( void )
|
||||
{
|
||||
openInBBEditor( FALSE );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTCO::resetName( void )
|
||||
{
|
||||
if( dynamic_cast<bbTrack *>( getTrack() ) != NULL )
|
||||
{
|
||||
m_name = dynamic_cast<bbTrack *>( getTrack() )->
|
||||
trackLabel()->text();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTCO::changeName( void )
|
||||
{
|
||||
renameDialog rename_dlg( m_name );
|
||||
rename_dlg.exec();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTCO::changeColor( void )
|
||||
{
|
||||
QColor _new_color = QColorDialog::getColor( m_color );
|
||||
if( _new_color.isValid() && _new_color != m_color )
|
||||
{
|
||||
m_color = _new_color;
|
||||
songEditor::inst()->setModified();
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bbTrack::bbTrack( trackContainer * _tc )
|
||||
: track( _tc )
|
||||
{
|
||||
getTrackWidget()->setFixedHeight( 32 );
|
||||
|
||||
csize bbNum = s_bbNums.size();
|
||||
bbInfoStruct bis = { bbNum, "" };
|
||||
s_bbNums[this] = bis;
|
||||
m_trackLabel = new nameLabel( tr( "Beat/Bassline %1" ).arg( bbNum ),
|
||||
getTrackSettingsWidget(),
|
||||
embed::getIconPixmap( "bb_track" ) );
|
||||
m_trackLabel->setGeometry( 1, 1, DEFAULT_SETTINGS_WIDGET_WIDTH-2, 29 );
|
||||
m_trackLabel->show();
|
||||
connect( m_trackLabel, SIGNAL( clicked() ), this,
|
||||
SLOT( clickedTrackLabel() ) );
|
||||
bbEditor::inst()->setCurrentBB( bbNum );
|
||||
|
||||
_tc->updateAfterTrackAdd();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bbTrack::~bbTrack()
|
||||
{
|
||||
csize bb = s_bbNums[this].num;
|
||||
bbEditor::inst()->removeBB( bb );
|
||||
for( QMap<bbTrack *, bbTrack::bbInfoStruct>::iterator it =
|
||||
s_bbNums.begin(); it != s_bbNums.end(); ++it )
|
||||
{
|
||||
#ifdef QT4
|
||||
if( it.value().num > bb )
|
||||
{
|
||||
--it.value().num;
|
||||
}
|
||||
#else
|
||||
if( it.data().num > bb )
|
||||
{
|
||||
--it.data().num;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
s_bbNums.remove( this );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
track::trackTypes bbTrack::trackType( void ) const
|
||||
{
|
||||
return( BB_TRACK );
|
||||
}
|
||||
|
||||
|
||||
|
||||
// play _frames frames of given TCO within starting with _start/_start_frame
|
||||
bool FASTCALL bbTrack::play( const midiTime & _start, Uint32 _start_frame,
|
||||
Uint32 _frames, Uint32 _frame_base,
|
||||
Sint16 _tco_num )
|
||||
{
|
||||
if( _tco_num >= 0 )
|
||||
{
|
||||
return( bbEditor::inst()->play( _start, _start_frame, _frames,
|
||||
_frame_base,
|
||||
s_bbNums[this].num ) );
|
||||
}
|
||||
|
||||
vlist<trackContentObject *> tcos;
|
||||
getTCOsInRange( tcos, _start, _start +static_cast<Sint32>( _frames *
|
||||
64 / songEditor::inst()->framesPerTact() ) );
|
||||
|
||||
if ( tcos.size() == 0 )
|
||||
{
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
midiTime lastPosition;
|
||||
midiTime lastLen;
|
||||
for( vlist<trackContentObject *>::iterator it = tcos.begin();
|
||||
it != tcos.end(); ++it )
|
||||
{
|
||||
if( ( *it )->startPosition() >= lastPosition )
|
||||
{
|
||||
lastPosition = ( *it )->startPosition();
|
||||
lastLen = ( *it )->length();
|
||||
}
|
||||
}
|
||||
if( _start - lastPosition < lastLen )
|
||||
{
|
||||
return( bbEditor::inst()->play( _start - lastPosition,
|
||||
_start_frame, _frames,
|
||||
_frame_base,
|
||||
s_bbNums[this].num ) );
|
||||
}
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
trackContentObject * bbTrack::createTCO( const midiTime & _pos )
|
||||
{
|
||||
// if we're creating a new bbTCO, we colorize it according to the
|
||||
// previous bbTCO, so we have to get all TCOs from 0 to _pos and
|
||||
// pickup the last and take the color if it
|
||||
vlist<trackContentObject *> tcos;
|
||||
getTCOsInRange( tcos, 0, _pos );
|
||||
if( tcos.size() > 0 && dynamic_cast<bbTCO *>( tcos.back() ) != NULL )
|
||||
{
|
||||
return( new bbTCO( this,
|
||||
dynamic_cast<bbTCO *>( tcos.back() )->color() ) );
|
||||
|
||||
}
|
||||
return( new bbTCO( this ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTrack::saveTrackSpecificSettings( QDomDocument & _doc,
|
||||
QDomElement & _parent )
|
||||
{
|
||||
QDomElement bbt_de = _doc.createElement( nodeName() );
|
||||
bbt_de.setAttribute( "name", m_trackLabel->text() );
|
||||
/* bbt_de.setAttribute( "current", s_bbNums[this].num ==
|
||||
bbEditor::inst()->currentBB() );*/
|
||||
_parent.appendChild( bbt_de );
|
||||
if( s_bbNums[this].num == 0 &&
|
||||
_parent.parentNode().nodeName() != "clone" )
|
||||
{
|
||||
bbEditor::inst()->saveSettings( _doc, bbt_de );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTrack::loadTrackSpecificSettings( const QDomElement & _this )
|
||||
{
|
||||
m_trackLabel->setText( _this.attribute( "name" ) );
|
||||
if( _this.firstChild().isElement() )
|
||||
{
|
||||
bbEditor::inst()->loadSettings(
|
||||
_this.firstChild().toElement() );
|
||||
}
|
||||
/* doesn't work yet because bbTrack-ctor also sets current bb so if
|
||||
bb-tracks are created after this function is called, this doesn't
|
||||
help at all....
|
||||
if( _this.attribute( "current" ).toInt() )
|
||||
{
|
||||
bbEditor::inst()->setCurrentBB( s_bbNums[this].num );
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// return pointer to bbTrack specified by _bb_num
|
||||
bbTrack * bbTrack::findBBTrack( csize _bb_num )
|
||||
{
|
||||
for( QMap<bbTrack *, bbTrack::bbInfoStruct>::iterator it =
|
||||
s_bbNums.begin();
|
||||
it != s_bbNums.end(); ++it )
|
||||
{
|
||||
#ifdef QT4
|
||||
if( it.value().num == _bb_num )
|
||||
#else
|
||||
if( it.data().num == _bb_num )
|
||||
#endif
|
||||
{
|
||||
return( it.key() );
|
||||
}
|
||||
}
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
csize bbTrack::numOfBBTrack( track * _track )
|
||||
{
|
||||
if( dynamic_cast<bbTrack *>( _track ) != NULL )
|
||||
{
|
||||
return( s_bbNums[dynamic_cast<bbTrack *>( _track )].num );
|
||||
}
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTrack::swapBBTracks( track * _track1, track * _track2 )
|
||||
{
|
||||
bbTrack * t1 = dynamic_cast<bbTrack *>( _track1 );
|
||||
bbTrack * t2 = dynamic_cast<bbTrack *>( _track2 );
|
||||
if( t1 != NULL && t2 != NULL )
|
||||
{
|
||||
qSwap( s_bbNums[t1].num, s_bbNums[t2].num );
|
||||
bbEditor::inst()->swapBB( s_bbNums[t1].num, s_bbNums[t2].num );
|
||||
bbEditor::inst()->setCurrentBB( s_bbNums[t2].num );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTrack::clickedTrackLabel( void )
|
||||
{
|
||||
bbEditor::inst()->setCurrentBB( s_bbNums[this].num );
|
||||
bbEditor::inst()->show();
|
||||
}
|
||||
1027
src/tracks/pattern.cpp
Normal file
1027
src/tracks/pattern.cpp
Normal file
File diff suppressed because it is too large
Load Diff
395
src/tracks/sample_track.cpp
Normal file
395
src/tracks/sample_track.cpp
Normal file
@@ -0,0 +1,395 @@
|
||||
/*
|
||||
* sample_track.cpp - implementation of class sampleTrack, a track which
|
||||
* provides arrangement of samples
|
||||
*
|
||||
* 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 <QPushButton>
|
||||
#include <QPainter>
|
||||
#include <Qt/QtXml>
|
||||
|
||||
#else
|
||||
|
||||
#include <qpushbutton.h>
|
||||
#include <qpainter.h>
|
||||
#include <qdom.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "sample_track.h"
|
||||
#include "song_editor.h"
|
||||
#include "name_label.h"
|
||||
#include "embed.h"
|
||||
#include "templates.h"
|
||||
#include "buffer_allocator.h"
|
||||
#include "tooltip.h"
|
||||
|
||||
|
||||
|
||||
sampleTCO::sampleTCO( track * _track ) :
|
||||
trackContentObject( _track ),
|
||||
m_sampleBuffer()
|
||||
{
|
||||
#ifndef QT4
|
||||
setBackgroundMode( Qt::NoBackground );
|
||||
#endif
|
||||
|
||||
setSampleFile( "" );
|
||||
|
||||
// we need to receive bpm-change-events, because then we have to
|
||||
// change length of this TCO
|
||||
connect( songEditor::inst(), SIGNAL( bpmChanged( int ) ), this,
|
||||
SLOT( updateLength( int ) ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
sampleTCO::~sampleTCO()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void sampleTCO::changeLength( const midiTime & _length )
|
||||
{
|
||||
trackContentObject::changeLength( tMax( static_cast<Sint32>( _length ),
|
||||
64 ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FASTCALL sampleTCO::play( sampleFrame * _ab, Uint32 _start_frame,
|
||||
Uint32 _frames )
|
||||
{
|
||||
_start_frame = static_cast<Uint32>( tMax( 0.0f, _start_frame -
|
||||
startPosition() *
|
||||
songEditor::inst()->framesPerTact() / 64 ) );
|
||||
m_sampleBuffer.play( _ab, _start_frame, _frames );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
const QString & sampleTCO::sampleFile( void ) const
|
||||
{
|
||||
return( m_sampleBuffer.audioFile() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void sampleTCO::setSampleFile( const QString & _sf )
|
||||
{
|
||||
m_sampleBuffer.setAudioFile( _sf );
|
||||
updateLength();
|
||||
update();
|
||||
// set tooltip to filename so that user can see what sample this
|
||||
// sample-tco contains
|
||||
toolTip::add( this, ( m_sampleBuffer.audioFile() != "" ) ?
|
||||
m_sampleBuffer.audioFile() :
|
||||
tr( "double-click to select sample" ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void sampleTCO::updateLength( int )
|
||||
{
|
||||
changeLength( getSampleLength() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void sampleTCO::paintEvent( QPaintEvent * )
|
||||
{
|
||||
#ifdef QT4
|
||||
QPainter p( this );
|
||||
p.fillRect( rect(), QColor( 0, 64, 255 ) );
|
||||
#else
|
||||
// create pixmap for whole widget
|
||||
QPixmap pm( rect().size() );
|
||||
pm.fill( QColor( 0, 64, 255 ) );
|
||||
// and a painter for it
|
||||
QPainter p( &pm );
|
||||
#endif
|
||||
|
||||
if( getTrack()->muted() )
|
||||
{
|
||||
p.setPen( QColor( 160, 160, 160 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
p.setPen( QColor( 0, 0, 128 ) );
|
||||
}
|
||||
p.drawRect( 0, 0, width(), height() );
|
||||
m_sampleBuffer.drawWaves( p, QRect( 1, 1, tMax( tMin( width() - 3,
|
||||
static_cast<int>( getSampleLength() *
|
||||
pixelsPerTact() / 64 ) ), 1 ),
|
||||
height() - 4 ) );
|
||||
#ifndef QT4
|
||||
bitBlt( this, rect().topLeft(), &pm );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void sampleTCO::mouseDoubleClickEvent( QMouseEvent * )
|
||||
{
|
||||
QString af = m_sampleBuffer.openAudioFile();
|
||||
if( af != "" && af != m_sampleBuffer.audioFile() )
|
||||
{
|
||||
setSampleFile( af );
|
||||
songEditor::inst()->setModified();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
midiTime sampleTCO::getSampleLength( void ) const
|
||||
{
|
||||
return( static_cast<Sint32>( m_sampleBuffer.frames() /
|
||||
songEditor::inst()->framesPerTact() *
|
||||
64 ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FASTCALL sampleTCO::saveSettings( QDomDocument & _doc, QDomElement & _parent )
|
||||
{
|
||||
QDomElement sampletco_de = _doc.createElement( nodeName() );
|
||||
if( _parent.nodeName() == "clipboard" )
|
||||
{
|
||||
sampletco_de.setAttribute( "pos", QString::number( -1 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
sampletco_de.setAttribute( "pos", QString::number(
|
||||
startPosition() ) );
|
||||
}
|
||||
sampletco_de.setAttribute( "len", QString::number( length() ) );
|
||||
sampletco_de.setAttribute( "src", sampleFile() );
|
||||
// TODO: start- and end-frame
|
||||
_parent.appendChild( sampletco_de );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FASTCALL sampleTCO::loadSettings( const QDomElement & _this )
|
||||
{
|
||||
if( _this.attribute( "pos" ).toInt() >= 0 )
|
||||
{
|
||||
movePosition( _this.attribute( "pos" ).toInt() );
|
||||
}
|
||||
changeLength( _this.attribute( "len" ).toInt() );
|
||||
setSampleFile( _this.attribute( "src" ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
sampleTCOSettingsDialog::sampleTCOSettingsDialog( sampleTCO * _stco ) :
|
||||
QDialog(),
|
||||
m_sampleTCO( _stco )
|
||||
{
|
||||
resize( 400, 300 );
|
||||
|
||||
QVBoxWidget * vb0 = new QVBoxWidget( this );
|
||||
vb0->resize( 400, 300 );
|
||||
QHBoxWidget * hb00 = new QHBoxWidget( vb0 );
|
||||
m_fileLbl = new QLabel( _stco->sampleFile(), hb00 );
|
||||
QPushButton * open_file_btn = new QPushButton(
|
||||
embed::getIconPixmap( "fileopen" ), "", hb00 );
|
||||
connect( open_file_btn, SIGNAL( clicked() ), this,
|
||||
SLOT( openSampleFile() ) );
|
||||
|
||||
QHBoxWidget * hb01 = new QHBoxWidget( vb0 );
|
||||
|
||||
QPushButton * ok_btn = new QPushButton( tr( "OK" ), hb01 );
|
||||
ok_btn->setGeometry( 10, 0, 100, 32 );
|
||||
connect( ok_btn, SIGNAL( clicked() ), this, SLOT( accept() ) );
|
||||
|
||||
QPushButton * cancel_btn = new QPushButton( tr( "Cancel" ), hb01 );
|
||||
cancel_btn->setGeometry( 120, 0, 100, 32 );
|
||||
connect( ok_btn, SIGNAL( clicked() ), this, SLOT( reject() ) );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
sampleTCOSettingsDialog::~sampleTCOSettingsDialog()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void sampleTCOSettingsDialog::openSampleFile( void )
|
||||
{
|
||||
QString af = m_sampleTCO->m_sampleBuffer.openAudioFile();
|
||||
if( af != "" )
|
||||
{
|
||||
setSampleFile( af );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void sampleTCOSettingsDialog::setSampleFile( const QString & _f )
|
||||
{
|
||||
m_fileLbl->setText( _f );
|
||||
m_sampleTCO->setSampleFile( _f );
|
||||
songEditor::inst()->setModified();
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
sampleTrack::sampleTrack( trackContainer * _tc )
|
||||
: track( _tc )
|
||||
{
|
||||
getTrackWidget()->setFixedHeight( 32 );
|
||||
|
||||
m_trackLabel = new nameLabel( tr( "Sample track" ),
|
||||
getTrackSettingsWidget(),
|
||||
embed::getIconPixmap(
|
||||
"sample_track" ) );
|
||||
m_trackLabel->setGeometry( 1, 1, DEFAULT_SETTINGS_WIDGET_WIDTH-2, 29 );
|
||||
m_trackLabel->show();
|
||||
|
||||
_tc->updateAfterTrackAdd();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
sampleTrack::~sampleTrack()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
track::trackTypes sampleTrack::trackType( void ) const
|
||||
{
|
||||
return( SAMPLE_TRACK );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool FASTCALL sampleTrack::play( const midiTime & _start, Uint32 _start_frame,
|
||||
Uint32 _frames, Uint32 _frame_base,
|
||||
Sint16 /*_tco_num*/ )
|
||||
{
|
||||
vlist<trackContentObject *> tcos;
|
||||
getTCOsInRange( tcos, _start, _start+static_cast<Sint32>( _frames * 64 /
|
||||
songEditor::inst()->framesPerTact() ) );
|
||||
|
||||
if ( tcos.size() == 0 )
|
||||
{
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
sampleFrame * buf = bufferAllocator::alloc<sampleFrame>( _frames );
|
||||
|
||||
volumeVector v = { 1.0f, 1.0f
|
||||
#ifndef DISABLE_SURROUND
|
||||
, 1.0f, 1.0f
|
||||
#endif
|
||||
} ;
|
||||
float fpt = songEditor::inst()->framesPerTact();
|
||||
|
||||
for( vlist<trackContentObject *>::iterator it = tcos.begin();
|
||||
it != tcos.end(); ++it )
|
||||
{
|
||||
sampleTCO * st = dynamic_cast<sampleTCO *>( *it );
|
||||
if( st != NULL )
|
||||
{
|
||||
st->play( buf, _start_frame +
|
||||
static_cast<Uint32>( _start.getTact() *
|
||||
fpt ),
|
||||
_frames );
|
||||
mixer::inst()->addBuffer( buf, _frames, _frame_base +
|
||||
static_cast<Uint32>(
|
||||
st->startPosition().getTact64th() *
|
||||
fpt / 64.0f ), v );
|
||||
}
|
||||
}
|
||||
|
||||
bufferAllocator::free( buf );
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
trackContentObject * sampleTrack::createTCO( const midiTime & )
|
||||
{
|
||||
return( new sampleTCO( this ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void sampleTrack::saveTrackSpecificSettings( QDomDocument & _doc,
|
||||
QDomElement & _parent )
|
||||
{
|
||||
QDomElement st_de = _doc.createElement( nodeName() );
|
||||
st_de.setAttribute( "name", m_trackLabel->text() );
|
||||
_parent.appendChild( st_de );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void sampleTrack::loadTrackSpecificSettings( const QDomElement & _this )
|
||||
{
|
||||
m_trackLabel->setText( _this.attribute( "name" ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#include "sample_track.moc"
|
||||
|
||||
234
src/widgets/group_box.cpp
Normal file
234
src/widgets/group_box.cpp
Normal file
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
* group_box.cpp - groupbox 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 "qt3support.h"
|
||||
|
||||
#ifdef QT4
|
||||
|
||||
#include <QPainter>
|
||||
#include <QTimer>
|
||||
#include <QMouseEvent>
|
||||
|
||||
#else
|
||||
|
||||
#include <qpainter.h>
|
||||
#include <qtimer.h>
|
||||
#include <qobjectlist.h>
|
||||
|
||||
#define setChecked setOn
|
||||
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
|
||||
|
||||
#include "group_box.h"
|
||||
#include "embed.h"
|
||||
#include "spc_bg_hndl_widget.h"
|
||||
#include "templates.h"
|
||||
|
||||
|
||||
QPixmap * groupBox::s_ledBg = NULL;
|
||||
|
||||
|
||||
groupBox::groupBox( const QString & _caption, QWidget * _parent ) :
|
||||
QWidget( _parent ),
|
||||
m_caption( _caption ),
|
||||
m_origHeight( height() ),
|
||||
m_animating( FALSE )
|
||||
{
|
||||
if( s_ledBg == NULL )
|
||||
{
|
||||
s_ledBg = new QPixmap( embed::getIconPixmap(
|
||||
"groupbox_led_bg" ) );
|
||||
}
|
||||
updatePixmap();
|
||||
|
||||
m_led = new pixmapButton( this );
|
||||
m_led->move( 2, 3 );
|
||||
m_led->setActiveGraphic( embed::getIconPixmap( "led_green" ) );
|
||||
m_led->setInactiveGraphic( embed::getIconPixmap( "led_off" ) );
|
||||
m_led->setBgGraphic( specialBgHandlingWidget::getBackground( m_led ) );
|
||||
connect( m_led, SIGNAL( toggled( bool ) ),
|
||||
this, SLOT( setState( bool ) ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
groupBox::~groupBox()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void groupBox::resizeEvent( QResizeEvent * )
|
||||
{
|
||||
updatePixmap();
|
||||
if( m_animating == FALSE )
|
||||
{
|
||||
m_origHeight = height();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void groupBox::mousePressEvent( QMouseEvent * _me )
|
||||
{
|
||||
if( _me->y() > 1 && _me->y() < 13 )
|
||||
{
|
||||
setState( !isActive(), TRUE );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void groupBox::setState( bool _on, bool _anim )
|
||||
{
|
||||
m_led->setChecked( _on );
|
||||
if( ( _anim == TRUE || ( _on == TRUE && height() < m_origHeight ) ) &&
|
||||
m_animating == FALSE )
|
||||
{
|
||||
m_animating = TRUE;
|
||||
animate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void groupBox::animate( void )
|
||||
{
|
||||
float state = (float)( m_origHeight - height() ) /
|
||||
(float)( m_origHeight - 19 );
|
||||
int dy = static_cast<int>( 3 - 2 * cosf( state * 2 * M_PI ) );
|
||||
if( isActive() && height() < m_origHeight )
|
||||
{
|
||||
}
|
||||
else if( !isActive() && height() > 19 )
|
||||
{
|
||||
dy = -dy;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_animating = FALSE;
|
||||
return;
|
||||
}
|
||||
resize( width(), height() + dy );
|
||||
QTimer::singleShot( 10, this, SLOT( animate() ) );
|
||||
#ifdef QT4
|
||||
QObjectList ch = parent()->children();
|
||||
#else
|
||||
QObjectList ch = *( parent()->children() );
|
||||
#endif
|
||||
for( csize i = 0; i < ch.count(); ++i )
|
||||
{
|
||||
QWidget * w = dynamic_cast<QWidget *>( ch.at( i ) );
|
||||
if( w == NULL || w->y() < y() + height() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
w->move( w->x(), w->y() + dy );
|
||||
}
|
||||
#ifdef QT4
|
||||
ch = children();
|
||||
#else
|
||||
ch = *children();
|
||||
#endif
|
||||
for( csize i = 0; i < ch.count(); ++i )
|
||||
{
|
||||
QWidget * w = dynamic_cast<QWidget *>( ch.at( i ) );
|
||||
if( w == NULL || w == m_led )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
w->move( w->x(), w->y() + dy );
|
||||
if( w->y() < 14)
|
||||
{
|
||||
w->hide();
|
||||
}
|
||||
else if( w->isHidden() == TRUE )
|
||||
{
|
||||
w->show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void groupBox::updatePixmap( void )
|
||||
{
|
||||
QPixmap pm( size() );
|
||||
pm.fill( QColor( 96, 96, 96 ) );
|
||||
|
||||
QPainter p( &pm );
|
||||
|
||||
// outer rect
|
||||
p.setPen( QColor( 64, 64, 64 ) );
|
||||
p.drawRect( 0, 0, width(), height() );
|
||||
|
||||
// brighter line at bottom/right
|
||||
p.setPen( QColor( 160, 160, 160 ) );
|
||||
p.drawLine( width() - 1, 0, width() - 1, height() - 1 );
|
||||
p.drawLine( 0, height() - 1, width() - 1, height() - 1 );
|
||||
|
||||
// draw our led-pixmap
|
||||
p.drawPixmap( 2, 2, *s_ledBg );
|
||||
|
||||
// draw groupbox-titlebar
|
||||
p.fillRect( 2, 2, width() - 4, 9, QColor( 30, 45, 60 ) );
|
||||
|
||||
// draw line below titlebar
|
||||
p.setPen( QColor( 0, 0, 0 ) );
|
||||
p.drawLine( 2 + s_ledBg->width(), 11, width() - 3, 11 );
|
||||
|
||||
// black inner rect
|
||||
p.drawRect( 1, 1, width() - 2, height() - 2 );
|
||||
|
||||
|
||||
p.setPen( QColor( 255, 255, 255 ) );
|
||||
p.setFont( pointSize<7>( font() ) );
|
||||
p.drawText( 22, 10, m_caption );
|
||||
|
||||
#ifdef QT4
|
||||
QPalette pal = palette();
|
||||
pal.setBrush( backgroundRole(), QBrush( pm ) );
|
||||
pal.setColor( QPalette::Background, QColor( 96, 96, 96 ) );
|
||||
setPalette( pal );
|
||||
#else
|
||||
setPaletteBackgroundColor( QColor( 96, 96, 96 ) );
|
||||
setErasePixmap( pm );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
#undef setChecked
|
||||
|
||||
#include "group_box.moc"
|
||||
|
||||
1148
src/widgets/kmultitabbar.cpp
Normal file
1148
src/widgets/kmultitabbar.cpp
Normal file
File diff suppressed because it is too large
Load Diff
812
src/widgets/knob.cpp
Normal file
812
src/widgets/knob.cpp
Normal file
@@ -0,0 +1,812 @@
|
||||
/*
|
||||
* knob.cpp - powerful knob-widget
|
||||
*
|
||||
* This file is based on the knob-widget of the Qwt Widget Library from
|
||||
* Josef Wilgen
|
||||
*
|
||||
* 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 <QPalette>
|
||||
#include <QBitmap>
|
||||
#include <QLabel>
|
||||
#include <QStatusBar>
|
||||
#include <QMouseEvent>
|
||||
#include <QMenu>
|
||||
#include <QStatusBar>
|
||||
#include <QFontMetrics>
|
||||
#include <QApplication>
|
||||
|
||||
#else
|
||||
|
||||
#include <qpainter.h>
|
||||
#include <qpalette.h>
|
||||
#include <qbitmap.h>
|
||||
#include <qlabel.h>
|
||||
#include <qpopupmenu.h>
|
||||
#include <qstatusbar.h>
|
||||
#include <qfontmetrics.h>
|
||||
#include <qapplication.h>
|
||||
|
||||
#define addSeparator insertSeparator
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef __USE_XOPEN
|
||||
#define __USE_XOPEN
|
||||
#endif
|
||||
#include <math.h>
|
||||
|
||||
#include "knob.h"
|
||||
#include "song_editor.h"
|
||||
#include "midi_device.h"
|
||||
#include "embed.h"
|
||||
#include "spc_bg_hndl_widget.h"
|
||||
//#include "tooltip.h"
|
||||
#include "config_mgr.h"
|
||||
#include "text_float.h"
|
||||
#include "mixer.h"
|
||||
|
||||
|
||||
const int WHEEL_DELTA = 120;
|
||||
|
||||
|
||||
static double MinRelStep = 1.0e-10;
|
||||
static double DefaultRelStep = 1.0e-2;
|
||||
static double MinEps = 1.0e-10;
|
||||
|
||||
|
||||
float knob::s_copiedValue = 0.0f;
|
||||
textFloat * knob::s_textFloat = NULL;
|
||||
|
||||
|
||||
|
||||
knob::knob( int _knob_num, QWidget * _parent, const QString & _name ) :
|
||||
QWidget( _parent
|
||||
#ifndef QT4
|
||||
, _name.ascii()
|
||||
#endif
|
||||
),
|
||||
m_scrollMode( ScrNone ),
|
||||
m_mouseOffset( 0.0f ),
|
||||
m_tracking( TRUE ),
|
||||
m_angle( 0.0f ),
|
||||
m_oldAngle( 0.0f ),
|
||||
m_nTurns( 0.0f ),
|
||||
m_knobNum( _knob_num ),
|
||||
m_hintTextBeforeValue( "" ),
|
||||
m_hintTextAfterValue( "" ),
|
||||
m_label( "" ),
|
||||
m_minValue( 0.0f ),
|
||||
m_maxValue( 100.0f ),
|
||||
m_value( 0.0f ),
|
||||
m_exactValue( 0.0f ),
|
||||
m_exactPrevValue( 0.0f ),
|
||||
m_prevValue( 0.0f ),
|
||||
m_initValue( 0.0f )
|
||||
{
|
||||
if( s_textFloat == NULL )
|
||||
{
|
||||
s_textFloat = new textFloat( this );
|
||||
}
|
||||
|
||||
#ifdef QT4
|
||||
setAccessibleName( _name );
|
||||
#endif
|
||||
setRange( 0.0, 100.0, 1.0 );
|
||||
|
||||
#ifdef QT4
|
||||
m_knobPixmap = new QPixmap( embed::getIconPixmap( QString( "knob0" +
|
||||
QString::number( m_knobNum + 1 ) ).toAscii().constData() ) );
|
||||
#else
|
||||
m_knobPixmap = new QPixmap( embed::getIconPixmap( "knob0" +
|
||||
QString::number( m_knobNum + 1 ) ) );
|
||||
#endif
|
||||
#ifdef QT4
|
||||
// setAttribute( Qt::WA_NoBackground );
|
||||
#else
|
||||
setBackgroundMode( Qt::NoBackground );
|
||||
#endif
|
||||
|
||||
m_knobWidth = m_knobPixmap->width();
|
||||
|
||||
setFixedSize( m_knobPixmap->width(), m_knobPixmap->height() );
|
||||
setTotalAngle( 270.0f );
|
||||
recalcAngle();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Destructor
|
||||
knob::~knob()
|
||||
{
|
||||
// make sure pointer to this knob isn't used anymore in active
|
||||
// midi-device-class
|
||||
if( mixer::inst()->getMIDIDevice()->pitchBendKnob() == this )
|
||||
{
|
||||
mixer::inst()->getMIDIDevice()->setPitchBendKnob( NULL );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void knob::setHintText( const QString & _txt_before,
|
||||
const QString & _txt_after )
|
||||
{
|
||||
m_hintTextBeforeValue = _txt_before;
|
||||
m_hintTextAfterValue = _txt_after;
|
||||
/* toolTip::add( this, m_hintTextBeforeValue + QString::number( value() ) +
|
||||
m_hintTextAfterValue );*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void knob::setLabel( const QString & _txt )
|
||||
{
|
||||
m_label = _txt;
|
||||
setFixedSize( tMax<int>( m_knobPixmap->width(),
|
||||
QFontMetrics( pointSize<6>( font()
|
||||
) ).width( m_label ) ),
|
||||
m_knobPixmap->height() + 10 );
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void knob::setTotalAngle( float _angle )
|
||||
{
|
||||
if( _angle < 10.0 )
|
||||
{
|
||||
m_totalAngle = 10.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_totalAngle = _angle;
|
||||
}
|
||||
|
||||
layoutKnob();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void knob::drawKnob( QPainter * _p )
|
||||
{
|
||||
_p->drawPixmap( 0, 0, specialBgHandlingWidget::getBackground( this ) );
|
||||
|
||||
const float radius = m_knobPixmap->width() / 2 - 1;
|
||||
const float xm = m_knobPixmap->width() / 2;//radius + 1;
|
||||
const float ym = m_knobPixmap->height() / 2;//radius+1;
|
||||
|
||||
const float rarc = m_angle * M_PI / 180.0;
|
||||
const float ca = cos( rarc );
|
||||
const float sa = -sin( rarc );
|
||||
|
||||
_p->drawPixmap( static_cast<int>( xm - m_knobPixmap->width() / 2 ), 0,
|
||||
*m_knobPixmap );
|
||||
|
||||
_p->setPen( QPen( QColor( 200, 0, 0 ), 2 ) );
|
||||
|
||||
switch( m_knobNum )
|
||||
{
|
||||
case knobSmall_17:
|
||||
{
|
||||
_p->drawLine( (int)( xm-sa ), (int)( ym-ca ),
|
||||
(int)( xm - sa*radius ),
|
||||
(int)( ym - ca*radius ) );
|
||||
break;
|
||||
}
|
||||
case knobBright_26:
|
||||
{
|
||||
_p->drawLine( (int)( xm-sa ), (int)( ym-ca ),
|
||||
(int)( xm - sa*( radius-5 ) ),
|
||||
(int)( ym - ca*( radius-5 ) ) );
|
||||
break;
|
||||
}
|
||||
case knobDark_28:
|
||||
{
|
||||
const float rb = tMax<float>( ( radius - 10 ) / 3.0,
|
||||
0.0 );
|
||||
const float re = tMax<float>( ( radius - 4 ), 0.0 );
|
||||
_p->drawLine( (int)( xm-sa*rb ) + 1,
|
||||
(int)( ym - ca*rb ) + 1,
|
||||
(int)( xm - sa*re ) + 1,
|
||||
(int)( ym - ca*re ) + 1 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void knob::valueChange( void )
|
||||
{
|
||||
recalcAngle();
|
||||
update();
|
||||
/* toolTip::add( this, m_hintTextBeforeValue + QString::number( value() ) +
|
||||
m_hintTextAfterValue );*/
|
||||
if( m_tracking )
|
||||
{
|
||||
emit valueChanged( value() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
float knob::getValue( const QPoint & _p )
|
||||
{
|
||||
if( configManager::inst()->value( "knobs", "classicalusability"
|
||||
).toInt() )
|
||||
{
|
||||
const float dx = float( ( rect().x() + rect().width() / 2 ) -
|
||||
_p.x() );
|
||||
const float dy = float( ( rect().y() + rect().height() / 2 ) -
|
||||
_p.y() );
|
||||
|
||||
const float arc = atan2( -dx, dy ) * 180.0 / M_PI;
|
||||
|
||||
float new_value = 0.5 * ( m_minValue + m_maxValue ) +
|
||||
( arc + m_nTurns * 360.0 ) *
|
||||
( m_maxValue - m_minValue ) /
|
||||
m_totalAngle;
|
||||
|
||||
const float oneTurn = tAbs<float>( m_maxValue - m_minValue ) *
|
||||
360.0 / m_totalAngle;
|
||||
const float eqValue = value() + m_mouseOffset;
|
||||
|
||||
if( tAbs<float>( new_value - eqValue ) > 0.5 * oneTurn )
|
||||
{
|
||||
if( new_value < eqValue )
|
||||
{
|
||||
new_value += oneTurn;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_value -= oneTurn;
|
||||
}
|
||||
}
|
||||
return( new_value );
|
||||
}
|
||||
return( ( _p.y() - m_origMousePos.y() ) * m_step );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void knob::getScrollMode( const QPoint &, int & _scroll_mode, int & _direction )
|
||||
{
|
||||
_scroll_mode = ScrMouse;
|
||||
_direction = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void knob::rangeChange()
|
||||
{
|
||||
layoutKnob();
|
||||
recalcAngle();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void knob::resizeEvent( QResizeEvent * )
|
||||
{
|
||||
layoutKnob( FALSE );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Recalculate the slider's geometry and layout based on
|
||||
// the current rect and fonts.
|
||||
void knob::layoutKnob( bool _update_geometry )
|
||||
{
|
||||
if( _update_geometry )
|
||||
{
|
||||
updateGeometry();
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void knob::paintEvent( QPaintEvent * _me )
|
||||
{
|
||||
// Use double-buffering
|
||||
QRect ur = _me->rect();
|
||||
#ifndef QT4
|
||||
if( ur.isValid() )
|
||||
{
|
||||
#endif
|
||||
#ifdef QT4
|
||||
QPainter p( this );
|
||||
#else
|
||||
QPixmap pix( ur.size() );
|
||||
pix.fill( this, ur.topLeft() );
|
||||
QPainter p( &pix, this );
|
||||
#endif
|
||||
p.translate( -ur.x(), -ur.y() );
|
||||
drawKnob( &p );
|
||||
if( m_label != "" )
|
||||
{
|
||||
p.setFont( pointSize<6>( p.font() ) );
|
||||
p.setPen( QColor( 255, 255, 255 ) );
|
||||
p.drawText( width() / 2 -
|
||||
QFontMetrics( p.font() ).width( m_label ) / 2,
|
||||
height() - 2, m_label );
|
||||
}
|
||||
#ifndef QT4
|
||||
p.end();
|
||||
bitBlt( this, ur.topLeft(), &pix );
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void knob::recalcAngle( void )
|
||||
{
|
||||
m_oldAngle = m_angle;
|
||||
|
||||
//
|
||||
// calculate the angle corresponding to the value
|
||||
//
|
||||
if( m_maxValue == m_minValue )
|
||||
{
|
||||
m_angle = 0;
|
||||
m_nTurns = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_angle = ( value() - 0.5 * ( m_minValue + m_maxValue ) ) /
|
||||
( m_maxValue - m_minValue ) * m_totalAngle;
|
||||
m_nTurns = floor( ( m_angle + 180.0 ) / 360.0 );
|
||||
m_angle = m_angle - m_nTurns * 360.0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//! Mouse press event handler
|
||||
void knob::mousePressEvent( QMouseEvent * _me )
|
||||
{
|
||||
const QPoint & p = _me->pos();
|
||||
m_origMousePos = p;
|
||||
|
||||
getScrollMode( p, m_scrollMode, m_direction );
|
||||
|
||||
switch( m_scrollMode )
|
||||
{
|
||||
case ScrMouse:
|
||||
m_mouseOffset = getValue( p ) - value();
|
||||
emit sliderPressed();
|
||||
break;
|
||||
|
||||
default:
|
||||
m_mouseOffset = 0;
|
||||
m_direction = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if( _me->button() == Qt::LeftButton )
|
||||
{
|
||||
if( !configManager::inst()->value( "knobs", "classicalusability"
|
||||
).toInt() )
|
||||
{
|
||||
QApplication::setOverrideCursor( Qt::BlankCursor );
|
||||
}
|
||||
s_textFloat->reparent( this );
|
||||
s_textFloat->setText( m_hintTextBeforeValue +
|
||||
QString::number( value() ) +
|
||||
m_hintTextAfterValue );
|
||||
s_textFloat->move( mapTo( topLevelWidget(), QPoint( 0, 0 ) ) +
|
||||
QPoint( m_knobPixmap->width() + 2, 0 ) );
|
||||
s_textFloat->show();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//! Emits a valueChanged() signal if necessary
|
||||
void knob::buttonReleased( void )
|
||||
{
|
||||
if( ( !m_tracking ) || ( value() != m_prevValue ) )
|
||||
{
|
||||
emit valueChanged( value() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//! Mouse Release Event handler
|
||||
void knob::mouseReleaseEvent( QMouseEvent * _me )
|
||||
{
|
||||
m_scrollMode = ScrNone;
|
||||
buttonReleased();
|
||||
|
||||
switch( m_scrollMode )
|
||||
{
|
||||
case ScrMouse:
|
||||
setPosition( _me->pos() );
|
||||
m_direction = 0;
|
||||
m_mouseOffset = 0;
|
||||
emit sliderReleased ();
|
||||
break;
|
||||
|
||||
case ScrDirect:
|
||||
setPosition( _me->pos() );
|
||||
m_direction = 0;
|
||||
m_mouseOffset = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if( !configManager::inst()->value( "knobs", "classicalusability"
|
||||
).toInt() )
|
||||
{
|
||||
QApplication::restoreOverrideCursor();
|
||||
}
|
||||
|
||||
s_textFloat->hide();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void knob::setPosition( const QPoint & _p )
|
||||
{
|
||||
if( configManager::inst()->value( "knobs", "classicalusability"
|
||||
).toInt() )
|
||||
{
|
||||
setNewValue( getValue( _p ) - m_mouseOffset, 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
setNewValue( m_value - getValue( _p ), 1 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void knob::setTracking( bool _enable )
|
||||
{
|
||||
m_tracking = _enable;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//! Mouse Move Event handler
|
||||
void knob::mouseMoveEvent( QMouseEvent * _me )
|
||||
{
|
||||
if( m_scrollMode == ScrMouse )
|
||||
{
|
||||
setPosition( _me->pos() );
|
||||
if( value() != m_prevValue )
|
||||
{
|
||||
emit sliderMoved( value() );
|
||||
}
|
||||
if( !configManager::inst()->value( "knobs", "classicalusability"
|
||||
).toInt() )
|
||||
{
|
||||
QCursor::setPos( mapToGlobal( m_origMousePos ) );
|
||||
}
|
||||
}
|
||||
songEditor::inst()->setModified();
|
||||
|
||||
s_textFloat->setText( m_hintTextBeforeValue +
|
||||
QString::number( value() ) +
|
||||
m_hintTextAfterValue );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! Qt wheel event
|
||||
void knob::wheelEvent( QWheelEvent * _me )
|
||||
{
|
||||
_me->accept();
|
||||
const int inc = _me->delta() / WHEEL_DELTA;
|
||||
incPages( inc );
|
||||
|
||||
songEditor::inst()->setModified();
|
||||
|
||||
s_textFloat->reparent( this );
|
||||
s_textFloat->setText( m_hintTextBeforeValue +
|
||||
QString::number( value() ) +
|
||||
m_hintTextAfterValue );
|
||||
s_textFloat->move( mapTo( topLevelWidget(), QPoint( 0, 0 ) ) +
|
||||
QPoint( m_knobPixmap->width() + 2, 0 ) );
|
||||
s_textFloat->setVisibilityTimeOut( 1000 );
|
||||
|
||||
/* toolTip::add( this, m_hintTextBeforeValue+QString::number( value() ) +
|
||||
m_hintTextAfterValue );*/
|
||||
|
||||
if( value() != m_prevValue )
|
||||
{
|
||||
emit sliderMoved( value() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void knob::setValue( float _val, bool _is_init_value )
|
||||
{
|
||||
if( _is_init_value )
|
||||
{
|
||||
m_initValue = _val;
|
||||
}
|
||||
|
||||
setNewValue( _val, 0 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void knob::fitValue( float _val )
|
||||
{
|
||||
setNewValue( _val, 1 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void knob::incValue( int _steps )
|
||||
{
|
||||
setNewValue( m_value + float( _steps ) * m_step, 1 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void knob::setRange( float _vmin, float _vmax, float _vstep, int _page_size )
|
||||
{
|
||||
int rchg = ( ( m_maxValue != _vmax ) || ( m_minValue != _vmin ) );
|
||||
|
||||
if( rchg )
|
||||
{
|
||||
m_minValue = _vmin;
|
||||
m_maxValue = _vmax;
|
||||
}
|
||||
|
||||
//
|
||||
// look if the step width has an acceptable
|
||||
// value or otherwise change it.
|
||||
//
|
||||
setStep( _vstep );
|
||||
|
||||
//
|
||||
// limit page size
|
||||
//
|
||||
/* m_pageSize = tLimit( pageSize, 0, int( tAbs<float>( ( m_maxValue -
|
||||
m_minValue ) / m_step ) ) ); */
|
||||
m_pageSize = tMax<float>( ( m_maxValue - m_minValue ) / 40.0f, _vstep );
|
||||
|
||||
//
|
||||
// If the value lies out of the range, it
|
||||
// will be changed. Note that it will not be adjusted to
|
||||
// the new step width.
|
||||
setNewValue( m_value, 0 );
|
||||
|
||||
// call notifier after the step width has been
|
||||
// adjusted.
|
||||
if( rchg )
|
||||
{
|
||||
rangeChange();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void knob::setNewValue( float _x, int _align )
|
||||
{
|
||||
m_prevValue = m_value;
|
||||
|
||||
m_value = tLimit( _x, m_minValue, m_maxValue );
|
||||
|
||||
m_exactPrevValue = m_exactValue;
|
||||
m_exactValue = m_value;
|
||||
|
||||
// align to grid
|
||||
if( _align )
|
||||
{
|
||||
if( m_step != 0.0 )
|
||||
{
|
||||
m_value = floorf( m_value / m_step ) * m_step;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_value = m_minValue;
|
||||
}
|
||||
|
||||
// correct rounding error at the border
|
||||
if( tAbs<float>( m_value - m_maxValue ) < MinEps *
|
||||
tAbs<float>( m_step ) )
|
||||
{
|
||||
m_value = m_maxValue;
|
||||
}
|
||||
|
||||
// correct rounding error if value = 0
|
||||
if( tAbs<float>( m_value ) < MinEps * tAbs<float>( m_step ) )
|
||||
{
|
||||
m_value = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
if( m_prevValue != m_value )
|
||||
{
|
||||
valueChange();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void knob::setStep( float _vstep )
|
||||
{
|
||||
float intv = m_maxValue - m_minValue;
|
||||
|
||||
float newStep;
|
||||
|
||||
if( _vstep == 0.0 )
|
||||
{
|
||||
newStep = intv * DefaultRelStep;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( ( intv > 0 ) && ( _vstep < 0 ) || ( intv < 0 ) &&
|
||||
( _vstep > 0 ) )
|
||||
{
|
||||
newStep = -_vstep;
|
||||
}
|
||||
else
|
||||
{
|
||||
newStep = _vstep;
|
||||
}
|
||||
if( tAbs<float>( newStep ) <
|
||||
tAbs<float>( MinRelStep * intv ) )
|
||||
{
|
||||
newStep = MinRelStep * intv;
|
||||
}
|
||||
}
|
||||
if( newStep != m_step )
|
||||
{
|
||||
m_step = newStep;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void knob::contextMenuEvent( QContextMenuEvent * )
|
||||
{
|
||||
QMenu contextMenu( this );
|
||||
#ifdef QT4
|
||||
contextMenu.setTitle( accessibleName() );
|
||||
#else
|
||||
QLabel * caption = new QLabel( "<font color=white><b>" +
|
||||
QString( accessibleName() ) + "</b></font>", this );
|
||||
caption->setPaletteBackgroundColor( QColor( 0, 0, 192 ) );
|
||||
caption->setAlignment( Qt::AlignCenter );
|
||||
contextMenu.addAction( caption );
|
||||
#endif
|
||||
contextMenu.addAction( embed::getIconPixmap( "reload" ),
|
||||
tr( "&Reset (%1%2)" ).arg( m_initValue ).arg(
|
||||
m_hintTextAfterValue ),
|
||||
this, SLOT( reset() ) );
|
||||
contextMenu.addSeparator();
|
||||
contextMenu.addAction( embed::getIconPixmap( "edit_copy" ),
|
||||
tr( "&Copy value (%1%2)" ).arg( value() ).arg(
|
||||
m_hintTextAfterValue ),
|
||||
this, SLOT( copyValue() ) );
|
||||
contextMenu.addAction( embed::getIconPixmap( "edit_paste" ),
|
||||
tr( "&Paste value (%1%2)"
|
||||
).arg( s_copiedValue ).arg(
|
||||
m_hintTextAfterValue ),
|
||||
this, SLOT( pasteValue() ) );
|
||||
contextMenu.addSeparator();
|
||||
contextMenu.addAction( tr( "Connect to MIDI-device" ), this,
|
||||
SLOT( connectToMidiDevice() ) );
|
||||
contextMenu.addSeparator();
|
||||
contextMenu.addAction( embed::getIconPixmap( "help" ), tr( "&Help" ),
|
||||
this, SLOT( displayHelp() ) );
|
||||
contextMenu.exec( QCursor::pos() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void knob::reset( void )
|
||||
{
|
||||
setValue( m_initValue );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void knob::copyValue( void )
|
||||
{
|
||||
s_copiedValue = value();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void knob::pasteValue( void )
|
||||
{
|
||||
setValue( s_copiedValue );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void knob::connectToMidiDevice( void )
|
||||
{
|
||||
mixer::inst()->getMIDIDevice()->setPitchBendKnob( this );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void knob::displayHelp( void )
|
||||
{
|
||||
#ifdef QT4
|
||||
QWhatsThis::showText( mapToGlobal( rect().bottomRight() ),
|
||||
whatsThis() );
|
||||
#else
|
||||
QWhatsThis::display( QWhatsThis::textFor( this ), mapToGlobal(
|
||||
rect().bottomRight() ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#include "knob.moc"
|
||||
|
||||
|
||||
#ifndef QT4
|
||||
#undef addSeparator
|
||||
#endif
|
||||
176
src/widgets/lcd_spinbox.cpp
Normal file
176
src/widgets/lcd_spinbox.cpp
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* lcd_spinbox.cpp - class lcdSpinBox, an improved QLCDNumber
|
||||
*
|
||||
* 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 <QMouseEvent>
|
||||
#include <QCursor>
|
||||
#include <QLabel>
|
||||
|
||||
#else
|
||||
|
||||
#include <qapplication.h>
|
||||
#include <qcursor.h>
|
||||
#include <qlabel.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "lcd_spinbox.h"
|
||||
#include "templates.h"
|
||||
|
||||
|
||||
|
||||
lcdSpinBox::lcdSpinBox( int _min, int _max, int _num_digits,
|
||||
QWidget * _parent ) :
|
||||
QWidget( _parent ),
|
||||
m_minValue( _min ),
|
||||
m_maxValue( _max ),
|
||||
m_step( 1 ),
|
||||
m_label( NULL ),
|
||||
m_origMousePos()
|
||||
{
|
||||
m_number = new QLCDNumber( _num_digits, this );
|
||||
m_number->setFrameShape( QFrame::Panel );
|
||||
m_number->setFrameShadow( QFrame::Sunken );
|
||||
m_number->setSegmentStyle( QLCDNumber::Flat );
|
||||
#ifdef QT4
|
||||
QPalette pal = m_number->palette();
|
||||
pal.setColor( QPalette::Background, QColor( 32, 32, 32 ) );
|
||||
pal.setColor( QPalette::Foreground, QColor( 255, 180, 0 ) );
|
||||
m_number->setPalette( pal );
|
||||
#else
|
||||
m_number->setPaletteBackgroundColor( QColor( 32, 32, 32 ) );
|
||||
m_number->setPaletteForegroundColor( QColor( 255, 180, 0 ) );
|
||||
#endif
|
||||
// value is automatically limited to given range
|
||||
setValue( 0 );
|
||||
|
||||
m_number->setFixedSize( m_number->sizeHint() * 0.9 );
|
||||
setFixedSize( m_number->size() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
lcdSpinBox::~lcdSpinBox()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
void lcdSpinBox::setStep( int _step )
|
||||
{
|
||||
m_step = tMax( _step, 1 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void lcdSpinBox::setValue( int _value )
|
||||
{
|
||||
_value = ( ( tLimit( _value, m_minValue, m_maxValue ) - m_minValue ) /
|
||||
m_step ) * m_step + m_minValue;
|
||||
QString s = QString::number( _value );
|
||||
while( (int) s.length() < m_number->numDigits() )
|
||||
{
|
||||
s = "0" + s;
|
||||
}
|
||||
|
||||
m_number->display( s );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void lcdSpinBox::setLabel( const QString & _txt )
|
||||
{
|
||||
if( m_label == NULL )
|
||||
{
|
||||
m_label = new QLabel( _txt, this );
|
||||
m_label->setFont( pointSize<6>( m_label->font() ) );
|
||||
m_label->setGeometry( 0, y() + height(),
|
||||
QFontMetrics( m_label->font() ).width( _txt ), 7 );
|
||||
setFixedSize( tMax( width(), m_label->width() ),
|
||||
height() + m_label->height() );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_label->setText( _txt );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void lcdSpinBox::mousePressEvent( QMouseEvent * _me )
|
||||
{
|
||||
if( _me->button() == Qt::LeftButton && _me->y() < m_number->height() )
|
||||
{
|
||||
m_origMousePos = _me->globalPos();
|
||||
QApplication::setOverrideCursor( Qt::BlankCursor );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void lcdSpinBox::mouseMoveEvent( QMouseEvent * _me )
|
||||
{
|
||||
if( _me->modifiers() == Qt::LeftButton )
|
||||
{
|
||||
int dy = _me->globalY() - m_origMousePos.y();
|
||||
if( dy > 1 || dy < -1 )
|
||||
{
|
||||
setValue( value() - dy / 2 * m_step );
|
||||
emit valueChanged( value() );
|
||||
QCursor::setPos( m_origMousePos );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void lcdSpinBox::mouseReleaseEvent( QMouseEvent * _me )
|
||||
{
|
||||
QCursor::setPos( m_origMousePos );
|
||||
QApplication::restoreOverrideCursor();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void lcdSpinBox::wheelEvent( QWheelEvent * _we )
|
||||
{
|
||||
setValue( value() + _we->delta() / 120 * m_step );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#include "lcd_spinbox.moc"
|
||||
|
||||
130
src/widgets/led_checkbox.cpp
Normal file
130
src/widgets/led_checkbox.cpp
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* led_checkbox.cpp - class ledCheckBox, an improved QCheckBox
|
||||
*
|
||||
* 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 <QPaintEvent>
|
||||
#include <QFontMetrics>
|
||||
#include <QPainter>
|
||||
|
||||
#else
|
||||
|
||||
#include <qfontmetrics.h>
|
||||
#include <qpainter.h>
|
||||
|
||||
#define setChecked setOn
|
||||
#define isChecked isOn
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "led_checkbox.h"
|
||||
#include "embed.h"
|
||||
#include "templates.h"
|
||||
#include "spc_bg_hndl_widget.h"
|
||||
|
||||
|
||||
static const QString names[ledCheckBox::TOTAL_COLORS] =
|
||||
{
|
||||
"led_yellow", "led_green"
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
ledCheckBox::ledCheckBox( const QString & _text, QWidget * _parent,
|
||||
ledColors _color ) :
|
||||
QCheckBox( _text, _parent )
|
||||
{
|
||||
if( _color >= TOTAL_COLORS || _color < YELLOW )
|
||||
{
|
||||
_color = YELLOW;
|
||||
}
|
||||
m_ledOnPixmap = new QPixmap( embed::getIconPixmap( names[_color]
|
||||
#ifdef QT4
|
||||
.toAscii().constData()
|
||||
#endif
|
||||
) );
|
||||
m_ledOffPixmap = new QPixmap( embed::getIconPixmap( "led_off" ) );
|
||||
|
||||
#ifndef QT4
|
||||
setBackgroundMode( Qt::NoBackground );
|
||||
#endif
|
||||
|
||||
setFont( pointSize<7>( font() ) );
|
||||
setFixedSize( m_ledOffPixmap->width() + 6 +
|
||||
QFontMetrics( font() ).width( text() ),
|
||||
m_ledOffPixmap->height() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
ledCheckBox::~ledCheckBox()
|
||||
{
|
||||
delete m_ledOnPixmap;
|
||||
delete m_ledOffPixmap;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void ledCheckBox::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.drawPixmap( 0, 0, specialBgHandlingWidget::getBackground( this ) );
|
||||
|
||||
#ifdef QT4
|
||||
if( checkState() == Qt::Checked )
|
||||
#else
|
||||
if( state() == On )
|
||||
#endif
|
||||
{
|
||||
p.drawPixmap( 0, 0, *m_ledOnPixmap );
|
||||
}
|
||||
else
|
||||
{
|
||||
p.drawPixmap( 0, 0, *m_ledOffPixmap );
|
||||
}
|
||||
|
||||
p.drawText( m_ledOffPixmap->width() + 2, 10, text() );
|
||||
|
||||
#ifndef QT4
|
||||
// and blit all the drawn stuff on the screen...
|
||||
bitBlt( this, rect().topLeft(), &draw_pm );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#undef setChecked
|
||||
#undef isChecked
|
||||
|
||||
143
src/widgets/nstate_button.cpp
Normal file
143
src/widgets/nstate_button.cpp
Normal file
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* nstate_button.cpp - implementation of n-state-button
|
||||
*
|
||||
* 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 "nstate_button.h"
|
||||
#include "embed.h"
|
||||
#include "tooltip.h"
|
||||
|
||||
|
||||
|
||||
nStateButton::nStateButton( QWidget * _parent ) :
|
||||
QWidget( _parent ),
|
||||
m_generalToolTip( "" ),
|
||||
m_curState( -1 )
|
||||
{
|
||||
#ifndef QT4
|
||||
setBackgroundMode( Qt::NoBackground );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
nStateButton::~nStateButton()
|
||||
{
|
||||
while( m_states.size() )
|
||||
{
|
||||
delete m_states.first().first;
|
||||
m_states.erase( m_states.begin() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void nStateButton::addState( const QPixmap & _pm, const QString & _tooltip )
|
||||
{
|
||||
m_states.push_back( qMakePair( new QPixmap( _pm ), _tooltip ) );
|
||||
// first inserted pixmap?
|
||||
if( m_states.size() == 1 )
|
||||
{
|
||||
// then resize ourself
|
||||
resize( _pm.width(), _pm.height() );
|
||||
// and set state to first pixmap
|
||||
changeState( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void nStateButton::changeState( int _n )
|
||||
{
|
||||
if( _n >= 0 && _n < (int) m_states.size() )
|
||||
{
|
||||
m_curState = _n;
|
||||
|
||||
const QString & _tooltip =
|
||||
( m_states[m_curState].second != "" ) ?
|
||||
m_states[m_curState].second :
|
||||
m_generalToolTip;
|
||||
toolTip::add( this, _tooltip );
|
||||
|
||||
emit stateChanged( m_curState );
|
||||
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void nStateButton::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
|
||||
|
||||
if( m_curState >= 0 && m_curState < (int) m_states.size() )
|
||||
{
|
||||
p.drawPixmap( 0, 0, *m_states[m_curState].first );
|
||||
}
|
||||
#ifndef QT4
|
||||
// and blit all the drawn stuff on the screen...
|
||||
bitBlt( this, rect().topLeft(), &draw_pm );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void nStateButton::mousePressEvent( QMouseEvent * _me )
|
||||
{
|
||||
if( _me->button() == Qt::LeftButton && m_states.size() )
|
||||
{
|
||||
changeState( ( ++m_curState ) % m_states.size() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#include "nstate_button.moc"
|
||||
|
||||
175
src/widgets/pixmap_button.cpp
Normal file
175
src/widgets/pixmap_button.cpp
Normal file
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* pixmap_button.cpp - implementation of pixmap-button (often used as "themed"
|
||||
* checkboxes/radiobuttons etc)
|
||||
*
|
||||
* 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 "pixmap_button.h"
|
||||
#include "embed.h"
|
||||
|
||||
|
||||
|
||||
pixmapButton::pixmapButton( QWidget * _parent ) :
|
||||
QPushButton( _parent ),
|
||||
m_activePixmap( NULL ),
|
||||
m_inactivePixmap( NULL ),
|
||||
m_bgPixmap( NULL )
|
||||
{
|
||||
setActiveGraphic( embed::getIconPixmap( "led_yellow" ) );
|
||||
setInactiveGraphic( embed::getIconPixmap( "led_off" ), FALSE );
|
||||
|
||||
#ifndef QT4
|
||||
setBackgroundMode( Qt::NoBackground );
|
||||
#endif
|
||||
|
||||
setCheckable( TRUE );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
pixmapButton::~pixmapButton()
|
||||
{
|
||||
delete m_activePixmap;
|
||||
delete m_inactivePixmap;
|
||||
delete m_bgPixmap;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void pixmapButton::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
|
||||
|
||||
if( m_bgPixmap != NULL )
|
||||
{
|
||||
p.drawPixmap( 0, 0, *m_bgPixmap );
|
||||
}
|
||||
|
||||
#ifdef QT4
|
||||
if( isChecked() )
|
||||
#else
|
||||
if( isOn() )
|
||||
#endif
|
||||
{
|
||||
if( m_activePixmap != NULL )
|
||||
{
|
||||
p.drawPixmap( 0, 0, *m_activePixmap );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( m_inactivePixmap != NULL )
|
||||
{
|
||||
p.drawPixmap( 0, 0, *m_inactivePixmap );
|
||||
}
|
||||
}
|
||||
#ifndef QT4
|
||||
// and blit all the drawn stuff on the screen...
|
||||
bitBlt( this, rect().topLeft(), &draw_pm );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void pixmapButton::mousePressEvent( QMouseEvent * _me)
|
||||
{
|
||||
if( _me->button() == Qt::RightButton )
|
||||
{
|
||||
emit( clickedRight() );
|
||||
}
|
||||
else
|
||||
{
|
||||
QPushButton::mousePressEvent( _me );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void pixmapButton::mouseDoubleClickEvent( QMouseEvent * )
|
||||
{
|
||||
emit doubleClicked();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void pixmapButton::setActiveGraphic( const QPixmap & _pm )
|
||||
{
|
||||
delete m_activePixmap;
|
||||
|
||||
m_activePixmap = new QPixmap( _pm );
|
||||
resize( m_activePixmap->width(), m_activePixmap->height() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void pixmapButton::setInactiveGraphic( const QPixmap & _pm, bool _update )
|
||||
{
|
||||
delete m_inactivePixmap;
|
||||
|
||||
m_inactivePixmap = new QPixmap( _pm );
|
||||
if( _update )
|
||||
{
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void pixmapButton::setBgGraphic( const QPixmap & _pm )
|
||||
{
|
||||
delete m_bgPixmap;
|
||||
|
||||
m_bgPixmap = new QPixmap( _pm );
|
||||
}
|
||||
|
||||
|
||||
|
||||
#include "pixmap_button.moc"
|
||||
|
||||
571
src/widgets/project_notes.cpp
Normal file
571
src/widgets/project_notes.cpp
Normal file
@@ -0,0 +1,571 @@
|
||||
/*
|
||||
* project_notes.h - header for project-notes-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 <QTextEdit>
|
||||
#include <QLineEdit>
|
||||
#include <QAction>
|
||||
#include <QToolBar>
|
||||
#include <QFontDatabase>
|
||||
#include <QComboBox>
|
||||
#include <QColorDialog>
|
||||
|
||||
#else
|
||||
|
||||
#include <qdom.h>
|
||||
#include <qapplication.h>
|
||||
#include <qtextedit.h>
|
||||
#include <qaction.h>
|
||||
#include <qlineedit.h>
|
||||
#include <qtoolbar.h>
|
||||
#include <qfontdatabase.h>
|
||||
#include <qcombobox.h>
|
||||
#include <qcolordialog.h>
|
||||
|
||||
#define isChecked isOn
|
||||
#define setChecked setOn
|
||||
#define setFontWeight setBold
|
||||
#define setFontUnderline setUnderline
|
||||
#define setFontItalic setItalic
|
||||
#define setFontFamily setFamily
|
||||
#define setFontPointSize setPointSize
|
||||
#define setTextColor setColor
|
||||
#define textColor color
|
||||
#define setHtml setText
|
||||
#define toHtml text
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "project_notes.h"
|
||||
#include "embed.h"
|
||||
#include "lmms_main_win.h"
|
||||
#include "song_editor.h"
|
||||
|
||||
|
||||
|
||||
projectNotes::projectNotes() :
|
||||
QMainWindow( lmmsMainWin::inst()->workspace()
|
||||
#ifndef QT4
|
||||
, 0, Qt::WStyle_Title
|
||||
#endif
|
||||
)
|
||||
{
|
||||
#ifdef QT4
|
||||
lmmsMainWin::inst()->workspace()->addWindow( this );
|
||||
#endif
|
||||
|
||||
m_edit = new QTextEdit( this );
|
||||
#ifdef QT4
|
||||
QPalette pal;
|
||||
pal.setColor( m_edit->backgroundRole(), QColor( 64, 64, 64 ) );
|
||||
m_edit->setPalette( pal );
|
||||
#else
|
||||
m_edit->setTextFormat( RichText );
|
||||
m_edit->setPaletteBackgroundColor( QColor( 64, 64, 64 ) );
|
||||
#endif
|
||||
clear();
|
||||
|
||||
connect( m_edit, SIGNAL( currentFontChanged( const QFont & ) ),
|
||||
this, SLOT( fontChanged( const QFont & ) ) );
|
||||
connect( m_edit, SIGNAL( currentColorChanged( const QColor & ) ),
|
||||
this, SLOT( colorChanged( const QColor & ) ) );
|
||||
connect( m_edit, SIGNAL( currentAlignmentChanged( int ) ),
|
||||
this, SLOT( alignmentChanged( int ) ) );
|
||||
connect( m_edit, SIGNAL( textChanged() ),
|
||||
songEditor::inst(), SLOT( setModified() ) );
|
||||
|
||||
setupActions();
|
||||
|
||||
setCentralWidget( m_edit );
|
||||
setWindowTitle( tr( "Project notes" ) );
|
||||
setWindowIcon( embed::getIconPixmap( "project_notes" ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void projectNotes::clear( void )
|
||||
{
|
||||
m_edit->setHtml( tr( "Put down your project notes here." ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void projectNotes::setupActions()
|
||||
{
|
||||
QToolBar * tb = new QToolBar( tr( "Edit Actions" ), this );
|
||||
QAction * a;
|
||||
|
||||
// changes between qt3's toolbar-system and this of qt4 are too
|
||||
// big, so we completely implement two versions
|
||||
#ifdef QT4
|
||||
a = new QAction( embed::getIconPixmap( "edit_undo" ), tr( "&Undo" ),
|
||||
tb );
|
||||
a->setShortcut( tr( "Ctrl+Z" ) );
|
||||
connect( a, SIGNAL( activated() ), m_edit, SLOT( undo() ) );
|
||||
|
||||
a = new QAction( embed::getIconPixmap( "edit_redo" ), tr( "&Redo" ),
|
||||
tb );
|
||||
a->setShortcut( tr( "Ctrl+Y" ) );
|
||||
connect( a, SIGNAL( activated() ), m_edit, SLOT( redo() ) );
|
||||
|
||||
a = new QAction( embed::getIconPixmap( "edit_copy" ), tr( "&Copy" ),
|
||||
tb );
|
||||
a->setShortcut( tr( "Ctrl+C" ) );
|
||||
connect( a, SIGNAL( activated() ), m_edit, SLOT( copy() ) );
|
||||
|
||||
a = new QAction( embed::getIconPixmap( "edit_cut" ), tr( "Cu&t" ),
|
||||
tb );
|
||||
a->setShortcut( tr( "Ctrl+X" ) );
|
||||
connect( a, SIGNAL( activated() ), m_edit, SLOT( cut() ) );
|
||||
|
||||
a = new QAction( embed::getIconPixmap( "edit_paste" ), tr( "&Paste" ),
|
||||
tb );
|
||||
a->setShortcut( tr( "Ctrl+V" ) );
|
||||
connect( a, SIGNAL( activated() ), m_edit, SLOT( paste() ) );
|
||||
|
||||
|
||||
tb = new QToolBar( tr( "Format Actions" ), this );
|
||||
|
||||
m_comboFont = new QComboBox( tb );
|
||||
m_comboFont->setEditable( TRUE );
|
||||
QFontDatabase db;
|
||||
m_comboFont->addItems( db.families() );
|
||||
connect( m_comboFont, SIGNAL( activated( const QString & ) ),
|
||||
m_edit, SLOT( setFontFamily( const QString & ) ) );
|
||||
m_comboFont->lineEdit()->setText( QApplication::font().family() );
|
||||
|
||||
m_comboSize = new QComboBox( tb );
|
||||
m_comboSize->setEditable( TRUE );
|
||||
vlist<int> sizes = db.standardSizes();
|
||||
vlist<int>::Iterator it = sizes.begin();
|
||||
for ( ; it != sizes.end(); ++it )
|
||||
{
|
||||
m_comboSize->addItem( QString::number( *it ) );
|
||||
}
|
||||
connect( m_comboSize, SIGNAL( activated( const QString & ) ),
|
||||
this, SLOT( textSize( const QString & ) ) );
|
||||
m_comboSize->lineEdit()->setText( QString::number(
|
||||
QApplication::font().pointSize() ) );
|
||||
|
||||
m_actionTextBold = new QAction( embed::getIconPixmap( "text_bold" ),
|
||||
tr( "&Bold" ), tb );
|
||||
m_actionTextBold->setShortcut( tr( "Ctrl+B" ) );
|
||||
connect( m_actionTextBold, SIGNAL( activated() ), this,
|
||||
SLOT( textBold() ) );
|
||||
|
||||
m_actionTextItalic = new QAction( embed::getIconPixmap( "text_italic" ),
|
||||
tr( "&Italic" ), tb );
|
||||
m_actionTextItalic->setShortcut( tr( "Ctrl+I" ) );
|
||||
connect( m_actionTextItalic, SIGNAL( activated() ), this,
|
||||
SLOT( textItalic() ) );
|
||||
|
||||
m_actionTextUnderline = new QAction( embed::getIconPixmap(
|
||||
"text_under" ),
|
||||
tr( "&Underline" ), tb );
|
||||
m_actionTextUnderline->setShortcut( tr( "Ctrl+U" ) );
|
||||
connect( m_actionTextUnderline, SIGNAL( activated() ), this,
|
||||
SLOT( textUnderline() ) );
|
||||
|
||||
|
||||
QActionGroup * grp = new QActionGroup( tb );
|
||||
connect( grp, SIGNAL( selected( QAction* ) ), this,
|
||||
SLOT( textAlign( QAction* ) ) );
|
||||
|
||||
m_actionAlignLeft = new QAction( embed::getIconPixmap( "text_left" ),
|
||||
tr( "&Left" ), grp );
|
||||
m_actionAlignLeft->setShortcut( tr( "Ctrl+L" ) );
|
||||
|
||||
m_actionAlignCenter = new QAction( embed::getIconPixmap(
|
||||
"text_center" ),
|
||||
tr( "C&enter" ), grp );
|
||||
m_actionAlignCenter->setShortcut( tr( "Ctrl+E" ) );
|
||||
|
||||
m_actionAlignRight = new QAction( embed::getIconPixmap( "text_right" ),
|
||||
tr( "&Right" ), grp );
|
||||
m_actionAlignRight->setShortcut( tr( "Ctrl+R" ) );
|
||||
|
||||
m_actionAlignJustify = new QAction( embed::getIconPixmap(
|
||||
"text_block" ),
|
||||
tr( "&Justify" ), grp );
|
||||
m_actionAlignJustify->setShortcut( tr( "Ctrl+J" ) );
|
||||
|
||||
|
||||
QPixmap pix( 16, 16 );
|
||||
pix.fill( Qt::black );
|
||||
m_actionTextColor = new QAction( pix, tr( "&Color..." ), tb );
|
||||
connect( m_actionTextColor, SIGNAL( activated() ), this,
|
||||
SLOT( textColor() ) );
|
||||
|
||||
#else
|
||||
#if QT_VERSION >= 0x030100
|
||||
a = new QAction(
|
||||
#if QT_VERSION < 0x030200
|
||||
"",
|
||||
#endif
|
||||
embed::getIconPixmap( "edit_undo" ), tr( "&Undo" ),
|
||||
CTRL + Key_Z, this );
|
||||
connect( a, SIGNAL( activated() ), m_edit, SLOT( undo() ) );
|
||||
a->addTo( tb );
|
||||
|
||||
a = new QAction(
|
||||
#if QT_VERSION < 0x030200
|
||||
"",
|
||||
#endif
|
||||
embed::getIconPixmap( "edit_redo" ), tr( "&Redo" ),
|
||||
CTRL + Key_Y, this );
|
||||
connect( a, SIGNAL( activated() ), m_edit, SLOT( redo() ) );
|
||||
a->addTo( tb );
|
||||
|
||||
a = new QAction(
|
||||
#if QT_VERSION < 0x030200
|
||||
"",
|
||||
#endif
|
||||
embed::getIconPixmap( "edit_copy" ), tr( "&Copy" ),
|
||||
CTRL + Key_C, this );
|
||||
connect( a, SIGNAL( activated() ), m_edit, SLOT( copy() ) );
|
||||
a->addTo( tb );
|
||||
|
||||
a = new QAction(
|
||||
#if QT_VERSION < 0x030200
|
||||
"",
|
||||
#endif
|
||||
embed::getIconPixmap( "edit_cut" ), tr( "Cu&t" ),
|
||||
CTRL + Key_X, this );
|
||||
connect( a, SIGNAL( activated() ), m_edit, SLOT( cut() ) );
|
||||
a->addTo( tb );
|
||||
|
||||
a = new QAction(
|
||||
#if QT_VERSION < 0x030200
|
||||
"",
|
||||
#endif
|
||||
embed::getIconPixmap( "edit_paste" ), tr( "&Paste" ),
|
||||
CTRL + Key_V, this );
|
||||
connect( a, SIGNAL( activated() ), m_edit, SLOT( paste() ) );
|
||||
a->addTo( tb );
|
||||
|
||||
|
||||
tb = new QToolBar( this );
|
||||
tb->setLabel( tr( "Format Actions" ) );
|
||||
|
||||
m_comboFont = new QComboBox( TRUE, tb );
|
||||
QFontDatabase db;
|
||||
m_comboFont->insertStringList( db.families() );
|
||||
connect( m_comboFont, SIGNAL( activated( const QString & ) ),
|
||||
m_edit, SLOT( setFamily( const QString & ) ) );
|
||||
m_comboFont->lineEdit()->setText( QApplication::font().family() );
|
||||
|
||||
m_comboSize = new QComboBox( TRUE, tb );
|
||||
vlist<int> sizes = db.standardSizes();
|
||||
vlist<int>::Iterator it = sizes.begin();
|
||||
for ( ; it != sizes.end(); ++it )
|
||||
{
|
||||
m_comboSize->insertItem( QString::number( *it ) );
|
||||
}
|
||||
connect( m_comboSize, SIGNAL( activated( const QString & ) ),
|
||||
this, SLOT( textSize( const QString & ) ) );
|
||||
m_comboSize->lineEdit()->setText( QString::number(
|
||||
QApplication::font().pointSize() ) );
|
||||
|
||||
m_actionTextBold = new QAction(
|
||||
#if QT_VERSION < 0x030200
|
||||
"",
|
||||
#endif
|
||||
embed::getIconPixmap( "text_bold" ),
|
||||
tr( "&Bold" ), CTRL + Key_B, this );
|
||||
connect( m_actionTextBold, SIGNAL( activated() ), this,
|
||||
SLOT( textBold() ) );
|
||||
m_actionTextBold->addTo( tb );
|
||||
m_actionTextBold->setToggleAction( TRUE );
|
||||
|
||||
m_actionTextItalic = new QAction(
|
||||
#if QT_VERSION < 0x030200
|
||||
"",
|
||||
#endif
|
||||
embed::getIconPixmap( "text_italic" ),
|
||||
tr( "&Italic" ), CTRL + Key_I, this );
|
||||
connect( m_actionTextItalic, SIGNAL( activated() ), this,
|
||||
SLOT( textItalic() ) );
|
||||
m_actionTextItalic->addTo( tb );
|
||||
m_actionTextItalic->setToggleAction( TRUE );
|
||||
|
||||
m_actionTextUnderline = new QAction(
|
||||
#if QT_VERSION < 0x030200
|
||||
"",
|
||||
#endif
|
||||
embed::getIconPixmap(
|
||||
"text_under" ),
|
||||
tr( "&Underline" ),
|
||||
CTRL + Key_U, this );
|
||||
connect( m_actionTextUnderline, SIGNAL( activated() ), this,
|
||||
SLOT( textUnderline() ) );
|
||||
m_actionTextUnderline->addTo( tb );
|
||||
m_actionTextUnderline->setToggleAction( TRUE );
|
||||
|
||||
QActionGroup * grp = new QActionGroup( this );
|
||||
connect( grp, SIGNAL( selected( QAction* ) ), this,
|
||||
SLOT( textAlign( QAction* ) ) );
|
||||
|
||||
m_actionAlignLeft = new QAction(
|
||||
#if QT_VERSION < 0x030200
|
||||
"",
|
||||
#endif
|
||||
embed::getIconPixmap( "text_left" ),
|
||||
tr( "&Left" ), CTRL + Key_L,
|
||||
grp );
|
||||
m_actionAlignLeft->setToggleAction( TRUE );
|
||||
m_actionAlignCenter = new QAction(
|
||||
#if QT_VERSION < 0x030200
|
||||
"",
|
||||
#endif
|
||||
embed::getIconPixmap(
|
||||
"text_center" ),
|
||||
tr( "C&enter" ), CTRL + Key_E,
|
||||
grp );
|
||||
m_actionAlignCenter->setToggleAction( TRUE );
|
||||
|
||||
m_actionAlignRight = new QAction(
|
||||
#if QT_VERSION < 0x030200
|
||||
"",
|
||||
#endif
|
||||
embed::getIconPixmap( "text_right" ),
|
||||
tr( "&Right" ), CTRL + Key_R,
|
||||
grp );
|
||||
m_actionAlignRight->setToggleAction( TRUE );
|
||||
|
||||
m_actionAlignJustify = new QAction(
|
||||
#if QT_VERSION < 0x030200
|
||||
"",
|
||||
#endif
|
||||
embed::getIconPixmap(
|
||||
"text_block" ),
|
||||
tr( "&Justify" ), CTRL + Key_J,
|
||||
grp );
|
||||
m_actionAlignJustify->setToggleAction( TRUE );
|
||||
|
||||
grp->addTo( tb );
|
||||
|
||||
|
||||
QPixmap pix( 16, 16 );
|
||||
pix.fill( Qt::black );
|
||||
m_actionTextColor = new QAction(
|
||||
#if QT_VERSION < 0x030200
|
||||
"",
|
||||
#endif
|
||||
pix, tr( "&Color..." ), 0, this );
|
||||
connect( m_actionTextColor, SIGNAL( activated() ), this,
|
||||
SLOT( textColor() ) );
|
||||
m_actionTextColor->addTo( tb );
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void projectNotes::textBold()
|
||||
{
|
||||
m_edit->setFontWeight( m_actionTextBold->isChecked() );
|
||||
songEditor::inst()->setModified();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void projectNotes::textUnderline()
|
||||
{
|
||||
m_edit->setFontUnderline( m_actionTextUnderline->isChecked() );
|
||||
songEditor::inst()->setModified();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void projectNotes::textItalic()
|
||||
{
|
||||
m_edit->setFontItalic( m_actionTextItalic->isChecked() );
|
||||
songEditor::inst()->setModified();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void projectNotes::textFamily( const QString & _f )
|
||||
{
|
||||
m_edit->setFontFamily( _f );
|
||||
m_edit->viewport()->setFocus();
|
||||
songEditor::inst()->setModified();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void projectNotes::textSize( const QString & _p )
|
||||
{
|
||||
m_edit->setFontPointSize( _p.toInt() );
|
||||
m_edit->viewport()->setFocus();
|
||||
songEditor::inst()->setModified();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void projectNotes::textColor()
|
||||
{
|
||||
QColor col = QColorDialog::getColor( m_edit->textColor(), this );
|
||||
if ( !col.isValid() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_edit->setTextColor( col );
|
||||
QPixmap pix( 16, 16 );
|
||||
pix.fill( Qt::black );
|
||||
#ifdef QT4
|
||||
m_actionTextColor->setIcon( pix );
|
||||
#else
|
||||
m_actionTextColor->setIconSet( pix );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void projectNotes::textAlign( QAction * _a )
|
||||
{
|
||||
if( _a == m_actionAlignLeft )
|
||||
{
|
||||
m_edit->setAlignment( Qt::AlignLeft );
|
||||
}
|
||||
else if( _a == m_actionAlignCenter )
|
||||
{
|
||||
m_edit->setAlignment( Qt::AlignHCenter );
|
||||
}
|
||||
else if( _a == m_actionAlignRight )
|
||||
{
|
||||
m_edit->setAlignment( Qt::AlignRight );
|
||||
}
|
||||
else if( _a == m_actionAlignJustify )
|
||||
{
|
||||
m_edit->setAlignment( Qt::AlignJustify );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void projectNotes::fontChanged( const QFont & _f )
|
||||
{
|
||||
m_comboFont->lineEdit()->setText( _f.family() );
|
||||
m_comboSize->lineEdit()->setText( QString::number( _f.pointSize() ) );
|
||||
m_actionTextBold->setChecked( _f.bold() );
|
||||
m_actionTextItalic->setChecked( _f.italic() );
|
||||
m_actionTextUnderline->setChecked( _f.underline() );
|
||||
songEditor::inst()->setModified();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void projectNotes::colorChanged( const QColor & _c )
|
||||
{
|
||||
QPixmap pix( 16, 16 );
|
||||
pix.fill( _c );
|
||||
#ifdef QT4
|
||||
m_actionTextColor->setIcon( pix );
|
||||
#else
|
||||
m_actionTextColor->setIconSet( pix );
|
||||
#endif
|
||||
songEditor::inst()->setModified();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void projectNotes::alignmentChanged( int _a )
|
||||
{
|
||||
if (
|
||||
#ifndef QT4
|
||||
( _a == Qt::AlignAuto ) ||
|
||||
#endif
|
||||
( _a & Qt::AlignLeft ) )
|
||||
{
|
||||
m_actionAlignLeft->setChecked( TRUE );
|
||||
}
|
||||
else if ( ( _a & Qt::AlignHCenter ) )
|
||||
{
|
||||
m_actionAlignCenter->setChecked( TRUE );
|
||||
}
|
||||
else if ( ( _a & Qt::AlignRight ) )
|
||||
{
|
||||
m_actionAlignRight->setChecked( TRUE );
|
||||
}
|
||||
else if ( ( _a & Qt::AlignJustify ) )
|
||||
{
|
||||
m_actionAlignJustify->setChecked( TRUE );
|
||||
}
|
||||
songEditor::inst()->setModified();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void projectNotes::saveSettings( QDomDocument & _doc, QDomElement & _parent )
|
||||
{
|
||||
QDomElement pn_de = _doc.createElement( nodeName() );
|
||||
QDomCDATASection ds = _doc.createCDATASection( m_edit->toHtml() );
|
||||
pn_de.appendChild( ds );
|
||||
_parent.appendChild( pn_de );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void projectNotes::loadSettings( const QDomElement & _this )
|
||||
{
|
||||
m_edit->setHtml( _this.text() );
|
||||
}
|
||||
|
||||
|
||||
#include "project_notes.moc"
|
||||
|
||||
|
||||
|
||||
#undef isChecked
|
||||
#undef setChecked
|
||||
#undef setFontWeight
|
||||
#undef setFontUnderline
|
||||
#undef setFontItalic
|
||||
#undef setFontFamily
|
||||
#undef setFontPointSize
|
||||
#undef textColor
|
||||
#undef setTextColor
|
||||
#undef setHtml
|
||||
#undef toHtml
|
||||
|
||||
89
src/widgets/rename_dialog.cpp
Normal file
89
src/widgets/rename_dialog.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* rename_dialog.cpp - implementation of dialog for renaming something
|
||||
*
|
||||
* 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 <QLineEdit>
|
||||
#include <QKeyEvent>
|
||||
|
||||
#else
|
||||
|
||||
#include <qlineedit.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "rename_dialog.h"
|
||||
|
||||
|
||||
|
||||
renameDialog::renameDialog( QString & _string ) :
|
||||
QDialog(),
|
||||
m_stringToEdit( _string ),
|
||||
m_originalString( _string )
|
||||
{
|
||||
setWindowTitle( tr("Rename...") );
|
||||
m_stringLE = new QLineEdit( this );
|
||||
m_stringLE->setText( _string );
|
||||
m_stringLE->setGeometry ( 10, 5, 220, 20 );
|
||||
connect( m_stringLE, SIGNAL( textChanged( const QString & ) ), this,
|
||||
SLOT( textChanged( const QString & ) ) );
|
||||
connect( m_stringLE, SIGNAL( returnPressed() ), this,
|
||||
SLOT( accept() ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
renameDialog::~renameDialog()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void renameDialog::keyPressEvent( QKeyEvent * _ke )
|
||||
{
|
||||
if( _ke->key() == Qt::Key_Escape )
|
||||
{
|
||||
m_stringLE->setText( m_originalString );
|
||||
accept();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void renameDialog::textChanged( const QString & _new_string )
|
||||
{
|
||||
m_stringToEdit = _new_string;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#include "rename_dialog.moc"
|
||||
|
||||
123
src/widgets/side_bar_widget.cpp
Normal file
123
src/widgets/side_bar_widget.cpp
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* side_bar_widget.cpp - implementation of base-widget for side-bar
|
||||
*
|
||||
* 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 <QFontMetrics>
|
||||
|
||||
#else
|
||||
|
||||
#include <qapplication.h>
|
||||
#include <qpainter.h>
|
||||
#include <qfontmetrics.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "side_bar_widget.h"
|
||||
#include "types.h"
|
||||
#include "templates.h"
|
||||
|
||||
|
||||
|
||||
sideBarWidget::sideBarWidget( const QString & _title, const QPixmap & _icon,
|
||||
QWidget * _parent ) :
|
||||
QWidget( _parent ),
|
||||
m_title( _title ),
|
||||
m_icon( _icon )
|
||||
{
|
||||
m_contents = new QWidget( this );
|
||||
m_layout = new QVBoxLayout( m_contents );
|
||||
m_layout->setSpacing( 5 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
sideBarWidget::~sideBarWidget()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void sideBarWidget::paintEvent( QPaintEvent * )
|
||||
{
|
||||
const Uint16 TITLE_FONT_HEIGHT = 16;
|
||||
|
||||
#ifdef QT4
|
||||
QPainter p( this );
|
||||
p.fillRect( 0, 0, width(), 27, palette().highlight().color() );
|
||||
#else
|
||||
QPixmap draw_pm( rect().size() );
|
||||
draw_pm.fill( QApplication::palette().color( QPalette::Normal,
|
||||
QColorGroup::Background ) );
|
||||
|
||||
QPainter p( &draw_pm, this );
|
||||
p.fillRect( 0, 0, width(), 27, QApplication::palette().color(
|
||||
QPalette::Normal,
|
||||
QColorGroup::Highlight ) );
|
||||
#endif
|
||||
|
||||
QFont f = p.font();
|
||||
f.setBold( TRUE );
|
||||
p.setFont( pointSize<TITLE_FONT_HEIGHT>( f ) );
|
||||
|
||||
#ifdef QT4
|
||||
p.setPen( palette().highlightedText().color() );
|
||||
#else
|
||||
p.setPen( QApplication::palette().color( QPalette::Normal,
|
||||
QColorGroup::HighlightedText ) );
|
||||
#endif
|
||||
const Uint16 tx = m_icon.width()+4;
|
||||
const Uint16 ty = 2+TITLE_FONT_HEIGHT;
|
||||
p.drawText( tx, ty, m_title );
|
||||
p.drawLine( tx, ty+4, width()-4, ty+4 );
|
||||
|
||||
p.drawPixmap( 2, 2, m_icon );
|
||||
|
||||
#ifndef QT4
|
||||
// and blit all drawn stuff on the screen...
|
||||
bitBlt( this, rect().topLeft(), &draw_pm );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
void sideBarWidget::resizeEvent( QResizeEvent * )
|
||||
{
|
||||
const Uint16 MARGIN = 6;
|
||||
m_contents->setGeometry( MARGIN, 40 + MARGIN, width() - MARGIN * 2,
|
||||
height() - MARGIN * 2 - 40 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
#include "side_bar.moc"
|
||||
#include "side_bar_widget.moc"
|
||||
|
||||
260
src/widgets/tab_bar.cpp
Normal file
260
src/widgets/tab_bar.cpp
Normal file
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
* tab_bar.cpp - implementation of tab-bar
|
||||
*
|
||||
* 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 "tab_bar.h"
|
||||
#include "tab_button.h"
|
||||
#include "templates.h"
|
||||
#include "tooltip.h"
|
||||
|
||||
#ifndef QT4
|
||||
|
||||
#define value data
|
||||
#define setChecked setOn
|
||||
#define isChecked isOn
|
||||
#define removeWidget remove
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
tabBar::tabBar( QWidget * _parent, QBoxLayout::Direction _dir ) :
|
||||
QWidget( _parent ),
|
||||
#ifdef QT4
|
||||
m_layout( new QBoxLayout( _dir, this ) ),
|
||||
#else
|
||||
m_layout( new QBoxLayout( this, _dir ) ),
|
||||
#endif
|
||||
m_exclusive( FALSE )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
tabBar::~tabBar()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
tabButton * tabBar::addTab( QWidget * _w, const QString & _text, int _id,
|
||||
bool _add_stretch, bool _text_is_tooltip )
|
||||
{
|
||||
// already tab with id?
|
||||
if( m_tabs.contains( _id ) )
|
||||
{
|
||||
// then remove it
|
||||
removeTab( _id );
|
||||
}
|
||||
QString caption = ( _text_is_tooltip ) ? "" : _text;
|
||||
// create tab-button
|
||||
tabButton * b = new tabButton( caption, _id, this );
|
||||
connect( b, SIGNAL( clicked( int ) ), this, SLOT( tabClicked( int ) ) );
|
||||
b->show();
|
||||
if( _text_is_tooltip )
|
||||
{
|
||||
toolTip::add( b, _text );
|
||||
}
|
||||
|
||||
// small workaround, because QBoxLayout::addWidget(...) doesn't
|
||||
// work properly, so we first have to remove all tabs from the
|
||||
// layout and them add them in the correct order
|
||||
QMap<int, QPair<tabButton *, QWidget *> >::iterator it;
|
||||
for( it = m_tabs.begin(); it != m_tabs.end(); ++it )
|
||||
{
|
||||
#if QT_VERSION >= 0x030100
|
||||
m_layout->removeWidget( it.value().first );
|
||||
#endif
|
||||
}
|
||||
m_tabs.insert( _id, qMakePair( b, _w ) );
|
||||
for( it = m_tabs.begin(); it != m_tabs.end(); ++it )
|
||||
{
|
||||
m_layout->addWidget( it.value().first );
|
||||
}
|
||||
|
||||
if( _add_stretch )
|
||||
{
|
||||
m_layout->addStretch();
|
||||
}
|
||||
|
||||
|
||||
// we assume, parent-widget is a widget acting as widget-stack so all
|
||||
// widgets have the same size and only the one on the top is visible
|
||||
_w->setFixedSize( _w->parentWidget()->size() );
|
||||
|
||||
b->setFont( pointSize<7>( b->font() ) );
|
||||
|
||||
return( b );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void tabBar::removeTab( int _id )
|
||||
{
|
||||
// find tab-button and delete it
|
||||
if( m_tabs.find( _id ) != m_tabs.end() )
|
||||
{
|
||||
delete m_tabs[_id].first;
|
||||
m_tabs.erase( m_tabs.find( _id ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void tabBar::setActiveTab( int _id )
|
||||
{
|
||||
setTabState( _id, TRUE );
|
||||
hideAll( _id );
|
||||
if( allHidden() )
|
||||
{
|
||||
emit allWidgetsHidden();
|
||||
}
|
||||
else
|
||||
{
|
||||
emit widgetShown();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int tabBar::activeTab( void )
|
||||
{
|
||||
QMap<int, QPair<tabButton *, QWidget *> >::iterator it;
|
||||
for( it = m_tabs.begin(); it != m_tabs.end(); ++it )
|
||||
{
|
||||
if( tabState( it.key() ) == TRUE )
|
||||
{
|
||||
return( it.key() );
|
||||
}
|
||||
}
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool tabBar::tabState( int _id )
|
||||
{
|
||||
if( m_tabs.find( _id ) == m_tabs.end() )
|
||||
{
|
||||
return( FALSE );
|
||||
}
|
||||
return( m_tabs[_id].first->isChecked() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void tabBar::setTabState( int _id, bool _checked )
|
||||
{
|
||||
if( m_tabs.find( _id ) != m_tabs.end() )
|
||||
{
|
||||
m_tabs[_id].first->setChecked( _checked );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void tabBar::hideAll( int _exception )
|
||||
{
|
||||
QMap<int, QPair<tabButton *, QWidget *> >::iterator it;
|
||||
for( it = m_tabs.begin(); it != m_tabs.end(); ++it )
|
||||
{
|
||||
if( it.key() != _exception )
|
||||
{
|
||||
setTabState( it.key(), FALSE );
|
||||
}
|
||||
it.value().second->hide();
|
||||
}
|
||||
if( m_tabs.find( _exception ) != m_tabs.end() )
|
||||
{
|
||||
if( tabState( _exception ) )
|
||||
{
|
||||
m_tabs[_exception].second->show();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tabs[_exception].second->hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void tabBar::tabClicked( int _id )
|
||||
{
|
||||
if( m_exclusive == TRUE && activeTab() == -1 )
|
||||
{
|
||||
setActiveTab( _id );
|
||||
}
|
||||
else
|
||||
{
|
||||
bool all_hidden_before = allHidden();
|
||||
// disable tabbar-buttons except the one clicked
|
||||
hideAll( _id );
|
||||
bool now_hidden = allHidden();
|
||||
if( all_hidden_before == TRUE && now_hidden == FALSE )
|
||||
{
|
||||
emit widgetShown();
|
||||
}
|
||||
else if( all_hidden_before == FALSE && now_hidden == TRUE )
|
||||
{
|
||||
emit allWidgetsHidden();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool tabBar::allHidden( void )
|
||||
{
|
||||
QMap<int, QPair<tabButton *, QWidget *> >::iterator it;
|
||||
for( it = m_tabs.begin(); it != m_tabs.end(); ++it )
|
||||
{
|
||||
if( !it.value().second->isHidden() )
|
||||
{
|
||||
return( FALSE );
|
||||
}
|
||||
}
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
|
||||
|
||||
#undef value
|
||||
#undef setChecked
|
||||
#undef isChecked
|
||||
#undef removeWidget
|
||||
|
||||
|
||||
#include "tab_bar.moc"
|
||||
#include "tab_button.moc"
|
||||
|
||||
177
src/widgets/tab_widget.cpp
Normal file
177
src/widgets/tab_widget.cpp
Normal file
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* tabwidget.cpp - tabwidget 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 "qt3support.h"
|
||||
|
||||
#ifdef QT4
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPixmap>
|
||||
#include <QMouseEvent>
|
||||
|
||||
#else
|
||||
|
||||
#include <qpainter.h>
|
||||
#include <qpixmap.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "tab_widget.h"
|
||||
#include "templates.h"
|
||||
|
||||
|
||||
|
||||
tabWidget::tabWidget( const QString & _caption, QWidget * _parent ) :
|
||||
QWidget( _parent ),
|
||||
m_curWidget( 0 ),
|
||||
m_caption( _caption )
|
||||
{
|
||||
setFont( pointSize<7>( font() ) );
|
||||
#ifdef QT4
|
||||
QPalette pal = palette();
|
||||
pal.setColor( QPalette::Background, QColor( 96, 96, 96 ) );
|
||||
setPalette( pal );
|
||||
#else
|
||||
setPaletteBackgroundColor( QColor( 96, 96, 96 ) );
|
||||
//setBackgroundMode( Qt::NoBackground );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
tabWidget::~tabWidget()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
void tabWidget::addTab( QWidget * _w, const QString & _name )
|
||||
{
|
||||
widgetDesc d = { _w, _name, fontMetrics().width( _name ) + 10 } ;
|
||||
m_widgets.push_back( d );
|
||||
// make sure new tab doesn't overlap current widget
|
||||
m_widgets[m_curWidget].w->raise();
|
||||
_w->setFixedSize( width() - 4, height() - 14 );
|
||||
_w->move( 2, 12 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void tabWidget::mousePressEvent( QMouseEvent * _me )
|
||||
{
|
||||
if( _me->y() > 1 && _me->y() < 13 )
|
||||
{
|
||||
int cx = 14 + fontMetrics().width( m_caption );
|
||||
for( widgetStack::iterator it = m_widgets.begin();
|
||||
it != m_widgets.end(); ++it )
|
||||
{
|
||||
if( _me->x() >= cx && _me->x() <= cx + it->nwidth )
|
||||
{
|
||||
it->w->raise();
|
||||
m_curWidget = it - m_widgets.begin();
|
||||
update();
|
||||
return;
|
||||
}
|
||||
cx += it->nwidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void tabWidget::resizeEvent( QResizeEvent * )
|
||||
{
|
||||
for( widgetStack::iterator it = m_widgets.begin();
|
||||
it != m_widgets.end(); ++it )
|
||||
{
|
||||
it->w->setFixedSize( width() - 4, height() - 14 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void tabWidget::paintEvent( QPaintEvent * _pe )
|
||||
{
|
||||
#ifdef QT4
|
||||
QPainter p( this );
|
||||
#else
|
||||
QPixmap pm( size() );
|
||||
pm.fill( QColor( 96, 96, 96 ) );
|
||||
|
||||
QPainter p( &pm );
|
||||
#endif
|
||||
|
||||
p.setPen( QColor( 64, 64, 64 ) );
|
||||
p.drawRect( 0, 0, width(), height() );
|
||||
|
||||
p.setPen( QColor( 160, 160, 160 ) );
|
||||
p.drawLine( width() - 1, 0, width() - 1, height() - 1 );
|
||||
p.drawLine( 0, height() - 1, width() - 1, height() - 1 );
|
||||
|
||||
p.setPen( QColor( 0, 0, 0 ) );
|
||||
p.drawRect( 1, 1, width() - 2, height() - 2 );
|
||||
|
||||
p.fillRect( 2, 2, width() - 4, 9, QColor( 30, 45, 60 ) );
|
||||
p.drawLine( 2, 11, width() - 3, 11 );
|
||||
|
||||
p.setPen( QColor( 255, 255, 255 ) );
|
||||
p.setFont( font() );
|
||||
p.drawText( 5, 10, m_caption );
|
||||
|
||||
int cx = 14 + fontMetrics().width( m_caption );
|
||||
|
||||
p.setFont( pointSize<6>( p.font() ) );
|
||||
|
||||
p.setPen( QColor( 160, 160, 160 ) );
|
||||
|
||||
for( widgetStack::iterator it = m_widgets.begin();
|
||||
it != m_widgets.end(); ++it )
|
||||
{
|
||||
if( it - m_widgets.begin() == m_curWidget )
|
||||
{
|
||||
p.setPen( QColor( 32, 48, 64 ) );
|
||||
p.fillRect( cx, 2, it->nwidth - 6, 9,
|
||||
QColor( 160, 160, 160 ) );
|
||||
}
|
||||
p.drawText( cx + 3, 9, it->name );
|
||||
p.setPen( QColor( 160, 160, 160 ) );
|
||||
cx += it->nwidth;
|
||||
}
|
||||
|
||||
#ifndef QT4
|
||||
bitBlt( this, rect().topLeft(), &pm );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#include "tab_widget.moc"
|
||||
|
||||
152
src/widgets/text_float.cpp
Normal file
152
src/widgets/text_float.cpp
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* text_float.cpp - class textFloat, a floating text-label
|
||||
*
|
||||
* 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 <QTimer>
|
||||
|
||||
#else
|
||||
|
||||
#include <qpainter.h>
|
||||
#include <qpixmap.h>
|
||||
#include <qtimer.h>
|
||||
|
||||
#define setParent reparent
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "text_float.h"
|
||||
#include "templates.h"
|
||||
|
||||
|
||||
|
||||
textFloat::textFloat( QWidget * _parent ) :
|
||||
QWidget( _parent
|
||||
#ifndef QT4
|
||||
, "textFloat", WStyle_Customize | WStyle_NoBorder | WStyle_StaysOnTop
|
||||
#endif
|
||||
),
|
||||
m_text( "" )
|
||||
{
|
||||
#ifndef QT4
|
||||
setBackgroundMode( Qt::NoBackground );
|
||||
#endif
|
||||
|
||||
reparent( parentWidget() );
|
||||
resize( 20, 20 );
|
||||
hide();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void textFloat::reparent( QWidget * _new_parent )
|
||||
{
|
||||
QPoint position = _new_parent->pos();
|
||||
|
||||
// Get position and reparent to either top level or dialog
|
||||
//
|
||||
while( _new_parent->parentWidget() && !_new_parent->isTopLevel()
|
||||
&&
|
||||
#ifdef QT4
|
||||
!_new_parent->windowType() == Qt::Dialog
|
||||
#else
|
||||
!_new_parent->isDialog()
|
||||
#endif
|
||||
)
|
||||
{
|
||||
_new_parent = _new_parent->parentWidget();
|
||||
position += _new_parent->pos();
|
||||
}
|
||||
|
||||
// Position this widget to the right of the parent
|
||||
//
|
||||
//move(pos + QPoint(parent->width() + 5, 5));
|
||||
|
||||
QWidget::setParent( _new_parent,
|
||||
#ifdef QT4
|
||||
Qt::FramelessWindowHint |
|
||||
Qt::WindowStaysOnTopHint );
|
||||
#else
|
||||
WStyle_Customize | WStyle_NoBorder |
|
||||
WStyle_StaysOnTop,
|
||||
position + QPoint( 20, 5 ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void textFloat::setVisibilityTimeOut( int _msecs )
|
||||
{
|
||||
QTimer::singleShot( _msecs, this, SLOT( hide() ) );
|
||||
show();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void textFloat::paintEvent( QPaintEvent * _pe )
|
||||
{
|
||||
#ifdef QT4
|
||||
QPainter p( this );
|
||||
#else
|
||||
QPixmap draw_pm( size() );
|
||||
QPainter p( &draw_pm );
|
||||
#endif
|
||||
p.setPen( QColor( 0, 0, 0 ) );
|
||||
p.setBrush( QColor( 255, 255, 255 ) );
|
||||
|
||||
p.setFont( pointSize<8>( p.font() ) );
|
||||
|
||||
QFontMetrics metrics( p.fontMetrics() );
|
||||
QRect textBound = metrics.boundingRect( m_text );
|
||||
|
||||
resize( textBound.width() + 5, textBound.height() + 5 );
|
||||
p.drawRect( rect() );
|
||||
|
||||
p.setPen( Qt::black );
|
||||
p.drawText( 2, 10, m_text );
|
||||
|
||||
#ifndef QT4
|
||||
bitBlt( this, rect().topLeft(), &draw_pm );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void textFloat::setText( const QString & _text )
|
||||
{
|
||||
m_text = _text;
|
||||
repaint();
|
||||
}
|
||||
|
||||
|
||||
#undef setParent
|
||||
|
||||
59
src/widgets/tooltip.cpp
Normal file
59
src/widgets/tooltip.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* tooltip.cpp - namespace toolTip, a tooltip-wrapper 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 "qt3support.h"
|
||||
|
||||
#ifdef QT4
|
||||
|
||||
#include <QToolTip>
|
||||
|
||||
#else
|
||||
|
||||
#include <qtooltip.h>
|
||||
|
||||
#endif
|
||||
|
||||
#include "tooltip.h"
|
||||
#include "config_mgr.h"
|
||||
|
||||
|
||||
void toolTip::add( QWidget * _w, const QString & _txt )
|
||||
{
|
||||
if( !configManager::inst()->value( "tooltips", "disabled" ).toInt() )
|
||||
{
|
||||
#ifdef QT4
|
||||
//_w->setToolTip( _txt );
|
||||
#else
|
||||
QToolTip::add( _w, _txt );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
void toolTip::remove( QWidget * _w )
|
||||
{
|
||||
QToolTip::remove( _w );
|
||||
}
|
||||
*/
|
||||
221
src/widgets/visualization_widget.cpp
Normal file
221
src/widgets/visualization_widget.cpp
Normal file
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* visualization_widget.cpp - widget for visualization of waves
|
||||
*
|
||||
* 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 <QPixmap>
|
||||
#include <QTimer>
|
||||
#include <QMouseEvent>
|
||||
|
||||
#else
|
||||
|
||||
#include <qpainter.h>
|
||||
#include <qpixmap.h>
|
||||
#include <qtimer.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "visualization_widget.h"
|
||||
#include "embed.h"
|
||||
#include "buffer_allocator.h"
|
||||
#include "templates.h"
|
||||
#include "tooltip.h"
|
||||
|
||||
|
||||
const int UPDATE_TIME = 1000 / 20; // 20 fps
|
||||
|
||||
|
||||
|
||||
visualizationWidget::visualizationWidget( const QPixmap & _bg, QWidget * _p,
|
||||
visualizationTypes _vtype ) :
|
||||
QWidget( _p ),
|
||||
s_background( _bg ),
|
||||
m_enabled( FALSE )
|
||||
{
|
||||
#ifndef QT4
|
||||
setBackgroundMode( Qt::NoBackground );
|
||||
#endif
|
||||
|
||||
const Uint32 frames = mixer::inst()->framesPerAudioBuffer();
|
||||
m_buffer = bufferAllocator::alloc<surroundSampleFrame>( frames );
|
||||
|
||||
for( Uint32 frame = 0; frame < frames; ++frame )
|
||||
{
|
||||
for( Uint8 chnl = 0; chnl < SURROUND_CHANNELS; ++chnl )
|
||||
{
|
||||
m_buffer[frame][chnl] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
setFixedSize( s_background.width(), s_background.height() );
|
||||
|
||||
|
||||
m_updateTimer = new QTimer( this );
|
||||
connect( m_updateTimer, SIGNAL( timeout() ), this, SLOT( update() ) );
|
||||
if( m_enabled )
|
||||
{
|
||||
m_updateTimer->start( UPDATE_TIME );
|
||||
}
|
||||
|
||||
connect( mixer::inst(), SIGNAL( nextAudioBuffer(
|
||||
const surroundSampleFrame *, Uint32 ) ),
|
||||
this, SLOT( setAudioBuffer(
|
||||
const surroundSampleFrame *, Uint32 ) ) );
|
||||
|
||||
toolTip::add( this, tr( "click to enable/disable visualization of "
|
||||
"master-output" ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
visualizationWidget::~visualizationWidget()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void visualizationWidget::setAudioBuffer( const surroundSampleFrame * _ab,
|
||||
Uint32 _frames )
|
||||
{
|
||||
if( m_enabled )
|
||||
{
|
||||
memcpy( m_buffer, *_ab, _frames * BYTES_PER_SURROUND_FRAME);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void visualizationWidget::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.drawPixmap( 0, 0, s_background );
|
||||
|
||||
if( m_enabled )
|
||||
{
|
||||
float master_output = mixer::inst()->masterOutput();
|
||||
Uint16 w = width()-4;
|
||||
float half_h = -( height() - 6 ) / 3.0 * master_output - 1;
|
||||
Uint16 x_base = 2;
|
||||
Uint16 y_base = height()/2 - 1;
|
||||
Uint16 old_y[DEFAULT_CHANNELS] = { y_base + (int)(
|
||||
m_buffer[0][0]*half_h ),
|
||||
y_base + (int)(
|
||||
m_buffer[0][1]*half_h )
|
||||
} ;
|
||||
|
||||
p.setClipRect( 2, 2, w, height()-4 );
|
||||
|
||||
float max_level = 0.0;
|
||||
|
||||
const Uint32 frames = mixer::inst()->framesPerAudioBuffer();
|
||||
|
||||
// analyse wave-stream for max-level
|
||||
for( Uint32 frame = 0; frame < frames; ++frame )
|
||||
{
|
||||
for( Uint8 chnl = 0; chnl < SURROUND_CHANNELS; ++chnl )
|
||||
{
|
||||
if( tAbs<float>( m_buffer[frame][chnl] ) >
|
||||
max_level )
|
||||
{
|
||||
max_level = tAbs<float>(
|
||||
m_buffer[frame][chnl] );
|
||||
}
|
||||
}
|
||||
}
|
||||
// and set color according to that...
|
||||
if( max_level * master_output < 0.9 )
|
||||
{
|
||||
p.setPen( QColor( 96, 255, 96 ) );
|
||||
}
|
||||
else if( max_level * master_output < 1.1 )
|
||||
{
|
||||
p.setPen( QColor( 255, 192, 64 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
p.setPen( QColor( 255, 64, 64 ) );
|
||||
}
|
||||
|
||||
// now draw all that stuff
|
||||
for( Uint32 frame = 0; frame < frames; ++frame )
|
||||
{
|
||||
for( Uint8 chnl = 0; chnl < DEFAULT_CHANNELS; ++chnl )
|
||||
{
|
||||
Uint16 cur_y = y_base +
|
||||
(Uint16)( m_buffer[frame][chnl] *
|
||||
half_h );
|
||||
Uint16 xp = x_base + frame * w / frames;
|
||||
p.drawLine( xp, old_y[chnl], xp, cur_y );
|
||||
old_y[chnl] = cur_y;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifndef QT4
|
||||
// and blit all drawn stuff on the screen...
|
||||
bitBlt( this, rect().topLeft(), &draw_pm );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void visualizationWidget::mousePressEvent( QMouseEvent * _me )
|
||||
{
|
||||
if( _me->button() == Qt::LeftButton )
|
||||
{
|
||||
m_enabled = !m_enabled;
|
||||
if( m_enabled )
|
||||
{
|
||||
m_updateTimer->start( UPDATE_TIME );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_updateTimer->stop();
|
||||
// we have to update (remove last waves),
|
||||
// because timer doesn't do that anymore
|
||||
update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#include <visualization_widget.moc>
|
||||
|
||||
Reference in New Issue
Block a user