motu: implement block async functions since they are ultimately required when dealing...
[ffado.git] / libffado / tests / test-ipcringbuffer.cpp
blob04c9d87d774d39dd8a68d5a34c1692e1c2ccdc38
1 /*
2 * Copyright (C) 2005-2008 by Pieter Palmers
4 * This file is part of FFADO
5 * FFADO = Free Firewire (pro-)audio drivers for linux
7 * FFADO is based upon FreeBoB
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.
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.
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/>.
24 #include "debugmodule/debugmodule.h"
26 #include "libutil/IpcRingBuffer.h"
27 #include "libutil/SystemTimeSource.h"
29 #include <argp.h>
30 #include <stdlib.h>
31 #include <iostream>
32 #include <signal.h>
33 #include <unistd.h>
35 using namespace Util;
37 DECLARE_GLOBAL_DEBUG_MODULE;
39 #define MAX_ARGS 2
41 int run=1;
42 int lastsig=-1;
43 static void sighandler (int sig)
45 run = 0;
48 ////////////////////////////////////////////////
49 // arg parsing
50 ////////////////////////////////////////////////
51 const char *argp_program_version = "test-ipcringbuffer 0.1";
52 const char *argp_program_bug_address = "<ffado-devel@lists.sf.net>";
53 static char doc[] = "test-avccmd -- test program to test the ipc ringbuffer class.";
54 static char args_doc[] = "DIRECTION";
55 static struct argp_option options[] = {
56 {"verbose", 'v', "level", 0, "Produce verbose output" },
57 { 0 }
60 struct arguments
62 arguments()
63 : nargs ( 0 )
64 , verbose( false )
66 args[0] = 0;
69 char* args[MAX_ARGS];
70 int nargs;
71 long int verbose;
72 } arguments;
74 // Parse a single option.
75 static error_t
76 parse_opt( int key, char* arg, struct argp_state* state )
78 // Get the input argument from `argp_parse', which we
79 // know is a pointer to our arguments structure.
80 struct arguments* arguments = ( struct arguments* ) state->input;
82 char* tail;
83 errno = 0;
84 switch (key) {
85 case 'v':
86 if (arg) {
87 arguments->verbose = strtol( arg, &tail, 0 );
88 if ( errno ) {
89 fprintf( stderr, "Could not parse 'verbose' argument\n" );
90 return ARGP_ERR_UNKNOWN;
93 break;
94 case ARGP_KEY_ARG:
95 if (state->arg_num >= MAX_ARGS) {
96 // Too many arguments.
97 argp_usage (state);
99 arguments->args[state->arg_num] = arg;
100 arguments->nargs++;
101 break;
102 case ARGP_KEY_END:
103 if(arguments->nargs <= 0) {
104 printMessage("not enough arguments\n");
105 return -1;
107 break;
108 default:
109 return ARGP_ERR_UNKNOWN;
111 return 0;
114 static struct argp argp = { options, parse_opt, args_doc, doc };
116 ///////////////////////////
117 // main
118 //////////////////////////
120 main(int argc, char **argv)
122 signal (SIGINT, sighandler);
123 signal (SIGPIPE, sighandler);
125 // arg parsing
126 if ( argp_parse ( &argp, argc, argv, 0, 0, &arguments ) ) {
127 fprintf( stderr, "Could not parse command line\n" );
128 exit(-1);
131 setDebugLevel(arguments.verbose);
133 errno = 0;
134 char* tail;
135 long int direction = strtol( arguments.args[0], &tail, 0 );
136 if ( errno ) {
137 fprintf( stderr, "Could not parse direction argument\n" );
138 exit(-1);
141 printMessage("Testing shared memory direction %ld\n", direction);
143 #define TEST_SAMPLERATE 44100
144 #define BUFF_SIZE 64
145 #define NB_BUFFERS 4
146 IpcRingBuffer* b = NULL;
147 if(direction == 0) {
148 b = new IpcRingBuffer("testbuff",
149 IpcRingBuffer::eBT_Master,
150 IpcRingBuffer::eD_Outward,
151 IpcRingBuffer::eB_Blocking,
152 NB_BUFFERS, BUFF_SIZE);
153 if(b == NULL) {
154 debugError("Could not create master\n");
155 exit(-1);
157 } else {
158 b = new IpcRingBuffer("testbuff",
159 IpcRingBuffer::eBT_Master,
160 IpcRingBuffer::eD_Inward,
161 IpcRingBuffer::eB_Blocking,
162 NB_BUFFERS, BUFF_SIZE);
163 if(b == NULL) {
164 debugError("Could not create master\n");
165 exit(-1);
169 b->setVerboseLevel(arguments.verbose);
171 char buff[BUFF_SIZE];
172 int cnt = 0;
173 long int time_to_sleep = 1000*1000*BUFF_SIZE/TEST_SAMPLERATE;
175 if(!b->init()) {
176 debugError("Could not init buffer\n");
177 goto out_err;
180 run=1;
181 while(run) {
182 if(direction == 0) {
183 snprintf(buff, BUFF_SIZE, "test %d", cnt);
184 if(cnt%1000==0) {
185 printMessage("writing '%s'...\n", buff);
187 IpcRingBuffer::eResult res = b->Write(buff);
188 if(res != IpcRingBuffer::eR_OK && res != IpcRingBuffer::eR_Again) {
189 debugError("Could not write to segment\n");
190 goto out_err;
192 if(res == IpcRingBuffer::eR_Again) {
193 printMessage(" Try again on %d...\n", cnt);
194 } else {
195 cnt++;
197 usleep(time_to_sleep);
198 } else {
199 if(cnt%1000==0) {
200 printMessage("reading...\n");
203 IpcRingBuffer::eResult res = b->Read(buff);
204 if(res != IpcRingBuffer::eR_OK && res != IpcRingBuffer::eR_Again) {
205 debugError("Could not receive from queue\n");
206 goto out_err;
208 if(cnt%1000==0) {
209 buff[BUFF_SIZE-1]=0;
210 printMessage(" read: '%s'\n", buff);
212 if(res == IpcRingBuffer::eR_Again) {
213 printMessage(" Try again on %d...\n", cnt);
214 } else {
215 cnt++;
220 delete b;
221 return 0;
223 out_err:
224 delete b;
225 return -1;