void server_oinfo (struct roar_connection * con) { struct roar_stream s; if ( roar_server_oinfo(con, &s) == -1 ) { fprintf(stderr, "Error: can not get server output info\n"); return; } printf("Stream direction : %s\n", roar_dir2str(s.dir)); printf("Server Output rate : %i\n", s.info.rate); printf("Server Output bits : %i\n", s.info.bits); printf("Server Output channels: %i\n", s.info.channels); printf("Server Output codec : %i (%s%s)\n", s.info.codec, roar_codec2str(s.info.codec), s.info.codec == ROAR_CODEC_DEFAULT ? " native" : ""); // printf("Server Output rate: %i", s.info.rate); if ( g_verbose > 1 && s.pos != (uint32_t)-1 ) printf("Server Position : %lu S (%.3fs)\n", (unsigned long int) s.pos, (float)s.pos/(s.info.rate*s.info.channels)); }
int show_aiprofile (const char * profile) { struct roar_audio_info info; if ( roar_profile2info(&info, profile) == -1 ) { fprintf(stderr, "Error: unknown profile: %s\n", profile); return -1; } printf("Profile Name : %s\n", profile); if ( info.rate ) printf("Profile sample rate : %i\n", info.rate); if ( info.bits ) printf("Profile bits : %i\n", info.bits); if ( info.channels ) printf("Profile channels : %i\n", info.channels); printf("Profile codec : %2i (%s%s)\n", info.codec, roar_codec2str(info.codec), info.codec == ROAR_CODEC_DEFAULT ? " native" : ""); return 0; }
void print_codecfilterlist (void) { int i; int flags; char mode[5]; char delay[6]; char subsys[7] = " "; uint_least32_t d; printf(" Codec Filtername Mode Subsys Delay - Description\n"); printf("-------------------------------------------------------------\n"); for (i = 0; g_codecfilter[i].name != NULL; i++) { strncpy(subsys, " ", 6); if ( g_codecfilter[i].subsystems & ROAR_SUBSYS_WAVEFORM ) subsys[0] = 'W'; if ( g_codecfilter[i].subsystems & ROAR_SUBSYS_MIDI ) subsys[1] = 'M'; if ( g_codecfilter[i].subsystems & ROAR_SUBSYS_CB ) subsys[2] = 'C'; if ( g_codecfilter[i].subsystems & ROAR_SUBSYS_LIGHT ) subsys[3] = 'L'; if ( g_codecfilter[i].subsystems & ROAR_SUBSYS_RAW ) subsys[4] = 'R'; if ( g_codecfilter[i].subsystems & ROAR_SUBSYS_COMPLEX ) subsys[5] = 'X'; flags = g_codecfilter[i].flags; if ( flags == ROAR_CODECFILTER_NONE ) { strcpy(mode, "none"); } else { strcpy(mode, " "); if ( flags & ROAR_CODECFILTER_READ ) mode[0] = 'r'; if ( flags & ROAR_CODECFILTER_WRITE ) mode[1] = 'w'; if ( flags & ROAR_CODECFILTER_PRETHRU ) mode[2] = 'P'; if ( flags & ROAR_CODECFILTER_PRETHRU_NN ) mode[2] = 'p'; } *delay = 0; if ( g_codecfilter[i].codec == -1 ) { // null codec filter strcpy(delay, "0ms"); } else if ( g_codecfilter[i].delay == NULL ) { strcpy(delay, "?"); } else { if ( codecfilter_delay(NULL, i, &d) == -1 ) { strcpy(delay, "dyn"); } else { snprintf(delay, 5, "%ims", d/1000); } } printf(" %-12s %-12s %-4s %6s %-5s - %s\n", roar_codec2str(g_codecfilter[i].codec), g_codecfilter[i].name, mode, subsys, delay, g_codecfilter[i].desc ); } }
input_module_t *roar_open_module(module_param_t *params) { input_module_t *mod = calloc(1, sizeof(input_module_t)); im_roar_state *s; module_param_t *current; const char * server = NULL; int dir = ROAR_DIR_MONITOR; enum { MD_NONE = 0, MD_FILE = 1, MD_STREAM = 2 } use_metadata = MD_STREAM; int err; mod->getdata = roar_read; mod->handle_event = event_handler; mod->metadata_update = metadata_update; mod->internal = calloc(1, sizeof(im_roar_state)); s = mod->internal; if(roar_profile2info(&s->info, "default") == -1) { LOG_ERROR1("Failed to get default audio profile: %s", roar_error2str(roar_error)); return NULL; } s->info.bits = 16; s->vss = NULL; s->plugins = roar_plugincontainer_new_simple(IM_ROAR_APPNAME, IM_ROAR_ABIVERSION); if (!s->plugins) { LOG_ERROR1("Failed to create plugin container: %s", roar_error2str(roar_error)); return NULL; } thread_mutex_create(&s->metadatalock); current = params; while(current) { if(!strcmp(current->name, "rate")) s->info.rate = roar_str2rate(current->value); else if(!strcmp(current->name, "channels")) s->info.channels = roar_str2channels(current->value); else if(!strcmp(current->name, "codec")) s->info.codec = roar_str2codec(current->value); else if(!strcmp(current->name, "aiprofile")) { if (roar_profile2info(&s->info, current->value) == -1) { LOG_WARN2("Can not get audio info profile %s: %s", current->value, roar_error2str(roar_error)); } s->info.bits = 16; } else if(!strcmp(current->name, "dir")) { if ( !strcasecmp(current->value, "monitor") ) { dir = ROAR_DIR_MONITOR; } else if ( !strcasecmp(current->value, "record") ) { dir = ROAR_DIR_RECORD; } else { LOG_WARN2("Unknown value %s for parameter %s for roar module", current->value, current->name); } } else if(!strcmp(current->name, "device") || !strcmp(current->name, "server")) server = current->value; else if(!strcmp(current->name, "metadata")) { if ( !strcasecmp(current->value, "none") ) { use_metadata = MD_NONE; } else if ( !strcasecmp(current->value, "file") ) { use_metadata = MD_FILE; } else if ( !strcasecmp(current->value, "stream") ) { use_metadata = MD_STREAM; } else { use_metadata = atoi(current->value); } } else if(!strcmp(current->name, "metadatafilename")) { ices_config->metadata_filename = current->value; use_metadata = MD_FILE; } else if(!strcmp(current->name, "plugin")) { roar_plugin_load(mod, current->value); } else LOG_WARN1("Unknown parameter %s for roar module", current->name); current = current->next; } mod->type = ICES_INPUT_PCM; switch (s->info.codec) { case ROAR_CODEC_PCM_LE: mod->subtype = INPUT_PCM_LE_16; break; case ROAR_CODEC_PCM_BE: mod->subtype = INPUT_PCM_BE_16; break; case ROAR_CODEC_OGG_GENERAL: LOG_WARN0("Codec may not work, specify ogg_vorbis for Vorbis streaming"); case ROAR_CODEC_OGG_VORBIS: mod->type = ICES_INPUT_VORBIS; // we do not set mod->subtype here, strange design ices2 has... break; case -1: LOG_ERROR0("Unknown Codec"); return NULL; default: LOG_ERROR1("Unsupported Codec: %s", roar_codec2str(s->info.codec)); return NULL; } roar_plugincontainer_appsched_trigger(s->plugins, ROAR_DL_APPSCHED_INIT); /* Open the VS connection */ if ( (s->vss = roar_vs_new(server, IM_ROAR_PROGNAME, &err)) == NULL ) { LOG_ERROR2("Failed to open sound server %s: %s", server, roar_vs_strerr(err)); goto fail; } /* Now, set the required parameters on that device */ if ( roar_vs_stream(s->vss, &s->info, dir, &err) == -1 ) { LOG_ERROR2("Failed to create a new stream on sound server %s: %s", server, roar_vs_strerr(err)); goto fail; } if ( _set_flags(roar_vs_connection_obj(s->vss, NULL), roar_vs_stream_obj(s->vss, NULL), ROAR_FLAG_META, ROAR_RESET_FLAG) != 0 ) { LOG_WARN0("Can not reset metadata flag from stream"); } /* We're done, and we didn't fail! */ LOG_INFO3("Opened sound server at %s at %d channel(s), %d Hz", server, s->info.channels, s->info.rate); switch (use_metadata) { case MD_NONE: break; case MD_FILE: LOG_INFO0("Starting metadata update thread"); if(ices_config->metadata_filename) thread_create("im_roar-metadata", metadata_thread_signal, mod, 1); else thread_create("im_roar-metadata", metadata_thread_stdin, mod, 1); break; case MD_STREAM: if ( _set_flags(roar_vs_connection_obj(s->vss, NULL), roar_vs_stream_obj(s->vss, NULL), ROAR_FLAG_META, ROAR_SET_FLAG) != 0 ) { LOG_WARN0("Can not set metadata flag from stream"); } break; } return mod; fail: close_module(mod); /* safe, this checks for valid contents */ return NULL; }
int cf_sndfile_write(CODECFILTER_USERDATA_T inst, char * buf, int len) { struct codecfilter_sndfile_inst * obj = (struct codecfilter_sndfile_inst *) inst; struct roar_stream * s = ROAR_STREAM(obj->stream); int ret; ROAR_WARN("cf_sndfile_write(*): obj->opened=%i", obj->opened); if ( !obj->opened ) { if ( s->fh == -1 ) { errno = EAGAIN; return -1; } switch (s->info.codec) { case ROAR_CODEC_PCM_S_LE: case ROAR_CODEC_PCM_S_BE: switch (s->info.bits) { case 8: obj->info.format = SF_FORMAT_PCM_S8; break; case 16: obj->info.format = SF_FORMAT_PCM_16; break; case 24: obj->info.format = SF_FORMAT_PCM_24; break; case 32: obj->info.format = SF_FORMAT_PCM_32; break; } //obj->info.format |= s->info.codec == ROAR_CODEC_PCM_S_LE ? SF_ENDIAN_LITTLE : SF_ENDIAN_BIG; obj->info.format |= SF_ENDIAN_FILE; obj->info.format |= SF_FORMAT_WAV; break; default: ROAR_ERR("cf_sndfile_write(*): codec(%s) not supported!", roar_codec2str(s->info.bits)); return -1; break; } obj->info.samplerate = s->info.rate; obj->info.channels = s->info.channels; obj->info.sections = 1; obj->info.frames = 182592; // 2147483647; obj->info.seekable = 1; obj->info.format = 0x00010002; if ( (obj->state = sf_open_fd(s->fh, SFM_WRITE, &(obj->info), 0)) == NULL ) { ROAR_ERR("cf_sndfile_write(*): can not sf_open_fd(*)!"); ROAR_ERR("cf_sndfile_write(*): s->fh=%i", s->fh); ROAR_ERR("cf_sndfile_write(*): obj->info={.format=0x%.8x, .samplerate=%i, .channels=%i}", obj->info.format, obj->info.samplerate, obj->info.channels); return -1; } obj->opened = 1; // errno = EAGAIN; } ROAR_WARN("cf_sndfile_write(*): obj->opened=%i", obj->opened); ret = sf_write_raw(obj->state, (void*) buf, len); ROAR_WARN("cf_sndfile_write(inst=%p, buf=%p, len=%i) = %i", inst, buf, len, ret); return ret; }
void list_clients (struct roar_connection * con) { int i; int num; int h; int id[ROAR_CLIENTS_MAX]; char tmp[80]; int self_id; struct roar_client self_client; struct roar_client c; #ifdef _POSIX_USERS struct group * grp = NULL; struct passwd * pwd = NULL; #endif if ( (self_id = roar_get_clientid(con)) != -1 ) { if ( roar_get_client(con, &self_client, self_id) == -1 ) self_id = -1; } if ( (num = roar_list_clients(con, id, ROAR_CLIENTS_MAX)) == -1 ) { fprintf(stderr, "Error: can not get client list\n"); return; } for (i = 0; i < num; i++) { printf("client %i:\n", id[i]); if ( roar_get_client(con, &c, id[i]) == -1 ) { fprintf(stderr, "Error: can not get client info\n"); continue; } if ( c.name[0] != '\0' ) printf("Client name : %s\n", c.name); if ( roar_nnode_get_socktype(&(c.nnode)) != ROAR_SOCKET_TYPE_UNKNOWN ) { if ( roar_nnode_to_str(&(c.nnode), tmp, 80) == 0 ) { printf("Client network node : %s\n", tmp); } } if ( c.pid != -1 ) { if ( self_id != -1 && roar_nnode_cmp(&(self_client.nnode), &(c.nnode)) == 0 ) { printf("Client PID : %i(%s)\n", c.pid, proc_name(c.pid)); } else { printf("Client PID : %i\n", c.pid); } } if ( c.uid != -1 ) { #ifdef _POSIX_USERS if ( self_id != -1 && roar_nnode_cmp(&(self_client.nnode), &(c.nnode)) == 0 ) { pwd = getpwuid(c.uid); grp = getgrgid(c.gid); printf("Client UID/GID : %i(%s)/%i(%s)\n", c.uid, pwd ? pwd->pw_name : "?", c.gid, grp ? grp->gr_name : "?"); } else { #else if ( 1 ) { #endif printf("Client UID/GID : %i/%i\n", c.uid, c.gid); } } if ( g_verbose && c.proto != ROAR_PROTO_NONE ) { printf("Client Protocol : %s\n", roar_proto2str(c.proto)); } if ( g_verbose && c.byteorder != ROAR_BYTEORDER_UNKNOWN ) { if ( c.byteorder == ROAR_BYTEORDER_NETWORK ) { strcpy(tmp, " (network byteorder"); } else { *tmp = 0; } if ( c.byteorder == ROAR_BYTEORDER_NATIVE ) { if ( *tmp ) { strcat(tmp, ", native"); } else { strcpy(tmp, " (native"); } } if ( *tmp ) strcat(tmp, ")"); printf("Client Byteorder : %s%s\n", roar_byteorder2str(c.byteorder), tmp); } if ( c.execed != -1 ) printf("Execed stream : %i\n", c.execed); for (h = 0; h < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; h++) if ( c.streams[h] != -1 ) printf("stream : %i\n", c.streams[h]); } } void list_streams (struct roar_connection * con) { int i; int num; int id[ROAR_STREAMS_MAX]; char chanmap[ROAR_MAX_CHANNELS]; struct roar_stream s; struct roar_stream_info info; char buffer[1024]; char * flags = buffer; char * name = buffer; char * infotext; size_t len; if ( (num = roar_list_streams(con, id, ROAR_STREAMS_MAX)) == -1 ) { fprintf(stderr, "Error: can not get stream list\n"); return; } for (i = 0; i < num; i++) { printf("stream %i:\n", id[i]); if ( roar_get_stream(con, &s, id[i]) == -1 ) { fprintf(stderr, "Error: can not get stream info\n"); continue; } printf("Stream direction : %s\n", roar_dir2str(s.dir)); if ( roar_stream_get_name(con, &s, name, 1024) == 0 ) printf("Stream name : %s\n", name); if ( (int)s.pos_rel_id == -1 ) { printf("Relativ position id : none (stream not synchronized)\n"); } else if ( (int)s.pos_rel_id == id[i] ) { printf("Relativ position id : %i (self synchronized)\n", s.pos_rel_id); } else { printf("Relativ position id : %i (synchronized)\n", s.pos_rel_id); } if ( g_verbose > 1 && s.pos != (uint32_t)-1 ) { if ( s.info.rate && s.info.channels ) { printf("Position : %lu S (%.3fs)\n", (unsigned long int) s.pos, (float)s.pos/(s.info.rate*s.info.channels)); } else { printf("Position : %lu S\n", (unsigned long int) s.pos); } } switch (s.dir) { case ROAR_DIR_MIDI_IN: case ROAR_DIR_MIDI_OUT: infotext = " ticks/s"; break; case ROAR_DIR_LIGHT_IN: case ROAR_DIR_LIGHT_OUT: infotext = " updates/s"; break; default: infotext = " Hz"; } if ( s.info.rate ) printf("Stream sample rate : %i%s\n", s.info.rate, infotext); if ( s.info.bits ) printf("Stream bits : %i\n", s.info.bits); if ( s.info.channels ) printf("Stream channels : %i\n", s.info.channels); printf("Stream codec : %2i (%s%s)\n", s.info.codec, roar_codec2str(s.info.codec), s.info.codec == ROAR_CODEC_DEFAULT ? " native" : ""); if ( roar_stream_get_info(con, &s, &info) != -1 ) { if ( info.codec != s.info.codec ) { printf("Streamed codec : %2i (%s%s)\n", info.codec, roar_codec2str(info.codec), info.codec == ROAR_CODEC_DEFAULT ? " native" : ""); } if ( g_verbose ) { if ( info.block_size ) printf("Stream block size : %i Byte\n", info.block_size); printf("Underruns pre/post : %i/%i\n", info.pre_underruns, info.post_underruns); if ( g_verbose > 1 ) printf("Stream delay : %ims (%.2fm)\n", (int)info.delay/1000, (info.delay*(float)_SPEED_OF_SOUND)); if ( g_verbose > 1 ) printf("Stream mixer : %i\n", info.mixer); if ( g_verbose > 1 ) printf("Stream state : %s\n", roar_streamstate2str(info.state)); if ( g_verbose > 1 ) printf("Stream role : %s\n", roar_role2str(info.role)); *flags = 0; if ( info.flags & ROAR_FLAG_PRIMARY ) strcat(flags, "primary "); if ( info.flags & ROAR_FLAG_SYNC ) strcat(flags, "sync "); if ( info.flags & ROAR_FLAG_OUTPUT ) strcat(flags, "output "); if ( info.flags & ROAR_FLAG_SOURCE ) strcat(flags, "source "); if ( info.flags & ROAR_FLAG_META ) strcat(flags, "meta "); if ( info.flags & ROAR_FLAG_AUTOCONF ) strcat(flags, "autoconf "); if ( info.flags & ROAR_FLAG_CLEANMETA ) strcat(flags, "cleanmeta "); if ( info.flags & ROAR_FLAG_HWMIXER ) strcat(flags, "hwmixer "); if ( info.flags & ROAR_FLAG_PAUSE ) strcat(flags, "pause "); if ( info.flags & ROAR_FLAG_MUTE ) strcat(flags, "mute "); if ( info.flags & ROAR_FLAG_MMAP ) strcat(flags, "mmap "); if ( info.flags & ROAR_FLAG_ANTIECHO ) strcat(flags, "antiecho "); if ( info.flags & ROAR_FLAG_VIRTUAL ) strcat(flags, "virtual "); if ( info.flags & ROAR_FLAG_RECSOURCE ) strcat(flags, "recsource "); if ( info.flags & ROAR_FLAG_PASSMIXER ) strcat(flags, "passmixer "); if ( info.flags & ROAR_FLAG_PRETHRU ) strcat(flags, "prethru "); if ( info.flags & ROAR_FLAG_IMMUTABLE ) strcat(flags, "immutable "); if ( info.flags & ROAR_FLAG_ENHANCE ) strcat(flags, "enhance "); printf("Flags : %s\n", flags); } } if ( g_verbose ) { len = ROAR_MAX_CHANNELS; if ( roar_stream_get_chanmap(con, &s, chanmap, &len) == -1 ) { fprintf(stderr, "Error: can not get stream channel map\n"); } else { if ( roardsp_chanlist2str(chanmap, len, buffer, 1024) == -1 ) { fprintf(stderr, "Error: can not convert channel map into string\n"); } else { printf("Channel Map : %s\n", buffer); } } } if ( s.dir != ROAR_DIR_THRU ) { display_mixer(con, id[i]); show_meta_all(con, id[i]); } } }