/[svn]/linuxsampler/trunk/src/engines/gig/EngineChannel.cpp
ViewVC logotype

Annotation of /linuxsampler/trunk/src/engines/gig/EngineChannel.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2611 - (hide annotations) (download)
Mon Jun 9 19:20:37 2014 UTC (9 years, 10 months ago) by schoenebeck
File size: 8108 byte(s)
* Fixed crash when loading an instrument script.
* Fixed "init" script handler only to be executed once:
  when the script was loaded.
* Fixed aftertouch script event which always had value zero
  and controller number was set to aftertouch value instead.
* gig Engine: Fixed handling of "smartmidi" dimension, which
  was recognized as "unknown" dimension.
* Fixed script function gig_set_dim_zone(): was accessing
  wrong event.
* ls_instr_script command line tool: is now not limited to
  core language scripts, but can now also parse sampler format
  dependent instrument scripts, with the respective specific
  built-in script variables and functions.
* ScriptVM: Fixed runtime behavior of "and" and "or" binary
  script expressions, which also evaluated the right hand side
  of the expression even if the left hand side already failed
  the overall expression semantic to become true.
* Bumped version (1.0.0.svn46).

1 schoenebeck 411 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5 iliev 2012 * Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck *
6 persson 2114 * Copyright (C) 2005-2008 Christian Schoenebeck *
7 schoenebeck 2330 * Copyright (C) 2009-2012 Christian Schoenebeck and Grigor Iliev *
8 schoenebeck 411 * *
9     * This program is free software; you can redistribute it and/or modify *
10     * it under the terms of the GNU General Public License as published by *
11     * the Free Software Foundation; either version 2 of the License, or *
12     * (at your option) any later version. *
13     * *
14     * This program is distributed in the hope that it will be useful, *
15     * but WITHOUT ANY WARRANTY; without even the implied warranty of *
16     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
17     * GNU General Public License for more details. *
18     * *
19     * You should have received a copy of the GNU General Public License *
20     * along with this program; if not, write to the Free Software *
21     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
22     * MA 02111-1307 USA *
23     ***************************************************************************/
24    
25     #include "EngineChannel.h"
26 iliev 2012 #include "Engine.h"
27 schoenebeck 411
28 persson 438 namespace LinuxSampler { namespace gig {
29 iliev 2012 EngineChannel::EngineChannel() {
30    
31 schoenebeck 411 }
32    
33     EngineChannel::~EngineChannel() {
34 schoenebeck 460 DisconnectAudioOutputDevice();
35 iliev 1826 // In case the channel was removed before the instrument was
36     // fully loaded, try to give back instrument again (see bug #113)
37 iliev 2012 InstrumentChangeCmd< ::gig::DimensionRegion, ::gig::Instrument>& cmd = ChangeInstrument(NULL);
38 iliev 1826 if (cmd.pInstrument) {
39 persson 2127 Engine::instruments.HandBack(cmd.pInstrument, this);
40 iliev 1826 }
41     ///////
42 schoenebeck 411 }
43    
44 iliev 2012 AbstractEngine::Format EngineChannel::GetEngineFormat() { return AbstractEngine::GIG; }
45 schoenebeck 660
46 iliev 2012 /** This method is not thread safe! */
47 schoenebeck 411 void EngineChannel::ResetInternal() {
48     CurrentKeyDimension = 0;
49 iliev 2012 EngineChannelBase<Voice, ::gig::DimensionRegion, ::gig::Instrument>::ResetInternal();
50 schoenebeck 411 }
51    
52     /**
53 iliev 2012 * Will be called by the MIDIIn Thread to signal that a program
54     * change should be performed. As a program change isn't
55     * real-time safe, the actual change is performed by the disk
56     * thread.
57 schoenebeck 411 *
58 iliev 2012 * @param Program - MIDI program change number
59 schoenebeck 411 */
60 iliev 2012 void EngineChannel::SendProgramChange(uint8_t Program) {
61 persson 2277 SetMidiProgram(Program);
62 iliev 2012 Engine* engine = dynamic_cast<Engine*>(pEngine);
63     if(engine == NULL) return;
64    
65     if(engine->GetDiskThread()) {
66 persson 2277 uint32_t merged = (GetMidiBankMsb() << 16) | (GetMidiBankLsb() << 8) | Program;
67     engine->GetDiskThread()->OrderProgramChange(merged, this);
68 iliev 2012 } else {
69     // TODO:
70     }
71 schoenebeck 411 }
72    
73     /**
74     * Load an instrument from a .gig file. PrepareLoadInstrument() has to
75     * be called first to provide the information which instrument to load.
76     * This method will then actually start to load the instrument and block
77     * the calling thread until loading was completed.
78     *
79     * @see PrepareLoadInstrument()
80     */
81     void EngineChannel::LoadInstrument() {
82 iliev 2012 InstrumentResourceManager* pInstrumentManager = dynamic_cast<InstrumentResourceManager*>(pEngine->GetInstrumentManager());
83    
84 persson 1646 // make sure we don't trigger any new notes with an old
85     // instrument
86 iliev 2012 InstrumentChangeCmd< ::gig::DimensionRegion, ::gig::Instrument>& cmd = ChangeInstrument(0);
87 persson 1646 if (cmd.pInstrument) {
88     // give old instrument back to instrument manager, but
89     // keep the dimension regions and samples that are in use
90 iliev 2012 pInstrumentManager->HandBackInstrument(cmd.pInstrument, this, cmd.pRegionsInUse);
91 schoenebeck 411 }
92 iliev 2012 cmd.pRegionsInUse->clear();
93 schoenebeck 411
94     // delete all key groups
95 persson 2114 DeleteGroupEventLists();
96 schoenebeck 411
97     // request gig instrument from instrument manager
98 persson 1038 ::gig::Instrument* newInstrument;
99 schoenebeck 411 try {
100 schoenebeck 947 InstrumentManager::instrument_id_t instrid;
101     instrid.FileName = InstrumentFile;
102     instrid.Index = InstrumentIdx;
103 iliev 2012
104     newInstrument = pInstrumentManager->Borrow(instrid, this);
105 persson 1038 if (!newInstrument) {
106 schoenebeck 1212 throw InstrumentManagerException("resource was not created");
107 schoenebeck 411 }
108 schoenebeck 2594
109 schoenebeck 2611 if (newInstrument->ScriptSlotCount() > 1) {
110     std::cerr << "WARNING: Executing more than one real-time instrument script slot is not implemented yet!\n";
111     }
112 schoenebeck 2594 ::gig::Script* script = newInstrument->GetScriptOfSlot(0);
113     if (script) {
114     String sourceCode = script->GetScriptAsText();
115 schoenebeck 2611 LoadInstrumentScript(sourceCode);
116 schoenebeck 2594 }
117 schoenebeck 411 }
118     catch (RIFF::Exception e) {
119     InstrumentStat = -2;
120 iliev 1309 StatusChanged(true);
121 schoenebeck 411 String msg = "gig::Engine error: Failed to load instrument, cause: " + e.Message;
122 schoenebeck 880 throw Exception(msg);
123 schoenebeck 411 }
124 schoenebeck 1212 catch (InstrumentManagerException e) {
125 schoenebeck 411 InstrumentStat = -3;
126 iliev 1309 StatusChanged(true);
127 schoenebeck 411 String msg = "gig::Engine error: Failed to load instrument, cause: " + e.Message();
128 schoenebeck 880 throw Exception(msg);
129 schoenebeck 411 }
130     catch (...) {
131     InstrumentStat = -4;
132 iliev 1309 StatusChanged(true);
133 schoenebeck 880 throw Exception("gig::Engine error: Failed to load instrument, cause: Unknown exception while trying to parse gig file.");
134 schoenebeck 411 }
135    
136 persson 2043 RoundRobinIndex = 0;
137     for (int i = 0 ; i < 128 ; i++) pMIDIKeyInfo[i].pRoundRobinIndex = NULL;
138    
139     // rebuild ActiveKeyGroups map with key groups of current
140     // instrument and set the round robin pointers to use one
141     // counter for each region
142     int region = 0;
143     for (::gig::Region* pRegion = newInstrument->GetFirstRegion(); pRegion; pRegion = newInstrument->GetNextRegion()) {
144 persson 2114 AddGroup(pRegion->KeyGroup);
145 schoenebeck 411
146 persson 2043 RoundRobinIndexes[region] = 0;
147     for (int iKey = pRegion->KeyRange.low; iKey <= pRegion->KeyRange.high; iKey++) {
148     pMIDIKeyInfo[iKey].pRoundRobinIndex = &RoundRobinIndexes[region];
149     }
150     region++;
151     }
152    
153 persson 1038 InstrumentIdxName = newInstrument->pInfo->Name;
154 schoenebeck 411 InstrumentStat = 100;
155    
156 persson 1646 ChangeInstrument(newInstrument);
157    
158 iliev 1298 StatusChanged(true);
159 schoenebeck 411 }
160    
161 iliev 2012 void EngineChannel::ProcessKeySwitchChange(int key) {
162     // Change key dimension value if key is in keyswitching area
163 persson 1646 {
164 iliev 2012 if (key >= pInstrument->DimensionKeyRange.low && key <= pInstrument->DimensionKeyRange.high)
165     CurrentKeyDimension = float(key - pInstrument->DimensionKeyRange.low) /
166     (pInstrument->DimensionKeyRange.high - pInstrument->DimensionKeyRange.low + 1);
167 persson 1646 }
168 schoenebeck 411 }
169 schoenebeck 2330
170     String EngineChannel::InstrumentFileName() {
171     return EngineChannelBase<Voice, ::gig::DimensionRegion, ::gig::Instrument>::InstrumentFileName();
172     }
173    
174     String EngineChannel::InstrumentFileName(int index) {
175     if (index == 0) return InstrumentFileName();
176     if (!pInstrument || !pInstrument->GetParent()) return "";
177     DLS::File* pMainFile = dynamic_cast<DLS::File*>(pInstrument->GetParent());
178     if (!pMainFile) return "";
179     RIFF::File* pExtensionFile = pMainFile->GetExtensionFile(index);
180     return (pExtensionFile) ? pExtensionFile->GetFileName() : "";
181     }
182 schoenebeck 411
183     }} // namespace LinuxSampler::gig

  ViewVC Help
Powered by ViewVC