andrewm@5
|
1 /*
|
andrewm@5
|
2 * RTAudioCommandLine.cpp
|
andrewm@5
|
3 *
|
andrewm@5
|
4 * Created on: Nov 8, 2014
|
andrewm@5
|
5 * Author: parallels
|
andrewm@5
|
6 */
|
andrewm@5
|
7
|
andrewm@5
|
8 #include <iostream>
|
andrewm@5
|
9 #include <cstdlib>
|
andrewm@5
|
10 #include <cstring>
|
andrewm@5
|
11 #include <getopt.h>
|
andrewm@5
|
12 #include "../include/RTAudio.h"
|
giuliomoro@24
|
13
|
giuliomoro@23
|
14 #ifndef OPT_PRU_FILE
|
giuliomoro@23
|
15 #define OPT_PRU_FILE -1
|
giuliomoro@23
|
16 #endif
|
andrewm@5
|
17
|
andrewm@5
|
18 // Default command-line options for RTAudio
|
andrewm@5
|
19 struct option gDefaultLongOptions[] =
|
andrewm@5
|
20 {
|
andrewm@5
|
21 {"period", 1, NULL, 'p'},
|
andrewm@5
|
22 {"verbose", 0, NULL, 'v'},
|
giuliomoro@19
|
23 {"use-analog", 1, NULL, 'm'},
|
giuliomoro@23
|
24 {"use-digital-gpio", 1, NULL, 'g'},
|
giuliomoro@19
|
25 {"analog-channels", 1, NULL, 'C'},
|
giuliomoro@24
|
26 {"digital-channels", 1, NULL, 'G'},
|
andrewm@5
|
27 {"mute-speaker", 1, NULL, 'M'},
|
andrewm@5
|
28 {"dac-level", 1, NULL, 'D'},
|
andrewm@5
|
29 {"adc-level", 1, NULL, 'A'},
|
andrewm@5
|
30 {"hp-level", 1, NULL, 'H'},
|
giuliomoro@24
|
31 {"receive-port", 1, NULL, 'r'},
|
giuliomoro@24
|
32 {"transmit-port", 1, NULL, 't'},
|
giuliomoro@24
|
33 {"server-name",1,NULL,'s'},
|
giuliomoro@23
|
34 {"pru-file",1,NULL,OPT_PRU_FILE},
|
andrewm@5
|
35 {NULL, 0, NULL, 0}
|
andrewm@5
|
36 };
|
giuliomoro@24
|
37
|
giuliomoro@24
|
38 const char gDefaultShortOptions[] = "p:vm:M:C:D:A:H:g:G:r:t:s:";
|
andrewm@5
|
39
|
andrewm@5
|
40 // This function sets the default settings for the RTAudioSettings structure
|
andrewm@5
|
41 void BeagleRT_defaultSettings(RTAudioSettings *settings)
|
andrewm@5
|
42 {
|
andrewm@5
|
43 // Set default values for settings
|
andrewm@5
|
44 settings->periodSize = 8;
|
andrewm@5
|
45 settings->beginMuted = 0;
|
andrewm@5
|
46 settings->dacLevel = DEFAULT_DAC_LEVEL;
|
andrewm@5
|
47 settings->adcLevel = DEFAULT_ADC_LEVEL;
|
andrewm@5
|
48 settings->headphoneLevel = DEFAULT_HP_LEVEL;
|
giuliomoro@19
|
49 settings->useAnalog = 1;
|
giuliomoro@19
|
50 settings->useDigital = 1;
|
giuliomoro@19
|
51 settings->numAnalogChannels = 8;
|
giuliomoro@19
|
52 settings->numDigitalChannels = 16;
|
andrewm@5
|
53 settings->verbose = 0;
|
giuliomoro@16
|
54 settings->pruFilename[0]='\0';
|
andrewm@5
|
55 settings->codecI2CAddress = CODEC_I2C_ADDRESS;
|
giuliomoro@24
|
56 settings->receivePort=9998;
|
giuliomoro@24
|
57 settings->transmitPort=9999;
|
giuliomoro@24
|
58 strcpy(settings->serverName, "127.0.0.1");
|
andrewm@5
|
59 settings->ampMutePin = kAmplifierMutePin;
|
andrewm@5
|
60 }
|
andrewm@5
|
61
|
andrewm@5
|
62 // This function drops in place of getopt() in the main() function
|
andrewm@5
|
63 // and handles the initialisation of the RTAudio settings using
|
andrewm@5
|
64 // standard command-line arguments. System default arguments will
|
andrewm@5
|
65 // be stored in settings, otherwise arguments will be returned
|
andrewm@5
|
66 // as getopt() normally does.
|
andrewm@5
|
67
|
andrewm@5
|
68 int BeagleRT_getopt_long(int argc, char *argv[], const char *customShortOptions, const struct option *customLongOptions, RTAudioSettings *settings)
|
andrewm@5
|
69 {
|
andrewm@5
|
70 static int firstRun = 1;
|
andrewm@5
|
71 static char totalShortOptions[256];
|
andrewm@5
|
72 static struct option totalLongOptions[256];
|
andrewm@5
|
73
|
andrewm@5
|
74 int c;
|
andrewm@5
|
75
|
andrewm@5
|
76 // Prep total option string the first time this is
|
andrewm@5
|
77 // run. As a getopt() substitute, it will be called repeatedly working its
|
andrewm@5
|
78 // way through argc and argv.
|
andrewm@5
|
79 if(firstRun) {
|
andrewm@5
|
80 firstRun = 0;
|
andrewm@5
|
81
|
andrewm@5
|
82 // Copy short options into one string
|
andrewm@5
|
83 strcpy(totalShortOptions, gDefaultShortOptions);
|
andrewm@5
|
84 strncat(totalShortOptions, customShortOptions, 256 - strlen(gDefaultShortOptions) - 1);
|
andrewm@5
|
85
|
andrewm@5
|
86 // Copy long options into one array
|
andrewm@5
|
87 int n = 0;
|
andrewm@5
|
88 while(1) {
|
andrewm@5
|
89 if(gDefaultLongOptions[n].name == NULL)
|
andrewm@5
|
90 break;
|
andrewm@5
|
91 totalLongOptions[n].name = gDefaultLongOptions[n].name;
|
andrewm@5
|
92 totalLongOptions[n].has_arg = gDefaultLongOptions[n].has_arg;
|
andrewm@5
|
93 totalLongOptions[n].flag = gDefaultLongOptions[n].flag;
|
andrewm@5
|
94 totalLongOptions[n].val = gDefaultLongOptions[n].val;
|
andrewm@5
|
95 n++;
|
andrewm@5
|
96 }
|
andrewm@5
|
97
|
andrewm@5
|
98 // Copy custom options into the array, if present
|
andrewm@5
|
99 if(customLongOptions == 0) {
|
andrewm@5
|
100 // Terminate the array
|
andrewm@5
|
101 totalLongOptions[n].name = NULL;
|
andrewm@5
|
102 totalLongOptions[n].has_arg = 0;
|
andrewm@5
|
103 totalLongOptions[n].flag = NULL;
|
andrewm@5
|
104 totalLongOptions[n].val = 0;
|
andrewm@5
|
105 }
|
andrewm@5
|
106 else {
|
andrewm@5
|
107 int customIndex = 0;
|
andrewm@5
|
108 while(n < 256) {
|
andrewm@5
|
109 if(customLongOptions[customIndex].name == NULL)
|
andrewm@5
|
110 break;
|
andrewm@5
|
111 totalLongOptions[n].name = customLongOptions[customIndex].name;
|
andrewm@5
|
112 totalLongOptions[n].has_arg = customLongOptions[customIndex].has_arg;
|
andrewm@5
|
113 totalLongOptions[n].flag = customLongOptions[customIndex].flag;
|
andrewm@5
|
114 totalLongOptions[n].val = customLongOptions[customIndex].val;
|
andrewm@5
|
115 n++;
|
andrewm@5
|
116 customIndex++;
|
andrewm@5
|
117 }
|
andrewm@5
|
118
|
andrewm@5
|
119 // Terminate the array
|
andrewm@5
|
120 totalLongOptions[n].name = NULL;
|
andrewm@5
|
121 totalLongOptions[n].has_arg = 0;
|
andrewm@5
|
122 totalLongOptions[n].flag = NULL;
|
andrewm@5
|
123 totalLongOptions[n].val = 0;
|
andrewm@5
|
124 }
|
andrewm@5
|
125 }
|
andrewm@5
|
126
|
andrewm@5
|
127 while(1) {
|
andrewm@5
|
128 if ((c = getopt_long(argc, argv, totalShortOptions, totalLongOptions, NULL)) < 0)
|
andrewm@5
|
129 return c;
|
andrewm@5
|
130
|
andrewm@5
|
131 switch (c) {
|
andrewm@5
|
132 case 'p':
|
andrewm@5
|
133 settings->periodSize = atoi(optarg);
|
andrewm@5
|
134 if(settings->periodSize < 1)
|
andrewm@5
|
135 settings->periodSize = 1;
|
andrewm@5
|
136 break;
|
andrewm@5
|
137 case 'v':
|
andrewm@5
|
138 settings->verbose = 1;
|
andrewm@5
|
139 break;
|
andrewm@5
|
140 case 'm':
|
giuliomoro@19
|
141 settings->useAnalog = atoi(optarg);
|
andrewm@5
|
142 break;
|
giuliomoro@16
|
143 case 'g':
|
giuliomoro@19
|
144 settings->useDigital = atoi(optarg);
|
giuliomoro@19
|
145 settings->numDigitalChannels = 0;
|
giuliomoro@16
|
146 break;
|
andrewm@12
|
147 case 'C':
|
giuliomoro@19
|
148 settings->numAnalogChannels = atoi(optarg);
|
giuliomoro@19
|
149 if(settings->numAnalogChannels >= 8)
|
giuliomoro@19
|
150 settings->numAnalogChannels = 8;
|
giuliomoro@19
|
151 else if(settings->numAnalogChannels >= 4)
|
giuliomoro@19
|
152 settings->numAnalogChannels = 4;
|
andrewm@12
|
153 else
|
giuliomoro@19
|
154 settings->numAnalogChannels = 2;
|
andrewm@12
|
155 break;
|
giuliomoro@16
|
156 case 'G':
|
giuliomoro@19
|
157 settings->numDigitalChannels = atoi(optarg);
|
giuliomoro@19
|
158 if(settings->numDigitalChannels >= 16)
|
giuliomoro@19
|
159 settings->numDigitalChannels = 16;
|
giuliomoro@19
|
160 else if (settings->numDigitalChannels < 1){
|
giuliomoro@19
|
161 settings->numDigitalChannels = 0;
|
giuliomoro@19
|
162 settings->useDigital = 0; //TODO: this actually works only if -G 0 is specified after -g 1.
|
giuliomoro@19
|
163 //No worries, though: disabling numDigital will only prevent the pins from being exported.
|
giuliomoro@16
|
164 }
|
giuliomoro@16
|
165 break;
|
andrewm@5
|
166 case 'M':
|
andrewm@5
|
167 settings->beginMuted = atoi(optarg);
|
andrewm@5
|
168 break;
|
andrewm@5
|
169 case 'D':
|
andrewm@5
|
170 settings->dacLevel = atof(optarg);
|
andrewm@5
|
171 break;
|
andrewm@5
|
172 case 'A':
|
andrewm@5
|
173 settings->adcLevel = atof(optarg);
|
andrewm@5
|
174 break;
|
andrewm@5
|
175 case 'H':
|
andrewm@5
|
176 settings->headphoneLevel = atof(optarg);
|
andrewm@5
|
177 break;
|
giuliomoro@24
|
178 case 'r':
|
giuliomoro@24
|
179 settings->receivePort = atoi(optarg);
|
giuliomoro@24
|
180 break;
|
giuliomoro@24
|
181 case 't':
|
giuliomoro@24
|
182 settings->transmitPort = atoi(optarg);
|
giuliomoro@24
|
183 break;
|
giuliomoro@24
|
184 case 's':
|
giuliomoro@24
|
185 if(strlen(optarg)<MAX_SERVERNAME_LENGTH)
|
giuliomoro@24
|
186 strcpy(settings->serverName, optarg);
|
giuliomoro@24
|
187 else
|
giuliomoro@24
|
188 std::cerr << "Warning: server name is too long (>" << MAX_SERVERNAME_LENGTH << " characters)."
|
giuliomoro@24
|
189 " Using default severName Instead ( " << settings->serverName << " ).\n";
|
giuliomoro@24
|
190 break;
|
giuliomoro@24
|
191 case 'OPT_PRU_FILE':
|
giuliomoro@16
|
192 if(strlen(optarg)<MAX_PRU_FILENAME_LENGTH)
|
giuliomoro@16
|
193 strcpy(settings->pruFilename, optarg);
|
giuliomoro@16
|
194 else
|
giuliomoro@16
|
195 std::cerr << "Warning: filename for the PRU code is too long (>" << MAX_PRU_FILENAME_LENGTH << " characters). Using embedded PRU code instead\n";
|
giuliomoro@16
|
196 break;
|
andrewm@5
|
197 case '?':
|
andrewm@5
|
198 default:
|
andrewm@5
|
199 return c;
|
andrewm@5
|
200 }
|
andrewm@5
|
201 }
|
andrewm@5
|
202 }
|
andrewm@5
|
203
|
andrewm@5
|
204 // This function prints standard usage information for default arguments
|
andrewm@5
|
205 // Call from within your own usage function
|
andrewm@5
|
206 void BeagleRT_usage()
|
andrewm@5
|
207 {
|
giuliomoro@19
|
208 std::cerr << " --period [-p] period: Set the hardware period (buffer) size in analog samples\n";
|
giuliomoro@16
|
209 std::cerr << " --dac-level [-D] dBs: Set the DAC output level (0dB max; -63.5dB min)\n";
|
giuliomoro@16
|
210 std::cerr << " --adc-level [-A] dBs: Set the ADC input level (0dB max; -12dB min)\n";
|
giuliomoro@16
|
211 std::cerr << " --hp-level [-H] dBs: Set the headphone output level (0dB max; -63.5dB min)\n";
|
giuliomoro@16
|
212 std::cerr << " --mute-speaker [-M] val: Set whether to mute the speaker initially (default: no)\n";
|
giuliomoro@19
|
213 std::cerr << " --use-analog [-m] val: Set whether to use ADC/DAC analog (default: yes)\n";
|
giuliomoro@24
|
214 std::cerr << " --use-digital [-g] val: Set whether to use digital GPIO channels (default: yes)\n";
|
giuliomoro@19
|
215 std::cerr << " --analog-channels [-C] val: Set the number of ADC/DAC channels (default: 8)\n";
|
giuliomoro@24
|
216 std::cerr << " --digital-channels [-G] val: Set the number of digital GPIO channels (default: 16)\n";
|
giuliomoro@24
|
217 std::cerr << " --receive-port [-r] val: Set the receive port (default: 9998)\n";
|
giuliomoro@24
|
218 std::cerr << " --transmit-port [-t] val: Set the transmit port (default: 9999)\n";
|
giuliomoro@24
|
219 std::cerr << " --server-name [-s] val: Set the destination server name (default: '127.0.0.1')\n";
|
giuliomoro@24
|
220 std::cerr << " --pru-file val: Set an optional external file to use for the PRU binary code\n";
|
giuliomoro@16
|
221 std::cerr << " --verbose [-v]: Enable verbose logging information\n";
|
andrewm@5
|
222 }
|
giuliomoro@16
|
223
|