diff options
Diffstat (limited to 'src/cachemanager.h')
-rw-r--r-- | src/cachemanager.h | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/src/cachemanager.h b/src/cachemanager.h new file mode 100644 index 0000000..d98d66c --- /dev/null +++ b/src/cachemanager.h @@ -0,0 +1,195 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * cachemanager.h + * + * Fri Apr 10 10:39:24 CEST 2015 + * Copyright 2015 Jonas Suhr Christensen + * jsc@umbraculum.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __DRUMGIZMO_CACHEMANAGER_H__ +#define __DRUMGIZMO_CACHEMANAGER_H__ + +#include <string> +#include <list> +#include <vector> + +#include "thread.h" +#include "semaphore.h" +#include "mutex.h" + +#include "audiotypes.h" +#include "audiofile.h" + +#define CACHE_DUMMYID -2 +#define CACHE_NOID -1 + +#define CHUNK_MULTIPLIER 16 + +class AudioFile; +typedef int cacheid_t; + + +//TODO: +// 1: Move nodata initialisation to init method. +// 2: Make semaphore in thread to block init call until thread has been started. + +//// next +// Pre: preloaded contains 2 x framesize. chunk size is framesize. +// allocate 2 chunks and copy initial_samples_needed to first buffer from +// preloaded data and enough to fill up the second buffer from preloaded +// returns the first buffer and its size in &size. +// get id from "free stack" and store pointers to buffers in id vector. +// event: open sndfile handle (if not already open) and increase refcount + +//// next +// Return which ever buffer is the front, swap them and add event to load the +// next chunk. + +//// close +// decrement file handle refcounter and close file if it is 0. +// free the 2 buffers +// (do not erase from the id vector), push index to +// "free stack" for reuse. + +class CacheManager : public Thread { +public: + /** + * Empty constructor... + */ + CacheManager(); + + /** + * Destroy object and stop thread if needed. + */ + ~CacheManager(); + + /** + * Initialise cache manager and allocate needed resources + * This method starts the cache manager thread. + * This method blocks until the thread has been started. + * @param poolsize The maximum number of parellel events supported. + */ + void init(size_t poolsize, bool threaded); + + /** + * Stop thread and clean up resources. + * This method blocks until the thread has stopped. + */ + void deinit(); + + /** + * Register new cache entry. + * Prepares an entry in the cache manager for future disk streaming. + * @param file A pointer to the file which is to be streamed from. + * @param initial_samples_needed The number of samples needed in the first + * read that is not nessecarily of framesize. This is the number of samples + * from the input event offset to the end of the frame in which it resides. + * initial_samples_needed <= framesize. + * @param channel The channel to which the cache id will be bound. + * @param [out] new_id The newly created cache id. + * @return A pointer to the first buffer containing the + * 'initial_samples_needed' number of samples. + */ + sample_t *open(AudioFile *file, size_t initial_samples_needed, int channel, + cacheid_t &new_id); + + /** + * Get next buffer. + * Returns the next buffer for reading based on cache id. + * This function will (if needed) schedule a new disk read to make sure that + * data is available in the next call to this method. + * @param id The cache id to read from. + * @param [out] size The size of the returned buffer. + * @return A pointer to the buffer. + */ + sample_t *next(cacheid_t id, size_t &size); + + /** + * Unregister cache entry. + * Close associated file handles and free associated buffers. + * @param id The cache id to close. + */ + void close(cacheid_t id); + + void setFrameSize(size_t framesize); + + ///! Internal thread main method - needs to be public. + void thread_main(); + +private: + size_t framesize; + sample_t *nodata; + + typedef struct { + AudioFile *file; + size_t channel; + size_t pos; //< File possition + volatile bool ready; + sample_t *front; + sample_t *back; + size_t localpos; //< Intra buffer (front) position. + } cache_t; + + typedef enum { + LOADNEXT = 0, + CLOSE = 1 + } cmd_t; + + typedef struct { + cmd_t cmd; + + // For close event: + cacheid_t id; + + // For load next event: + size_t pos; + sample_t *buffer; + volatile bool *ready; + AudioFile *file; + size_t channel; + } cevent_t; + + cevent_t createLoadNextEvent(AudioFile *file, size_t channel, size_t pos, + sample_t* buffer); + cevent_t createCloseEvent(cacheid_t id); + + void handleLoadNextEvent(cevent_t &e); + void handleCloseEvent(cevent_t &e); + + void handleEvent(cevent_t &e); + void pushEvent(cevent_t e); + + std::vector<cache_t> id2cache; + + // Protected by mutex: + std::list<cevent_t> eventqueue; + std::list<cacheid_t> availableids; + + Mutex m_events; + Mutex m_ids; + + bool threaded; // Indicates if we are running in thread mode or offline mode. + Semaphore sem; + Semaphore sem_run; + bool running; +}; + +#endif/*__DRUMGIZMO_CACHEMANAGER_H__*/ |