/[svn]/linuxsampler/trunk/src/engines/common/SampleManager.h
ViewVC logotype

Annotation of /linuxsampler/trunk/src/engines/common/SampleManager.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3492 - (hide annotations) (download) (as text)
Thu Mar 7 12:34:44 2019 UTC (5 years, 2 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 8350 byte(s)
* SFZ: Fixed potential crash when a sample is shared by more than one
  region (fixes bug #308, patch by Jacek Roszkowski).
* SFZ: Added OVERRIDEs to avoid bug #307 in future.
* Bumped version (2.1.0.svn6).

1 iliev 2012 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5     * Copyright (C) 2009 Grigor Iliev *
6     * *
7     * This program is free software; you can redistribute it and/or modify *
8     * it under the terms of the GNU General Public License as published by *
9     * the Free Software Foundation; either version 2 of the License, or *
10     * (at your option) any later version. *
11     * *
12     * This program is distributed in the hope that it will be useful, *
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15     * GNU General Public License for more details. *
16     * *
17     * You should have received a copy of the GNU General Public License *
18     * along with this program; if not, write to the Free Software *
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
20     * MA 02111-1307 USA *
21     ***************************************************************************/
22    
23     #ifndef __LS_SAMPLEMANAGER_H__
24     #define __LS_SAMPLEMANAGER_H__
25    
26     #include <map>
27     #include <vector>
28     #include <set>
29    
30     #include "../../common/Exception.h"
31    
32     namespace LinuxSampler {
33    
34     /**
35 schoenebeck 3492 * Used to determine and manage the relations between samples and consumers
36     * (e.g. regions). Even though this class is currently stored at a shared
37     * source file location, this class is actually only used by the sfz engine
38     * ATM. So the gig and sf2 engines are not using this class at all.
39     *
40     * NOTE: This class currently uses a somewhat unclean design by maintaining
41     * a separate set of information of "consumers of a sample" vs. "consumers
42     * actually using a sample" (see bug #308). We might need to revise this
43     * design of this class in case new problems appear (e.g. when encountering
44     * memory leaks after closing an sfz instrument).
45 iliev 2012 */
46     template <class S /* Sample */, class C /* Sample Consumer */>
47     class SampleManager {
48     public:
49     /**
50     * Adds the specified sample to the sample manager
51     */
52     void AddSample(S* pSample) {
53     if (pSample == NULL) return;
54     sampleMap[pSample];
55     }
56    
57     void RemoveSample(S* pSample) throw (Exception) {
58     if (sampleMap.find(pSample) == sampleMap.end()) return;
59     if (!sampleMap[pSample].empty()) {
60     throw Exception("Can't remove. Sample has consumers");
61     }
62    
63     sampleMap.erase(sampleMap.find(pSample));
64     }
65    
66     /**
67     * Adds pConsumer as consumer to the specified sample.
68     * The sample is automatically added to the sample manager if
69     * it is not added yet. This method does nothing if pConsumer is
70     * already added as consumer to pSample.
71     */
72     void AddSampleConsumer(S* pSample, C* pConsumer) {
73     if (pSample == NULL || pConsumer == NULL) return;
74     if(sampleMap[pSample].find(pConsumer) != sampleMap[pSample].end()) return;
75     sampleMap[pSample].insert(pConsumer);
76     }
77    
78     std::vector<C*> GetConsumers(S* pSample) throw (Exception) {
79     if (sampleMap.find(pSample) == sampleMap.end()) {
80     throw Exception("SampleManager::GetConsumers: unknown sample");
81     }
82     std::set<C*>* pConsumers = &sampleMap[pSample];
83     std::vector<C*> v;
84     v.insert(pConsumers->begin(), pConsumers->end());
85     return v ;
86     }
87    
88     /**
89     * @return true if the specified consumer was in the list
90     * of consumers for the specified sample.
91     */
92     bool RemoveSampleConsumer(S* pSample, C* pConsumer) throw (Exception) {
93     if (sampleMap.find(pSample) == sampleMap.end()) {
94     throw Exception("SampleManager::RemoveConsumer: unknown sample");
95     }
96    
97     std::set<C*>* consumers = &sampleMap[pSample];
98     typename std::set<C*>::iterator it = consumers->find(pConsumer);
99     if (it != consumers->end()) {
100     consumers->erase(it);
101     return true;
102     }
103     return false;
104     }
105    
106     /**
107     * Determines whether pSample is managed by this sample manager
108     */
109     bool HasSample(S* pSample) {
110     return sampleMap.find(pSample) != sampleMap.end();
111     }
112    
113     bool HasSampleConsumers(S* pSample) throw (Exception) {
114     if (sampleMap.find(pSample) == sampleMap.end()) {
115     throw Exception("SampleManager::HasConsumers: unknown sample");
116     }
117    
118     return !sampleMap[pSample].empty();
119     }
120    
121     /**
122     * Determines whether pConsumer is consumer of pSample.
123     */
124     bool IsSampleConsumerOf(S* pSample, C* pConsumer) {
125     if (sampleMap.find(pSample) == sampleMap.end()) {
126     throw Exception("SampleManager::IsSampleConsumerOf: unknown sample");
127     }
128    
129     typename std::set<C*>::iterator it = sampleMap[pSample].find(pConsumer);
130     return it != sampleMap[pSample].end();
131     }
132    
133     /**
134     * Sets that pSample is now in use by pConsumer.
135     */
136     void SetSampleInUse(S* pSample, C* pConsumer) {
137     verifyPair(pSample, pConsumer, "SampleManager::SetSampleInUse");
138    
139     bool inUse = !samplesInUseMap[pSample].empty();
140     samplesInUseMap[pSample].insert(pConsumer);
141     if(!inUse) OnSampleInUse(pSample);
142     }
143    
144     /**
145     * Sets that pSample is now not in use by pConsumer.
146     */
147     void SetSampleNotInUse(S* pSample, C* pConsumer) {
148     verifyPair(pSample, pConsumer, "SampleManager::SetSampleNotInUse");
149    
150     bool inUse = !samplesInUseMap[pSample].empty();
151 schoenebeck 3492 // Remove only one consumer at a time
152     typename std::multiset<C*>::iterator it = samplesInUseMap[pSample].find(pConsumer);
153     if (it != samplesInUseMap[pSample].end()) {
154     samplesInUseMap[pSample].erase(it);
155     }
156 iliev 2012 bool inUseNew = !samplesInUseMap[pSample].empty();
157 schoenebeck 3492 // Wih no consumers, erase sample
158     if (!inUseNew) samplesInUseMap.erase(pSample);
159 iliev 2012 if(inUse && !inUseNew) OnSampleNotInUse(pSample);
160     }
161    
162     protected:
163     std::map<S*, std::set<C*> > sampleMap;
164 schoenebeck 3492 std::map<S*, std::multiset<C*> > samplesInUseMap; // std::multiset as data type fixes bug #308.
165 iliev 2012
166     void verifyPair(S* pSample, C* pConsumer, String caller) {
167     if(!HasSample(pSample)) {
168     throw Exception(caller + ": unknown sample");
169     }
170    
171     if(!IsSampleConsumerOf(pSample, pConsumer)) {
172     throw Exception("SampleManager::SetSampleInUse: unknown consumer");
173     }
174     }
175    
176     /**
177     * Override this method to handle the state change (not in use -> in use)
178     * of the specified sample.
179     */
180 schoenebeck 3492 virtual void OnSampleInUse(S* pSample) = 0;
181 iliev 2012
182     /**
183     * Override this method to handle the state change (in use -> not in use)
184     * of the specified sample.
185     */
186 schoenebeck 3492 virtual void OnSampleNotInUse(S* pSample) = 0;
187 iliev 2012 };
188     } // namespace LinuxSampler
189    
190     #endif /* __LS_SAMPLEMANAGER_H__ */
191    

  ViewVC Help
Powered by ViewVC