root/trunk/libffado/tests/streaming/test-ipcclient.cpp

Revision 1172, 8.3 kB (checked in by ppalmers, 13 years ago)

lay down the foundations for easy ALSA/Pulse support

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 #include "debugmodule/debugmodule.h"
25
26 #include "libutil/IpcRingBuffer.h"
27 #include "libutil/SystemTimeSource.h"
28
29 #include <argp.h>
30 #include <stdlib.h>
31 #include <iostream>
32 #include <signal.h>
33
34 using namespace Util;
35
36 DECLARE_GLOBAL_DEBUG_MODULE;
37
38 #define MAX_ARGS 2
39
40 int run=1;
41 int lastsig=-1;
42 static void sighandler (int sig)
43 {
44     run = 0;
45 }
46
47 ////////////////////////////////////////////////
48 // arg parsing
49 ////////////////////////////////////////////////
50 const char *argp_program_version = "test-ipcringbuffer 0.1";
51 const char *argp_program_bug_address = "<ffado-devel@lists.sf.net>";
52 static char doc[] = "test-avccmd -- test program to test the ipc ringbuffer class.";
53 static char args_doc[] = "DIRECTION";
54 static struct argp_option options[] = {
55     {"verbose",  'v', "level",    0,  "Produce verbose output" },
56     {"playback", 'o', "count",    0,  "Number of playback channels" },
57     {"capture",  'i', "count",    0,  "Number of capture channels" },
58     {"period",  'p', "frames",    0,  "Period size in frames" },
59     {"nb_buffers",  'n', "count",    0,  "Number of IPC buffers" },
60   { 0 }
61 };
62
63 struct arguments
64 {
65     arguments()
66         : nargs ( 0 )
67         , verbose( false )
68         , playback( 0 )
69         , capture( 0 )
70         {
71             args[0] = 0;
72         }
73
74     char* args[MAX_ARGS];
75     int   nargs;
76     long int verbose;
77     long int playback;
78     long int capture;
79     long int period;
80     long int nb_buffers;
81 } arguments;
82
83 // Parse a single option.
84 static error_t
85 parse_opt( int key, char* arg, struct argp_state* state )
86 {
87     // Get the input argument from `argp_parse', which we
88     // know is a pointer to our arguments structure.
89     struct arguments* arguments = ( struct arguments* ) state->input;
90
91     char* tail;
92     errno = 0;
93     switch (key) {
94     case 'v':
95         if (arg) {
96             arguments->verbose = strtol( arg, &tail, 0 );
97             if ( errno ) {
98                 fprintf( stderr,  "Could not parse 'verbose' argument\n" );
99                 return ARGP_ERR_UNKNOWN;
100             }
101         }
102         break;
103     case 'o':
104         if (arg) {
105             arguments->playback = strtol( arg, &tail, 0 );
106             if ( errno ) {
107                 fprintf( stderr,  "Could not parse 'playback' argument\n" );
108                 return ARGP_ERR_UNKNOWN;
109             }
110         }
111         break;
112     case 'i':
113         if (arg) {
114             arguments->capture = strtol( arg, &tail, 0 );
115             if ( errno ) {
116                 fprintf( stderr,  "Could not parse 'capture' argument\n" );
117                 return ARGP_ERR_UNKNOWN;
118             }
119         }
120         break;
121     case 'p':
122         if (arg) {
123             arguments->period = strtol( arg, &tail, 0 );
124             if ( errno ) {
125                 fprintf( stderr,  "Could not parse 'periods' argument\n" );
126                 return ARGP_ERR_UNKNOWN;
127             }
128         }
129         break;
130     case 'n':
131         if (arg) {
132             arguments->nb_buffers = strtol( arg, &tail, 0 );
133             if ( errno ) {
134                 fprintf( stderr,  "Could not parse 'nb_buffers' argument\n" );
135                 return ARGP_ERR_UNKNOWN;
136             }
137         }
138         break;
139     case ARGP_KEY_ARG:
140         if (state->arg_num >= MAX_ARGS) {
141             // Too many arguments.
142             argp_usage (state);
143         }
144         arguments->args[state->arg_num] = arg;
145         arguments->nargs++;
146         break;
147     case ARGP_KEY_END:
148         if(arguments->nargs <= 0) {
149             printMessage("not enough arguments\n");
150             return -1;
151         }
152         break;
153     default:
154         return ARGP_ERR_UNKNOWN;
155     }
156     return 0;
157 }
158
159 static struct argp argp = { options, parse_opt, args_doc, doc };
160
161 ///////////////////////////
162 // main
163 //////////////////////////
164 int
165 main(int argc, char **argv)
166 {
167     signal (SIGINT, sighandler);
168     signal (SIGPIPE, sighandler);
169
170     // arg parsing
171     if ( argp_parse ( &argp, argc, argv, 0, 0, &arguments ) ) {
172         fprintf( stderr, "Could not parse command line\n" );
173         exit(-1);
174     }
175
176     setDebugLevel(arguments.verbose);
177
178     if(arguments.playback == 0 && arguments.capture == 0) {
179         debugError("No playback nor capture channels requested\n");
180         return -1;
181     }
182
183     printMessage("Testing shared memory streaming IPC\n");
184
185     // prepare the IPC buffers
186     unsigned int capture_buffsize = arguments.capture * arguments.period * 4;
187     unsigned int playback_buffsize = arguments.playback * arguments.period * 4;
188     IpcRingBuffer* capturebuffer = NULL;
189     IpcRingBuffer* playbackbuffer = NULL;
190     if(arguments.playback == 0) {
191         playbackbuffer = new IpcRingBuffer("playbackbuffer",
192                               IpcRingBuffer::eBT_Slave,
193                               IpcRingBuffer::eD_Outward,
194                               IpcRingBuffer::eB_Blocking,
195                               arguments.nb_buffers, playback_buffsize);
196         if(playbackbuffer == NULL) {
197             debugError("Could not create playbackbuffer\n");
198             exit(-1);
199         }
200         if(!playbackbuffer->init()) {
201             debugError("Could not init playbackbuffer\n");
202             delete playbackbuffer;
203             exit(-1);
204         }
205         playbackbuffer->setVerboseLevel(arguments.verbose);
206     }
207     if(arguments.capture) {
208         capturebuffer = new IpcRingBuffer("capturebuffer",
209                               IpcRingBuffer::eBT_Slave,
210                               IpcRingBuffer::eD_Inward,
211                               IpcRingBuffer::eB_Blocking,
212                               arguments.nb_buffers, capture_buffsize);
213         if(capturebuffer == NULL) {
214             debugError("Could not create capturebuffer\n");
215             delete playbackbuffer;
216             exit(-1);
217         }
218         if(!capturebuffer->init()) {
219             debugError("Could not init capturebuffer\n");
220             delete playbackbuffer;
221             delete capturebuffer;
222             exit(-1);
223         }
224         capturebuffer->setVerboseLevel(arguments.verbose);
225     }
226
227
228     // dummy buffers
229     char capture_buff[capture_buffsize];
230     char playback_buff[playback_buffsize];
231
232     int cnt = 0;
233
234
235     run=1;
236     while(run) {
237         // write the data
238         IpcRingBuffer::eResult res;
239         res = playbackbuffer->Write(playback_buff);
240         if(res != IpcRingBuffer::eR_OK && res != IpcRingBuffer::eR_Again) {
241             debugError("Could not write to segment\n");
242             goto out_err;
243         }
244         if(res == IpcRingBuffer::eR_Again) {
245             printMessage(" Try playback again on %d...\n", cnt);
246         }
247
248         res = capturebuffer->Read(capture_buff);
249         if(res != IpcRingBuffer::eR_OK && res != IpcRingBuffer::eR_Again) {
250             debugError("Could not receive from queue\n");
251             goto out_err;
252         }
253         if(res == IpcRingBuffer::eR_Again) {
254             printMessage(" Try again on %d...\n", cnt);
255         } else {
256             if(cnt%10==0) {
257                 uint32_t *tmp = (uint32_t *)capture_buff;
258                 for(int i=0;i<arguments.capture;i++) {
259                     printMessage(" channel %d: ", i);
260                     for(int j=0; j < 6;j+=1) {
261                         uint32_t tmp2 = tmp[j] << 8;
262                         int32_t *tmp3 = (int32_t *)&tmp2;
263                         printMessageShort("%10d ", *tmp3);
264                     }
265                     tmp += arguments.period;
266                     printMessageShort("\n");
267                 }
268             }
269             cnt++;
270         }
271     }
272
273     delete capturebuffer;
274     delete playbackbuffer;
275     return 0;
276
277 out_err:
278     delete capturebuffer;
279     delete playbackbuffer;
280     return -1;
281 }
282
Note: See TracBrowser for help on using the browser.