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

Revision 1240, 9.0 kB (checked in by ppalmers, 16 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 #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[] = "";
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     arguments.verbose           = 6;
171     arguments.period            = 1024;
172     arguments.nb_buffers        = 3;
173     arguments.playback          = 0;
174     arguments.capture           = 0;
175
176     // arg parsing
177     if ( argp_parse ( &argp, argc, argv, 0, 0, &arguments ) ) {
178         fprintf( stderr, "Could not parse command line\n" );
179         exit(-1);
180     }
181
182     setDebugLevel(arguments.verbose);
183
184     if(arguments.playback == 0 && arguments.capture == 0) {
185         debugError("No playback nor capture channels requested\n");
186         return -1;
187     }
188
189     printMessage("Testing shared memory streaming IPC\n");
190     printMessage(" period %d, nb_buffers %d, playback %d, capture %d\n",
191                  arguments.period, arguments.nb_buffers,
192                  arguments.playback,
193                  arguments.capture );
194
195     // prepare the IPC buffers
196     unsigned int capture_buffsize = arguments.capture * arguments.period * 4;
197     unsigned int playback_buffsize = arguments.playback * arguments.period * 4;
198     IpcRingBuffer* capturebuffer = NULL;
199     IpcRingBuffer* playbackbuffer = NULL;
200     if(arguments.playback) {
201         playbackbuffer = new IpcRingBuffer("playbackbuffer",
202                               IpcRingBuffer::eBT_Slave,
203                               IpcRingBuffer::eD_Outward,
204                               IpcRingBuffer::eB_Blocking,
205                               arguments.nb_buffers, playback_buffsize);
206         if(playbackbuffer == NULL) {
207             debugError("Could not create playbackbuffer\n");
208             exit(-1);
209         }
210         if(!playbackbuffer->init()) {
211             debugError("Could not init playbackbuffer\n");
212             delete playbackbuffer;
213             exit(-1);
214         }
215         playbackbuffer->setVerboseLevel(arguments.verbose);
216     }
217     if(arguments.capture) {
218         capturebuffer = new IpcRingBuffer("capturebuffer",
219                               IpcRingBuffer::eBT_Slave,
220                               IpcRingBuffer::eD_Inward,
221                               IpcRingBuffer::eB_Blocking,
222                               arguments.nb_buffers, capture_buffsize);
223         if(capturebuffer == NULL) {
224             debugError("Could not create capturebuffer\n");
225             delete playbackbuffer;
226             exit(-1);
227         }
228         if(!capturebuffer->init()) {
229             debugError("Could not init capturebuffer\n");
230             delete playbackbuffer;
231             delete capturebuffer;
232             exit(-1);
233         }
234         capturebuffer->setVerboseLevel(arguments.verbose);
235     }
236
237
238     // dummy buffers
239     char capture_buff[capture_buffsize];
240     char playback_buff[playback_buffsize];
241
242     int cnt = 0;
243     int pbkcnt = 0;
244
245     run=1;
246     while(run) {
247         // write the data
248         IpcRingBuffer::eResult res;
249         if(playbackbuffer) {
250             res = playbackbuffer->Write(playback_buff);
251             if(res != IpcRingBuffer::eR_OK && res != IpcRingBuffer::eR_Again) {
252                 debugError("Could not write to segment\n");
253                 goto out_err;
254             }
255             if(res == IpcRingBuffer::eR_Again) {
256                 printMessage(" Try playback again on %d...\n", cnt);
257             } else {
258                 if(pbkcnt%100==0) {
259                     printMessage(" Period %d...\n", pbkcnt);
260                 }
261                 pbkcnt++;
262             }
263         }
264         // read data
265         if (capturebuffer) {
266             res = capturebuffer->Read(capture_buff);
267             if(res != IpcRingBuffer::eR_OK && res != IpcRingBuffer::eR_Again) {
268                 debugError("Could not receive from queue\n");
269                 goto out_err;
270             }
271             if(res == IpcRingBuffer::eR_Again) {
272                 printMessage(" Try again on %d...\n", cnt);
273             } else {
274                 if(cnt%10==0) {
275                     uint32_t *tmp = (uint32_t *)capture_buff;
276                     for(int i=0;i<arguments.capture;i++) {
277                         printMessage(" channel %d: ", i);
278                         for(int j=0; j < 6;j+=1) {
279                             uint32_t tmp2 = tmp[j] << 8;
280                             int32_t *tmp3 = (int32_t *)&tmp2;
281                             printMessageShort("%10d ", *tmp3);
282                         }
283                         tmp += arguments.period;
284                         printMessageShort("\n");
285                     }
286                 }
287                 cnt++;
288             }
289         }
290     }
291
292     delete capturebuffer;
293     delete playbackbuffer;
294     return 0;
295
296 out_err:
297     delete capturebuffer;
298     delete playbackbuffer;
299     return -1;
300 }
301
Note: See TracBrowser for help on using the browser.