summaryrefslogtreecommitdiffstats
path: root/src/sound/AudioPlayQueue.h
blob: e33dc0681db276f6bf96c1f0674079c49d698749 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/*
    Rosegarden
    A sequencer and musical notation editor.

    This program is Copyright 2000-2008
        Guillaume Laurent   <glaurent@telegraph-road.org>,
        Chris Cannam        <cannam@all-day-breakfast.com>,
        Richard Bown        <bownie@bownie.com>

    The moral right of the authors to claim authorship of this work
    has been asserted.

    This program 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.  See the file
    COPYING included with this distribution for more information.
*/

#ifndef _AUDIO_PLAY_QUEUE_H_
#define _AUDIO_PLAY_QUEUE_H_

#include "RealTime.h"
#include "Instrument.h"

#include <set>
#include <vector>
#include <map>
#include <list>

namespace Rosegarden
{

class PlayableAudioFile;

/**
 * An ordered list of PlayableAudioFiles that does not aim to be quick
 * to add to or remove files from, but that aims to quickly answer the
 * question of which files are playing within a given time slice.
 *
 * Note that there is no locking between audio file add/remove and
 * lookup.  Add/remove should only be carried out when it is known
 * that no threads will be performing lookup.
 */

class AudioPlayQueue
{
public:
    AudioPlayQueue();
    virtual ~AudioPlayQueue();

    struct FileTimeCmp {
        bool operator()(const PlayableAudioFile &, const PlayableAudioFile &) const;
        bool operator()(const PlayableAudioFile *, const PlayableAudioFile *) const;
    };
    typedef std::set<PlayableAudioFile *, FileTimeCmp> FileSet;
    typedef std::list<PlayableAudioFile *> FileList;

    /**
     * Add a file to the queue.  AudioPlayQueue takes ownership of the
     * file and will delete it when removed.
     */
    void addScheduled(PlayableAudioFile *file);

    /**
     * Add a file to the unscheduled list.  AudioPlayQueue takes
     * ownership of the file and will delete it when removed.
     * Unscheduled files will be returned along with schuled ones for
     * normal lookups, but everything will be less efficient when
     * there are unscheduled files on the queue.  This is intended
     * for asynchronous (preview) playback.
     */
    void addUnscheduled(PlayableAudioFile *file);

    /**
     * Remove a scheduled or unscheduled file from the queue and
     * delete it.
     */
    void erase(PlayableAudioFile *file);

    /**
     * Remove all files and delete them.
     */
    void clear();

    /**
     * Return true if the queue is empty.
     */
    bool empty() const;

    /**
     * Return the total number of files in the queue.  (May be slow.)
     */
    size_t size() const;

    /**
     * Look up the files playing during a given slice and return them
     * in the passed FileSet.  The pointers returned are still owned
     * by me and the caller should not delete them.
     */ 
    void getPlayingFiles(const RealTime &sliceStart,
                         const RealTime &sliceDuration,
                         FileSet &) const;

    /**
     * Look up the files playing during a given slice on a given
     * instrument and return them in the passed array.  The size arg
     * gives the available size of the array and is used to return the
     * number of file pointers written.  The pointers returned are
     * still owned by me and the caller should not delete them.
     */
    void getPlayingFilesForInstrument(const RealTime &sliceStart,
                                      const RealTime &sliceDuration,
                                      InstrumentId instrumentId,
                                      PlayableAudioFile **files,
                                      size_t &size) const;

    /**
     * Return true if at least one scheduled or unscheduled file is
     * associated with the given instrument somewhere in the queue.
     */
    bool haveFilesForInstrument(InstrumentId instrumentId) const;

    /**
     * Return a (shared reference to an) ordered set of all files on
     * the scheduled queue.
     */
    const FileSet &getAllScheduledFiles() const;

    /**
     * Return a (shared reference to an) ordered set of all files on
     * the unscheduled queue.
     */
    const FileList &getAllUnscheduledFiles() const;

    /**
     * Get an approximate (but always pessimistic) estimate of the
     * number of ring buffers required for the current queue -- that
     * is, the maximum possible number of audio channels playing at
     * once from non-small-file-cached-files.
     */
    size_t getMaxBuffersRequired() const { return m_maxBuffers; }

private:
    FileSet m_files;

    typedef std::vector<PlayableAudioFile *> FileVector;
    typedef std::map<int, FileVector> ReverseFileMap;
    ReverseFileMap m_index;

    typedef std::vector<ReverseFileMap> InstrumentReverseFileMap;
    InstrumentReverseFileMap m_instrumentIndex;

    FileList m_unscheduled;

    typedef std::map<int, size_t> FileCountMap;
    FileCountMap m_counts;

    size_t m_maxBuffers;
};


}

#endif