@@ -83,26 +83,34 @@ static void print_dl_error(const char *message) {
8383}
8484
8585static struct option long_options [] = {
86- {"access_key" , required_argument , NULL , 'a' },
87- {"library_path" , required_argument , NULL , 'l' },
88- {"model_path" , required_argument , NULL , 'm' },
89- {"context_path" , required_argument , NULL , 'c' },
90- {"audio_device_index" , required_argument , NULL , 'd' },
91- {"sensitivity" , required_argument , NULL , 't' },
92- {"endpoint_duration_sec" , required_argument , NULL , 'u' },
93- {"require_endpoint" , required_argument , NULL , 'e' },
94- {"show_audio_devices" , no_argument , NULL , 's' },
86+ {"access_key" , required_argument , NULL , 'a' },
87+ {"library_path" , required_argument , NULL , 'l' },
88+ {"model_path" , required_argument , NULL , 'm' },
89+ {"device" , required_argument , NULL , 'y' },
90+ {"context_path" , required_argument , NULL , 'c' },
91+ {"audio_device_index" , required_argument , NULL , 'd' },
92+ {"sensitivity" , required_argument , NULL , 't' },
93+ {"endpoint_duration_sec" , required_argument , NULL , 'u' },
94+ {"require_endpoint" , required_argument , NULL , 'e' },
95+ {"show_audio_devices" , no_argument , NULL , 's' },
96+ {"show_inference_devices" , no_argument , NULL , 'i' },
9597};
9698
9799static void print_usage (const char * program_name ) {
98100 fprintf (stderr ,
99- "Usage : %s -a ACCESS_KEY -l LIBRARY_PATH -m MODEL_PATH -c CONTEXT_PATH [-d AUDIO_DEVICE_INDEX] "
101+ "Usage : %s -a ACCESS_KEY -l LIBRARY_PATH -m MODEL_PATH -y DEVICE - c CONTEXT_PATH [-d AUDIO_DEVICE_INDEX] "
100102 "[-t SENSITIVITY] [-u, --endpoint_duration_sec] [-e, --require_endpoint (true,false)]\n"
101103 " %s [-s, --show_audio_devices]\n" ,
102104 program_name ,
103105 program_name );
104106}
105107
108+ void print_error_message (char * * message_stack , int32_t message_stack_depth ) {
109+ for (int32_t i = 0 ; i < message_stack_depth ; i ++ ) {
110+ fprintf (stderr , " [%d] %s\n" , i , message_stack [i ]);
111+ }
112+ }
113+
106114void interrupt_handler (int _ ) {
107115 (void ) _ ;
108116 is_interrupted = true;
@@ -126,10 +134,81 @@ void show_audio_devices(void) {
126134 pv_recorder_free_available_devices (count , devices );
127135}
128136
129- void print_error_message (char * * message_stack , int32_t message_stack_depth ) {
130- for (int32_t i = 0 ; i < message_stack_depth ; i ++ ) {
131- fprintf (stderr , " [%d] %s\n" , i , message_stack [i ]);
137+ void print_inference_devices (const char * library_path ) {
138+ void * dl_handle = open_dl (library_path );
139+ if (!dl_handle ) {
140+ fprintf (stderr , "Failed to open library at '%s'.\n" , library_path );
141+ exit (EXIT_FAILURE );
142+ }
143+
144+ const char * (* pv_status_to_string_func )(pv_status_t ) = load_symbol (dl_handle , "pv_status_to_string" );
145+ if (!pv_status_to_string_func ) {
146+ print_dl_error ("Failed to load 'pv_status_to_string'" );
147+ exit (EXIT_FAILURE );
148+ }
149+
150+ pv_status_t (* pv_rhino_list_hardware_devices_func )(char * * * , int32_t * ) =
151+ load_symbol (dl_handle , "pv_rhino_list_hardware_devices" );
152+ if (!pv_eagle_list_hardware_devices_func ) {
153+ print_dl_error ("failed to load `pv_rhino_list_hardware_devices`" );
154+ exit (EXIT_FAILURE );
155+ }
156+
157+ pv_status_t (* pv_rhino_free_hardware_devices_func )(char * * , int32_t ) =
158+ load_symbol (dl_handle , "pv_rhino_free_hardware_devices" );
159+ if (!pv_eagle_free_hardware_devices_func ) {
160+ print_dl_error ("failed to load `pv_rhino_free_hardware_devices`" );
161+ exit (EXIT_FAILURE );
162+ }
163+
164+ pv_status_t (* pv_get_error_stack_func )(char * * * , int32_t * ) =
165+ load_symbol (dl_handle , "pv_get_error_stack" );
166+ if (!pv_get_error_stack_func ) {
167+ print_dl_error ("failed to load 'pv_get_error_stack_func'" );
168+ exit (EXIT_FAILURE );
169+ }
170+
171+ void (* pv_free_error_stack_func )(char * * ) =
172+ load_symbol (dl_handle , "pv_free_error_stack" );
173+ if (!pv_free_error_stack_func ) {
174+ print_dl_error ("failed to load 'pv_free_error_stack_func'" );
175+ exit (EXIT_FAILURE );
176+ }
177+
178+ char * * message_stack = NULL ;
179+ int32_t message_stack_depth = 0 ;
180+ pv_status_t error_status = PV_STATUS_RUNTIME_ERROR ;
181+
182+ char * * hardware_devices = NULL ;
183+ int32_t num_hardware_devices = 0 ;
184+ pv_status_t status = pv_rhino_list_hardware_devices_func (& hardware_devices , & num_hardware_devices );
185+ if (status != PV_STATUS_SUCCESS ) {
186+ fprintf (
187+ stderr ,
188+ "Failed to list hardware devices with `%s`.\n" ,
189+ pv_status_to_string_func (status ));
190+ error_status = pv_get_error_stack_func (& message_stack , & message_stack_depth );
191+ if (error_status != PV_STATUS_SUCCESS ) {
192+ fprintf (
193+ stderr ,
194+ ".\nUnable to get Rhino error state with '%s'.\n" ,
195+ pv_status_to_string_func (error_status ));
196+ exit (EXIT_FAILURE );
197+ }
198+
199+ if (message_stack_depth > 0 ) {
200+ fprintf (stderr , ":\n" );
201+ print_error_message (message_stack , message_stack_depth );
202+ pv_free_error_stack_func (message_stack );
203+ }
204+ exit (EXIT_FAILURE );
205+ }
206+
207+ for (int32_t i = 0 ; i < num_hardware_devices ; i ++ ) {
208+ fprintf (stdout , "%s\n" , hardware_devices [i ]);
132209 }
210+ pv_rhino_free_hardware_devices_func (hardware_devices , num_hardware_devices );
211+ close_dl (dl_handle );
133212}
134213
135214int picovoice_main (int argc , char * argv []) {
@@ -138,14 +217,16 @@ int picovoice_main(int argc, char *argv[]) {
138217 const char * access_key = NULL ;
139218 const char * library_path = NULL ;
140219 const char * model_path = NULL ;
220+ const char * device = "best" ;
141221 const char * context_path = NULL ;
142222 int32_t device_index = -1 ;
143223 float sensitivity = 0.5f ;
144224 float endpoint_duration_sec = 1.f ;
145225 bool require_endpoint = true;
226+ bool show_inference_devices = false;
146227
147228 int c ;
148- while ((c = getopt_long (argc , argv , "a:l:m:c:d:t:u:e:s " , long_options , NULL )) != -1 ) {
229+ while ((c = getopt_long (argc , argv , "a:l:m:y: c:d:t:u:e:si " , long_options , NULL )) != -1 ) {
149230 switch (c ) {
150231 case 'a' :
151232 access_key = optarg ;
@@ -156,6 +237,9 @@ int picovoice_main(int argc, char *argv[]) {
156237 case 'm' :
157238 model_path = optarg ;
158239 break ;
240+ case 'y' :
241+ device = optarg ;
242+ break ;
159243 case 'c' :
160244 context_path = optarg ;
161245 break ;
@@ -174,11 +258,25 @@ int picovoice_main(int argc, char *argv[]) {
174258 case 's' :
175259 show_audio_devices ();
176260 return 0 ;
261+ case 'i' :
262+ show_inference_devices = true;
263+ break ;
177264 default :
178265 exit (1 );
179266 }
180267 }
181268
269+ if (show_inference_devices ) {
270+ if (!library_path ) {
271+ fprintf (stderr , "`library_path` is required to view available inference devices.\n" );
272+ print_usage (argv [0 ]);
273+ exit (1 );
274+ }
275+
276+ print_inference_devices (library_path );
277+ return 0 ;
278+ }
279+
182280 if (!access_key || !library_path || !model_path || !context_path ) {
183281 print_usage (argv [0 ]);
184282 exit (1 );
@@ -206,6 +304,7 @@ int picovoice_main(int argc, char *argv[]) {
206304 const char * ,
207305 const char * ,
208306 const char * ,
307+ const char * ,
209308 float ,
210309 float ,
211310 bool ,
@@ -296,6 +395,7 @@ int picovoice_main(int argc, char *argv[]) {
296395 pv_status_t status = pv_rhino_init_func (
297396 access_key ,
298397 model_path ,
398+ device ,
299399 context_path ,
300400 sensitivity ,
301401 endpoint_duration_sec ,
0 commit comments