11/*
2- Copyright 2018-2023 Picovoice Inc.
2+ Copyright 2018-2025 Picovoice Inc.
33
44 You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE"
55 file accompanying this source.
@@ -90,19 +90,21 @@ static struct option long_options[] = {
9090 {"access_key" , required_argument , NULL , 'a' },
9191 {"library_path" , required_argument , NULL , 'l' },
9292 {"model_path" , required_argument , NULL , 'm' },
93+ {"device" , required_argument , NULL , 'y' },
9394 {"context_path" , required_argument , NULL , 'c' },
9495 {"wav_path" , required_argument , NULL , 'w' },
9596 {"sensitivity" , required_argument , NULL , 't' },
9697 {"endpoint_duration_sec" , required_argument , NULL , 'u' },
9798 {"require_endpoint" , required_argument , NULL , 'e' },
98- {"performance_threshold_sec" , optional_argument , NULL , 'p' }
99+ {"performance_threshold_sec" , optional_argument , NULL , 'p' },
100+ {"show_inference_devices" , no_argument , NULL , 'i' },
99101};
100102
101103void print_usage (const char * program_name ) {
102104 fprintf (
103105 stderr ,
104- "Usage : %s -a ACCESS_KEY -l LIBRARY_PATH -m MODEL_PATH -c CONTEXT_PATH -w WAV_PATH [-t SENSITIVITY] "
105- "[-u, --endpoint_duration_sec] [-e, --require_endpoint (true,false)]\n" ,
106+ "Usage : %s -a ACCESS_KEY -l LIBRARY_PATH -m MODEL_PATH -y DEVICE - c CONTEXT_PATH -w WAV_PATH [-t SENSITIVITY] "
107+ "[-u, --endpoint_duration_sec] [-e, --require_endpoint (true,false)] [-i, --show_inference_devices] \n" ,
106108 program_name );
107109}
108110
@@ -112,19 +114,98 @@ void print_error_message(char **message_stack, int32_t message_stack_depth) {
112114 }
113115}
114116
117+ void print_inference_devices (const char * library_path ) {
118+ void * dl_handle = open_dl (library_path );
119+ if (!dl_handle ) {
120+ fprintf (stderr , "Failed to open library at '%s'.\n" , library_path );
121+ exit (EXIT_FAILURE );
122+ }
123+
124+ const char * (* pv_status_to_string_func )(pv_status_t ) = load_symbol (dl_handle , "pv_status_to_string" );
125+ if (!pv_status_to_string_func ) {
126+ print_dl_error ("Failed to load 'pv_status_to_string'" );
127+ exit (EXIT_FAILURE );
128+ }
129+
130+ pv_status_t (* pv_rhino_list_hardware_devices_func )(char * * * , int32_t * ) =
131+ load_symbol (dl_handle , "pv_rhino_list_hardware_devices" );
132+ if (!pv_rhino_list_hardware_devices_func ) {
133+ print_dl_error ("failed to load `pv_rhino_list_hardware_devices`" );
134+ exit (EXIT_FAILURE );
135+ }
136+
137+ pv_status_t (* pv_rhino_free_hardware_devices_func )(char * * , int32_t ) =
138+ load_symbol (dl_handle , "pv_rhino_free_hardware_devices" );
139+ if (!pv_rhino_free_hardware_devices_func ) {
140+ print_dl_error ("failed to load `pv_rhino_free_hardware_devices`" );
141+ exit (EXIT_FAILURE );
142+ }
143+
144+ pv_status_t (* pv_get_error_stack_func )(char * * * , int32_t * ) =
145+ load_symbol (dl_handle , "pv_get_error_stack" );
146+ if (!pv_get_error_stack_func ) {
147+ print_dl_error ("failed to load 'pv_get_error_stack_func'" );
148+ exit (EXIT_FAILURE );
149+ }
150+
151+ void (* pv_free_error_stack_func )(char * * ) =
152+ load_symbol (dl_handle , "pv_free_error_stack" );
153+ if (!pv_free_error_stack_func ) {
154+ print_dl_error ("failed to load 'pv_free_error_stack_func'" );
155+ exit (EXIT_FAILURE );
156+ }
157+
158+ char * * message_stack = NULL ;
159+ int32_t message_stack_depth = 0 ;
160+ pv_status_t error_status = PV_STATUS_RUNTIME_ERROR ;
161+
162+ char * * hardware_devices = NULL ;
163+ int32_t num_hardware_devices = 0 ;
164+ pv_status_t status = pv_rhino_list_hardware_devices_func (& hardware_devices , & num_hardware_devices );
165+ if (status != PV_STATUS_SUCCESS ) {
166+ fprintf (
167+ stderr ,
168+ "Failed to list hardware devices with `%s`.\n" ,
169+ pv_status_to_string_func (status ));
170+ error_status = pv_get_error_stack_func (& message_stack , & message_stack_depth );
171+ if (error_status != PV_STATUS_SUCCESS ) {
172+ fprintf (
173+ stderr ,
174+ ".\nUnable to get Rhino error state with '%s'.\n" ,
175+ pv_status_to_string_func (error_status ));
176+ exit (EXIT_FAILURE );
177+ }
178+
179+ if (message_stack_depth > 0 ) {
180+ fprintf (stderr , ":\n" );
181+ print_error_message (message_stack , message_stack_depth );
182+ pv_free_error_stack_func (message_stack );
183+ }
184+ exit (EXIT_FAILURE );
185+ }
186+
187+ for (int32_t i = 0 ; i < num_hardware_devices ; i ++ ) {
188+ fprintf (stdout , "%s\n" , hardware_devices [i ]);
189+ }
190+ pv_rhino_free_hardware_devices_func (hardware_devices , num_hardware_devices );
191+ close_dl (dl_handle );
192+ }
193+
115194int picovoice_main (int argc , char * argv []) {
116195 const char * access_key = NULL ;
117196 const char * library_path = NULL ;
118197 const char * model_path = NULL ;
198+ const char * device = "best" ;
119199 const char * context_path = NULL ;
120200 const char * wav_path = NULL ;
121201 float sensitivity = 0.5f ;
122202 float endpoint_duration_sec = 1.f ;
123203 bool require_endpoint = true;
124204 double performance_threshold_sec = 0 ;
205+ bool show_inference_devices = false;
125206
126207 int c ;
127- while ((c = getopt_long (argc , argv , "a:l:m:c:w:t:u:e:p:" , long_options , NULL )) != -1 ) {
208+ while ((c = getopt_long (argc , argv , "a:l:m:y: c:w:t:u:e:p:i " , long_options , NULL )) != -1 ) {
128209 switch (c ) {
129210 case 'a' :
130211 access_key = optarg ;
@@ -135,6 +216,9 @@ int picovoice_main(int argc, char *argv[]) {
135216 case 'm' :
136217 model_path = optarg ;
137218 break ;
219+ case 'y' :
220+ device = optarg ;
221+ break ;
138222 case 'c' :
139223 context_path = optarg ;
140224 break ;
@@ -153,11 +237,25 @@ int picovoice_main(int argc, char *argv[]) {
153237 case 'p' :
154238 performance_threshold_sec = strtod (optarg , NULL );
155239 break ;
240+ case 'i' :
241+ show_inference_devices = true;
242+ break ;
156243 default :
157244 exit (1 );
158245 }
159246 }
160247
248+ if (show_inference_devices ) {
249+ if (!library_path ) {
250+ fprintf (stderr , "`library_path` is required to view available inference devices.\n" );
251+ print_usage (argv [0 ]);
252+ exit (1 );
253+ }
254+
255+ print_inference_devices (library_path );
256+ return 0 ;
257+ }
258+
161259 if (!access_key || !library_path || !model_path || !context_path || !wav_path ) {
162260 print_usage (argv [0 ]);
163261 exit (1 );
@@ -185,6 +283,7 @@ int picovoice_main(int argc, char *argv[]) {
185283 const char * ,
186284 const char * ,
187285 const char * ,
286+ const char * ,
188287 float ,
189288 float ,
190289 bool ,
@@ -303,6 +402,7 @@ int picovoice_main(int argc, char *argv[]) {
303402 pv_status_t status = pv_rhino_init_func (
304403 access_key ,
305404 model_path ,
405+ device ,
306406 context_path ,
307407 sensitivity ,
308408 endpoint_duration_sec ,
0 commit comments