root/trunk/libffado/src/libutil/IpcRingBuffer.h

Revision 1240, 6.0 kB (checked in by ppalmers, 13 years ago)

fix bugs in IPC comms. Add preliminary FFADO-IPC ALSA plugin

Line 
1 /*
2  * Copyright (C) 2005-2008 by Pieter Palmers
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB
8  *
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) version 3 of the License.
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, see <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 #ifndef __UTIL_IPC_RINGBUFFER__
25 #define __UTIL_IPC_RINGBUFFER__
26
27 #include "debugmodule/debugmodule.h"
28 #include <string>
29
30 #include "config.h"
31
32 #define FFADO_IPC_RINGBUFFER_MAGIC   0x57439812
33 #define FFADO_IPC_RINGBUFFER_VERSION 0
34
35 #define FFADO_IPC_MAX_MESSAGE_SIZE 16
36
37 #include "PosixMessageQueue.h"
38
39 #include <semaphore.h>
40
41 namespace Util {
42
43 /**
44  * @brief A Ringbuffer for IPC use.
45  */
46
47 class PosixMessageQueue;
48 class PosixSharedMemory;
49 class Mutex;
50 class Functor;
51
52 class IpcRingBuffer
53 {
54 // the message types
55 protected:
56     enum eMessagePriorities {
57         eMP_Realtime = 10,
58     };
59
60     // these are the views on the message contents
61     struct DataWrittenMessage {
62         unsigned int idx;
63         unsigned int id;
64     };
65
66     class IpcMessage : public PosixMessageQueue::Message
67     {
68     public:
69         enum eMessageType {
70             eMT_Unknown     = 0,
71             eMT_DataWritten = 1,
72             eMT_DataAck     = 2,
73         };
74
75         IpcMessage()
76         : Message()
77         , m_priority( 0 )
78         , m_data_len( 0 )
79         {
80             m_header.magic = FFADO_IPC_RINGBUFFER_MAGIC;
81             m_header.version = FFADO_IPC_RINGBUFFER_VERSION;
82             m_header.type = eMT_Unknown;
83         };
84
85         IpcMessage(enum eMessageType t)
86         : Message()
87         , m_priority( 0 )
88         , m_data_len( 0 )
89         {
90             m_header.magic = FFADO_IPC_RINGBUFFER_MAGIC;
91             m_header.version = FFADO_IPC_RINGBUFFER_VERSION;
92             m_header.type = t;
93         };
94
95         virtual ~IpcMessage() {};
96
97         virtual unsigned getPriority()
98             {return m_priority;};
99         virtual unsigned int getLength()
100             {return sizeof(m_header)
101                     + sizeof(m_data);};
102
103         virtual bool serialize(char *buff);
104         virtual bool deserialize(const char *buff, unsigned int length, unsigned prio);
105
106         void setType(enum eMessageType t) {m_header.type=t;};
107         enum eMessageType getType() {return m_header.type;};
108         char *getDataPtr() {return m_data;};
109         void setDataSize(unsigned int i)
110                 { assert(i<FFADO_IPC_MAX_MESSAGE_SIZE);
111                   m_data_len = i; };
112     private:
113         unsigned            m_priority;
114         struct header {
115             unsigned int        magic;
116             unsigned int        version;
117             enum eMessageType   type;
118         } m_header;
119         unsigned int        m_data_len;
120         char                m_data[FFADO_IPC_MAX_MESSAGE_SIZE];
121     };
122
123 public:
124     // the master is in control of the data structures
125     // it represents one view of the ipc buffer
126     // the slave represents the other side
127     enum eBufferType {
128         eBT_Master,
129         eBT_Slave,
130     };
131     // the direction determines wheter we are going
132     // to read from, or write to the memory block
133     enum eDirection {
134         eD_Outward,
135         eD_Inward,
136     };
137     // blocking mode
138     enum eBlocking {
139         eB_Blocking,
140         eB_NonBlocking,
141     };
142     // possible responses of the operations
143     enum eResult {
144         eR_OK,
145         eR_Again,
146         eR_Error,
147         eR_Timeout,
148     };
149
150 public:
151     IpcRingBuffer(std::string, enum eBufferType, enum eDirection,
152                   enum eBlocking, unsigned int, unsigned int);
153     ~IpcRingBuffer();
154
155     bool init();
156
157     enum IpcRingBuffer::eResult Write(char *block);
158     enum IpcRingBuffer::eResult Read(char *block);
159     // request a pointer to the next block to read
160     // user has to call releaseBlockForRead before calling
161     // next requestBlockForRead or Read
162     enum IpcRingBuffer::eResult requestBlockForRead(void **block);
163     // release the requested block.
164     enum IpcRingBuffer::eResult releaseBlockForRead();
165
166     // request a pointer to the next block to write
167     // user has to call releaseBlockForWrite before calling
168     // next requestBlockForWrite or Write
169     enum IpcRingBuffer::eResult requestBlockForWrite(void **block);
170     // release the requested block.
171     enum IpcRingBuffer::eResult releaseBlockForWrite();
172
173     void show();
174     void setVerboseLevel(int l);
175     // only makes sense for outward buffers
176     unsigned int getBufferFill();
177 private:
178     void notificationHandler();
179
180 private:
181     std::string         m_name;
182     unsigned int        m_blocks;
183     unsigned int        m_blocksize;
184     enum eBufferType    m_type;
185     enum eDirection     m_direction;
186     enum eBlocking      m_blocking;
187     bool                m_initialized;
188     unsigned int        m_next_block;
189     unsigned int        m_last_block_ack;
190     unsigned int        m_idx;
191     unsigned int        m_last_idx_ack;
192
193     PosixMessageQueue&  m_ping_queue;     // for notifications
194     PosixMessageQueue&  m_pong_queue;     // for responses
195     PosixSharedMemory&  m_memblock;       // the actual data carrier
196     Mutex&              m_access_lock;    // to make operations atomic
197     Functor&            m_notify_functor; // to receive async notifications
198     sem_t               m_activity;       // to signal that async activity occurred
199
200     IpcMessage          m_LastDataMessageReceived;
201     Mutex&              m_block_requested_for_read;
202     IpcMessage          m_LastDataMessageSent;
203     Mutex&              m_block_requested_for_write;
204
205 protected:
206     DECLARE_DEBUG_MODULE;
207 };
208
209 } // Util
210
211 #endif // __UTIL_IPC_RINGBUFFER__
Note: See TracBrowser for help on using the browser.