static int open_esound(audio_output_t *ao) { esd_format_t format = ESD_STREAM | ESD_PLAY; if (!esd_rate) { int esd; esd_server_info_t *info; esd_format_t fmt; if ((esd = esd_open_sound(NULL)) >= 0) { info = esd_get_server_info(esd); esd_rate = info->rate; fmt = info->format; esd_free_server_info(info); esd_close(esd); } else { esd_rate = esd_audio_rate; fmt = esd_audio_format; } esd_format = MPG123_ENC_UNSIGNED_8; if ((fmt & ESD_MASK_BITS) == ESD_BITS16) esd_format |= MPG123_ENC_SIGNED_16; esd_channels = fmt & ESD_MASK_CHAN; } if (ao->format == -1) ao->format = esd_format; else if (!(ao->format & esd_format)) { error1("Unsupported audio format: %d\n", ao->format); errno = EINVAL; return -1; } if (ao->format & MPG123_ENC_SIGNED_16) format |= ESD_BITS16; else if (ao->format & MPG123_ENC_UNSIGNED_8) format |= ESD_BITS8; else assert(0); if (ao->channels == -1) ao->channels = 2; else if (ao->channels <= 0 || ao->channels > esd_channels) { error1("Unsupported no of channels: %d\n", ao->channels); errno = EINVAL; return -1; } if (ao->channels == 1) format |= ESD_MONO; else if (ao->channels == 2) format |= ESD_STEREO; else assert(0); if (ao->rate == -1) ao->rate = esd_rate; else if (ao->rate > esd_rate) return -1; ao->fn = esd_play_stream_fallback(format, ao->rate, ao->device, "mpg123"); return (ao->fn); }
int audio_open(struct audio_info_struct *ai) { esd_format_t format = ESD_STREAM | ESD_PLAY; if (!esd_rate) { int esd; esd_server_info_t *info; esd_format_t fmt; if ((esd = esd_open_sound(NULL)) >= 0) { info = esd_get_server_info(esd); esd_rate = info->rate; fmt = info->format; esd_free_server_info(info); esd_close(esd); } else { esd_rate = esd_audio_rate; fmt = esd_audio_format; } esd_format = AUDIO_FORMAT_UNSIGNED_8; if ((fmt & ESD_MASK_BITS) == ESD_BITS16) esd_format |= AUDIO_FORMAT_SIGNED_16; esd_channels = fmt & ESD_MASK_CHAN; } if (ai->format == -1) ai->format = esd_format; else if (!(ai->format & esd_format)) { fprintf(stderr, "audio: Unsupported audio format: %d\n", ai->format); errno = EINVAL; return -1; } if (ai->format & AUDIO_FORMAT_SIGNED_16) format |= ESD_BITS16; else if (ai->format & AUDIO_FORMAT_UNSIGNED_8) format |= ESD_BITS8; else assert(0); if (ai->channels == -1) ai->channels = 2; else if (ai->channels <= 0 || ai->channels > esd_channels) { fprintf(stderr, "audio: Unsupported no of channels: %d\n", ai->channels); errno = EINVAL; return -1; } if (ai->channels == 1) format |= ESD_MONO; else if (ai->channels == 2) format |= ESD_STEREO; else assert(0); if (ai->rate == -1) ai->rate = esd_rate; else if (ai->rate > esd_rate) return -1; ai->fn = esd_play_stream_fallback(format, ai->rate, param.esdserver, "mpg123"); return (ai->fn); }
static gboolean gst_esdsink_open (GstAudioSink * asink) { esd_server_info_t *server_info; GstPadTemplate *pad_template; GstEsdSink *esdsink; gchar *saved_env; gint i; esdsink = GST_ESDSINK (asink); GST_DEBUG_OBJECT (esdsink, "open"); /* ensure libesd doesn't auto-spawn a sound daemon if none is running yet */ saved_env = g_strdup (g_getenv ("ESD_NO_SPAWN")); g_setenv ("ESD_NO_SPAWN", "1", TRUE); /* now try to connect to any existing/running sound daemons */ esdsink->ctrl_fd = esd_open_sound (esdsink->host); /* and restore the previous state */ if (saved_env != NULL) { g_setenv ("ESD_NO_SPAWN", saved_env, TRUE); } else { g_unsetenv ("ESD_NO_SPAWN"); } g_free (saved_env); if (esdsink->ctrl_fd < 0) goto couldnt_connect; /* get server info */ server_info = esd_get_server_info (esdsink->ctrl_fd); if (!server_info) goto no_server_info; GST_INFO_OBJECT (esdsink, "got server info rate: %i", server_info->rate); pad_template = gst_static_pad_template_get (&sink_factory); esdsink->cur_caps = gst_caps_copy (gst_pad_template_get_caps (pad_template)); gst_object_unref (pad_template); for (i = 0; i < esdsink->cur_caps->structs->len; i++) { GstStructure *s; s = gst_caps_get_structure (esdsink->cur_caps, i); gst_structure_set (s, "rate", G_TYPE_INT, server_info->rate, NULL); } esd_free_server_info (server_info); GST_INFO_OBJECT (esdsink, "server caps: %" GST_PTR_FORMAT, esdsink->cur_caps); return TRUE; /* ERRORS */ couldnt_connect: { GST_ELEMENT_ERROR (esdsink, RESOURCE, OPEN_WRITE, (_("Could not establish connection to sound server")), ("can't open connection to esound server")); return FALSE; } no_server_info: { GST_ELEMENT_ERROR (esdsink, RESOURCE, OPEN_WRITE, (_("Failed to query sound server capabilities")), ("couldn't get server info!")); return FALSE; } }
/* * open & setup audio device * return: 1=success 0=fail */ static int init(int rate_hz, int channels, int format, int flags) { esd_format_t esd_fmt; int bytes_per_sample; int fl; char *server = ao_subdevice; /* NULL for localhost */ float lag_seconds, lag_net, lag_serv; struct timeval proto_start, proto_end; esd_fd = esd_open_sound(server); if (esd_fd < 0) { mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ESD_CantOpenSound, strerror(errno)); return 0; } /* get server info, and measure network latency */ gettimeofday(&proto_start, NULL); esd_svinfo = esd_get_server_info(esd_fd); if(server) { gettimeofday(&proto_end, NULL); lag_net = (proto_end.tv_sec - proto_start.tv_sec) + (proto_end.tv_usec - proto_start.tv_usec) / 1000000.0; lag_net /= 2.0; /* round trip -> one way */ } else lag_net = 0.0; /* no network lag */ /* if (esd_svinfo) { mp_msg(MSGT_AO, MSGL_INFO, "AO: [esd] server info:\n"); esd_print_server_info(esd_svinfo); } */ esd_fmt = ESD_STREAM | ESD_PLAY; #if ESD_RESAMPLES /* let the esd daemon convert sample rate */ #else /* let mplayer's audio filter convert the sample rate */ if (esd_svinfo != NULL) rate_hz = esd_svinfo->rate; #endif ao_data.samplerate = rate_hz; /* EsounD can play mono or stereo */ switch (channels) { case 1: esd_fmt |= ESD_MONO; ao_data.channels = bytes_per_sample = 1; break; default: esd_fmt |= ESD_STEREO; ao_data.channels = bytes_per_sample = 2; break; } /* EsounD can play 8bit unsigned and 16bit signed native */ switch (format) { case AF_FORMAT_S8: case AF_FORMAT_U8: esd_fmt |= ESD_BITS8; ao_data.format = AF_FORMAT_U8; break; default: esd_fmt |= ESD_BITS16; ao_data.format = AF_FORMAT_S16_NE; bytes_per_sample *= 2; break; } /* modify audio_delay depending on esd_latency * latency is number of samples @ 44.1khz stereo 16 bit * adjust according to rate_hz & bytes_per_sample */ #ifdef CONFIG_ESD_LATENCY esd_latency = esd_get_latency(esd_fd); #else esd_latency = ((channels == 1 ? 2 : 1) * ESD_DEFAULT_RATE * (ESD_BUF_SIZE + 64 * (4.0f / bytes_per_sample)) ) / rate_hz; esd_latency += ESD_BUF_SIZE * 2; #endif if(esd_latency > 0) { lag_serv = (esd_latency * 4.0f) / (bytes_per_sample * rate_hz); lag_seconds = lag_net + lag_serv; audio_delay += lag_seconds; mp_msg(MSGT_AO, MSGL_INFO,MSGTR_AO_ESD_LatencyInfo, lag_serv, lag_net, lag_seconds); } esd_play_fd = esd_play_stream_fallback(esd_fmt, rate_hz, server, ESD_CLIENT_NAME); if (esd_play_fd < 0) { mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ESD_CantOpenPBStream, strerror(errno)); return 0; } /* enable non-blocking i/o on the socket connection to the esd server */ if ((fl = fcntl(esd_play_fd, F_GETFL)) >= 0) fcntl(esd_play_fd, F_SETFL, O_NDELAY|fl); #if ESD_DEBUG { int sbuf, rbuf, len; len = sizeof(sbuf); getsockopt(esd_play_fd, SOL_SOCKET, SO_SNDBUF, &sbuf, &len); len = sizeof(rbuf); getsockopt(esd_play_fd, SOL_SOCKET, SO_RCVBUF, &rbuf, &len); dprintf("esd: send/receive socket buffer space %d/%d bytes\n", sbuf, rbuf); } #endif ao_data.bps = bytes_per_sample * rate_hz; ao_data.outburst = ao_data.bps > 100000 ? 4*ESD_BUF_SIZE : 2*ESD_BUF_SIZE; esd_play_start.tv_sec = 0; esd_samples_written = 0; esd_bytes_per_sample = bytes_per_sample; return 1; }
/* retrieve all information from server */ esd_info_t *esd_get_all_info( int esd ) { esd_info_t * r; int i; int num; int clients[ROAR_CLIENTS_MAX]; struct roar_client c; struct roar_stream s; struct roar_connection con[1]; struct roar_mixer_settings mixer; int channels; float fs; esd_player_info_t * new_player, * cur = NULL; // = NULL to avoid gcc warning roar_connect_fh(con, esd); r = malloc(sizeof(esd_info_t)); if ( r == NULL ) return NULL; r->server = esd_get_server_info(esd); r->player_list = NULL; r->sample_list = NULL; if ( (num = roar_list_clients(con, clients, ROAR_CLIENTS_MAX)) == -1 ) { ROAR_ERR("esd_get_all_info(*): can not get client list"); num = 0; } for (i = 0; i < num; i++) { if ( roar_get_client(con, &c, clients[i]) == -1 ) { ROAR_ERR("esd_get_all_info(*): can not get client info"); continue; } if ( c.execed != -1 ) { if ( roar_get_stream(con, &s, c.execed) == -1 ) { ROAR_ERR("esd_get_all_info(*): can not get stream info"); continue; } if ( (new_player = malloc(sizeof(esd_player_info_t))) == NULL ) { ROAR_ERR("esd_get_all_info(*): can not alloc memory for new player! BAD"); continue; } new_player->next = NULL; new_player->source_id = c.execed; new_player->rate = s.info.rate; new_player->format = ROAR_S2ESD(&s); // sprintf(new_player->name, "roar stream %i", c.execed); strncpy(new_player->name, c.name, ESD_NAME_MAX < ROAR_BUFFER_NAME ? ESD_NAME_MAX : ESD_NAME_MAX); new_player->server = r->server; if ( roar_get_vol(con, c.execed, &mixer, &channels) == -1 ) { ROAR_ERR("esd_get_all_info(*): can not get stream mixer info"); new_player->left_vol_scale = new_player->right_vol_scale = 256; } else { fs = mixer.scale / 257; if ( channels == 1 ) { new_player->left_vol_scale = new_player->right_vol_scale = mixer.mixer[0] == mixer.scale ? 256 : mixer.mixer[0] / fs; } else { if ( channels != 2 ) { ROAR_ERR("esd_get_all_info(*): server seems to run in > 2 channel mode. ignoring any but the first two channels!"); } new_player->left_vol_scale = mixer.mixer[0] == mixer.scale ? 256 : mixer.mixer[0] / fs; new_player->right_vol_scale = mixer.mixer[1] == mixer.scale ? 256 : mixer.mixer[1] / fs; } } if ( r->player_list == NULL ) { r->player_list = cur = new_player; } else { cur->next = new_player; // add to old player cur = new_player; // hop to next player } } } return r; }