root/trunk/libffado/tests/test-messagequeue.cpp

Revision 1172, 7.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/PosixMessageQueue.h"
27 #include "libutil/Functors.h"
28
29 #include <argp.h>
30 #include <stdlib.h>
31 #include <iostream>
32 #include <signal.h>
33
34 #include <semaphore.h>
35
36 using namespace Util;
37
38 DECLARE_GLOBAL_DEBUG_MODULE;
39
40 #define MAX_ARGS 2
41
42 int run=1;
43 int lastsig=-1;
44 static void sighandler (int sig)
45 {
46     run = 0;
47 }
48
49 sem_t peep_sem;
50
51 ////////////////////////////////////////////////
52 // arg parsing
53 ////////////////////////////////////////////////
54 const char *argp_program_version = "test-messagequeue 0.1";
55 const char *argp_program_bug_address = "<ffado-devel@lists.sf.net>";
56 static char doc[] = "test-avccmd -- test program to test the message queues.";
57 static char args_doc[] = "DIRECTION";
58 static struct argp_option options[] = {
59     {"verbose",  'v', "level",    0,  "Produce verbose output" },
60    { 0 }
61 };
62
63 struct arguments
64 {
65     arguments()
66         : nargs ( 0 )
67         , verbose( false )
68         {
69             args[0] = 0;
70         }
71
72     char* args[MAX_ARGS];
73     int   nargs;
74     long int verbose;
75 } arguments;
76
77 // Parse a single option.
78 static error_t
79 parse_opt( int key, char* arg, struct argp_state* state )
80 {
81     // Get the input argument from `argp_parse', which we
82     // know is a pointer to our arguments structure.
83     struct arguments* arguments = ( struct arguments* ) state->input;
84
85     char* tail;
86     errno = 0;
87     switch (key) {
88     case 'v':
89         if (arg) {
90             arguments->verbose = strtol( arg, &tail, 0 );
91             if ( errno ) {
92                 fprintf( stderr,  "Could not parse 'verbose' argument\n" );
93                 return ARGP_ERR_UNKNOWN;
94             }
95         }
96         break;
97     case ARGP_KEY_ARG:
98         if (state->arg_num >= MAX_ARGS) {
99             // Too many arguments.
100             argp_usage (state);
101         }
102         arguments->args[state->arg_num] = arg;
103         arguments->nargs++;
104         break;
105     case ARGP_KEY_END:
106         if(arguments->nargs <= 0) {
107             printMessage("not enough arguments\n");
108             return -1;
109         }
110         break;
111     default:
112         return ARGP_ERR_UNKNOWN;
113     }
114     return 0;
115 }
116
117 static struct argp argp = { options, parse_opt, args_doc, doc };
118
119 class TestMessage : public Util::PosixMessageQueue::Message
120 {
121 public:
122     TestMessage()
123     : Message()
124     , m_prio( 0 )
125     , m_length( 64 )
126     , m_cnt( 0 )
127     {};
128     virtual ~TestMessage()
129     {};
130
131     virtual unsigned int getPriority()
132         {return m_prio;};
133     virtual unsigned int getLength() {
134         return m_length;
135     };
136
137     virtual bool serialize(char *buff) {
138         snprintf(buff, m_length, "cnt: %d", m_cnt++);
139         return true;
140     }
141
142     virtual bool deserialize(const char *buff, unsigned int length, unsigned prio) {
143         char tmp[length+1];
144         snprintf(tmp, length, "%s", buff);
145         tmp[length]=0;
146         printMessage("got message: '%s', prio %u\n", tmp, prio);
147         m_prio = prio;
148         return true;
149     };
150
151 private:
152     unsigned m_prio;
153     unsigned int m_length;
154     int m_cnt;
155 };
156
157 void peep() {
158      printMessage("peep...\n");
159      sem_post(&peep_sem);
160 }
161
162 ///////////////////////////
163 // main
164 //////////////////////////
165 int
166 main(int argc, char **argv)
167 {
168     int rv=0;
169     signal (SIGINT, sighandler);
170     signal (SIGPIPE, sighandler);
171
172     // arg parsing
173     if ( argp_parse ( &argp, argc, argv, 0, 0, &arguments ) ) {
174         fprintf( stderr, "Could not parse command line\n" );
175         exit(-1);
176     }
177
178     setDebugLevel(arguments.verbose);
179
180     errno = 0;
181     char* tail;
182     long int direction = strtol( arguments.args[0], &tail, 0 );
183     if ( errno ) {
184         fprintf( stderr,  "Could not parse direction argument\n" );
185         exit(-1);
186     }
187
188     if(sem_init(&peep_sem, 0, 0)) {
189         debugError("Could not init wait sem\n");
190         exit(-1);
191     }
192
193     printMessage("Testing message queue direction %ld\n", direction);
194
195     Util::Functor* peepfunc = NULL;
196
197     PosixMessageQueue p = PosixMessageQueue("testqueue1");
198     p.setVerboseLevel(arguments.verbose);
199     if(direction == 0) {
200         if(!p.Create(PosixMessageQueue::eD_WriteOnly)) {
201             debugError("Could not create queue\n");
202             exit(-1);
203         }
204     } else {
205         if(!p.Open(PosixMessageQueue::eD_ReadOnly, PosixMessageQueue::eB_NonBlocking)) {
206             debugError("Could not open queue\n");
207             exit(-1);
208         }
209         peepfunc = new Util::CallbackFunctor0< void (*)() >
210                     ( &peep, false );
211         if ( !peepfunc ) {
212             debugError( "Could not create peep handler\n" );
213             exit(-1);
214         }
215         if(!p.setNotificationHandler(peepfunc)) {
216             debugError("Could not set Notification Handler\n");
217              exit(-1);
218         }
219 //         if(!p.enableNotification()) {
220 //             debugError("Could not enable Notification\n");
221 //             exit(-1);
222 //         }
223     }
224
225     #define TIME_TO_SLEEP 1000*100
226     TestMessage m = TestMessage();
227     //m.setVerboseLevel(arguments.verbose);
228     run=1;
229     while(run) {
230         if(direction == 0) {
231             printMessage("sending...\n");
232             if(p.Send(m) != PosixMessageQueue::eR_OK) {
233                 debugError("Could not send to queue\n");
234                 goto out_err;
235             }
236             usleep(TIME_TO_SLEEP);
237         } else {
238             printMessage("receiving...\n");
239             printMessage(" enable notification...\n");
240             // first enable notification
241             if(!p.enableNotification()) {
242                 debugError("Could not enable Notification\n");
243                 goto out_err;
244             }
245             // then read all there is to read
246             printMessage(" reading...\n");
247             enum PosixMessageQueue::eResult ret;
248             while((ret = p.Receive(m)) == PosixMessageQueue::eR_OK) {
249                 // nothing
250             }
251             if (ret != PosixMessageQueue::eR_OK && ret != PosixMessageQueue::eR_Again) {
252                 debugError("Could not receive from queue\n");
253                 goto out_err;
254             }
255             // wait for a notification
256             printMessage(" waiting...\n");
257             if(sem_wait(&peep_sem)) {
258                 printMessage(" error: %s\n", strerror(errno));
259                 goto out_err;
260             }
261         }
262     }
263
264 cleanup:
265     if(peepfunc) {
266         if(!p.disableNotification()) {
267             debugError("Could not disable Notification\n");
268         }
269         if(!p.unsetNotificationHandler()) {
270             debugError("Could not unset Notification Handler\n");
271              exit(-1);
272         }
273         delete peepfunc;
274     }
275    
276     sem_destroy(&peep_sem);
277     return rv;
278
279 out_err:
280     rv=-1;
281     goto cleanup;
282
283 }
284
Note: See TracBrowser for help on using the browser.