Merge with 2.0-ongoing R3071.
git-svn-id: svn://localhost/ardour2/branches/3.0@3074 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
8aa9508c82
commit
859e9106e7
|
@ -31,6 +31,7 @@ opts.AddOptions(
|
|||
BoolOption('COREAUDIO', 'Compile with Apple\'s CoreAudio library', 0),
|
||||
BoolOption('GTKOSX', 'Compile for use with GTK-OSX, not GTK-X11', 0),
|
||||
BoolOption('NATIVE_OSX_KEYS', 'Build key bindings file that matches OS X conventions', 0),
|
||||
BoolOption('OLDFONTS', 'Old school font sizes', 0),
|
||||
BoolOption('DEBUG', 'Set to build with debugging information and no optimizations', 0),
|
||||
PathOption('DESTDIR', 'Set the intermediate install "prefix"', '/'),
|
||||
EnumOption('DIST_TARGET', 'Build target for cross compiling packagers', 'auto', allowed_values=('auto', 'i386', 'i686', 'x86_64', 'powerpc', 'tiger', 'panther', 'leopard', 'none' ), ignorecase=2),
|
||||
|
@ -538,7 +539,7 @@ if env['LV2']:
|
|||
else:
|
||||
print 'Building Ardour with LV2 support requires SLV2 >= 0.6.0'
|
||||
print 'WARNING: SLV2 not found, or too old. Ardour will be built without LV2 support.'
|
||||
print 'Until the 2.3 release, Ardour requires SLV2 out of SVN.'
|
||||
print 'Until the 2.4 release, Ardour requires SLV2 out of SVN.'
|
||||
print 'Testing would be very much appreciated! svn co http://svn.drobilla.net/lad/slv2'
|
||||
env['LV2'] = 0
|
||||
conf.Finish()
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
<Option name="plugins-stop-with-transport" value="no"/>
|
||||
<Option name="no-sw-monitoring" value="no"/>
|
||||
<Option name="stop-recording-on-xrun" value="no"/>
|
||||
<Option name="create-xrun-marker" value="yes"/>
|
||||
<Option name="stop-at-session-end" value="no"/>
|
||||
<Option name="auto-xfade" value="yes"/>
|
||||
<Option name="crossfades-active" value="1"/>
|
||||
|
|
|
@ -809,6 +809,8 @@ AudioRegionView::create_waves ()
|
|||
|
||||
ChanCount nchans = atv.get_diskstream()->n_channels();
|
||||
|
||||
cerr << "creating waves for " << _region->name() << " with wfd = " << wait_for_data << " and channels = " << nchans << endl;
|
||||
|
||||
/* in tmp_waves, set up null pointers for each channel so the vector is allocated */
|
||||
for (uint32_t n = 0; n < nchans.n_audio(); ++n) {
|
||||
tmp_waves.push_back (0);
|
||||
|
@ -822,15 +824,20 @@ AudioRegionView::create_waves ()
|
|||
|
||||
wave_caches.push_back (WaveView::create_cache ());
|
||||
|
||||
cerr << "\tchannel " << n << endl;
|
||||
|
||||
if (wait_for_data) {
|
||||
if (audio_region()->audio_source(n)->peaks_ready (bind (mem_fun(*this, &AudioRegionView::peaks_ready_handler), n), data_ready_connection)) {
|
||||
cerr << "\tData is ready\n";
|
||||
create_one_wave (n, true);
|
||||
} else {
|
||||
cerr << "\tdata is not ready\n";
|
||||
// we'll get a PeaksReady signal from the source in the future
|
||||
// and will call create_one_wave(n) then.
|
||||
}
|
||||
|
||||
} else {
|
||||
cerr << "\tdon't delay, display today!\n";
|
||||
create_one_wave (n, true);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,134 @@
|
|||
/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved.
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
|
||||
("Apple") in consideration of your agreement to the following terms, and your
|
||||
use, installation, modification or redistribution of this Apple software
|
||||
constitutes acceptance of these terms. If you do not agree with these terms,
|
||||
please do not use, install, modify or redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and subject
|
||||
to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
|
||||
copyrights in this original Apple software (the "Apple Software"), to use,
|
||||
reproduce, modify and redistribute the Apple Software, with or without
|
||||
modifications, in source and/or binary forms; provided that if you redistribute
|
||||
the Apple Software in its entirety and without modifications, you must retain
|
||||
this notice and the following text and disclaimers in all such redistributions of
|
||||
the Apple Software. Neither the name, trademarks, service marks or logos of
|
||||
Apple Computer, Inc. may be used to endorse or promote products derived from the
|
||||
Apple Software without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or implied,
|
||||
are granted by Apple herein, including but not limited to any patent rights that
|
||||
may be infringed by your derivative works or by other works in which the Apple
|
||||
Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
|
||||
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
|
||||
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
|
||||
COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
|
||||
OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
|
||||
(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*=============================================================================
|
||||
AUParamInfo.cpp
|
||||
|
||||
=============================================================================*/
|
||||
#include "AUParamInfo.h"
|
||||
#include "CAXException.h"
|
||||
|
||||
AUParamInfo::AUParamInfo (AudioUnit inAU,
|
||||
bool inIncludeExpert,
|
||||
bool inIncludeReadOnly,
|
||||
AudioUnitScope inScope,
|
||||
AudioUnitElement inElement)
|
||||
: mAU (inAU),
|
||||
mNumParams (0),
|
||||
mParamListID(NULL),
|
||||
mScope (inScope),
|
||||
mElement (inElement)
|
||||
{
|
||||
UInt32 size;
|
||||
OSStatus result = AudioUnitGetPropertyInfo(mAU, kAudioUnitProperty_ParameterList, inScope, mElement, &size, NULL);
|
||||
if (size == 0 || result) return;
|
||||
|
||||
int nparams = size / sizeof(AudioUnitPropertyID);
|
||||
mParamListID = new AudioUnitParameterID[nparams];
|
||||
|
||||
memset (mParamListID, 0xFF, size);
|
||||
|
||||
AudioUnitParameterID *paramList = new AudioUnitParameterID[nparams];
|
||||
|
||||
result = AudioUnitGetProperty(mAU, kAudioUnitProperty_ParameterList, mScope, mElement, paramList, &size);
|
||||
if (result) {
|
||||
delete [] mParamListID;
|
||||
delete [] paramList;
|
||||
mParamListID = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
ParameterMap params;
|
||||
for (int i = 0; i < nparams; ++i)
|
||||
{
|
||||
CAAUParameter auvp (mAU, paramList[i], mScope, mElement); // took out only using global scope in CAAUParameter creation
|
||||
const AudioUnitParameterInfo ¶mInfo = auvp.ParamInfo();
|
||||
|
||||
// don't include if parameter can't be read or written
|
||||
if (!(paramInfo.flags & kAudioUnitParameterFlag_IsWritable)
|
||||
&& !(paramInfo.flags & kAudioUnitParameterFlag_IsReadable))
|
||||
continue;
|
||||
|
||||
// only include if expert params wanted
|
||||
if (!inIncludeExpert && auvp.IsExpert())
|
||||
continue;
|
||||
|
||||
// only include if read only params are wanted
|
||||
if (!(paramInfo.flags & kAudioUnitParameterFlag_IsWritable)
|
||||
&& (paramInfo.flags & kAudioUnitParameterFlag_IsReadable))
|
||||
{
|
||||
if (!inIncludeReadOnly)
|
||||
continue;
|
||||
}
|
||||
|
||||
mParamListID[mNumParams] = paramList[i];
|
||||
mNumParams++;
|
||||
|
||||
// ok - if we're here, then we have a parameter we are going to display.
|
||||
UInt32 clump = 0;
|
||||
auvp.GetClumpID (clump);
|
||||
mParams[clump].push_back (auvp);
|
||||
}
|
||||
|
||||
delete [] paramList;
|
||||
}
|
||||
|
||||
AUParamInfo::~AUParamInfo()
|
||||
{
|
||||
delete [] mParamListID;
|
||||
}
|
||||
|
||||
UInt32 AUParamInfo::NumParamsForClump (UInt32 inClump) const
|
||||
{
|
||||
ParameterMap::const_iterator it = mParams.find(inClump);
|
||||
if (it != mParams.end())
|
||||
return (*it).second.size();
|
||||
return 0;
|
||||
}
|
||||
|
||||
const CAAUParameter* AUParamInfo::GetParamInfo (AudioUnitParameterID inParamID) const
|
||||
{
|
||||
for (ParameterMap::const_iterator it = mParams.begin(); it != mParams.end(); ++it) {
|
||||
const ParameterList &list = (*it).second;
|
||||
for (ParameterList::const_iterator iter = list.begin(); iter != list.end(); ++iter) {
|
||||
if (inParamID == (*iter).mParameterID) {
|
||||
return &(*iter);
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved.
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
|
||||
("Apple") in consideration of your agreement to the following terms, and your
|
||||
use, installation, modification or redistribution of this Apple software
|
||||
constitutes acceptance of these terms. If you do not agree with these terms,
|
||||
please do not use, install, modify or redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and subject
|
||||
to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
|
||||
copyrights in this original Apple software (the "Apple Software"), to use,
|
||||
reproduce, modify and redistribute the Apple Software, with or without
|
||||
modifications, in source and/or binary forms; provided that if you redistribute
|
||||
the Apple Software in its entirety and without modifications, you must retain
|
||||
this notice and the following text and disclaimers in all such redistributions of
|
||||
the Apple Software. Neither the name, trademarks, service marks or logos of
|
||||
Apple Computer, Inc. may be used to endorse or promote products derived from the
|
||||
Apple Software without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or implied,
|
||||
are granted by Apple herein, including but not limited to any patent rights that
|
||||
may be infringed by your derivative works or by other works in which the Apple
|
||||
Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
|
||||
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
|
||||
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
|
||||
COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
|
||||
OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
|
||||
(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*=============================================================================
|
||||
AUParamInfo.h
|
||||
|
||||
=============================================================================*/
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <AudioUnit/AudioUnit.h>
|
||||
#include "CAAUParameter.h"
|
||||
|
||||
/*
|
||||
The ParameterMap returned by the Map() method is a map where
|
||||
- the key is the clumpID
|
||||
- the value is a ParameterList (vector<CAAUParameter>)
|
||||
|
||||
If you have parameters on multiple scopes (or elements within a scope), then you should create one of these
|
||||
for each scope-element pair
|
||||
*/
|
||||
|
||||
class AUParamInfo {
|
||||
|
||||
public:
|
||||
typedef std::vector <CAAUParameter> ParameterList;
|
||||
typedef std::map <UInt32, ParameterList, std::less<UInt32> > ParameterMap;
|
||||
|
||||
|
||||
|
||||
AUParamInfo (AudioUnit inAU,
|
||||
bool inIncludeExpert,
|
||||
bool inIncludeReadOnly,
|
||||
AudioUnitScope inScope = kAudioUnitScope_Global,
|
||||
AudioUnitElement inElement = 0);
|
||||
|
||||
~AUParamInfo();
|
||||
|
||||
const ParameterMap& Map () const { return mParams; }
|
||||
|
||||
// some convenience methods
|
||||
UInt32 NumParams () const { return mNumParams; }
|
||||
|
||||
AudioUnitParameterID ParamID (UInt32 inIndex) const
|
||||
{
|
||||
if (inIndex < mNumParams) return mParamListID[inIndex];
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
UInt32 NumClumps () const { return mParams.size(); }
|
||||
|
||||
UInt32 NumParamsForClump (UInt32 inClump) const;
|
||||
|
||||
// returns NULL if there's no info for the parameter
|
||||
const CAAUParameter* GetParamInfo (AudioUnitParameterID inParamID) const;
|
||||
|
||||
AudioUnitScope GetScope () const { return mScope; }
|
||||
AudioUnitElement GetElement () const { return mElement; }
|
||||
|
||||
private:
|
||||
|
||||
AudioUnit mAU;
|
||||
UInt32 mNumParams;
|
||||
AudioUnitParameterID * mParamListID;
|
||||
|
||||
ParameterMap mParams;
|
||||
AudioUnitScope mScope;
|
||||
AudioUnitElement mElement;
|
||||
|
||||
// disallow
|
||||
AUParamInfo () {}
|
||||
AUParamInfo (const AUParamInfo &c) {}
|
||||
AUParamInfo& operator= (const AUParamInfo& c) { return *this; }
|
||||
};
|
|
@ -0,0 +1,316 @@
|
|||
/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved.
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
|
||||
("Apple") in consideration of your agreement to the following terms, and your
|
||||
use, installation, modification or redistribution of this Apple software
|
||||
constitutes acceptance of these terms. If you do not agree with these terms,
|
||||
please do not use, install, modify or redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and subject
|
||||
to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
|
||||
copyrights in this original Apple software (the "Apple Software"), to use,
|
||||
reproduce, modify and redistribute the Apple Software, with or without
|
||||
modifications, in source and/or binary forms; provided that if you redistribute
|
||||
the Apple Software in its entirety and without modifications, you must retain
|
||||
this notice and the following text and disclaimers in all such redistributions of
|
||||
the Apple Software. Neither the name, trademarks, service marks or logos of
|
||||
Apple Computer, Inc. may be used to endorse or promote products derived from the
|
||||
Apple Software without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or implied,
|
||||
are granted by Apple herein, including but not limited to any patent rights that
|
||||
may be infringed by your derivative works or by other works in which the Apple
|
||||
Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
|
||||
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
|
||||
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
|
||||
COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
|
||||
OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
|
||||
(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*=============================================================================
|
||||
CAAUParameter.cpp
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include "CAAUParameter.h"
|
||||
|
||||
CAAUParameter::CAAUParameter()
|
||||
{
|
||||
memset(this, 0, sizeof(CAAUParameter));
|
||||
}
|
||||
|
||||
CAAUParameter::CAAUParameter(AudioUnit au, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement element)
|
||||
{
|
||||
memset(this, 0, sizeof(CAAUParameter));
|
||||
Init (au, param, scope, element);
|
||||
}
|
||||
|
||||
CAAUParameter::CAAUParameter (AudioUnitParameter &inParam)
|
||||
{
|
||||
memset(this, 0, sizeof(CAAUParameter));
|
||||
Init (inParam.mAudioUnit, inParam.mParameterID, inParam.mScope, inParam.mElement);
|
||||
}
|
||||
|
||||
CAAUParameter::CAAUParameter(const CAAUParameter &a)
|
||||
{
|
||||
memset(this, 0, sizeof(CAAUParameter));
|
||||
*this = a;
|
||||
}
|
||||
|
||||
CAAUParameter & CAAUParameter::operator = (const CAAUParameter &a)
|
||||
{
|
||||
if (mParamName) CFRelease(mParamName);
|
||||
if (mParamTag) CFRelease(mParamTag);
|
||||
if (mNamedParams) CFRelease(mNamedParams);
|
||||
|
||||
memcpy(this, &a, sizeof(CAAUParameter));
|
||||
|
||||
if (mParamName) CFRetain(mParamName);
|
||||
if (mParamTag) CFRetain(mParamTag);
|
||||
if (mNamedParams) CFRetain(mNamedParams);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CAAUParameter::~CAAUParameter()
|
||||
{
|
||||
if (mParamName) CFRelease(mParamName);
|
||||
if (mParamTag) CFRelease(mParamTag);
|
||||
if (mNamedParams) CFRelease (mNamedParams);
|
||||
}
|
||||
|
||||
void CAAUParameter::Init (AudioUnit au, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement element)
|
||||
{
|
||||
mAudioUnit = au;
|
||||
mParameterID = param;
|
||||
mScope = scope;
|
||||
mElement = element;
|
||||
|
||||
UInt32 propertySize = sizeof(mParamInfo);
|
||||
OSStatus err = AudioUnitGetProperty(au, kAudioUnitProperty_ParameterInfo,
|
||||
scope, param, &mParamInfo, &propertySize);
|
||||
if (err)
|
||||
memset(&mParamInfo, 0, sizeof(mParamInfo));
|
||||
if (mParamInfo.flags & kAudioUnitParameterFlag_HasCFNameString) {
|
||||
mParamName = mParamInfo.cfNameString;
|
||||
if (!(mParamInfo.flags & kAudioUnitParameterFlag_CFNameRelease))
|
||||
CFRetain (mParamName);
|
||||
} else
|
||||
mParamName = CFStringCreateWithCString(NULL, mParamInfo.name, kCFStringEncodingUTF8);
|
||||
|
||||
char* str = 0;
|
||||
switch (mParamInfo.unit)
|
||||
{
|
||||
case kAudioUnitParameterUnit_Boolean:
|
||||
str = "T/F";
|
||||
break;
|
||||
case kAudioUnitParameterUnit_Percent:
|
||||
case kAudioUnitParameterUnit_EqualPowerCrossfade:
|
||||
str = "%";
|
||||
break;
|
||||
case kAudioUnitParameterUnit_Seconds:
|
||||
str = "Secs";
|
||||
break;
|
||||
case kAudioUnitParameterUnit_SampleFrames:
|
||||
str = "Samps";
|
||||
break;
|
||||
case kAudioUnitParameterUnit_Phase:
|
||||
case kAudioUnitParameterUnit_Degrees:
|
||||
str = "Degr.";
|
||||
break;
|
||||
case kAudioUnitParameterUnit_Hertz:
|
||||
str = "Hz";
|
||||
break;
|
||||
case kAudioUnitParameterUnit_Cents:
|
||||
case kAudioUnitParameterUnit_AbsoluteCents:
|
||||
str = "Cents";
|
||||
break;
|
||||
case kAudioUnitParameterUnit_RelativeSemiTones:
|
||||
str = "S-T";
|
||||
break;
|
||||
case kAudioUnitParameterUnit_MIDINoteNumber:
|
||||
case kAudioUnitParameterUnit_MIDIController:
|
||||
str = "MIDI";
|
||||
//these are inclusive, so add one value here
|
||||
mNumIndexedParams = short(mParamInfo.maxValue+1 - mParamInfo.minValue);
|
||||
break;
|
||||
case kAudioUnitParameterUnit_Decibels:
|
||||
str = "dB";
|
||||
break;
|
||||
case kAudioUnitParameterUnit_MixerFaderCurve1:
|
||||
case kAudioUnitParameterUnit_LinearGain:
|
||||
str = "Gain";
|
||||
break;
|
||||
case kAudioUnitParameterUnit_Pan:
|
||||
str = "L/R";
|
||||
break;
|
||||
case kAudioUnitParameterUnit_Meters:
|
||||
str = "Mtrs";
|
||||
break;
|
||||
case kAudioUnitParameterUnit_Octaves:
|
||||
str = "8ve";
|
||||
break;
|
||||
case kAudioUnitParameterUnit_BPM:
|
||||
str = "BPM";
|
||||
break;
|
||||
case kAudioUnitParameterUnit_Beats:
|
||||
str = "Beats";
|
||||
break;
|
||||
case kAudioUnitParameterUnit_Milliseconds:
|
||||
str = "msecs";
|
||||
break;
|
||||
case kAudioUnitParameterUnit_Ratio:
|
||||
str = "ratio";
|
||||
break;
|
||||
case kAudioUnitParameterUnit_Indexed:
|
||||
{
|
||||
propertySize = sizeof(mNamedParams);
|
||||
err = AudioUnitGetProperty (au,
|
||||
kAudioUnitProperty_ParameterValueStrings,
|
||||
scope,
|
||||
param,
|
||||
&mNamedParams,
|
||||
&propertySize);
|
||||
if (!err && mNamedParams) {
|
||||
mNumIndexedParams = CFArrayGetCount(mNamedParams);
|
||||
} else {
|
||||
//these are inclusive, so add one value here
|
||||
mNumIndexedParams = short(mParamInfo.maxValue+1 - mParamInfo.minValue);
|
||||
}
|
||||
str = NULL;
|
||||
}
|
||||
break;
|
||||
case kAudioUnitParameterUnit_CustomUnit:
|
||||
{
|
||||
CFStringRef unitName = mParamInfo.unitName;
|
||||
static char paramStr[256];
|
||||
CFStringGetCString (unitName, paramStr, 256, kCFStringEncodingUTF8);
|
||||
if (mParamInfo.flags & kAudioUnitParameterFlag_CFNameRelease)
|
||||
CFRelease (unitName);
|
||||
str = paramStr;
|
||||
break;
|
||||
}
|
||||
case kAudioUnitParameterUnit_Generic:
|
||||
case kAudioUnitParameterUnit_Rate:
|
||||
default:
|
||||
str = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (str)
|
||||
mParamTag = CFStringCreateWithCString(NULL, str, kCFStringEncodingUTF8);
|
||||
else
|
||||
mParamTag = NULL;
|
||||
}
|
||||
|
||||
|
||||
Float32 CAAUParameter::GetValue() const
|
||||
{
|
||||
Float32 value = 0.;
|
||||
//OSStatus err =
|
||||
AudioUnitGetParameter(mAudioUnit, mParameterID, mScope, mElement, &value);
|
||||
return value;
|
||||
}
|
||||
|
||||
CFStringRef CAAUParameter::GetStringFromValueCopy(const Float32 *value) const
|
||||
{
|
||||
if (HasNamedParams())
|
||||
{
|
||||
Float32 val = (value == NULL ? GetValue() : *value);
|
||||
int index = int(mParamInfo.minValue) + int(val);
|
||||
CFStringRef str = GetParamName (index);
|
||||
if (str) {
|
||||
CFRetain (str);
|
||||
return str;
|
||||
}
|
||||
}
|
||||
else if (ValuesHaveStrings())
|
||||
{
|
||||
AudioUnitParameterStringFromValue stringValue;
|
||||
stringValue.inParamID = mParameterID;
|
||||
stringValue.inValue = value;
|
||||
stringValue.outString = NULL;
|
||||
UInt32 propertySize = sizeof(stringValue);
|
||||
|
||||
OSStatus err = AudioUnitGetProperty (mAudioUnit,
|
||||
kAudioUnitProperty_ParameterStringFromValue,
|
||||
mScope,
|
||||
mParameterID,
|
||||
&stringValue,
|
||||
&propertySize);
|
||||
|
||||
if (err == noErr && stringValue.outString != NULL)
|
||||
return stringValue.outString;
|
||||
}
|
||||
|
||||
Float32 val = (value == NULL ? GetValue() : *value);
|
||||
char valstr[32];
|
||||
AUParameterFormatValue (val, this, valstr, 4);
|
||||
return CFStringCreateWithCString(NULL, valstr, kCFStringEncodingUTF8);
|
||||
}
|
||||
|
||||
Float32 CAAUParameter::GetValueFromString(CFStringRef str) const
|
||||
{
|
||||
if (ValuesHaveStrings())
|
||||
{
|
||||
AudioUnitParameterValueFromString valueString;
|
||||
valueString.inParamID = mParameterID;
|
||||
valueString.inString = str;
|
||||
UInt32 propertySize = sizeof(valueString);
|
||||
|
||||
OSStatus err = AudioUnitGetProperty (mAudioUnit,
|
||||
kAudioUnitProperty_ParameterValueFromString,
|
||||
mScope,
|
||||
mParameterID,
|
||||
&valueString,
|
||||
&propertySize);
|
||||
|
||||
if (err == noErr) {
|
||||
return valueString.outValue;
|
||||
}
|
||||
}
|
||||
|
||||
Float32 paramValue = mParamInfo.defaultValue;
|
||||
char valstr[32];
|
||||
CFStringGetCString(str, valstr, sizeof(valstr), kCFStringEncodingUTF8);
|
||||
sscanf(valstr, "%f", ¶mValue);
|
||||
return paramValue;
|
||||
}
|
||||
|
||||
void CAAUParameter::SetValue( AUParameterListenerRef inListener,
|
||||
void * inObject,
|
||||
Float32 inValue) const
|
||||
{
|
||||
// clip inValue as: maxValue >= inValue >= minValue before setting
|
||||
Float32 valueToSet = inValue;
|
||||
if (valueToSet > mParamInfo.maxValue)
|
||||
valueToSet = mParamInfo.maxValue;
|
||||
if (valueToSet < mParamInfo.minValue)
|
||||
valueToSet = mParamInfo.minValue;
|
||||
|
||||
AUParameterSet(inListener, inObject, this, valueToSet, 0);
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
void CAAUParameter::Print() const
|
||||
{
|
||||
UInt32 clump = 0;
|
||||
GetClumpID (clump);
|
||||
|
||||
UInt32 len = CFStringGetLength(mParamName);
|
||||
char* chars = (char*)malloc (len * 2); // give us plenty of room for unichar chars
|
||||
if (!CFStringGetCString (mParamName, chars, len * 2, kCFStringEncodingUTF8))
|
||||
chars[0] = 0;
|
||||
|
||||
printf ("ID: %ld, Clump: %ld, Name: %s\n", mParameterID, clump, chars);
|
||||
free (chars);
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,187 @@
|
|||
/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved.
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
|
||||
("Apple") in consideration of your agreement to the following terms, and your
|
||||
use, installation, modification or redistribution of this Apple software
|
||||
constitutes acceptance of these terms. If you do not agree with these terms,
|
||||
please do not use, install, modify or redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and subject
|
||||
to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
|
||||
copyrights in this original Apple software (the "Apple Software"), to use,
|
||||
reproduce, modify and redistribute the Apple Software, with or without
|
||||
modifications, in source and/or binary forms; provided that if you redistribute
|
||||
the Apple Software in its entirety and without modifications, you must retain
|
||||
this notice and the following text and disclaimers in all such redistributions of
|
||||
the Apple Software. Neither the name, trademarks, service marks or logos of
|
||||
Apple Computer, Inc. may be used to endorse or promote products derived from the
|
||||
Apple Software without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or implied,
|
||||
are granted by Apple herein, including but not limited to any patent rights that
|
||||
may be infringed by your derivative works or by other works in which the Apple
|
||||
Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
|
||||
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
|
||||
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
|
||||
COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
|
||||
OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
|
||||
(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*=============================================================================
|
||||
CAAUParameter.h
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#ifndef __CAAUParameter_h__
|
||||
#define __CAAUParameter_h__
|
||||
|
||||
#include <AudioToolbox/AudioUnitUtilities.h>
|
||||
|
||||
// ____________________________________________________________________________
|
||||
// CAAUParameter
|
||||
// complete parameter specification
|
||||
/*! @class CAAUParameter */
|
||||
class CAAUParameter : public AudioUnitParameter {
|
||||
public:
|
||||
/*! @ctor CAAUParameter.0 */
|
||||
CAAUParameter();
|
||||
/*! @ctor CAAUParameter.1 */
|
||||
CAAUParameter(AudioUnit au, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement element);
|
||||
/*! @ctor CAAUParameter.2 */
|
||||
CAAUParameter(AudioUnitParameter &inParam);
|
||||
/*! @ctor CAAUParameter.3 */
|
||||
CAAUParameter(const CAAUParameter &a);
|
||||
/*! @dtor ~CAAUParameter */
|
||||
~CAAUParameter();
|
||||
|
||||
/*! @method operator <@ */
|
||||
bool operator < (const CAAUParameter &a) const
|
||||
{
|
||||
return memcmp(this, &a, sizeof(AudioUnitParameter)) < 0;
|
||||
}
|
||||
|
||||
/*! @method operator ==@ */
|
||||
bool operator == (const CAAUParameter &a) const
|
||||
{
|
||||
return !memcmp(this, &a, sizeof(AudioUnitParameter));
|
||||
}
|
||||
|
||||
/*! @method operator =@ */
|
||||
CAAUParameter & operator = (const CAAUParameter &a);
|
||||
|
||||
/*! @method GetValue */
|
||||
Float32 GetValue() const;
|
||||
/*! @method SetValue */
|
||||
void SetValue( AUParameterListenerRef inListener,
|
||||
void * inObject,
|
||||
Float32 inValue) const;
|
||||
|
||||
/*! @method GetName */
|
||||
CFStringRef GetName() const { return mParamName; }
|
||||
// borrowed reference!
|
||||
|
||||
/*! @method GetStringFromValueCopy */
|
||||
CFStringRef GetStringFromValueCopy(const Float32 *value = NULL) const;
|
||||
// returns a copy of the name of the current parameter value
|
||||
// or null if there is no name associated
|
||||
// caller must release
|
||||
/*! @method ValuesHaveStrings */
|
||||
bool ValuesHaveStrings () const
|
||||
{
|
||||
return (mParamInfo.flags & kAudioUnitParameterFlag_ValuesHaveStrings) != 0;
|
||||
}
|
||||
|
||||
/*! @method GetValueFromString */
|
||||
Float32 GetValueFromString (CFStringRef str) const;
|
||||
// caller must release
|
||||
|
||||
/*! @method ParamInfo */
|
||||
const AudioUnitParameterInfo &
|
||||
ParamInfo() const { return mParamInfo; }
|
||||
|
||||
/*! @method GetParamTag */
|
||||
CFStringRef GetParamTag() const { return mParamTag; }
|
||||
// this may return null! -
|
||||
// in which case there is no descriptive tag for the parameter
|
||||
|
||||
/*! @method GetParamName */
|
||||
CFStringRef GetParamName (int inIndex) const
|
||||
// this can return null if there is no name for the parameter
|
||||
{
|
||||
return (mNamedParams && inIndex < mNumIndexedParams)
|
||||
? (CFStringRef) CFArrayGetValueAtIndex(mNamedParams, inIndex)
|
||||
: 0;
|
||||
}
|
||||
|
||||
/*! @method GetNumIndexedParams */
|
||||
int GetNumIndexedParams () const { return mNumIndexedParams; }
|
||||
|
||||
/*! @method IsIndexedParam */
|
||||
bool IsIndexedParam () const { return mNumIndexedParams != 0; }
|
||||
|
||||
/*! @method HasNamedParams */
|
||||
bool HasNamedParams () const { return IsIndexedParam() && mNamedParams; }
|
||||
|
||||
/*! @method GetClumpID */
|
||||
bool GetClumpID (UInt32 &outClumpID) const
|
||||
{
|
||||
if (mParamInfo.flags & kAudioUnitParameterFlag_HasClump) {
|
||||
outClumpID = mParamInfo.clumpID;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*! @method HasDisplayTransformation */
|
||||
bool HasDisplayTransformation () const
|
||||
{
|
||||
return GetAudioUnitParameterDisplayType (mParamInfo.flags);
|
||||
}
|
||||
|
||||
/*! @method IsExpert */
|
||||
bool IsExpert () const
|
||||
{
|
||||
return mParamInfo.flags & kAudioUnitParameterFlag_ExpertMode;
|
||||
}
|
||||
#if DEBUG
|
||||
void Print () const;
|
||||
#endif
|
||||
|
||||
// these methods are defined in CAPersistence.cpp
|
||||
// they will persist and restore only the scope, element and param ID's of the AudioUnitParameter
|
||||
// however, this is sufficient to be able to save/restore a CAAUParameter object
|
||||
void Save (CFPropertyListRef &outData) const;
|
||||
|
||||
static void Save (const AudioUnitParameter &inParam, CFPropertyListRef &outData);
|
||||
|
||||
static OSStatus Restore (const CFPropertyListRef inData, AudioUnitParameter &outParam);
|
||||
|
||||
protected:
|
||||
// cached parameter info
|
||||
/*! @var mParamInfo */
|
||||
AudioUnitParameterInfo mParamInfo;
|
||||
/*! @var mParamName */
|
||||
CFStringRef mParamName;
|
||||
/*! @var mParamTag */
|
||||
CFStringRef mParamTag;
|
||||
/*! @var mNumIndexedParams */
|
||||
short mNumIndexedParams;
|
||||
/*! @var mNamedParams */
|
||||
CFArrayRef mNamedParams;
|
||||
|
||||
private:
|
||||
void Init (AudioUnit au, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement element);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // __CAAUParameter_h__
|
|
@ -20,6 +20,9 @@ ardour.Append(CXXFLAGS=["-DLIBSIGC_DISABLE_DEPRECATED", "-DGLIBMM_EXCEPTIONS_ENA
|
|||
ardour.Append(PACKAGE = domain)
|
||||
ardour.Append(POTFILE = domain + '.pot')
|
||||
|
||||
if ardour['IS_OSX']:
|
||||
ardour.Append (LINKFLAGS="-Xlinker -headerpad -Xlinker 2048")
|
||||
|
||||
#
|
||||
# explicitly reference the control protocol LGPL library for includes
|
||||
#
|
||||
|
@ -312,7 +315,7 @@ ardour.Merge ([
|
|||
libraries['sndfile-ardour'],
|
||||
libraries['vamp'],
|
||||
libraries['vamphost'],
|
||||
libraries['xml'],
|
||||
libraries['xml']
|
||||
])
|
||||
|
||||
if ardour['RUBBERBAND']:
|
||||
|
@ -380,5 +383,10 @@ env.Alias('tarball', env.Distribute (env['DISTTREE'],
|
|||
[ 'SConscript', 'i18n.h', 'gettext.h' ] +
|
||||
[ 'sse_functions_xmm.cc', 'sse_functions.s', 'sse_functions_64bit.s' ] +
|
||||
[ 'rb_effect.cc', 'st_stretch.cc', 'st_pitch.cc' ] +
|
||||
ardour_files + osc_files + vst_files + coreaudio_files + audiounit_files +
|
||||
ardour_files +
|
||||
osc_files +
|
||||
vst_files +
|
||||
coreaudio_files +
|
||||
audiounit_files +
|
||||
lv2_files +
|
||||
glob.glob('po/*.po') + glob.glob('ardour/*.h')))
|
||||
|
|
|
@ -95,7 +95,7 @@ Analyser::work ()
|
|||
|
||||
boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src);
|
||||
|
||||
if (afs) {
|
||||
if (afs && afs->length()) {
|
||||
analyse_audio_file_source (afs);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,8 +20,10 @@
|
|||
#ifndef __ardour_ardour_h__
|
||||
#define __ardour_ardour_h__
|
||||
|
||||
#include <limits.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include <limits.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <pbd/error.h>
|
||||
|
@ -43,12 +45,15 @@ namespace ARDOUR {
|
|||
extern OSC* osc;
|
||||
|
||||
static const nframes_t max_frames = JACK_MAX_FRAMES;
|
||||
extern sigc::signal<void,std::string> BootMessage;
|
||||
|
||||
int init (bool with_vst, bool try_optimization);
|
||||
int cleanup ();
|
||||
|
||||
std::string get_ardour_revision ();
|
||||
|
||||
void find_bindings_files (std::map<std::string,std::string>&);
|
||||
|
||||
const layer_t max_layer = UCHAR_MAX;
|
||||
|
||||
microseconds_t get_microseconds ();
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <ardour/plugin.h>
|
||||
|
||||
#include <AudioUnit/AudioUnit.h>
|
||||
#include <appleutility/AUParamInfo.h>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
|
@ -45,6 +46,16 @@ namespace ARDOUR {
|
|||
class AudioEngine;
|
||||
class Session;
|
||||
|
||||
struct AUParameterDescriptor : public Plugin::ParameterDescriptor {
|
||||
// additional fields to make operations more efficient
|
||||
AudioUnitParameterID id;
|
||||
AudioUnitScope scope;
|
||||
AudioUnitElement element;
|
||||
float default_value;
|
||||
bool automatable;
|
||||
AudioUnitParameterUnit unit;
|
||||
};
|
||||
|
||||
class AUPlugin : public ARDOUR::Plugin
|
||||
{
|
||||
public:
|
||||
|
@ -105,7 +116,7 @@ class AUPlugin : public ARDOUR::Plugin
|
|||
private:
|
||||
boost::shared_ptr<CAComponent> comp;
|
||||
boost::shared_ptr<CAAudioUnit> unit;
|
||||
|
||||
|
||||
AudioStreamBasicDescription streamFormat;
|
||||
bool initialized;
|
||||
int format_set;
|
||||
|
@ -119,6 +130,7 @@ class AUPlugin : public ARDOUR::Plugin
|
|||
int set_input_format ();
|
||||
int set_stream_format (int scope, uint32_t cnt);
|
||||
int _set_block_size (nframes_t nframes);
|
||||
void discover_parameters ();
|
||||
|
||||
std::vector<std::pair<uint32_t, uint32_t> > parameter_map;
|
||||
uint32_t current_maxbuf;
|
||||
|
@ -126,6 +138,8 @@ class AUPlugin : public ARDOUR::Plugin
|
|||
nframes_t cb_offset;
|
||||
vector<Sample*>* current_buffers;
|
||||
nframes_t frames_processed;
|
||||
|
||||
std::vector<AUParameterDescriptor> descriptors;
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<AUPlugin> AUPluginPtr;
|
||||
|
|
|
@ -116,7 +116,6 @@ class AudioSource : public Source, public boost::enable_shared_from_this<ARDOUR:
|
|||
static bool _build_peakfiles;
|
||||
|
||||
bool _peaks_built;
|
||||
bool _analysed;
|
||||
mutable Glib::Mutex _lock;
|
||||
mutable Glib::Mutex _peaks_ready_lock;
|
||||
Glib::ustring peakpath;
|
||||
|
|
|
@ -57,7 +57,10 @@ public:
|
|||
|
||||
virtual void add_control(boost::shared_ptr<AutomationControl>);
|
||||
|
||||
virtual void automation_snapshot(nframes_t now);
|
||||
virtual void automation_snapshot(nframes_t now, bool force);
|
||||
bool should_snapshot (nframes_t now) {
|
||||
return (_last_automation_snapshot > now || (now - _last_automation_snapshot) > _automation_interval);
|
||||
}
|
||||
virtual void transport_stopped(nframes_t now);
|
||||
|
||||
virtual bool find_next_event(nframes_t start, nframes_t end, ControlEvent& ev) const;
|
||||
|
|
|
@ -105,6 +105,7 @@ CONFIG_VARIABLE (bool, punch_out, "punch-out", false)
|
|||
CONFIG_VARIABLE (bool, plugins_stop_with_transport, "plugins-stop-with-transport", false)
|
||||
CONFIG_VARIABLE (bool, do_not_record_plugins, "do-not-record-plugins", false)
|
||||
CONFIG_VARIABLE (bool, stop_recording_on_xrun, "stop-recording-on-xrun", false)
|
||||
CONFIG_VARIABLE (bool, create_xrun_marker, "create-xrun-marker", true)
|
||||
CONFIG_VARIABLE (bool, stop_at_session_end, "stop-at-session-end", true)
|
||||
CONFIG_VARIABLE (bool, seamless_loop, "seamless-loop", false)
|
||||
CONFIG_VARIABLE (nframes_t, preroll, "preroll", 0)
|
||||
|
|
|
@ -251,8 +251,8 @@ class IO : public Automatable, public Latent
|
|||
|
||||
void set_parameter_automation_state (Parameter, AutoState);
|
||||
|
||||
virtual void transport_stopped (nframes_t now); // interface: matches Insert
|
||||
void automation_snapshot (nframes_t now); // interface: matches Automatable
|
||||
virtual void transport_stopped (nframes_t now);
|
||||
virtual void automation_snapshot (nframes_t now, bool force);
|
||||
|
||||
void start_pan_touch (uint32_t which);
|
||||
void end_pan_touch (uint32_t which);
|
||||
|
|
|
@ -65,7 +65,7 @@ class IOProcessor : public Processor
|
|||
boost::shared_ptr<IO> io() { return _io; }
|
||||
boost::shared_ptr<const IO> io() const { return _io; }
|
||||
|
||||
virtual void automation_snapshot (nframes_t now) { _io->automation_snapshot(now); }
|
||||
virtual void automation_snapshot (nframes_t now, bool force) { _io->automation_snapshot(now, force); }
|
||||
|
||||
virtual void run_in_place (BufferSet& in, nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset) = 0;
|
||||
|
||||
|
|
|
@ -126,7 +126,6 @@ class Playlist : public SessionObject, public boost::enable_shared_from_this<Pla
|
|||
sigc::signal<void> LengthChanged;
|
||||
|
||||
static string bump_name (string old_name, Session&);
|
||||
static string bump_name_once (string old_name);
|
||||
|
||||
void freeze ();
|
||||
void thaw ();
|
||||
|
|
|
@ -75,6 +75,8 @@ class Route : public IO
|
|||
Route (Session&, const XMLNode&, DataType default_type = DataType::AUDIO);
|
||||
virtual ~Route();
|
||||
|
||||
static std::string ensure_track_or_route_name(std::string, Session &);
|
||||
|
||||
std::string comment() { return _comment; }
|
||||
void set_comment (std::string str, void *src);
|
||||
|
||||
|
@ -247,7 +249,7 @@ class Route : public IO
|
|||
return _mute_control;
|
||||
}
|
||||
|
||||
void automation_snapshot (nframes_t now);
|
||||
void automation_snapshot (nframes_t now, bool force=false);
|
||||
void protect_automation ();
|
||||
|
||||
void set_remote_control_id (uint32_t id);
|
||||
|
|
|
@ -353,7 +353,7 @@ class Session : public PBD::StatefulDestructible
|
|||
sigc::signal<void> TransportStateChange; /* generic */
|
||||
sigc::signal<void,nframes_t> PositionChanged; /* sent after any non-sequential motion */
|
||||
sigc::signal<void> DurationChanged;
|
||||
sigc::signal<void> HaltOnXrun;
|
||||
sigc::signal<void,nframes_t> Xrun;
|
||||
sigc::signal<void> TransportLooped;
|
||||
|
||||
sigc::signal<void,RouteList&> RouteAdded;
|
||||
|
@ -563,8 +563,11 @@ class Session : public PBD::StatefulDestructible
|
|||
|
||||
/* region info */
|
||||
|
||||
sigc::signal<void,boost::shared_ptr<Region> > RegionAdded;
|
||||
sigc::signal<void,boost::shared_ptr<Region> > RegionRemoved;
|
||||
void add_regions (std::vector<boost::shared_ptr<Region> >&);
|
||||
|
||||
sigc::signal<void,boost::weak_ptr<Region> > RegionAdded;
|
||||
sigc::signal<void,std::vector<boost::weak_ptr<Region> >& > RegionsAdded;
|
||||
sigc::signal<void,boost::weak_ptr<Region> > RegionRemoved;
|
||||
|
||||
int region_name (string& result, string base = string(""), bool newlevel = false) const;
|
||||
string new_region_name (string);
|
||||
|
@ -586,10 +589,10 @@ class Session : public PBD::StatefulDestructible
|
|||
string doing_what;
|
||||
|
||||
/* control info */
|
||||
bool sample_convert;
|
||||
SrcQuality quality;
|
||||
volatile bool freeze;
|
||||
std::vector<Glib::ustring> paths;
|
||||
bool replace_existing_source;
|
||||
|
||||
/* result */
|
||||
SourceList sources;
|
||||
|
@ -1480,6 +1483,12 @@ class Session : public PBD::StatefulDestructible
|
|||
|
||||
SourceMap sources;
|
||||
|
||||
public:
|
||||
SourceMap get_sources() { return sources; }
|
||||
|
||||
private:
|
||||
|
||||
|
||||
int load_sources (const XMLNode& node);
|
||||
XMLNode& get_sources_as_xml ();
|
||||
|
||||
|
|
|
@ -257,7 +257,8 @@ namespace ARDOUR {
|
|||
|
||||
enum EditMode {
|
||||
Slide,
|
||||
Splice
|
||||
Splice,
|
||||
Lock
|
||||
};
|
||||
|
||||
enum RegionPoint {
|
||||
|
|
|
@ -45,6 +45,8 @@ static inline float f_max(float x, float a) {
|
|||
return (x);
|
||||
}
|
||||
|
||||
std::string bump_name_once(std::string s);
|
||||
|
||||
int cmp_nocase (const std::string& s, const std::string& s2);
|
||||
|
||||
int touch_file(Glib::ustring path);
|
||||
|
|
|
@ -519,7 +519,7 @@ AudioTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
|
|||
if (lm.locked()) {
|
||||
// automation snapshot can also be called from the non-rt context
|
||||
// and it uses the redirect list, so we take the lock out here
|
||||
automation_snapshot (start_frame);
|
||||
automation_snapshot (start_frame, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <ardour/utils.h>
|
||||
|
||||
#include <appleutility/CAAudioUnit.h>
|
||||
#include <appleutility/CAAUParameter.h>
|
||||
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#include <AudioUnit/AudioUnit.h>
|
||||
|
@ -83,6 +84,7 @@ AUPlugin::AUPlugin (AudioEngine& engine, Session& session, boost::shared_ptr<CAC
|
|||
throw failed_constructor();
|
||||
}
|
||||
|
||||
unit->GetElementCount (kAudioUnitScope_Global, global_elements);
|
||||
unit->GetElementCount (kAudioUnitScope_Input, input_elements);
|
||||
unit->GetElementCount (kAudioUnitScope_Output, output_elements);
|
||||
|
||||
|
@ -106,6 +108,10 @@ AUPlugin::AUPlugin (AudioEngine& engine, Session& session, boost::shared_ptr<CAC
|
|||
error << _("AUPlugin: cannot set processing block size") << endmsg;
|
||||
throw failed_constructor();
|
||||
}
|
||||
|
||||
discover_parameters ();
|
||||
|
||||
Plugin::setup_controls ();
|
||||
}
|
||||
|
||||
AUPlugin::~AUPlugin ()
|
||||
|
@ -119,6 +125,124 @@ AUPlugin::~AUPlugin ()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
AUPlugin::discover_parameters ()
|
||||
{
|
||||
/* discover writable parameters */
|
||||
|
||||
cerr << "get param info, there are " << global_elements << " global elements\n";
|
||||
|
||||
AudioUnitScope scopes[] = {
|
||||
kAudioUnitScope_Global,
|
||||
kAudioUnitScope_Output,
|
||||
kAudioUnitScope_Input
|
||||
};
|
||||
|
||||
descriptors.clear ();
|
||||
|
||||
for (uint32_t i = 0; i < sizeof (scopes) / sizeof (scopes[0]); ++i) {
|
||||
|
||||
AUParamInfo param_info (unit->AU(), false, false, scopes[i]);
|
||||
|
||||
cerr << "discovered " << param_info.NumParams() << " parameters in scope " << i << endl;
|
||||
|
||||
for (uint32_t i = 0; i < param_info.NumParams(); ++i) {
|
||||
|
||||
AUParameterDescriptor d;
|
||||
|
||||
d.id = param_info.ParamID (i);
|
||||
|
||||
const CAAUParameter* param = param_info.GetParamInfo (d.id);
|
||||
const AudioUnitParameterInfo& info (param->ParamInfo());
|
||||
|
||||
const int len = CFStringGetLength (param->GetName());;
|
||||
char local_buffer[len*2];
|
||||
Boolean good = CFStringGetCString(param->GetName(),local_buffer,len*2,kCFStringEncodingMacRoman);
|
||||
if (!good) {
|
||||
d.label = "???";
|
||||
} else {
|
||||
d.label = local_buffer;
|
||||
}
|
||||
|
||||
d.scope = param_info.GetScope ();
|
||||
d.element = param_info.GetElement ();
|
||||
|
||||
/* info.units to consider */
|
||||
/*
|
||||
kAudioUnitParameterUnit_Generic = 0
|
||||
kAudioUnitParameterUnit_Indexed = 1
|
||||
kAudioUnitParameterUnit_Boolean = 2
|
||||
kAudioUnitParameterUnit_Percent = 3
|
||||
kAudioUnitParameterUnit_Seconds = 4
|
||||
kAudioUnitParameterUnit_SampleFrames = 5
|
||||
kAudioUnitParameterUnit_Phase = 6
|
||||
kAudioUnitParameterUnit_Rate = 7
|
||||
kAudioUnitParameterUnit_Hertz = 8
|
||||
kAudioUnitParameterUnit_Cents = 9
|
||||
kAudioUnitParameterUnit_RelativeSemiTones = 10
|
||||
kAudioUnitParameterUnit_MIDINoteNumber = 11
|
||||
kAudioUnitParameterUnit_MIDIController = 12
|
||||
kAudioUnitParameterUnit_Decibels = 13
|
||||
kAudioUnitParameterUnit_LinearGain = 14
|
||||
kAudioUnitParameterUnit_Degrees = 15
|
||||
kAudioUnitParameterUnit_EqualPowerCrossfade = 16
|
||||
kAudioUnitParameterUnit_MixerFaderCurve1 = 17
|
||||
kAudioUnitParameterUnit_Pan = 18
|
||||
kAudioUnitParameterUnit_Meters = 19
|
||||
kAudioUnitParameterUnit_AbsoluteCents = 20
|
||||
kAudioUnitParameterUnit_Octaves = 21
|
||||
kAudioUnitParameterUnit_BPM = 22
|
||||
kAudioUnitParameterUnit_Beats = 23
|
||||
kAudioUnitParameterUnit_Milliseconds = 24
|
||||
kAudioUnitParameterUnit_Ratio = 25
|
||||
*/
|
||||
|
||||
/* info.flags to consider */
|
||||
|
||||
/*
|
||||
|
||||
kAudioUnitParameterFlag_CFNameRelease = (1L << 4)
|
||||
kAudioUnitParameterFlag_HasClump = (1L << 20)
|
||||
kAudioUnitParameterFlag_HasName = (1L << 21)
|
||||
kAudioUnitParameterFlag_DisplayLogarithmic = (1L << 22)
|
||||
kAudioUnitParameterFlag_IsHighResolution = (1L << 23)
|
||||
kAudioUnitParameterFlag_NonRealTime = (1L << 24)
|
||||
kAudioUnitParameterFlag_CanRamp = (1L << 25)
|
||||
kAudioUnitParameterFlag_ExpertMode = (1L << 26)
|
||||
kAudioUnitParameterFlag_HasCFNameString = (1L << 27)
|
||||
kAudioUnitParameterFlag_IsGlobalMeta = (1L << 28)
|
||||
kAudioUnitParameterFlag_IsElementMeta = (1L << 29)
|
||||
kAudioUnitParameterFlag_IsReadable = (1L << 30)
|
||||
kAudioUnitParameterFlag_IsWritable = (1L << 31)
|
||||
*/
|
||||
|
||||
d.lower = info.minValue;
|
||||
d.upper = info.maxValue;
|
||||
d.default_value = info.defaultValue;
|
||||
|
||||
d.integer_step = (info.unit & kAudioUnitParameterUnit_Indexed);
|
||||
d.toggled = (info.unit & kAudioUnitParameterUnit_Boolean) ||
|
||||
(d.integer_step && ((d.upper - d.lower) == 1.0));
|
||||
d.sr_dependent = (info.unit & kAudioUnitParameterUnit_SampleFrames);
|
||||
d.automatable = !d.toggled &&
|
||||
!(info.flags & kAudioUnitParameterFlag_NonRealTime) &&
|
||||
(info.flags & kAudioUnitParameterFlag_IsWritable);
|
||||
|
||||
d.logarithmic = (info.flags & kAudioUnitParameterFlag_DisplayLogarithmic);
|
||||
d.unit = info.unit;
|
||||
|
||||
d.step = 1.0;
|
||||
d.smallstep = 0.1;
|
||||
d.largestep = 10.0;
|
||||
d.min_unbound = 0; // lower is bound
|
||||
d.max_unbound = 0; // upper is bound
|
||||
|
||||
descriptors.push_back (d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
string
|
||||
AUPlugin::unique_id () const
|
||||
{
|
||||
|
@ -134,13 +258,16 @@ AUPlugin::label () const
|
|||
uint32_t
|
||||
AUPlugin::parameter_count () const
|
||||
{
|
||||
return 0;
|
||||
return descriptors.size();
|
||||
}
|
||||
|
||||
float
|
||||
AUPlugin::default_value (uint32_t port)
|
||||
{
|
||||
// AudioUnits don't have default values. Maybe presets though?
|
||||
if (port < descriptors.size()) {
|
||||
return descriptors[port].default_value;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -157,28 +284,41 @@ AUPlugin::signal_latency () const
|
|||
void
|
||||
AUPlugin::set_parameter (uint32_t which, float val)
|
||||
{
|
||||
// unit->SetParameter (parameter_map[which].first, parameter_map[which].second, 0, val);
|
||||
if (which < descriptors.size()) {
|
||||
const AUParameterDescriptor& d (descriptors[which]);
|
||||
unit->SetParameter (d.id, d.scope, d.element, val);
|
||||
}
|
||||
}
|
||||
|
||||
float
|
||||
AUPlugin::get_parameter (uint32_t which) const
|
||||
{
|
||||
float outValue = 0.0;
|
||||
|
||||
// unit->GetParameter(parameter_map[which].first, parameter_map[which].second, 0, outValue);
|
||||
|
||||
return outValue;
|
||||
float val = 0.0;
|
||||
if (which < descriptors.size()) {
|
||||
const AUParameterDescriptor& d (descriptors[which]);
|
||||
unit->GetParameter(d.id, d.scope, d.element, val);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
int
|
||||
AUPlugin::get_parameter_descriptor (uint32_t which, ParameterDescriptor&) const
|
||||
AUPlugin::get_parameter_descriptor (uint32_t which, ParameterDescriptor& pd) const
|
||||
{
|
||||
return 0;
|
||||
if (which < descriptors.size()) {
|
||||
pd = descriptors[which];
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
AUPlugin::nth_parameter (uint32_t which, bool& ok) const
|
||||
{
|
||||
if (which < descriptors.size()) {
|
||||
ok = true;
|
||||
return which;
|
||||
}
|
||||
ok = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -397,20 +537,26 @@ set<uint32_t>
|
|||
AUPlugin::automatable() const
|
||||
{
|
||||
set<uint32_t> automates;
|
||||
|
||||
|
||||
for (uint32_t i = 0; i < descriptors.size(); ++i) {
|
||||
if (descriptors[i].automatable) {
|
||||
automates.insert (i);
|
||||
}
|
||||
}
|
||||
|
||||
return automates;
|
||||
}
|
||||
|
||||
string
|
||||
AUPlugin::describe_parameter (uint32_t)
|
||||
AUPlugin::describe_parameter (uint32_t param)
|
||||
{
|
||||
return "";
|
||||
return descriptors[param].label;
|
||||
}
|
||||
|
||||
void
|
||||
AUPlugin::print_parameter (uint32_t, char*, uint32_t len) const
|
||||
AUPlugin::print_parameter (uint32_t param, char* buf, uint32_t len) const
|
||||
{
|
||||
|
||||
// NameValue stuff here
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -422,7 +568,7 @@ AUPlugin::parameter_is_audio (uint32_t) const
|
|||
bool
|
||||
AUPlugin::parameter_is_control (uint32_t) const
|
||||
{
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -126,6 +126,8 @@ AudioEngine::start ()
|
|||
if (session) {
|
||||
nframes_t blocksize = jack_get_buffer_size (_jack);
|
||||
|
||||
BootMessage (_("Connect session to engine"));
|
||||
|
||||
session->set_block_size (blocksize);
|
||||
session->set_frame_rate (jack_get_sample_rate (_jack));
|
||||
|
||||
|
|
|
@ -677,20 +677,18 @@ bool
|
|||
AudioFileSource::safe_file_extension(ustring file)
|
||||
{
|
||||
return !(file.rfind(".wav") == ustring::npos &&
|
||||
file.rfind(".aiff")== ustring::npos &&
|
||||
file.rfind(".aif") == ustring::npos &&
|
||||
file.rfind(".snd") == ustring::npos &&
|
||||
file.rfind(".au") == ustring::npos &&
|
||||
file.rfind(".raw") == ustring::npos &&
|
||||
file.rfind(".sf") == ustring::npos &&
|
||||
file.rfind(".cdr") == ustring::npos &&
|
||||
file.rfind(".smp") == ustring::npos &&
|
||||
file.rfind(".maud")== ustring::npos &&
|
||||
file.rfind(".vwe") == ustring::npos &&
|
||||
file.rfind(".paf") == ustring::npos &&
|
||||
/* protools convention */
|
||||
file.rfind(".L") == ustring::npos &&
|
||||
file.rfind(".R") == ustring::npos &&
|
||||
file.rfind(".aiff")== ustring::npos &&
|
||||
file.rfind(".aif") == ustring::npos &&
|
||||
file.rfind(".amb") == ustring::npos &&
|
||||
file.rfind(".snd") == ustring::npos &&
|
||||
file.rfind(".au") == ustring::npos &&
|
||||
file.rfind(".raw") == ustring::npos &&
|
||||
file.rfind(".sf") == ustring::npos &&
|
||||
file.rfind(".cdr") == ustring::npos &&
|
||||
file.rfind(".smp") == ustring::npos &&
|
||||
file.rfind(".maud")== ustring::npos &&
|
||||
file.rfind(".vwe") == ustring::npos &&
|
||||
file.rfind(".paf") == ustring::npos &&
|
||||
#ifdef HAVE_FLAC
|
||||
file.rfind(".flac")== ustring::npos &&
|
||||
#endif // HAVE_FLAC
|
||||
|
|
|
@ -1316,6 +1316,8 @@ AudioRegion::get_transients (AnalysisFeatureList& results, bool force_new)
|
|||
return 0;
|
||||
}
|
||||
|
||||
cerr << "startup analysis of " << _name << endl;
|
||||
|
||||
TransientDetector t (pl->session().frame_rate());
|
||||
bool existing_results = !results.empty();
|
||||
|
||||
|
@ -1328,10 +1330,14 @@ AudioRegion::get_transients (AnalysisFeatureList& results, bool force_new)
|
|||
|
||||
t.reset ();
|
||||
|
||||
cerr << "working on channel " << i << endl;
|
||||
|
||||
if (t.run ("", this, i, these_results)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
cerr << "done\n";
|
||||
|
||||
/* translate all transients to give absolute position */
|
||||
|
||||
for (AnalysisFeatureList::iterator i = these_results.begin(); i != these_results.end(); ++i) {
|
||||
|
@ -1357,6 +1363,11 @@ AudioRegion::get_transients (AnalysisFeatureList& results, bool force_new)
|
|||
/* make sure ours are clean too */
|
||||
|
||||
TransientDetector::cleanup_transients (_transients, pl->session().frame_rate(), 3.0);
|
||||
|
||||
} else {
|
||||
|
||||
TransientDetector::cleanup_transients (_transients, pl->session().frame_rate(), 3.0);
|
||||
results = _transients;
|
||||
}
|
||||
|
||||
_valid_transients = true;
|
||||
|
|
|
@ -70,6 +70,7 @@ AudioSource::AudioSource (Session& s, ustring name)
|
|||
AudioSource::AudioSource (Session& s, const XMLNode& node)
|
||||
: Source (s, node)
|
||||
{
|
||||
|
||||
_peaks_built = false;
|
||||
_peak_byte_max = 0;
|
||||
peakfile = -1;
|
||||
|
@ -213,7 +214,7 @@ AudioSource::initialize_peakfile (bool newfile, ustring audio_path)
|
|||
|
||||
/* we found it in the peaks dir, so check it out */
|
||||
|
||||
if (statbuf.st_size == 0) {
|
||||
if (statbuf.st_size == 0 || (statbuf.st_size < ((length() / _FPP) * sizeof (PeakData)))) {
|
||||
// empty
|
||||
_peaks_built = false;
|
||||
} else {
|
||||
|
@ -221,12 +222,22 @@ AudioSource::initialize_peakfile (bool newfile, ustring audio_path)
|
|||
struct stat stat_file;
|
||||
int err = stat (audio_path.c_str(), &stat_file);
|
||||
|
||||
if (!err && stat_file.st_mtime > statbuf.st_mtime){
|
||||
if (err) {
|
||||
_peaks_built = false;
|
||||
_peak_byte_max = 0;
|
||||
} else {
|
||||
_peaks_built = true;
|
||||
_peak_byte_max = statbuf.st_size;
|
||||
|
||||
/* allow 6 seconds slop on checking peak vs. file times because of various
|
||||
disk action "races"
|
||||
*/
|
||||
|
||||
if (stat_file.st_mtime > statbuf.st_mtime && (stat_file.st_mtime - statbuf.st_mtime > 6)) {
|
||||
_peaks_built = false;
|
||||
_peak_byte_max = 0;
|
||||
} else {
|
||||
_peaks_built = true;
|
||||
_peak_byte_max = statbuf.st_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -422,9 +422,9 @@ Automatable::protect_automation ()
|
|||
}
|
||||
|
||||
void
|
||||
Automatable::automation_snapshot (nframes_t now)
|
||||
Automatable::automation_snapshot (nframes_t now, bool force)
|
||||
{
|
||||
if (_last_automation_snapshot > now || (now - _last_automation_snapshot) > _automation_interval) {
|
||||
if (force || _last_automation_snapshot > now || (now - _last_automation_snapshot) > _automation_interval) {
|
||||
|
||||
for (Controls::iterator i = _controls.begin(); i != _controls.end(); ++i) {
|
||||
if (i->second->list()->automation_write()) {
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <ardour/filter.h>
|
||||
#include <ardour/region_factory.h>
|
||||
#include <ardour/source_factory.h>
|
||||
#include <ardour/analyser.h>
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
|
@ -101,6 +102,10 @@ Filter::finish (boost::shared_ptr<Region> region, SourceList& nsrcs, string regi
|
|||
smfs->set_timeline_position (region->position());
|
||||
smfs->flush_footer ();
|
||||
}
|
||||
|
||||
/* now that there is data there, requeue the file for analysis */
|
||||
|
||||
Analyser::queue_source_for_analysis (*si, false);
|
||||
}
|
||||
|
||||
/* create a new region */
|
||||
|
|
|
@ -19,9 +19,12 @@
|
|||
#include <cstdio> // Needed so that libraptor (included in lrdf) won't complain
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <locale.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef VST_SUPPORT
|
||||
#include <fst.h>
|
||||
|
@ -31,12 +34,16 @@
|
|||
#include <xmmintrin.h>
|
||||
#endif
|
||||
|
||||
#include <glibmm/fileutils.h>
|
||||
#include <glibmm/miscutils.h>
|
||||
|
||||
#include <lrdf.h>
|
||||
|
||||
#include <pbd/error.h>
|
||||
#include <pbd/id.h>
|
||||
#include <pbd/strsplit.h>
|
||||
#include <pbd/fpu.h>
|
||||
#include <pbd/file_utils.h>
|
||||
|
||||
#include <midi++/port.h>
|
||||
#include <midi++/manager.h>
|
||||
|
@ -54,6 +61,7 @@
|
|||
#include <ardour/source_factory.h>
|
||||
#include <ardour/control_protocol_manager.h>
|
||||
#include <ardour/audioengine.h>
|
||||
#include <ardour/filesystem_paths.h>
|
||||
|
||||
#ifdef HAVE_LIBLO
|
||||
#include <ardour/osc.h>
|
||||
|
@ -96,6 +104,8 @@ apply_gain_to_buffer_t ARDOUR::apply_gain_to_buffer = 0;
|
|||
mix_buffers_with_gain_t ARDOUR::mix_buffers_with_gain = 0;
|
||||
mix_buffers_no_gain_t ARDOUR::mix_buffers_no_gain = 0;
|
||||
|
||||
sigc::signal<void,std::string> ARDOUR::BootMessage;
|
||||
|
||||
#ifdef HAVE_LIBLO
|
||||
static int
|
||||
setup_osc ()
|
||||
|
@ -107,6 +117,7 @@ setup_osc ()
|
|||
osc = new OSC (Config->get_osc_port());
|
||||
|
||||
if (Config->get_use_osc ()) {
|
||||
BootMessage (_("Starting OSC"));
|
||||
return osc->start ();
|
||||
} else {
|
||||
return 0;
|
||||
|
@ -122,6 +133,8 @@ setup_midi ()
|
|||
return 0;
|
||||
}
|
||||
|
||||
BootMessage (_("Configuring MIDI ports"));
|
||||
|
||||
for (std::map<string,XMLNode>::iterator i = Config->midi_ports.begin(); i != Config->midi_ports.end(); ++i) {
|
||||
MIDI::Manager::instance()->add_port (i->second);
|
||||
}
|
||||
|
@ -253,6 +266,33 @@ setup_hardware_optimization (bool try_optimization)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
lotsa_files_please ()
|
||||
{
|
||||
struct rlimit rl;
|
||||
|
||||
if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
|
||||
|
||||
rl.rlim_cur = rl.rlim_max;
|
||||
|
||||
if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
|
||||
if (rl.rlim_cur == RLIM_INFINITY) {
|
||||
error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
|
||||
} else {
|
||||
error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
|
||||
}
|
||||
} else {
|
||||
if (rl.rlim_cur == RLIM_INFINITY) {
|
||||
info << _("Removed open file count limit. Excellent!") << endmsg;
|
||||
} else {
|
||||
info << string_compose (_("Ardour will be limited to %1 open files"), rl.rlim_cur) << endmsg;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ARDOUR::init (bool use_vst, bool try_optimization)
|
||||
{
|
||||
|
@ -262,9 +302,14 @@ ARDOUR::init (bool use_vst, bool try_optimization)
|
|||
|
||||
setup_enum_writer ();
|
||||
|
||||
// allow ardour the absolute maximum number of open files
|
||||
lotsa_files_please ();
|
||||
|
||||
lrdf_init();
|
||||
Library = new AudioLibrary;
|
||||
|
||||
BootMessage (_("Loading configuration"));
|
||||
|
||||
Config = new Configuration;
|
||||
|
||||
if (Config->load_state ()) {
|
||||
|
@ -367,6 +412,34 @@ ARDOUR::get_ardour_revision ()
|
|||
return "$Rev$";
|
||||
}
|
||||
|
||||
void
|
||||
ARDOUR::find_bindings_files (map<string,string>& files)
|
||||
{
|
||||
vector<sys::path> found;
|
||||
|
||||
SearchPath spath = ardour_search_path() + user_config_directory() + system_config_search_path();
|
||||
|
||||
if (getenv ("ARDOUR_SAE")) {
|
||||
Glib::PatternSpec pattern("*SAE-*.bindings");
|
||||
find_matching_files_in_search_path (spath, pattern, found);
|
||||
} else {
|
||||
Glib::PatternSpec pattern("*.bindings");
|
||||
find_matching_files_in_search_path (spath, pattern, found);
|
||||
}
|
||||
|
||||
if (found.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (vector<sys::path>::iterator x = found.begin(); x != found.end(); ++x) {
|
||||
sys::path path = *x;
|
||||
pair<string,string> namepath;
|
||||
namepath.second = path.to_string();
|
||||
namepath.first = path.leaf().substr (0, path.leaf().find_first_of ('.'));
|
||||
files.insert (namepath);
|
||||
}
|
||||
}
|
||||
|
||||
ARDOUR::LocaleGuard::LocaleGuard (const char* str)
|
||||
{
|
||||
old = strdup (setlocale (LC_NUMERIC, NULL));
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include <ardour/region_factory.h>
|
||||
#include <ardour/source_factory.h>
|
||||
#include <ardour/resampled_source.h>
|
||||
#include <ardour/analyser.h>
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
|
@ -65,7 +66,7 @@ open_importable_source (const string& path, nframes_t samplerate, ARDOUR::SrcQua
|
|||
}
|
||||
|
||||
static std::string
|
||||
get_non_existent_filename (const std::string& basename, uint channel, uint channels)
|
||||
get_non_existent_filename (const bool allow_replacing, const std::string destdir, const std::string& basename, uint channel, uint channels)
|
||||
{
|
||||
char buf[PATH_MAX+1];
|
||||
bool goodfile = false;
|
||||
|
@ -84,7 +85,9 @@ get_non_existent_filename (const std::string& basename, uint channel, uint chann
|
|||
snprintf (buf, sizeof(buf), "%s.wav", base.c_str());
|
||||
}
|
||||
|
||||
if (Glib::file_test (buf, Glib::FILE_TEST_EXISTS)) {
|
||||
|
||||
string tempname = destdir + "/" + buf;
|
||||
if (!allow_replacing && Glib::file_test (tempname, Glib::FILE_TEST_EXISTS)) {
|
||||
|
||||
/* if the file already exists, we must come up with
|
||||
* a new name for it. for now we just keep appending
|
||||
|
@ -104,7 +107,7 @@ get_non_existent_filename (const std::string& basename, uint channel, uint chann
|
|||
}
|
||||
|
||||
static vector<string>
|
||||
get_paths_for_new_sources (const string& import_file_path, const string& session_dir, uint channels)
|
||||
get_paths_for_new_sources (const bool allow_replacing, const string& import_file_path, const string& session_dir, uint channels)
|
||||
{
|
||||
vector<string> new_paths;
|
||||
const string basename = basename_nosuffix (import_file_path);
|
||||
|
@ -115,7 +118,7 @@ get_paths_for_new_sources (const string& import_file_path, const string& session
|
|||
|
||||
filepath = session_dir;
|
||||
filepath += '/';
|
||||
filepath += get_non_existent_filename (basename, n, channels);
|
||||
filepath += get_non_existent_filename (allow_replacing, session_dir, basename, n, channels);
|
||||
|
||||
new_paths.push_back (filepath);
|
||||
}
|
||||
|
@ -123,6 +126,25 @@ get_paths_for_new_sources (const string& import_file_path, const string& session
|
|||
return new_paths;
|
||||
}
|
||||
|
||||
static bool
|
||||
map_existing_mono_sources (const vector<string>& new_paths, Session& sess,
|
||||
uint samplerate, vector<boost::shared_ptr<AudioFileSource> >& newfiles, Session *session)
|
||||
{
|
||||
for (vector<string>::const_iterator i = new_paths.begin();
|
||||
i != new_paths.end(); ++i)
|
||||
{
|
||||
boost::shared_ptr<Source> source = session->source_by_path_and_channel(*i, 0);
|
||||
|
||||
if (source == 0) {
|
||||
error << string_compose(_("Could not find a source for %1 even though we are updating this file!"), (*i)) << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
newfiles.push_back(boost::dynamic_pointer_cast<AudioFileSource>(source));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
create_mono_sources_for_writing (const vector<string>& new_paths, Session& sess,
|
||||
uint samplerate, vector<boost::shared_ptr<AudioFileSource> >& newfiles)
|
||||
|
@ -228,6 +250,10 @@ remove_file_source (boost::shared_ptr<AudioFileSource> file_source)
|
|||
::unlink (file_source->path().c_str());
|
||||
}
|
||||
|
||||
// This function is still unable to cleanly update an existing source, even though
|
||||
// it is possible to set the import_status flag accordingly. The functinality
|
||||
// is disabled at the GUI until the Source implementations are able to provide
|
||||
// the necessary API.
|
||||
void
|
||||
Session::import_audiofiles (import_status& status)
|
||||
{
|
||||
|
@ -254,13 +280,19 @@ Session::import_audiofiles (import_status& status)
|
|||
return;
|
||||
}
|
||||
|
||||
vector<string> new_paths = get_paths_for_new_sources (*p,
|
||||
vector<string> new_paths = get_paths_for_new_sources (status.replace_existing_source,
|
||||
*p,
|
||||
get_best_session_directory_for_new_source (),
|
||||
source->channels());
|
||||
|
||||
AudioSources newfiles;
|
||||
|
||||
status.cancel = !create_mono_sources_for_writing (new_paths, *this, frame_rate(), newfiles);
|
||||
if (status.replace_existing_source) {
|
||||
fatal << "THIS IS NOT IMPLEMENTED YET, IT SHOULD NEVER GET CALLED!!! DYING!" << endl;
|
||||
status.cancel = !map_existing_mono_sources (new_paths, *this, frame_rate(), newfiles, this);
|
||||
} else {
|
||||
status.cancel = !create_mono_sources_for_writing (new_paths, *this, frame_rate(), newfiles);
|
||||
}
|
||||
|
||||
// copy on cancel/failure so that any files that were created will be removed below
|
||||
std::copy (newfiles.begin(), newfiles.end(), std::back_inserter(all_new_sources));
|
||||
|
@ -286,11 +318,14 @@ Session::import_audiofiles (import_status& status)
|
|||
|
||||
/* flush the final length(s) to the header(s) */
|
||||
|
||||
for (AudioSources::iterator x = all_new_sources.begin();
|
||||
x != all_new_sources.end(); ++x)
|
||||
for (AudioSources::iterator x = all_new_sources.begin(); x != all_new_sources.end(); ++x)
|
||||
{
|
||||
(*x)->update_header(0, *now, xnow);
|
||||
(*x)->done_with_peakfile_writes ();
|
||||
|
||||
/* now that there is data there, requeue the file for analysis */
|
||||
|
||||
Analyser::queue_source_for_analysis (boost::static_pointer_cast<Source>(*x), false);
|
||||
}
|
||||
|
||||
/* save state so that we don't lose these new Sources */
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include <ardour/audioengine.h>
|
||||
#include <ardour/io.h>
|
||||
#include <ardour/route.h>
|
||||
#include <ardour/port.h>
|
||||
#include <ardour/audio_port.h>
|
||||
#include <ardour/midi_port.h>
|
||||
|
@ -1800,14 +1801,22 @@ IO::parse_gain_string (const string& str, vector<string>& ports)
|
|||
}
|
||||
|
||||
bool
|
||||
IO::set_name (const string& str)
|
||||
IO::set_name (const string& requested_name)
|
||||
{
|
||||
if (str == _name) {
|
||||
if (requested_name == _name) {
|
||||
return true;
|
||||
}
|
||||
|
||||
string name;
|
||||
Route *rt;
|
||||
if ( (rt = dynamic_cast<Route *>(this))) {
|
||||
name = Route::ensure_track_or_route_name(requested_name, _session);
|
||||
} else {
|
||||
name = requested_name;
|
||||
}
|
||||
|
||||
|
||||
/* replace all colons in the name. i wish we didn't have to do this */
|
||||
string name = str;
|
||||
|
||||
if (replace_all (name, ":", "-")) {
|
||||
warning << _("you cannot use colons to name objects with I/O connections") << endmsg;
|
||||
|
@ -2224,13 +2233,16 @@ IO::end_pan_touch (uint32_t which)
|
|||
}
|
||||
|
||||
void
|
||||
IO::automation_snapshot (nframes_t now)
|
||||
IO::automation_snapshot (nframes_t now, bool force)
|
||||
{
|
||||
Automatable::automation_snapshot (now);
|
||||
Automatable::automation_snapshot (now, force);
|
||||
|
||||
if (_last_automation_snapshot > now || (now - _last_automation_snapshot) > _automation_interval) {
|
||||
_panner->snapshot (now);
|
||||
}
|
||||
|
||||
_panner->snapshot (now);
|
||||
_last_automation_snapshot = now;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -1814,50 +1814,12 @@ Playlist::bump_name (string name, Session &session)
|
|||
string newname = name;
|
||||
|
||||
do {
|
||||
newname = Playlist::bump_name_once (newname);
|
||||
newname = bump_name_once (newname);
|
||||
} while (session.playlist_by_name (newname)!=NULL);
|
||||
|
||||
return newname;
|
||||
}
|
||||
|
||||
string
|
||||
Playlist::bump_name_once (string name)
|
||||
{
|
||||
string::size_type period;
|
||||
string newname;
|
||||
|
||||
if ((period = name.find_last_of ('.')) == string::npos) {
|
||||
newname = name;
|
||||
newname += ".1";
|
||||
} else {
|
||||
int isnumber = 1;
|
||||
const char *last_element = name.c_str() + period + 1;
|
||||
for (size_t i = 0; i < strlen(last_element); i++) {
|
||||
if (!isdigit(last_element[i])) {
|
||||
isnumber = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
long int version = strtol (name.c_str()+period+1, (char **)NULL, 10);
|
||||
|
||||
if (isnumber == 0 || errno != 0) {
|
||||
// last_element is not a number, or is too large
|
||||
newname = name;
|
||||
newname += ".1";
|
||||
} else {
|
||||
char buf[32];
|
||||
|
||||
snprintf (buf, sizeof(buf), "%ld", version+1);
|
||||
|
||||
newname = name.substr (0, period+1);
|
||||
newname += buf;
|
||||
}
|
||||
}
|
||||
|
||||
return newname;
|
||||
}
|
||||
|
||||
layer_t
|
||||
Playlist::top_layer() const
|
||||
|
|
|
@ -224,6 +224,19 @@ ARDOUR::find_plugin(Session& session, string identifier, PluginType type)
|
|||
return (*i)->load (session);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef VST_SUPPORT
|
||||
/* hmm, we didn't find it. could be because in older versions of Ardour.
|
||||
we used to store the name of a VST plugin, not its unique ID. so try
|
||||
again.
|
||||
*/
|
||||
|
||||
for (i = plugs.begin(); i != plugs.end(); ++i) {
|
||||
if (identifier == (*i)->name){
|
||||
return (*i)->load (session);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return PluginPtr ((Plugin*) 0);
|
||||
}
|
||||
|
|
|
@ -957,15 +957,15 @@ Region::adjust_to_sync (nframes_t pos)
|
|||
// cerr << "adjusting pos = " << pos << " to sync at " << _sync_position << " offset = " << offset << " with dir = " << sync_dir << endl;
|
||||
|
||||
if (sync_dir > 0) {
|
||||
if (max_frames - pos > offset) {
|
||||
pos -= offset;
|
||||
}
|
||||
} else {
|
||||
if (pos > offset) {
|
||||
pos += offset;
|
||||
pos -= offset;
|
||||
} else {
|
||||
pos = 0;
|
||||
}
|
||||
} else {
|
||||
if (max_frames - pos > offset) {
|
||||
pos += offset;
|
||||
}
|
||||
}
|
||||
|
||||
return pos;
|
||||
|
|
|
@ -46,6 +46,9 @@
|
|||
#include <ardour/amp.h>
|
||||
#include <ardour/meter.h>
|
||||
#include <ardour/buffer_set.h>
|
||||
#include <ardour/mix.h>
|
||||
#include <ardour/profile.h>
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
using namespace std;
|
||||
|
@ -190,6 +193,20 @@ Route::sync_order_keys ()
|
|||
}
|
||||
}
|
||||
|
||||
string
|
||||
Route::ensure_track_or_route_name(string name, Session &session)
|
||||
{
|
||||
string newname = name;
|
||||
|
||||
while (session.route_by_name (newname)!=NULL)
|
||||
{
|
||||
newname = bump_name_once (newname);
|
||||
}
|
||||
|
||||
return newname;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Route::inc_gain (gain_t fraction, void *src)
|
||||
{
|
||||
|
@ -843,8 +860,8 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorStreams*
|
|||
reset_panner ();
|
||||
}
|
||||
|
||||
|
||||
processors_changed (); /* EMIT SIGNAL */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2291,7 +2308,7 @@ Route::handle_transport_stopped (bool abort_ignored, bool did_locate, bool can_f
|
|||
Glib::RWLock::ReaderLock lm (_processor_lock);
|
||||
|
||||
if (!did_locate) {
|
||||
automation_snapshot (now);
|
||||
automation_snapshot (now, true);
|
||||
}
|
||||
|
||||
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
|
||||
|
@ -2398,7 +2415,7 @@ Route::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nfra
|
|||
if (lm.locked()) {
|
||||
// automation snapshot can also be called from the non-rt context
|
||||
// and it uses the processor list, so we take the lock out here
|
||||
automation_snapshot (_session.transport_frame());
|
||||
automation_snapshot (_session.transport_frame(), false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2569,12 +2586,15 @@ Route::set_latency_delay (nframes_t longest_session_latency)
|
|||
}
|
||||
|
||||
void
|
||||
Route::automation_snapshot (nframes_t now)
|
||||
Route::automation_snapshot (nframes_t now, bool force)
|
||||
{
|
||||
IO::automation_snapshot (now);
|
||||
if (!force && !should_snapshot(now)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
|
||||
(*i)->automation_snapshot (now);
|
||||
// IO::automation_snapshot (now, force); ?
|
||||
(*i)->automation_snapshot (now, force);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -504,9 +504,13 @@ Session::when_engine_running ()
|
|||
|
||||
/* we don't want to run execute this again */
|
||||
|
||||
BootMessage (_("Set block size and sample rate"));
|
||||
|
||||
set_block_size (_engine.frames_per_cycle());
|
||||
set_frame_rate (_engine.frame_rate());
|
||||
|
||||
BootMessage (_("Using configuration"));
|
||||
|
||||
Config->map_parameters (mem_fun (*this, &Session::config_changed));
|
||||
|
||||
/* every time we reconnect, recompute worst case output latencies */
|
||||
|
@ -562,6 +566,8 @@ Session::when_engine_running ()
|
|||
error << _("cannot setup Click I/O") << endmsg;
|
||||
}
|
||||
|
||||
BootMessage (_("Compute I/O Latencies"));
|
||||
|
||||
set_worst_io_latencies ();
|
||||
|
||||
if (_clicking) {
|
||||
|
@ -572,6 +578,8 @@ Session::when_engine_running ()
|
|||
to the physical outputs currently available
|
||||
*/
|
||||
|
||||
BootMessage (_("Set up standard connections"));
|
||||
|
||||
/* ONE: MONO */
|
||||
|
||||
for (uint32_t np = 0; np < n_physical_outputs; ++np) {
|
||||
|
@ -672,11 +680,15 @@ Session::when_engine_running ()
|
|||
}
|
||||
add_bundle (c);
|
||||
}
|
||||
|
||||
BootMessage (_("Connect ports"));
|
||||
|
||||
hookup_io ();
|
||||
|
||||
/* catch up on send+insert cnts */
|
||||
|
||||
BootMessage (_("Catch up with send/insert state"));
|
||||
|
||||
insert_cnt = 0;
|
||||
|
||||
for (list<PortInsert*>::iterator i = _port_inserts.begin(); i != _port_inserts.end(); ++i) {
|
||||
|
@ -704,14 +716,17 @@ Session::when_engine_running ()
|
|||
|
||||
_state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
|
||||
|
||||
|
||||
/* hook us up to the engine */
|
||||
|
||||
BootMessage (_("Connect to engine"));
|
||||
|
||||
_engine.set_session (this);
|
||||
|
||||
#ifdef HAVE_LIBLO
|
||||
/* and to OSC */
|
||||
|
||||
BootMessage (_("OSC startup"));
|
||||
|
||||
osc->set_session (*this);
|
||||
#endif
|
||||
|
||||
|
@ -2545,42 +2560,55 @@ Session::region_name (string& result, string base, bool newlevel) const
|
|||
|
||||
void
|
||||
Session::add_region (boost::shared_ptr<Region> region)
|
||||
{
|
||||
vector<boost::shared_ptr<Region> > v;
|
||||
v.push_back (region);
|
||||
add_regions (v);
|
||||
}
|
||||
|
||||
void
|
||||
Session::add_regions (vector<boost::shared_ptr<Region> >& new_regions)
|
||||
{
|
||||
bool added = false;
|
||||
|
||||
{
|
||||
Glib::Mutex::Lock lm (region_lock);
|
||||
|
||||
if (region == 0) {
|
||||
error << _("Session::add_region() ignored a null region. Warning: you might have lost a region.") << endmsg;
|
||||
} else {
|
||||
for (vector<boost::shared_ptr<Region> >::iterator ii = new_regions.begin(); ii != new_regions.end(); ++ii) {
|
||||
|
||||
boost::shared_ptr<Region> region = *ii;
|
||||
|
||||
if (region == 0) {
|
||||
|
||||
RegionList::iterator x;
|
||||
|
||||
for (x = regions.begin(); x != regions.end(); ++x) {
|
||||
|
||||
if (region->region_list_equivalent (x->second)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (x == regions.end()) {
|
||||
|
||||
pair<RegionList::key_type,RegionList::mapped_type> entry;
|
||||
|
||||
entry.first = region->id();
|
||||
entry.second = region;
|
||||
|
||||
pair<RegionList::iterator,bool> x = regions.insert (entry);
|
||||
error << _("Session::add_region() ignored a null region. Warning: you might have lost a region.") << endmsg;
|
||||
|
||||
} else {
|
||||
|
||||
if (!x.second) {
|
||||
return;
|
||||
RegionList::iterator x;
|
||||
|
||||
for (x = regions.begin(); x != regions.end(); ++x) {
|
||||
|
||||
if (region->region_list_equivalent (x->second)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
added = true;
|
||||
}
|
||||
|
||||
|
||||
if (x == regions.end()) {
|
||||
|
||||
pair<RegionList::key_type,RegionList::mapped_type> entry;
|
||||
|
||||
entry.first = region->id();
|
||||
entry.second = region;
|
||||
|
||||
pair<RegionList::iterator,bool> x = regions.insert (entry);
|
||||
|
||||
if (!x.second) {
|
||||
return;
|
||||
}
|
||||
|
||||
added = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2591,9 +2619,33 @@ Session::add_region (boost::shared_ptr<Region> region)
|
|||
set_dirty();
|
||||
|
||||
if (added) {
|
||||
region->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_region), boost::weak_ptr<Region>(region)));
|
||||
region->StateChanged.connect (sigc::bind (mem_fun (*this, &Session::region_changed), boost::weak_ptr<Region>(region)));
|
||||
RegionAdded (region); /* EMIT SIGNAL */
|
||||
|
||||
vector<boost::weak_ptr<Region> > v;
|
||||
boost::shared_ptr<Region> first_r;
|
||||
|
||||
for (vector<boost::shared_ptr<Region> >::iterator ii = new_regions.begin(); ii != new_regions.end(); ++ii) {
|
||||
|
||||
boost::shared_ptr<Region> region = *ii;
|
||||
|
||||
if (region == 0) {
|
||||
|
||||
error << _("Session::add_region() ignored a null region. Warning: you might have lost a region.") << endmsg;
|
||||
|
||||
} else {
|
||||
v.push_back (region);
|
||||
|
||||
if (!first_r) {
|
||||
first_r = region;
|
||||
}
|
||||
}
|
||||
|
||||
region->StateChanged.connect (sigc::bind (mem_fun (*this, &Session::region_changed), boost::weak_ptr<Region>(region)));
|
||||
region->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_region), boost::weak_ptr<Region>(region)));
|
||||
}
|
||||
|
||||
if (!v.empty()) {
|
||||
RegionsAdded (v); /* EMIT SIGNAL */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2680,18 +2732,12 @@ Session::destroy_region (boost::shared_ptr<Region> region)
|
|||
vector<boost::shared_ptr<Source> > srcs;
|
||||
|
||||
{
|
||||
boost::shared_ptr<AudioRegion> aregion;
|
||||
|
||||
if ((aregion = boost::dynamic_pointer_cast<AudioRegion> (region)) == 0) {
|
||||
return 0;
|
||||
if (region->playlist()) {
|
||||
region->playlist()->destroy_region (region);
|
||||
}
|
||||
|
||||
if (aregion->playlist()) {
|
||||
aregion->playlist()->destroy_region (region);
|
||||
}
|
||||
|
||||
for (uint32_t n = 0; n < aregion->n_channels(); ++n) {
|
||||
srcs.push_back (aregion->source (n));
|
||||
for (uint32_t n = 0; n < region->n_channels(); ++n) {
|
||||
srcs.push_back (region->source (n));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2699,17 +2745,10 @@ Session::destroy_region (boost::shared_ptr<Region> region)
|
|||
|
||||
for (vector<boost::shared_ptr<Source> >::iterator i = srcs.begin(); i != srcs.end(); ++i) {
|
||||
|
||||
if (!(*i)->used()) {
|
||||
boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*i);
|
||||
|
||||
if (afs) {
|
||||
(afs)->mark_for_remove ();
|
||||
}
|
||||
|
||||
(*i)->mark_for_remove ();
|
||||
(*i)->drop_references ();
|
||||
|
||||
cerr << "source was not used by any playlist\n";
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -350,11 +350,15 @@ Session::second_stage_init (bool new_session)
|
|||
return -1;
|
||||
}
|
||||
|
||||
BootMessage (_("Reset Remote Controls"));
|
||||
|
||||
//send_full_time_code ();
|
||||
_engine.transport_locate (0);
|
||||
deliver_mmc (MIDI::MachineControl::cmdMmcReset, 0);
|
||||
deliver_mmc (MIDI::MachineControl::cmdLocate, 0);
|
||||
|
||||
BootMessage (_("Reset Control Protocols"));
|
||||
|
||||
ControlProtocolManager::instance().set_session (*this);
|
||||
|
||||
if (new_session) {
|
||||
|
@ -364,7 +368,6 @@ Session::second_stage_init (bool new_session)
|
|||
}
|
||||
|
||||
_state_of_the_state = Clean;
|
||||
|
||||
|
||||
DirtyChanged (); /* EMIT SIGNAL */
|
||||
|
||||
|
@ -374,6 +377,8 @@ Session::second_stage_init (bool new_session)
|
|||
state_was_pending = false;
|
||||
}
|
||||
|
||||
BootMessage (_("Session loading complete"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1373,6 +1378,8 @@ Session::load_routes (const XMLNode& node)
|
|||
return -1;
|
||||
}
|
||||
|
||||
BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
|
||||
|
||||
new_routes.push_back (route);
|
||||
}
|
||||
|
||||
|
|
|
@ -1267,9 +1267,9 @@ Session::engine_halted ()
|
|||
void
|
||||
Session::xrun_recovery ()
|
||||
{
|
||||
if (Config->get_stop_recording_on_xrun() && actively_recording()) {
|
||||
Xrun (transport_frame()); //EMIT SIGNAL
|
||||
|
||||
HaltOnXrun (); /* EMIT SIGNAL */
|
||||
if (Config->get_stop_recording_on_xrun() && actively_recording()) {
|
||||
|
||||
/* it didn't actually halt, but we need
|
||||
to handle things in the same way.
|
||||
|
|
|
@ -195,6 +195,7 @@ Source::set_been_analysed (bool yn)
|
|||
}
|
||||
|
||||
if (yn) {
|
||||
load_transients (get_transients_path());
|
||||
AnalysisChanged(); // EMIT SIGNAL
|
||||
}
|
||||
}
|
||||
|
@ -265,3 +266,4 @@ Source::check_for_analysis_data_on_disk ()
|
|||
set_been_analysed (ok);
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,18 +6,20 @@ using namespace Vamp;
|
|||
using namespace ARDOUR;
|
||||
using namespace std;
|
||||
|
||||
string TransientDetector::_op_id;
|
||||
/* need a static initializer function for this */
|
||||
|
||||
string TransientDetector::_op_id = X_("libardourvampplugins:percussiononsets:2");
|
||||
|
||||
TransientDetector::TransientDetector (float sr)
|
||||
: AudioAnalyser (sr, X_("libardourvampplugins:percussiononsets"))
|
||||
{
|
||||
if (_op_id.empty()) {
|
||||
_op_id = X_("libardourvampplugins:percussiononsets");
|
||||
/* update the op_id */
|
||||
|
||||
// XXX this should load the above-named plugin and get the current version
|
||||
|
||||
_op_id += ":2";
|
||||
}
|
||||
_op_id = X_("libardourvampplugins:percussiononsets");
|
||||
|
||||
// XXX this should load the above-named plugin and get the current version
|
||||
|
||||
_op_id += ":2";
|
||||
}
|
||||
|
||||
TransientDetector::~TransientDetector()
|
||||
|
|
|
@ -86,6 +86,45 @@ legalize_for_path (string str)
|
|||
}
|
||||
#endif
|
||||
|
||||
string bump_name_once(std::string name)
|
||||
{
|
||||
string::size_type period;
|
||||
string newname;
|
||||
|
||||
if ((period = name.find_last_of ('.')) == string::npos) {
|
||||
newname = name;
|
||||
newname += ".1";
|
||||
} else {
|
||||
int isnumber = 1;
|
||||
const char *last_element = name.c_str() + period + 1;
|
||||
for (size_t i = 0; i < strlen(last_element); i++) {
|
||||
if (!isdigit(last_element[i])) {
|
||||
isnumber = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
long int version = strtol (name.c_str()+period+1, (char **)NULL, 10);
|
||||
|
||||
if (isnumber == 0 || errno != 0) {
|
||||
// last_element is not a number, or is too large
|
||||
newname = name;
|
||||
newname += ".1";
|
||||
} else {
|
||||
char buf[32];
|
||||
|
||||
snprintf (buf, sizeof(buf), "%ld", version+1);
|
||||
|
||||
newname = name.substr (0, period+1);
|
||||
newname += buf;
|
||||
}
|
||||
}
|
||||
|
||||
return newname;
|
||||
|
||||
}
|
||||
|
||||
ostream&
|
||||
operator<< (ostream& o, const BBT_Time& bbt)
|
||||
{
|
||||
|
@ -289,6 +328,8 @@ string_to_edit_mode (string str)
|
|||
return Splice;
|
||||
} else if (str == _("Slide Edit")) {
|
||||
return Slide;
|
||||
} else if (str == _("Lock Edit")) {
|
||||
return Lock;
|
||||
}
|
||||
fatal << string_compose (_("programming error: unknown edit mode string \"%1\""), str) << endmsg;
|
||||
/*NOTREACHED*/
|
||||
|
@ -302,6 +343,9 @@ edit_mode_to_string (EditMode mode)
|
|||
case Slide:
|
||||
return _("Slide Edit");
|
||||
|
||||
case Lock:
|
||||
return _("Lock Edit");
|
||||
|
||||
default:
|
||||
case Splice:
|
||||
return _("Splice Edit");
|
||||
|
|
|
@ -10,6 +10,9 @@ Import('env libraries install_prefix')
|
|||
pangomm = env.Copy()
|
||||
pangomm.Merge([libraries['glibmm2'], libraries['pango'], libraries['sigc2'], libraries['cairomm'], libraries['cairo']])
|
||||
|
||||
if pangomm['IS_OSX']:
|
||||
pangomm.Append (LINKFLAGS="-Xlinker -headerpad -Xlinker 2048")
|
||||
|
||||
libpangomm = pangomm.SharedLibrary('pangomm', pangomm_files)
|
||||
Default(libpangomm)
|
||||
|
||||
|
|
|
@ -32,6 +32,8 @@ gtkmm2ext.Append(CXXFLAGS=["-DLIBSIGC_DISABLE_DEPRECATED", "-DGLIBMM_DEFAULT_SIG
|
|||
gtkmm2ext.Append(PACKAGE=domain)
|
||||
gtkmm2ext.Append(POTFILE=domain + '.pot')
|
||||
|
||||
extra_sources = []
|
||||
|
||||
gtkmm2ext_files = Split("""
|
||||
auto_spin.cc
|
||||
barcontroller.cc
|
||||
|
@ -61,12 +63,21 @@ version.cc
|
|||
window_title.cc
|
||||
""")
|
||||
|
||||
gtkosx_files=Split("""
|
||||
sync-menu.c
|
||||
""")
|
||||
|
||||
if gtkmm2ext['GTKOSX']:
|
||||
extra_sources += gtkosx_files
|
||||
gtkmm2ext.Append (CCFLAGS="-DTOP_MENUBAR -DGTKOSX")
|
||||
gtkmm2ext.Append (LINKFLAGS="-framework Carbon")
|
||||
|
||||
gtkmm2ext.VersionBuild(['version.cc','gtkmm2ext/version.h'], [])
|
||||
|
||||
gtkmm2ext.Append(CCFLAGS="-D_REENTRANT")
|
||||
gtkmm2ext.Append(CCFLAGS="-DLOCALEDIR=\\\""+final_prefix+"/share/locale\\\"")
|
||||
|
||||
libgtkmm2ext = gtkmm2ext.SharedLibrary('gtkmm2ext', gtkmm2ext_files)
|
||||
libgtkmm2ext = gtkmm2ext.SharedLibrary('gtkmm2ext', gtkmm2ext_files + extra_sources)
|
||||
|
||||
Default(libgtkmm2ext)
|
||||
|
||||
|
@ -78,5 +89,6 @@ env.Alias('install', env.Install(os.path.join(install_prefix, env['LIBDIR'], 'ar
|
|||
env.Alias('tarball', env.Distribute (env['DISTTREE'],
|
||||
[ 'SConscript', 'i18n.h', 'gettext.h'] +
|
||||
gtkmm2ext_files +
|
||||
gtkosx_files +
|
||||
glob.glob('po/*.po') +
|
||||
glob.glob('gtkmm2ext/*.h')))
|
||||
|
|
|
@ -560,10 +560,31 @@ UI::popup_error (const char *text)
|
|||
pup->touch ();
|
||||
}
|
||||
|
||||
#ifdef GTKOSX
|
||||
extern "C" {
|
||||
int gdk_quartz_in_carbon_menu_event_handler ();
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
UI::flush_pending ()
|
||||
{
|
||||
#ifdef GTKOSX
|
||||
/* as of february 11th 2008, gtk/osx has a problem in that mac menu events
|
||||
are handled using Carbon with an "internal" event handling system that
|
||||
doesn't pass things back to the glib/gtk main loop. this makes
|
||||
gtk_main_iteration() block if we call it while in a menu event handler
|
||||
because glib gets confused and thinks there are two threads running
|
||||
g_main_poll_func().
|
||||
|
||||
this hack (relies on code in gtk2_ardour/sync-menu.c) works
|
||||
around that.
|
||||
*/
|
||||
|
||||
if (gdk_quartz_in_carbon_menu_event_handler()) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (!caller_is_ui_thread()) {
|
||||
error << "non-UI threads cannot call UI::flush_pending()"
|
||||
<< endmsg;
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace Gtkmm2ext {
|
|||
|
||||
class PixFader : public Gtk::DrawingArea {
|
||||
public:
|
||||
PixFader (Glib::RefPtr<Gdk::Pixbuf> belt_image, Gtk::Adjustment& adjustment);
|
||||
PixFader (Glib::RefPtr<Gdk::Pixbuf> belt_image, Gtk::Adjustment& adjustment, int orientation);
|
||||
virtual ~PixFader ();
|
||||
|
||||
protected:
|
||||
|
@ -44,23 +44,32 @@ class PixFader : public Gtk::DrawingArea {
|
|||
bool on_motion_notify_event (GdkEventMotion*);
|
||||
bool on_scroll_event (GdkEventScroll* ev);
|
||||
|
||||
private:
|
||||
enum Orientation {
|
||||
VERT=1,
|
||||
HORIZ=2,
|
||||
};
|
||||
|
||||
private:
|
||||
Glib::RefPtr<Gdk::Pixbuf> pixbuf;
|
||||
gint pixheight;
|
||||
int span, girth;
|
||||
int _orien;
|
||||
|
||||
GdkRectangle view;
|
||||
|
||||
GdkWindow* grab_window;
|
||||
double grab_y;
|
||||
double grab_loc;
|
||||
double grab_start;
|
||||
int last_drawn;
|
||||
bool dragging;
|
||||
float default_value;
|
||||
int unity_y;
|
||||
int unity_loc;
|
||||
|
||||
void adjustment_changed ();
|
||||
|
||||
int display_height ();
|
||||
int display_span ();
|
||||
|
||||
static int fine_scale_modifier;
|
||||
static int extra_fine_scale_modifier;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ class SliderController : public Gtkmm2ext::PixFader
|
|||
{
|
||||
public:
|
||||
SliderController (Glib::RefPtr<Gdk::Pixbuf> image,
|
||||
Gtk::Adjustment* adj,
|
||||
Gtk::Adjustment* adj, int orientation,
|
||||
PBD::Controllable&,
|
||||
bool with_numeric = true);
|
||||
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/* GTK+ Integration for the Mac OS X Menubar.
|
||||
*
|
||||
* Copyright (C) 2007 Pioneer Research Center USA, Inc.
|
||||
* Copyright (C) 2007 Imendio AB
|
||||
*
|
||||
* For further information, see:
|
||||
* http://developer.imendio.com/projects/gtk-macosx/menubar
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __IGE_MAC_MENU_H__
|
||||
#define __IGE_MAC_MENU_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _IgeMacMenuGroup IgeMacMenuGroup;
|
||||
|
||||
void ige_mac_menu_set_menu_bar (GtkMenuShell *menu_shell);
|
||||
void ige_mac_menu_set_quit_menu_item (GtkMenuItem *menu_item);
|
||||
|
||||
IgeMacMenuGroup * ige_mac_menu_add_app_menu_group (void);
|
||||
void ige_mac_menu_add_app_menu_item (IgeMacMenuGroup *group,
|
||||
GtkMenuItem *menu_item,
|
||||
const gchar *label);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __IGE_MAC_MENU_H__ */
|
|
@ -27,21 +27,36 @@ using namespace Gtk;
|
|||
using namespace Gdk;
|
||||
using namespace std;
|
||||
|
||||
PixFader::PixFader (Glib::RefPtr<Pixbuf> belt, Gtk::Adjustment& adj)
|
||||
#ifdef GTKOSX
|
||||
int PixFader::fine_scale_modifier = GDK_META_MASK;
|
||||
#else
|
||||
int PixFader::fine_scale_modifier = GDK_CONTROL_MASK;
|
||||
#endif
|
||||
|
||||
int PixFader::extra_fine_scale_modifier = GDK_MOD1_MASK;
|
||||
|
||||
PixFader::PixFader (Glib::RefPtr<Pixbuf> belt, Gtk::Adjustment& adj, int orientation)
|
||||
|
||||
: adjustment (adj),
|
||||
pixbuf (belt)
|
||||
pixbuf (belt),
|
||||
_orien(orientation)
|
||||
{
|
||||
dragging = false;
|
||||
default_value = adjustment.get_value();
|
||||
last_drawn = -1;
|
||||
pixheight = pixbuf->get_height();
|
||||
|
||||
view.x = 0;
|
||||
view.y = 0;
|
||||
view.width = pixbuf->get_width();
|
||||
view.height = pixheight / 2;
|
||||
|
||||
unity_y = (int) rint (view.height - (default_value * view.height)) - 1;
|
||||
if (orientation == VERT) {
|
||||
view.width = girth = pixbuf->get_width();
|
||||
view.height = span = pixbuf->get_height() / 2;
|
||||
unity_loc = (int) rint (view.height - (default_value * view.height)) - 1;
|
||||
} else {
|
||||
view.width = span = pixbuf->get_width () / 2;
|
||||
view.height = girth = pixbuf->get_height();
|
||||
unity_loc = (int) rint (default_value * view.width) - 1;
|
||||
}
|
||||
|
||||
add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK);
|
||||
|
||||
|
@ -57,13 +72,20 @@ bool
|
|||
PixFader::on_expose_event (GdkEventExpose* ev)
|
||||
{
|
||||
GdkRectangle intersection;
|
||||
int dh = display_height ();
|
||||
int offset_into_pixbuf = (int) floor (view.height / ((float) view.height / dh));
|
||||
int srcx, srcy, ds = display_span ();
|
||||
int offset_into_pixbuf = (int) floor (span / ((float) span / ds));
|
||||
Glib::RefPtr<Gdk::GC> fg_gc (get_style()->get_fg_gc(get_state()));
|
||||
|
||||
if (gdk_rectangle_intersect (&view, &ev->area, &intersection)) {
|
||||
if (_orien == VERT) {
|
||||
srcx = intersection.x;
|
||||
srcy = offset_into_pixbuf + intersection.y;
|
||||
} else {
|
||||
srcx = offset_into_pixbuf + intersection.x;
|
||||
srcy = intersection.y;
|
||||
}
|
||||
get_window()->draw_pixbuf (fg_gc, pixbuf,
|
||||
intersection.x, offset_into_pixbuf + intersection.y,
|
||||
srcx, srcy,
|
||||
intersection.x, intersection.y,
|
||||
intersection.width, intersection.height,
|
||||
Gdk::RGB_DITHER_NONE, 0, 0);
|
||||
|
@ -75,10 +97,12 @@ PixFader::on_expose_event (GdkEventExpose* ev)
|
|||
}
|
||||
|
||||
/* always draw the line */
|
||||
|
||||
get_window()->draw_line (fg_gc, 1, unity_y, view.width - 2, unity_y);
|
||||
|
||||
last_drawn = dh;
|
||||
if (_orien == VERT) {
|
||||
get_window()->draw_line (fg_gc, 1, unity_loc, girth - 2, unity_loc);
|
||||
} else {
|
||||
get_window()->draw_line (fg_gc, unity_loc, 1, unity_loc, girth - 2);
|
||||
}
|
||||
last_drawn = ds;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -96,8 +120,8 @@ PixFader::on_button_press_event (GdkEventButton* ev)
|
|||
case 1:
|
||||
case 2:
|
||||
add_modal_grab();
|
||||
grab_y = ev->y;
|
||||
grab_start = ev->y;
|
||||
grab_loc = (_orien == VERT) ? ev->y : ev->x;
|
||||
grab_start = (_orien == VERT) ? ev->y : ev->x;
|
||||
grab_window = ev->window;
|
||||
dragging = true;
|
||||
break;
|
||||
|
@ -112,7 +136,9 @@ PixFader::on_button_press_event (GdkEventButton* ev)
|
|||
bool
|
||||
PixFader::on_button_release_event (GdkEventButton* ev)
|
||||
{
|
||||
double fract;
|
||||
double fract, ev_pos;
|
||||
|
||||
ev_pos = (_orien == VERT) ? ev->y : 0; // Don't step if we are horizontal
|
||||
|
||||
switch (ev->button) {
|
||||
case 1:
|
||||
|
@ -120,15 +146,15 @@ PixFader::on_button_release_event (GdkEventButton* ev)
|
|||
remove_modal_grab();
|
||||
dragging = false;
|
||||
|
||||
if (ev->y == grab_start) {
|
||||
if (ev_pos == grab_start) {
|
||||
|
||||
/* no motion - just a click */
|
||||
|
||||
if (ev->state & Gdk::SHIFT_MASK) {
|
||||
adjustment.set_value (default_value);
|
||||
} else if (ev->state & GDK_CONTROL_MASK) {
|
||||
} else if (ev->state & fine_scale_modifier) {
|
||||
adjustment.set_value (adjustment.get_lower());
|
||||
} else if (ev->y < view.height - display_height()) {
|
||||
} else if (ev_pos < span - display_span()) {
|
||||
/* above the current display height, remember X Window coords */
|
||||
adjustment.set_value (adjustment.get_value() + adjustment.get_step_increment());
|
||||
} else {
|
||||
|
@ -144,7 +170,7 @@ PixFader::on_button_release_event (GdkEventButton* ev)
|
|||
remove_modal_grab();
|
||||
dragging = false;
|
||||
|
||||
fract = 1.0 - (ev->y / view.height); // inverted X Window coordinates, grrr
|
||||
fract = 1.0 - (ev_pos / span); // inverted X Window coordinates, grrr
|
||||
|
||||
fract = min (1.0, fract);
|
||||
fract = max (0.0, fract);
|
||||
|
@ -164,29 +190,45 @@ bool
|
|||
PixFader::on_scroll_event (GdkEventScroll* ev)
|
||||
{
|
||||
double scale;
|
||||
|
||||
if (ev->state & GDK_CONTROL_MASK) {
|
||||
if (ev->state & GDK_MOD1_MASK) {
|
||||
scale = 0.05;
|
||||
|
||||
if (ev->state & fine_scale_modifier) {
|
||||
if (ev->state & extra_fine_scale_modifier) {
|
||||
scale = 0.01;
|
||||
} else {
|
||||
scale = 0.1;
|
||||
scale = 0.05;
|
||||
}
|
||||
} else {
|
||||
scale = 0.5;
|
||||
scale = 0.25;
|
||||
}
|
||||
|
||||
switch (ev->direction) {
|
||||
if (_orien == VERT) {
|
||||
switch (ev->direction) {
|
||||
|
||||
case GDK_SCROLL_UP:
|
||||
/* wheel up */
|
||||
adjustment.set_value (adjustment.get_value() + (adjustment.get_page_increment() * scale));
|
||||
break;
|
||||
case GDK_SCROLL_DOWN:
|
||||
/* wheel down */
|
||||
adjustment.set_value (adjustment.get_value() - (adjustment.get_page_increment() * scale));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case GDK_SCROLL_UP:
|
||||
/* wheel up */
|
||||
adjustment.set_value (adjustment.get_value() + (adjustment.get_page_increment() * scale));
|
||||
break;
|
||||
case GDK_SCROLL_DOWN:
|
||||
/* wheel down */
|
||||
adjustment.set_value (adjustment.get_value() - (adjustment.get_page_increment() * scale));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (ev->direction) {
|
||||
|
||||
case GDK_SCROLL_RIGHT:
|
||||
/* wheel right */
|
||||
adjustment.set_value (adjustment.get_value() + (adjustment.get_page_increment() * scale));
|
||||
break;
|
||||
case GDK_SCROLL_LEFT:
|
||||
/* wheel left */
|
||||
adjustment.set_value (adjustment.get_value() - (adjustment.get_page_increment() * scale));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -195,18 +237,17 @@ bool
|
|||
PixFader::on_motion_notify_event (GdkEventMotion* ev)
|
||||
{
|
||||
if (dragging) {
|
||||
double fract;
|
||||
double delta;
|
||||
double scale;
|
||||
|
||||
double fract, delta, scale, ev_pos;
|
||||
ev_pos = (_orien == VERT) ? ev->y : ev->x;
|
||||
//cerr << "PixFader::on_motion_notify_event() called x:y = " << ev->x << ":" << ev->y;
|
||||
if (ev->window != grab_window) {
|
||||
grab_y = ev->y;
|
||||
grab_loc = ev_pos;
|
||||
grab_window = ev->window;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ev->state & GDK_CONTROL_MASK) {
|
||||
if (ev->state & GDK_MOD1_MASK) {
|
||||
if (ev->state & fine_scale_modifier) {
|
||||
if (ev->state & extra_fine_scale_modifier) {
|
||||
scale = 0.05;
|
||||
} else {
|
||||
scale = 0.1;
|
||||
|
@ -214,20 +255,23 @@ PixFader::on_motion_notify_event (GdkEventMotion* ev)
|
|||
} else {
|
||||
scale = 1.0;
|
||||
}
|
||||
//cerr << " ev_pos=" << ev_pos << " grab_loc=" << grab_loc;
|
||||
delta = ev_pos - grab_loc;
|
||||
grab_loc = ev_pos;
|
||||
|
||||
delta = ev->y - grab_y;
|
||||
grab_y = ev->y;
|
||||
|
||||
fract = (delta / view.height);
|
||||
fract = (delta / span);
|
||||
|
||||
fract = min (1.0, fract);
|
||||
fract = max (-1.0, fract);
|
||||
|
||||
// X Window is top->bottom for 0..Y
|
||||
|
||||
fract = -fract;
|
||||
if (_orien == VERT) {
|
||||
fract = -fract;
|
||||
}
|
||||
|
||||
adjustment.set_value (adjustment.get_value() + scale * fract * (adjustment.get_upper() - adjustment.get_lower()));
|
||||
//cerr << " adj=" << adjustment.get_value() << " fract=" << fract << " delta=" << delta << " scale=" << scale << endl;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -236,14 +280,15 @@ PixFader::on_motion_notify_event (GdkEventMotion* ev)
|
|||
void
|
||||
PixFader::adjustment_changed ()
|
||||
{
|
||||
if (display_height() != last_drawn) {
|
||||
if (display_span() != last_drawn) {
|
||||
queue_draw ();
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
PixFader::display_height ()
|
||||
PixFader::display_span ()
|
||||
{
|
||||
float fract = (adjustment.get_upper() - adjustment.get_value ()) / ((adjustment.get_upper() - adjustment.get_lower()));
|
||||
return (int) floor (view.height * (1.0 - fract));
|
||||
return (_orien == VERT) ? (int)floor (span * (1.0 - fract)) : (int)floor (span * fract);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,11 +29,11 @@ using namespace Gtkmm2ext;
|
|||
using namespace PBD;
|
||||
|
||||
SliderController::SliderController (Glib::RefPtr<Gdk::Pixbuf> image,
|
||||
Gtk::Adjustment *adj,
|
||||
Gtk::Adjustment *adj, int orientation,
|
||||
Controllable& c,
|
||||
bool with_numeric)
|
||||
|
||||
: PixFader (image, *adj),
|
||||
: PixFader (image, *adj, orientation),
|
||||
binding_proxy (c),
|
||||
spin (*adj, 0, 2)
|
||||
{
|
||||
|
@ -63,7 +63,7 @@ VSliderController::VSliderController (Glib::RefPtr<Gdk::Pixbuf> image,
|
|||
Controllable& control,
|
||||
bool with_numeric)
|
||||
|
||||
: SliderController (image, adj, control, with_numeric)
|
||||
: SliderController (image, adj, VERT, control, with_numeric)
|
||||
{
|
||||
if (with_numeric) {
|
||||
spin_frame.add (spin);
|
||||
|
@ -79,7 +79,7 @@ HSliderController::HSliderController (Glib::RefPtr<Gdk::Pixbuf> image,
|
|||
Controllable& control,
|
||||
bool with_numeric)
|
||||
|
||||
: SliderController (image, adj, control, with_numeric)
|
||||
: SliderController (image, adj, HORIZ, control, with_numeric)
|
||||
{
|
||||
if (with_numeric) {
|
||||
spin_frame.add (spin);
|
||||
|
|
|
@ -0,0 +1,977 @@
|
|||
/* GTK+ Integration for the Mac OS X Menubar.
|
||||
*
|
||||
* Copyright (C) 2007 Pioneer Research Center USA, Inc.
|
||||
* Copyright (C) 2007 Imendio AB
|
||||
*
|
||||
* For further information, see:
|
||||
* http://developer.imendio.com/projects/gtk-macosx/menubar
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
#include <gtkmm2ext/sync-menu.h>
|
||||
|
||||
|
||||
/* TODO
|
||||
*
|
||||
* - Sync adding/removing/reordering items
|
||||
* - Create on demand? (can this be done with gtk+? ie fill in menu
|
||||
items when the menu is opened)
|
||||
* - Figure out what to do per app/window...
|
||||
*
|
||||
*/
|
||||
|
||||
#define IGE_QUARTZ_MENU_CREATOR 'IGEC'
|
||||
#define IGE_QUARTZ_ITEM_WIDGET 'IWID'
|
||||
|
||||
|
||||
static void sync_menu_shell (GtkMenuShell *menu_shell,
|
||||
MenuRef carbon_menu,
|
||||
gboolean toplevel,
|
||||
gboolean debug);
|
||||
|
||||
|
||||
/*
|
||||
* utility functions
|
||||
*/
|
||||
|
||||
static GtkWidget *
|
||||
find_menu_label (GtkWidget *widget)
|
||||
{
|
||||
GtkWidget *label = NULL;
|
||||
|
||||
if (GTK_IS_LABEL (widget))
|
||||
return widget;
|
||||
|
||||
if (GTK_IS_CONTAINER (widget))
|
||||
{
|
||||
GList *children;
|
||||
GList *l;
|
||||
|
||||
children = gtk_container_get_children (GTK_CONTAINER (widget));
|
||||
|
||||
for (l = children; l; l = l->next)
|
||||
{
|
||||
label = find_menu_label (l->data);
|
||||
if (label)
|
||||
break;
|
||||
}
|
||||
|
||||
g_list_free (children);
|
||||
}
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
static const gchar *
|
||||
get_menu_label_text (GtkWidget *menu_item,
|
||||
GtkWidget **label)
|
||||
{
|
||||
GtkWidget *my_label;
|
||||
|
||||
my_label = find_menu_label (menu_item);
|
||||
if (label)
|
||||
*label = my_label;
|
||||
|
||||
if (my_label)
|
||||
return gtk_label_get_text (GTK_LABEL (my_label));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
accel_find_func (GtkAccelKey *key,
|
||||
GClosure *closure,
|
||||
gpointer data)
|
||||
{
|
||||
return (GClosure *) data == closure;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* CarbonMenu functions
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
MenuRef menu;
|
||||
} CarbonMenu;
|
||||
|
||||
static GQuark carbon_menu_quark = 0;
|
||||
|
||||
static CarbonMenu *
|
||||
carbon_menu_new (void)
|
||||
{
|
||||
return g_slice_new0 (CarbonMenu);
|
||||
}
|
||||
|
||||
static void
|
||||
carbon_menu_free (CarbonMenu *menu)
|
||||
{
|
||||
g_slice_free (CarbonMenu, menu);
|
||||
}
|
||||
|
||||
static CarbonMenu *
|
||||
carbon_menu_get (GtkWidget *widget)
|
||||
{
|
||||
return g_object_get_qdata (G_OBJECT (widget), carbon_menu_quark);
|
||||
}
|
||||
|
||||
static void
|
||||
carbon_menu_connect (GtkWidget *menu,
|
||||
MenuRef menuRef)
|
||||
{
|
||||
CarbonMenu *carbon_menu = carbon_menu_get (menu);
|
||||
|
||||
if (!carbon_menu)
|
||||
{
|
||||
carbon_menu = carbon_menu_new ();
|
||||
|
||||
g_object_set_qdata_full (G_OBJECT (menu), carbon_menu_quark,
|
||||
carbon_menu,
|
||||
(GDestroyNotify) carbon_menu_free);
|
||||
}
|
||||
|
||||
carbon_menu->menu = menuRef;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* CarbonMenuItem functions
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
MenuRef menu;
|
||||
MenuItemIndex index;
|
||||
MenuRef submenu;
|
||||
GClosure *accel_closure;
|
||||
} CarbonMenuItem;
|
||||
|
||||
static GQuark carbon_menu_item_quark = 0;
|
||||
|
||||
static CarbonMenuItem *
|
||||
carbon_menu_item_new (void)
|
||||
{
|
||||
return g_slice_new0 (CarbonMenuItem);
|
||||
}
|
||||
|
||||
static void
|
||||
carbon_menu_item_free (CarbonMenuItem *menu_item)
|
||||
{
|
||||
if (menu_item->accel_closure)
|
||||
g_closure_unref (menu_item->accel_closure);
|
||||
|
||||
g_slice_free (CarbonMenuItem, menu_item);
|
||||
}
|
||||
|
||||
static CarbonMenuItem *
|
||||
carbon_menu_item_get (GtkWidget *widget)
|
||||
{
|
||||
return g_object_get_qdata (G_OBJECT (widget), carbon_menu_item_quark);
|
||||
}
|
||||
|
||||
static void
|
||||
carbon_menu_item_update_state (CarbonMenuItem *carbon_item,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
gboolean sensitive;
|
||||
gboolean visible;
|
||||
UInt32 set_attrs = 0;
|
||||
UInt32 clear_attrs = 0;
|
||||
|
||||
g_object_get (widget,
|
||||
"sensitive", &sensitive,
|
||||
"visible", &visible,
|
||||
NULL);
|
||||
|
||||
if (!sensitive)
|
||||
set_attrs |= kMenuItemAttrDisabled;
|
||||
else
|
||||
clear_attrs |= kMenuItemAttrDisabled;
|
||||
|
||||
if (!visible)
|
||||
set_attrs |= kMenuItemAttrHidden;
|
||||
else
|
||||
clear_attrs |= kMenuItemAttrHidden;
|
||||
|
||||
ChangeMenuItemAttributes (carbon_item->menu, carbon_item->index,
|
||||
set_attrs, clear_attrs);
|
||||
}
|
||||
|
||||
static void
|
||||
carbon_menu_item_update_active (CarbonMenuItem *carbon_item,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
gboolean active;
|
||||
|
||||
g_object_get (widget,
|
||||
"active", &active,
|
||||
NULL);
|
||||
|
||||
CheckMenuItem (carbon_item->menu, carbon_item->index,
|
||||
active);
|
||||
}
|
||||
|
||||
static void
|
||||
carbon_menu_item_update_submenu (CarbonMenuItem *carbon_item,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
GtkWidget *submenu;
|
||||
|
||||
submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget));
|
||||
|
||||
if (submenu)
|
||||
{
|
||||
const gchar *label_text;
|
||||
CFStringRef cfstr = NULL;
|
||||
|
||||
label_text = get_menu_label_text (widget, NULL);
|
||||
if (label_text)
|
||||
cfstr = CFStringCreateWithCString (NULL, label_text,
|
||||
kCFStringEncodingUTF8);
|
||||
|
||||
CreateNewMenu (0, 0, &carbon_item->submenu);
|
||||
SetMenuTitleWithCFString (carbon_item->submenu, cfstr);
|
||||
SetMenuItemHierarchicalMenu (carbon_item->menu, carbon_item->index,
|
||||
carbon_item->submenu);
|
||||
|
||||
sync_menu_shell (GTK_MENU_SHELL (submenu), carbon_item->submenu, FALSE, FALSE);
|
||||
|
||||
if (cfstr)
|
||||
CFRelease (cfstr);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetMenuItemHierarchicalMenu (carbon_item->menu, carbon_item->index,
|
||||
NULL);
|
||||
carbon_item->submenu = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
carbon_menu_item_update_label (CarbonMenuItem *carbon_item,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
const gchar *label_text;
|
||||
CFStringRef cfstr = NULL;
|
||||
|
||||
label_text = get_menu_label_text (widget, NULL);
|
||||
if (label_text)
|
||||
cfstr = CFStringCreateWithCString (NULL, label_text,
|
||||
kCFStringEncodingUTF8);
|
||||
|
||||
SetMenuItemTextWithCFString (carbon_item->menu, carbon_item->index,
|
||||
cfstr);
|
||||
|
||||
if (cfstr)
|
||||
CFRelease (cfstr);
|
||||
}
|
||||
|
||||
static void
|
||||
carbon_menu_item_update_accelerator (CarbonMenuItem *carbon_item,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
GtkWidget *label;
|
||||
|
||||
get_menu_label_text (widget, &label);
|
||||
|
||||
if (GTK_IS_ACCEL_LABEL (label) &&
|
||||
GTK_ACCEL_LABEL (label)->accel_closure)
|
||||
{
|
||||
GtkAccelKey *key;
|
||||
|
||||
key = gtk_accel_group_find (GTK_ACCEL_LABEL (label)->accel_group,
|
||||
accel_find_func,
|
||||
GTK_ACCEL_LABEL (label)->accel_closure);
|
||||
|
||||
if (key &&
|
||||
key->accel_key &&
|
||||
key->accel_flags & GTK_ACCEL_VISIBLE)
|
||||
{
|
||||
GdkDisplay *display = gtk_widget_get_display (widget);
|
||||
GdkKeymap *keymap = gdk_keymap_get_for_display (display);
|
||||
GdkKeymapKey *keys;
|
||||
gint n_keys;
|
||||
gint use_command;
|
||||
gboolean add_modifiers = FALSE;
|
||||
|
||||
if (gdk_keymap_get_entries_for_keyval (keymap, key->accel_key,
|
||||
&keys, &n_keys) == 0)
|
||||
{
|
||||
gint realkey = -1;
|
||||
|
||||
switch (key->accel_key) {
|
||||
case GDK_rightarrow:
|
||||
case GDK_Right:
|
||||
realkey = kRightArrowCharCode;
|
||||
break;
|
||||
case GDK_leftarrow:
|
||||
case GDK_Left:
|
||||
realkey = kLeftArrowCharCode;
|
||||
break;
|
||||
case GDK_uparrow:
|
||||
case GDK_Up:
|
||||
realkey = kUpArrowCharCode;
|
||||
break;
|
||||
case GDK_downarrow:
|
||||
case GDK_Down:
|
||||
realkey = kDownArrowCharCode;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (realkey != -1) {
|
||||
SetMenuItemCommandKey (carbon_item->menu, carbon_item->index,
|
||||
false, realkey);
|
||||
add_modifiers = TRUE;
|
||||
}
|
||||
|
||||
} else {
|
||||
SetMenuItemCommandKey (carbon_item->menu, carbon_item->index,
|
||||
true, keys[0].keycode);
|
||||
g_free (keys);
|
||||
add_modifiers = TRUE;
|
||||
}
|
||||
|
||||
if (add_modifiers)
|
||||
{
|
||||
UInt8 modifiers = 0; /* implies Command key */
|
||||
|
||||
use_command = 0;
|
||||
|
||||
if (key->accel_mods)
|
||||
{
|
||||
if (key->accel_mods & GDK_SHIFT_MASK) {
|
||||
modifiers |= kMenuShiftModifier;
|
||||
}
|
||||
|
||||
/* gdk/quartz maps Alt/Option to Mod1 */
|
||||
|
||||
if (key->accel_mods & (GDK_MOD1_MASK)) {
|
||||
modifiers |= kMenuOptionModifier;
|
||||
}
|
||||
|
||||
if (key->accel_mods & GDK_CONTROL_MASK) {
|
||||
modifiers |= kMenuControlModifier;
|
||||
}
|
||||
|
||||
/* gdk/quartz maps Command to Meta */
|
||||
|
||||
if (key->accel_mods & GDK_META_MASK) {
|
||||
use_command = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!use_command)
|
||||
modifiers |= kMenuNoCommandModifier;
|
||||
|
||||
SetMenuItemModifiers (carbon_item->menu, carbon_item->index,
|
||||
modifiers);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* otherwise, clear the menu shortcut */
|
||||
SetMenuItemModifiers (carbon_item->menu, carbon_item->index,
|
||||
kMenuNoModifiers | kMenuNoCommandModifier);
|
||||
ChangeMenuItemAttributes (carbon_item->menu, carbon_item->index,
|
||||
0, kMenuItemAttrUseVirtualKey);
|
||||
SetMenuItemCommandKey (carbon_item->menu, carbon_item->index,
|
||||
false, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
carbon_menu_item_accel_changed (GtkAccelGroup *accel_group,
|
||||
guint keyval,
|
||||
GdkModifierType modifier,
|
||||
GClosure *accel_closure,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
CarbonMenuItem *carbon_item = carbon_menu_item_get (widget);
|
||||
GtkWidget *label;
|
||||
|
||||
get_menu_label_text (widget, &label);
|
||||
|
||||
if (GTK_IS_ACCEL_LABEL (label) &&
|
||||
GTK_ACCEL_LABEL (label)->accel_closure == accel_closure)
|
||||
carbon_menu_item_update_accelerator (carbon_item, widget);
|
||||
}
|
||||
|
||||
static void
|
||||
carbon_menu_item_update_accel_closure (CarbonMenuItem *carbon_item,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
GtkAccelGroup *group;
|
||||
GtkWidget *label;
|
||||
|
||||
get_menu_label_text (widget, &label);
|
||||
|
||||
if (carbon_item->accel_closure)
|
||||
{
|
||||
group = gtk_accel_group_from_accel_closure (carbon_item->accel_closure);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (group,
|
||||
carbon_menu_item_accel_changed,
|
||||
widget);
|
||||
|
||||
g_closure_unref (carbon_item->accel_closure);
|
||||
carbon_item->accel_closure = NULL;
|
||||
}
|
||||
|
||||
if (GTK_IS_ACCEL_LABEL (label))
|
||||
carbon_item->accel_closure = GTK_ACCEL_LABEL (label)->accel_closure;
|
||||
|
||||
if (carbon_item->accel_closure)
|
||||
{
|
||||
g_closure_ref (carbon_item->accel_closure);
|
||||
|
||||
group = gtk_accel_group_from_accel_closure (carbon_item->accel_closure);
|
||||
|
||||
g_signal_connect_object (group, "accel-changed",
|
||||
G_CALLBACK (carbon_menu_item_accel_changed),
|
||||
widget, 0);
|
||||
}
|
||||
|
||||
carbon_menu_item_update_accelerator (carbon_item, widget);
|
||||
}
|
||||
|
||||
static void
|
||||
carbon_menu_item_notify (GObject *object,
|
||||
GParamSpec *pspec,
|
||||
CarbonMenuItem *carbon_item)
|
||||
{
|
||||
if (!strcmp (pspec->name, "sensitive") ||
|
||||
!strcmp (pspec->name, "visible"))
|
||||
{
|
||||
carbon_menu_item_update_state (carbon_item, GTK_WIDGET (object));
|
||||
}
|
||||
else if (!strcmp (pspec->name, "active"))
|
||||
{
|
||||
carbon_menu_item_update_active (carbon_item, GTK_WIDGET (object));
|
||||
}
|
||||
else if (!strcmp (pspec->name, "submenu"))
|
||||
{
|
||||
carbon_menu_item_update_submenu (carbon_item, GTK_WIDGET (object));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
carbon_menu_item_notify_label (GObject *object,
|
||||
GParamSpec *pspec,
|
||||
gpointer data)
|
||||
{
|
||||
CarbonMenuItem *carbon_item = carbon_menu_item_get (GTK_WIDGET (object));
|
||||
|
||||
if (!strcmp (pspec->name, "label"))
|
||||
{
|
||||
carbon_menu_item_update_label (carbon_item,
|
||||
GTK_WIDGET (object));
|
||||
}
|
||||
else if (!strcmp (pspec->name, "accel-closure"))
|
||||
{
|
||||
carbon_menu_item_update_accel_closure (carbon_item,
|
||||
GTK_WIDGET (object));
|
||||
}
|
||||
}
|
||||
|
||||
static CarbonMenuItem *
|
||||
carbon_menu_item_connect (GtkWidget *menu_item,
|
||||
GtkWidget *label,
|
||||
MenuRef menu,
|
||||
MenuItemIndex index)
|
||||
{
|
||||
CarbonMenuItem *carbon_item = carbon_menu_item_get (menu_item);
|
||||
|
||||
if (!carbon_item)
|
||||
{
|
||||
carbon_item = carbon_menu_item_new ();
|
||||
|
||||
g_object_set_qdata_full (G_OBJECT (menu_item), carbon_menu_item_quark,
|
||||
carbon_item,
|
||||
(GDestroyNotify) carbon_menu_item_free);
|
||||
|
||||
g_signal_connect (menu_item, "notify",
|
||||
G_CALLBACK (carbon_menu_item_notify),
|
||||
carbon_item);
|
||||
|
||||
if (label)
|
||||
g_signal_connect_swapped (label, "notify::label",
|
||||
G_CALLBACK (carbon_menu_item_notify_label),
|
||||
menu_item);
|
||||
}
|
||||
|
||||
carbon_item->menu = menu;
|
||||
carbon_item->index = index;
|
||||
|
||||
return carbon_item;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* carbon event handler
|
||||
*/
|
||||
|
||||
static int _in_carbon_menu_event_handler = 0;
|
||||
|
||||
int
|
||||
gdk_quartz_in_carbon_menu_event_handler ()
|
||||
{
|
||||
return _in_carbon_menu_event_handler;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
dummy_gtk_menu_item_activate (gpointer *arg)
|
||||
{
|
||||
gtk_menu_item_activate (GTK_MENU_ITEM(arg));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static OSStatus
|
||||
menu_event_handler_func (EventHandlerCallRef event_handler_call_ref,
|
||||
EventRef event_ref,
|
||||
void *data)
|
||||
{
|
||||
UInt32 event_class = GetEventClass (event_ref);
|
||||
UInt32 event_kind = GetEventKind (event_ref);
|
||||
MenuRef menu_ref;
|
||||
OSStatus ret;
|
||||
|
||||
_in_carbon_menu_event_handler = 1;
|
||||
|
||||
switch (event_class)
|
||||
{
|
||||
case kEventClassCommand:
|
||||
/* This is called when activating (is that the right GTK+ term?)
|
||||
* a menu item.
|
||||
*/
|
||||
if (event_kind == kEventCommandProcess)
|
||||
{
|
||||
HICommand command;
|
||||
OSStatus err;
|
||||
|
||||
/*g_printerr ("Menu: kEventClassCommand/kEventCommandProcess\n");*/
|
||||
|
||||
err = GetEventParameter (event_ref, kEventParamDirectObject,
|
||||
typeHICommand, 0,
|
||||
sizeof (command), 0, &command);
|
||||
|
||||
if (err == noErr)
|
||||
{
|
||||
GtkWidget *widget = NULL;
|
||||
|
||||
/* Get any GtkWidget associated with the item. */
|
||||
err = GetMenuItemProperty (command.menu.menuRef,
|
||||
command.menu.menuItemIndex,
|
||||
IGE_QUARTZ_MENU_CREATOR,
|
||||
IGE_QUARTZ_ITEM_WIDGET,
|
||||
sizeof (widget), 0, &widget);
|
||||
if (err == noErr && GTK_IS_WIDGET (widget))
|
||||
{
|
||||
g_idle_add (dummy_gtk_menu_item_activate, widget);
|
||||
// gtk_menu_item_activate (GTK_MENU_ITEM (widget));
|
||||
_in_carbon_menu_event_handler = 0;
|
||||
return noErr;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case kEventClassMenu:
|
||||
GetEventParameter (event_ref,
|
||||
kEventParamDirectObject,
|
||||
typeMenuRef,
|
||||
NULL,
|
||||
sizeof (menu_ref),
|
||||
NULL,
|
||||
&menu_ref);
|
||||
|
||||
switch (event_kind)
|
||||
{
|
||||
case kEventMenuTargetItem:
|
||||
/* This is called when an item is selected (what is the
|
||||
* GTK+ term? prelight?)
|
||||
*/
|
||||
/*g_printerr ("kEventClassMenu/kEventMenuTargetItem\n");*/
|
||||
break;
|
||||
|
||||
case kEventMenuOpening:
|
||||
/* Is it possible to dynamically build the menu here? We
|
||||
* can at least set visibility/sensitivity.
|
||||
*/
|
||||
/*g_printerr ("kEventClassMenu/kEventMenuOpening\n");*/
|
||||
break;
|
||||
|
||||
case kEventMenuClosed:
|
||||
/*g_printerr ("kEventClassMenu/kEventMenuClosed\n");*/
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ret = CallNextEventHandler (event_handler_call_ref, event_ref);
|
||||
_in_carbon_menu_event_handler = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
setup_menu_event_handler (void)
|
||||
{
|
||||
EventHandlerUPP menu_event_handler_upp;
|
||||
EventHandlerRef menu_event_handler_ref;
|
||||
const EventTypeSpec menu_events[] = {
|
||||
{ kEventClassCommand, kEventCommandProcess },
|
||||
{ kEventClassMenu, kEventMenuTargetItem },
|
||||
{ kEventClassMenu, kEventMenuOpening },
|
||||
{ kEventClassMenu, kEventMenuClosed }
|
||||
};
|
||||
|
||||
/* FIXME: We might have to install one per window? */
|
||||
|
||||
menu_event_handler_upp = NewEventHandlerUPP (menu_event_handler_func);
|
||||
InstallEventHandler (GetApplicationEventTarget (), menu_event_handler_upp,
|
||||
GetEventTypeCount (menu_events), menu_events, 0,
|
||||
&menu_event_handler_ref);
|
||||
|
||||
#if 0
|
||||
/* FIXME: Remove the handler with: */
|
||||
RemoveEventHandler(menu_event_handler_ref);
|
||||
DisposeEventHandlerUPP(menu_event_handler_upp);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
sync_menu_shell (GtkMenuShell *menu_shell,
|
||||
MenuRef carbon_menu,
|
||||
gboolean toplevel,
|
||||
gboolean debug)
|
||||
{
|
||||
GList *children;
|
||||
GList *l;
|
||||
MenuItemIndex carbon_index = 1;
|
||||
|
||||
if (debug)
|
||||
g_printerr ("%s: syncing shell %p\n", G_STRFUNC, menu_shell);
|
||||
|
||||
carbon_menu_connect (GTK_WIDGET (menu_shell), carbon_menu);
|
||||
|
||||
children = gtk_container_get_children (GTK_CONTAINER (menu_shell));
|
||||
|
||||
for (l = children; l; l = l->next)
|
||||
{
|
||||
GtkWidget *menu_item = l->data;
|
||||
CarbonMenuItem *carbon_item;
|
||||
|
||||
if (GTK_IS_TEAROFF_MENU_ITEM (menu_item))
|
||||
continue;
|
||||
|
||||
if (toplevel && g_object_get_data (G_OBJECT (menu_item),
|
||||
"gtk-empty-menu-item"))
|
||||
continue;
|
||||
|
||||
carbon_item = carbon_menu_item_get (menu_item);
|
||||
|
||||
if (debug)
|
||||
g_printerr ("%s: carbon_item %d for menu_item %d (%s, %s)\n",
|
||||
G_STRFUNC, carbon_item ? carbon_item->index : -1,
|
||||
carbon_index, get_menu_label_text (menu_item, NULL),
|
||||
g_type_name (G_TYPE_FROM_INSTANCE (menu_item)));
|
||||
|
||||
if (carbon_item && carbon_item->index != carbon_index)
|
||||
{
|
||||
if (debug)
|
||||
g_printerr ("%s: -> not matching, deleting\n", G_STRFUNC);
|
||||
|
||||
DeleteMenuItem (carbon_item->menu, carbon_index);
|
||||
carbon_item = NULL;
|
||||
}
|
||||
|
||||
if (!carbon_item)
|
||||
{
|
||||
GtkWidget *label = NULL;
|
||||
const gchar *label_text;
|
||||
CFStringRef cfstr = NULL;
|
||||
MenuItemAttributes attributes = 0;
|
||||
|
||||
if (debug)
|
||||
g_printerr ("%s: -> creating new\n", G_STRFUNC);
|
||||
|
||||
label_text = get_menu_label_text (menu_item, &label);
|
||||
if (label_text)
|
||||
cfstr = CFStringCreateWithCString (NULL, label_text,
|
||||
kCFStringEncodingUTF8);
|
||||
|
||||
if (GTK_IS_SEPARATOR_MENU_ITEM (menu_item))
|
||||
attributes |= kMenuItemAttrSeparator;
|
||||
|
||||
if (!GTK_WIDGET_IS_SENSITIVE (menu_item))
|
||||
attributes |= kMenuItemAttrDisabled;
|
||||
|
||||
if (!GTK_WIDGET_VISIBLE (menu_item))
|
||||
attributes |= kMenuItemAttrHidden;
|
||||
|
||||
InsertMenuItemTextWithCFString (carbon_menu, cfstr,
|
||||
carbon_index - 1,
|
||||
attributes, 0);
|
||||
SetMenuItemProperty (carbon_menu, carbon_index,
|
||||
IGE_QUARTZ_MENU_CREATOR,
|
||||
IGE_QUARTZ_ITEM_WIDGET,
|
||||
sizeof (menu_item), &menu_item);
|
||||
|
||||
if (cfstr)
|
||||
CFRelease (cfstr);
|
||||
|
||||
carbon_item = carbon_menu_item_connect (menu_item, label,
|
||||
carbon_menu,
|
||||
carbon_index);
|
||||
|
||||
if (GTK_IS_CHECK_MENU_ITEM (menu_item))
|
||||
carbon_menu_item_update_active (carbon_item, menu_item);
|
||||
|
||||
carbon_menu_item_update_accel_closure (carbon_item, menu_item);
|
||||
|
||||
if (gtk_menu_item_get_submenu (GTK_MENU_ITEM (menu_item)))
|
||||
carbon_menu_item_update_submenu (carbon_item, menu_item);
|
||||
}
|
||||
|
||||
carbon_index++;
|
||||
}
|
||||
|
||||
g_list_free (children);
|
||||
}
|
||||
|
||||
|
||||
static gulong emission_hook_id = 0;
|
||||
|
||||
static gboolean
|
||||
parent_set_emission_hook (GSignalInvocationHint *ihint,
|
||||
guint n_param_values,
|
||||
const GValue *param_values,
|
||||
gpointer data)
|
||||
{
|
||||
GtkWidget *instance = g_value_get_object (param_values);
|
||||
|
||||
if (GTK_IS_MENU_ITEM (instance))
|
||||
{
|
||||
GtkWidget *previous_parent = g_value_get_object (param_values + 1);
|
||||
GtkWidget *menu_shell = NULL;
|
||||
|
||||
if (GTK_IS_MENU_SHELL (previous_parent))
|
||||
{
|
||||
menu_shell = previous_parent;
|
||||
}
|
||||
else if (GTK_IS_MENU_SHELL (instance->parent))
|
||||
{
|
||||
menu_shell = instance->parent;
|
||||
}
|
||||
|
||||
if (menu_shell)
|
||||
{
|
||||
CarbonMenu *carbon_menu = carbon_menu_get (menu_shell);
|
||||
|
||||
if (carbon_menu)
|
||||
{
|
||||
#if 0
|
||||
g_printerr ("%s: item %s %p (%s, %s)\n", G_STRFUNC,
|
||||
previous_parent ? "removed from" : "added to",
|
||||
menu_shell,
|
||||
get_menu_label_text (instance, NULL),
|
||||
g_type_name (G_TYPE_FROM_INSTANCE (instance)));
|
||||
#endif
|
||||
|
||||
sync_menu_shell (GTK_MENU_SHELL (menu_shell),
|
||||
carbon_menu->menu,
|
||||
carbon_menu->menu == (MenuRef) data,
|
||||
FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
parent_set_emission_hook_remove (GtkWidget *widget,
|
||||
gpointer data)
|
||||
{
|
||||
g_signal_remove_emission_hook (g_signal_lookup ("parent-set",
|
||||
GTK_TYPE_WIDGET),
|
||||
emission_hook_id);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* public functions
|
||||
*/
|
||||
|
||||
void
|
||||
ige_mac_menu_set_menu_bar (GtkMenuShell *menu_shell)
|
||||
{
|
||||
MenuRef carbon_menubar;
|
||||
|
||||
g_return_if_fail (GTK_IS_MENU_SHELL (menu_shell));
|
||||
|
||||
if (carbon_menu_quark == 0)
|
||||
carbon_menu_quark = g_quark_from_static_string ("CarbonMenu");
|
||||
|
||||
if (carbon_menu_item_quark == 0)
|
||||
carbon_menu_item_quark = g_quark_from_static_string ("CarbonMenuItem");
|
||||
|
||||
CreateNewMenu (0 /*id*/, 0 /*options*/, &carbon_menubar);
|
||||
SetRootMenu (carbon_menubar);
|
||||
|
||||
setup_menu_event_handler ();
|
||||
|
||||
emission_hook_id =
|
||||
g_signal_add_emission_hook (g_signal_lookup ("parent-set",
|
||||
GTK_TYPE_WIDGET),
|
||||
0,
|
||||
parent_set_emission_hook,
|
||||
carbon_menubar, NULL);
|
||||
|
||||
g_signal_connect (menu_shell, "destroy",
|
||||
G_CALLBACK (parent_set_emission_hook_remove),
|
||||
NULL);
|
||||
|
||||
sync_menu_shell (menu_shell, carbon_menubar, TRUE, FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
ige_mac_menu_set_quit_menu_item (GtkMenuItem *menu_item)
|
||||
{
|
||||
MenuRef appmenu;
|
||||
MenuItemIndex index;
|
||||
|
||||
g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
|
||||
|
||||
if (GetIndMenuItemWithCommandID (NULL, kHICommandQuit, 1,
|
||||
&appmenu, &index) == noErr)
|
||||
{
|
||||
SetMenuItemCommandID (appmenu, index, 0);
|
||||
SetMenuItemProperty (appmenu, index,
|
||||
IGE_QUARTZ_MENU_CREATOR,
|
||||
IGE_QUARTZ_ITEM_WIDGET,
|
||||
sizeof (menu_item), &menu_item);
|
||||
|
||||
gtk_widget_hide (GTK_WIDGET (menu_item));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct _IgeMacMenuGroup
|
||||
{
|
||||
GList *items;
|
||||
};
|
||||
|
||||
static GList *app_menu_groups = NULL;
|
||||
|
||||
IgeMacMenuGroup *
|
||||
ige_mac_menu_add_app_menu_group (void)
|
||||
{
|
||||
IgeMacMenuGroup *group = g_slice_new0 (IgeMacMenuGroup);
|
||||
|
||||
app_menu_groups = g_list_append (app_menu_groups, group);
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
void
|
||||
ige_mac_menu_add_app_menu_item (IgeMacMenuGroup *group,
|
||||
GtkMenuItem *menu_item,
|
||||
const gchar *label)
|
||||
{
|
||||
MenuRef appmenu;
|
||||
GList *list;
|
||||
gint index = 0;
|
||||
|
||||
g_return_if_fail (group != NULL);
|
||||
g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
|
||||
|
||||
if (GetIndMenuItemWithCommandID (NULL, kHICommandHide, 1,
|
||||
&appmenu, NULL) != noErr)
|
||||
{
|
||||
g_warning ("%s: retrieving app menu failed",
|
||||
G_STRFUNC);
|
||||
return;
|
||||
}
|
||||
|
||||
for (list = app_menu_groups; list; list = g_list_next (list))
|
||||
{
|
||||
IgeMacMenuGroup *list_group = list->data;
|
||||
|
||||
index += g_list_length (list_group->items);
|
||||
|
||||
/* adjust index for the separator between groups, but not
|
||||
* before the first group
|
||||
*/
|
||||
if (list_group->items && list->prev)
|
||||
index++;
|
||||
|
||||
if (group == list_group)
|
||||
{
|
||||
CFStringRef cfstr;
|
||||
|
||||
/* add a separator before adding the first item, but not
|
||||
* for the first group
|
||||
*/
|
||||
if (!group->items && list->prev)
|
||||
{
|
||||
InsertMenuItemTextWithCFString (appmenu, NULL, index,
|
||||
kMenuItemAttrSeparator, 0);
|
||||
index++;
|
||||
}
|
||||
|
||||
if (!label)
|
||||
label = get_menu_label_text (GTK_WIDGET (menu_item), NULL);
|
||||
|
||||
cfstr = CFStringCreateWithCString (NULL, label,
|
||||
kCFStringEncodingUTF8);
|
||||
|
||||
InsertMenuItemTextWithCFString (appmenu, cfstr, index, 0, 0);
|
||||
SetMenuItemProperty (appmenu, index + 1,
|
||||
IGE_QUARTZ_MENU_CREATOR,
|
||||
IGE_QUARTZ_ITEM_WIDGET,
|
||||
sizeof (menu_item), &menu_item);
|
||||
|
||||
CFRelease (cfstr);
|
||||
|
||||
gtk_widget_hide (GTK_WIDGET (menu_item));
|
||||
|
||||
group->items = g_list_append (group->items, menu_item);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!list)
|
||||
g_warning ("%s: app menu group %p does not exist",
|
||||
G_STRFUNC, group);
|
||||
}
|
|
@ -8,7 +8,7 @@ void
|
|||
disable_screen_updates ()
|
||||
{
|
||||
#ifdef GTKOSX
|
||||
NSDisableScreenUpdates ();
|
||||
// NSDisableScreenUpdates ();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,6 @@ void
|
|||
enable_screen_updates ()
|
||||
{
|
||||
#ifdef GTKOSX
|
||||
NSEnableScreenUpdates();
|
||||
// NSEnableScreenUpdates();
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -21,6 +21,6 @@ Default(libvampplugins)
|
|||
env.Alias('install', env.Install(os.path.join(install_prefix, env['LIBDIR'], 'ardour2', 'vamp'), libvampplugins))
|
||||
|
||||
env.Alias('tarball', env.Distribute (env['DISTTREE'],
|
||||
[ 'SConscript', 'COPYING', 'README' ] +
|
||||
[ 'SConscript' ] +
|
||||
plugin_files +
|
||||
glob.glob('*.h')))
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef __ardour_svn_revision_h__
|
||||
#define __ardour_svn_revision_h__
|
||||
static const char* ardour_svn_revision = "2985";
|
||||
static const char* ardour_svn_revision = "3046";
|
||||
#endif
|
||||
|
|
|
@ -53,6 +53,10 @@ if not File.exist?(libdir+"/surfaces") then
|
|||
Dir.mkdir(libdir + "/surfaces")
|
||||
end
|
||||
|
||||
if not File.exist?(libdir+"/vamp-plugins") then
|
||||
Dir.mkdir(libdir + "/vamp-plugins")
|
||||
end
|
||||
|
||||
|
||||
odir = Dir.getwd
|
||||
Dir.chdir("../..")
|
||||
|
@ -67,6 +71,9 @@ results = results + result.split("\n").slice(1,result.size-1)
|
|||
result = `otool -L libs/surfaces/*/*.dylib`
|
||||
results = results + result.split("\n").slice(1,result.size-1)
|
||||
|
||||
result = `otool -L libs/vamp-plugins/*.dylib`
|
||||
results = results + result.split("\n").slice(1,result.size-1)
|
||||
|
||||
results.uniq!
|
||||
|
||||
$stdout.print("Copying libs to #{libdir} ...\n");
|
||||
|
@ -117,6 +124,9 @@ begin
|
|||
rescue
|
||||
end
|
||||
|
||||
# vamp plugins
|
||||
`cp ../../libs/vamp-plugins/*.dylib #{libdir}/vamp-plugins`
|
||||
|
||||
|
||||
# copy gtk and pango lib stuff
|
||||
`cp -R /opt/local/lib/pango #{libdir}/`
|
||||
|
|
|
@ -24,10 +24,13 @@ export ARDOUR_MODULE_PATH="$TOP/lib/"
|
|||
export ARDOUR_DATA_PATH="$TOP/share"
|
||||
export ARDOUR_GLADE_PATH="$TOP/share/ardour2/glade"
|
||||
|
||||
export LADSPA_RDF_PATH="$HOME/Library/Audio/Plug-Ins/LADSPA/rdf:/Library/Audio/Plug-Ins/LADSPA/rdf:$TOP/s
|
||||
hare/ladspa/rdf:/usr/local/share/ladspa/rdf:/usr/share/ladspa/rdf"
|
||||
export LADSPA_PATH="$HOME/Library/Audio/Plug-Ins/LADSPA:/Library/Audio/Plug-Ins/LADSPA:/usr/local/lib/lad
|
||||
spa:/usr/lib/ladspa"
|
||||
export ARDOUR_PATH="$TOP/share/ardour/icons:$TOP/share/ardour/pixmaps"
|
||||
|
||||
|
||||
export LADSPA_RDF_PATH="$HOME/Library/Audio/Plug-Ins/LADSPA/rdf:/Library/Audio/Plug-Ins/LADSPA/rdf:$TOP/share/ladspa/rdf:/usr/local/share/ladspa/rdf:/usr/share/ladspa/rdf"
|
||||
export LADSPA_PATH="$HOME/Library/Audio/Plug-Ins/LADSPA:/Library/Audio/Plug-Ins/LADSPA:/usr/local/lib/ladspa:/usr/lib/ladspa"
|
||||
|
||||
export VAMP_PATH="$TOP/lib/vamp-plugins"
|
||||
|
||||
mkdir -p "$ETC"
|
||||
sed 's|${HOME}|'"$HOME|g" "$TOP/etc/pango/pangorc" > "$ETC/pangorc"
|
||||
|
|
|
@ -68,7 +68,7 @@ wine_executable = ardour_vst.SubstInFile ('ardourvst', 'ardourvst.in', SUBST_DIC
|
|||
|
||||
if ardour_vst['VST']:
|
||||
ardour_vst.AddPostAction (wine_executable, ardour_vst.Action (Chmod ('vst/ardevst', 0755)))
|
||||
ardour_vst.AddPostAction (wine_executable, ardour_vst.Action (Chmod (wine_executable, 0755)))
|
||||
ardour_vst.AddPostAction (wine_executable, ardour_vst.Action (Chmod ("vst/" + str(wine_executable[0]), 0755)))
|
||||
Default([wine_generated_executable, wine_executable])
|
||||
|
||||
# the wine script - into the bin dir
|
||||
|
|
Loading…
Reference in New Issue