Essentia  2.1-beta5-dev
sourceproxy.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006-2016 Music Technology Group - Universitat Pompeu Fabra
3  *
4  * This file is part of Essentia
5  *
6  * Essentia is free software: you can redistribute it and/or modify it under
7  * the terms of the GNU Affero General Public License as published by the Free
8  * Software Foundation (FSF), either version 3 of the License, or (at your
9  * option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14  * details.
15  *
16  * You should have received a copy of the Affero GNU General Public License
17  * version 3 along with this program. If not, see http://www.gnu.org/licenses/
18  */
19 
20 #ifndef ESSENTIA_SOURCEPROXY_H
21 #define ESSENTIA_SOURCEPROXY_H
22 
23 #include <vector>
24 #include "sourcebase.h"
25 #include "multiratebuffer.h"
26 #include "sink.h"
27 #include "essentiautil.h"
28 
29 
30 namespace essentia {
31 namespace streaming {
32 
37 class SourceProxyBase : public SourceBase {
38  protected:
40 
41  public:
42  SourceProxyBase(Algorithm* parent = 0, const std::string& name = "unnamed") :
43  SourceBase(parent, name), _proxiedSource(0) {}
44 
45  SourceProxyBase(const std::string& name) : SourceBase(name), _proxiedSource(0) {}
46 
48  E_DEBUG(EMemory, "Deleting SourceProxy " << fullName());
49  if (_proxiedSource) essentia::streaming::detach(*_proxiedSource, *this);
50  }
51 
53 
54 
55  //---- Buffer access methods ----------------------------------------//
56 
57  const void* buffer() const {
58  if (!_proxiedSource)
59  throw EssentiaException("SourceProxy ", fullName(), " is not currently attached to another Source");
60 
61  return _proxiedSource->buffer();
62  }
63 
64  void* buffer() {
65  if (!_proxiedSource)
66  throw EssentiaException("SourceProxy ", fullName(), " is not currently attached to another Source");
67 
68  return _proxiedSource->buffer();
69  }
70 
72  _proxiedSource->setBufferType(type);
73  }
74 
75  virtual BufferInfo bufferInfo() const {
76  return _proxiedSource->bufferInfo();
77  }
78 
79  virtual void setBufferInfo(const BufferInfo& info) {
80  _proxiedSource->setBufferInfo(info);
81  }
82 
83 
84  //---- StreamConnector interface hijacking for proxies ----------------------------------------//
85 
86  inline void acquire() { StreamConnector::acquire(); }
87 
88  virtual bool acquire(int n) {
89  throw EssentiaException("Cannot acquire for SourceProxy ", fullName(), ": you need to call acquire() on the Source which is proxied by it");
90  }
91 
92  virtual int acquireSize() const {
93  if (!_proxiedSource)
94  throw EssentiaException("Cannot call ::acquireSize() on SourceProxy ", fullName(), " because it is not attached");
95 
96  return _proxiedSource->acquireSize();
97  }
98 
99  inline void release() { StreamConnector::release(); }
100 
101  virtual void release(int n) {
102  throw EssentiaException("Cannot release for SourceProxy ", fullName(), ": you need to call release() on the Source which is proxied by it");
103  }
104 
105  virtual int releaseSize() const {
106  if (!_proxiedSource)
107  throw EssentiaException("Cannot call ::releaseSize() on SourceProxy ", fullName(), " because it is not attached");
108 
109  return _proxiedSource->releaseSize();
110  }
111 
112  //---------------------------------------------------------------------------------------------//
113 
114 
115  void detach() {
116  if (_proxiedSource) essentia::streaming::detach(*_proxiedSource, *this);
117  }
118 
119  virtual void connect(SinkBase& sink) {
120  SourceBase::connect(sink);
121  if (_proxiedSource) {
122  E_DEBUG(EConnectors, " SourceProxy " << fullName() << "::connect: " << _proxiedSource->fullName()
123  << "::connect(" << sink.fullName() << ")");
124 
125  _proxiedSource->connect(sink);
126  }
127  }
128 
129  virtual void disconnect(SinkBase& sink) {
131  if (_proxiedSource) {
132  E_DEBUG(EConnectors, " SourceProxy " << fullName() << "::disconnect: " << _proxiedSource->fullName()
133  << "::disconnect(" << sink.fullName() << ")");
134  _proxiedSource->disconnect(sink);
135  }
136  }
137 
138  protected:
142  void attach(SourceBase* source) {
143  checkSameTypeAs(*source);
144 
145  if (_proxiedSource) {
146  std::ostringstream msg;
147  msg << "Could not attach SourceProxy " << fullName() << " to " << source->fullName()
148  << " because it is already attached to " << _proxiedSource->fullName();
149  throw EssentiaException(msg);
150  }
151 
152  E_DEBUG(EConnectors, " SourceProxy::attach: " << fullName() << "::_proxiedSource = " << source->fullName());
153  _proxiedSource = source;
154  }
155 
156  friend void attach(SourceBase& innerSource, SourceProxyBase& proxy);
157  friend void detach(SourceBase& innerSource, SourceProxyBase& proxy);
158 
159  void detach(SourceBase* source) {
160  if (source != _proxiedSource) {
161  E_WARNING("Cannot detach SourceProxy " << fullName() << " from " << source->fullName() << " as they are not attached");
162  return;
163  }
164 
165  E_DEBUG(EConnectors, " SourceProxy::detach: " << fullName() << "::_proxiedSource = 0");
166  _proxiedSource = 0;
167  }
168 
169  // for SourceBase destructor
170  friend class SourceBase;
171 };
172 
173 
174 template<typename TokenType>
175 class SourceProxy : public SourceProxyBase {
176  USE_TYPE_INFO(TokenType);
177 
178  public:
179 
180  SourceProxy(Algorithm* parent = 0, const std::string& name = "unnamed") :
182 
183  SourceProxy(const std::string& name) : SourceProxyBase(name) {}
184 
186 
187 
188  public:
189 
190  //---- Buffer access methods ----------------------------------------//
191 
192 
194  return *static_cast<const MultiRateBuffer<TokenType>*>(buffer());
195  }
196 
198  return *static_cast<MultiRateBuffer<TokenType>*>(buffer());
199  }
200 
201 
202  //---- Connect methods ----------------------------------------------//
203 
205  // return some (random) value as it's gonna be overwritten as soon as we're connected to a real source somehow
206  return _sinks.size();
207  }
208 
210  return;
211  }
212 
213  virtual void* getTokens() {
214  throw EssentiaException("Cannot get tokens for SourceProxy ", fullName(),
215  ": you need to call getTokens() on the Source which is proxied by it");
216  }
217 
218  virtual void* getFirstToken() {
219  throw EssentiaException("Cannot get first token for SourceProxy ", fullName(),
220  ": you need to call getFirstToken() on the Source which is proxied by it");
221  }
222 
223 
224  virtual int available() const {
225  return typedBuffer().availableForWrite(false);
226  }
227 
228  int totalProduced() const {
229  if (!_proxiedSource)
230  throw EssentiaException("Cannot call ::totalProduced() on SourceProxy ", fullName(), " because it is not attached");
231 
232  return _proxiedSource->totalProduced();
233  }
234 
235  virtual void reset() {
236  // NB: do not throw an exception here, it is ok to reset a non-attached SourceProxy
238  }
239 
240 };
241 
242 
243 inline void attach(SourceBase& innerSource, SourceProxyBase& proxy) {
244  E_DEBUG(EConnectors, "Attaching SourceProxy " << proxy.fullName() << " to " << innerSource.fullName());
245  // check types here to have a more informative error message in case it fails
246  if (!sameType(innerSource, proxy)) {
247  std::ostringstream msg;
248  msg << "Cannot attach " << innerSource.fullName() << " (type: " << nameOfType(innerSource)
249  << ") to SourceProxy " << proxy.fullName() << " (type: " << nameOfType(proxy) << ")";
250  throw EssentiaException(msg);
251  }
252  proxy.attach(&innerSource);
253  innerSource.attachProxy(&proxy);
254 }
255 
256 inline void operator>>(SourceBase& innerSource, SourceProxyBase& proxy) {
257  attach(innerSource, proxy);
258 }
259 
260 inline void detach(SourceBase& innerSource, SourceProxyBase& proxy) {
261  E_DEBUG(EConnectors, "Detaching SourceProxy " << proxy.fullName() << " from " << innerSource.fullName());
262  proxy.detach(&innerSource);
263  innerSource.detachProxy(&proxy);
264 }
265 
266 
267 } // namespace essentia
268 } // namespace streaming
269 
270 
271 #endif // ESSENTIA_SOURCEPROXY_H
virtual int totalProduced() const =0
virtual void connect(SinkBase &sink)
Definition: sourceproxy.h:119
Definition: debugging.h:43
void detach(SinkProxyBase &proxy, SinkBase &innerSink)
Definition: sinkproxy.h:257
const Algorithm * parent() const
Definition: connector.h:53
int ReaderID
Definition: types.h:343
SourceBase * proxiedSource()
Definition: sourceproxy.h:52
void removeReader(ReaderID id)
Definition: sourceproxy.h:209
SourceProxy(Algorithm *parent=0, const std::string &name="unnamed")
Definition: sourceproxy.h:180
virtual void setBufferInfo(const BufferInfo &info)=0
Definition: sourcebase.h:52
#define E_WARNING(msg)
Definition: debugging.h:164
MultiRateBuffer< TokenType > & typedBuffer()
Definition: sourceproxy.h:197
void release()
Definition: sourceproxy.h:99
virtual void setBufferType(BufferUsage::BufferUsageType type)=0
int totalProduced() const
Definition: sourceproxy.h:228
virtual int acquireSize() const
Definition: streamconnector.h:69
std::string nameOfType(const std::type_info &type)
void detach()
Definition: sourceproxy.h:115
bool acquire()
Definition: streamconnector.h:49
virtual int available() const
Definition: sourceproxy.h:224
virtual void * getFirstToken()
Definition: sourceproxy.h:218
BufferUsageType
Definition: types.h:397
virtual void disconnect(SinkBase &sink)
Definition: sourceproxy.h:129
bool sameType(const std::type_info &t1, const std::type_info &t2)
Definition: types.h:259
ReaderID addReader()
Definition: sourceproxy.h:204
void attach(SourceBase *source)
Definition: sourceproxy.h:142
virtual BufferInfo bufferInfo() const
Definition: sourceproxy.h:75
Definition: sourceproxy.h:37
void release()
Definition: streamconnector.h:59
Definition: sinkbase.h:52
void operator>>(SourceBase &source, DevNullConnector devnull)
Definition: devnull.h:81
void detach(SourceBase *source)
Definition: sourceproxy.h:159
Definition: debugging.h:48
virtual void connect(SinkBase &sink)
virtual void * getTokens()
Definition: sourceproxy.h:213
SourceProxy(const std::string &name)
Definition: sourceproxy.h:183
virtual int acquireSize() const
Definition: sourceproxy.h:92
std::string fullName() const
const MultiRateBuffer< TokenType > & typedBuffer() const
Definition: sourceproxy.h:193
const void * buffer() const
Definition: sourceproxy.h:57
SourceProxyBase(const std::string &name)
Definition: sourceproxy.h:45
SourceBase * _proxiedSource
Definition: sourceproxy.h:39
#define USE_TYPE_INFO(TokenType)
Definition: types.h:331
void acquire()
Definition: sourceproxy.h:86
Definition: types.h:381
void detachProxy(SourceProxyBase *sproxy)
void attachProxy(SourceProxyBase *sproxy)
virtual void reset()
Definition: sourceproxy.h:235
Definition: algorithm.h:28
virtual bool acquire(int n)
Definition: sourceproxy.h:88
Definition: sourceproxy.h:175
Definition: types.h:76
Definition: streamingalgorithm.h:140
virtual int releaseSize() const
Definition: sourceproxy.h:105
virtual void setBufferType(BufferUsage::BufferUsageType type)
Definition: sourceproxy.h:71
~SourceProxy()
Definition: sourceproxy.h:185
virtual BufferInfo bufferInfo() const =0
std::vector< SinkBase * > _sinks
Definition: sourcebase.h:54
virtual int releaseSize() const
Definition: streamconnector.h:74
void checkSameTypeAs(const TypeProxy &obj) const
Definition: types.h:301
SourceProxyBase(Algorithm *parent=0, const std::string &name="unnamed")
Definition: sourceproxy.h:42
const std::string & name() const
Definition: types.h:283
void * buffer()
Definition: sourceproxy.h:64
#define E_DEBUG(module, msg)
Definition: debugging.h:157
~SourceProxyBase()
Definition: sourceproxy.h:47
virtual void setBufferInfo(const BufferInfo &info)
Definition: sourceproxy.h:79
virtual void release(int n)
Definition: sourceproxy.h:101
virtual void disconnect(SinkBase &sink)