[pulseaudio-discuss] How to capture one of multiple radios that these radios play at the same time?
Tsai Yu-Chin
yorjing at gmail.com
Thu Nov 18 18:29:17 PST 2010
Thank you for your help.
I refer to source code of pavucontrol and I program a simple code below:
///////////////////////////////code//////////////////////////////
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <pulse/pulseaudio.h>
#include <signal.h>
int file_name_length=20;
int record_time=5;
int end=0;
static pa_sample_spec sample_spec = {
.format = PA_SAMPLE_S16LE,
.rate = 44100,
.channels = 2
};
struct thread_data
{
char *pa_ctx_name;
char *sink_input_index;
};
void get_monitor_source_index_callback(pa_context *context,const
pa_sink_info *i,int eol,void *userdata);
void get_sink_index_callback(pa_context *context,const
pa_sink_input_info *i,int eol,void *userdata);
void pa_state_callback(pa_context *c, void *userdata);
void read_callback(pa_stream *stream,size_t length,void *userdata);
void alarm_handler(int sig);
void quit(pa_mainloop_api *pa_mlapi,int ret);
void record_thread(void *data);
uint32_t get_monitor_source_index(pa_context *context,pa_mainloop
*pa_ml,uint32_t sink_input_index);
int main(int argc,char *argv[]){
struct thread_data td;
pthread_t id;
td.pa_ctx_name=argv[1];
td.sink_input_index=argv[2];
pthread_create(&id,NULL,(void *)record_thread,&td);
while(!end)
sleep(1);
return 0;
}
void record_thread(void *data){
pa_stream *stream;
pa_mainloop *pa_ml;
pa_mainloop_api *pa_mlapi;
pa_context *context;
pa_buffer_attr attr;
int fd;
int ret=1;
char msi[16];
struct thread_data *td=(struct thread_data*)data;
memset(&attr,0,sizeof(attr));
attr.fragsize=(uint32_t)-1;
attr.maxlength=(uint32_t)-1;
char output_file_name[file_name_length];
strcpy(output_file_name,(*td).pa_ctx_name);
strcat(output_file_name,".raw");
if((fd=open(output_file_name,O_WRONLY|O_TRUNC|O_CREAT,0777))<0){
printf("Failed to create file\n");
goto quit;
}
pa_ml=pa_mainloop_new();
pa_mlapi=pa_mainloop_get_api(pa_ml);
context=pa_context_new(pa_mlapi,(*td).pa_ctx_name);
pa_context_connect(context,NULL,0,NULL);
if(!(stream=pa_stream_new(context,(*td).pa_ctx_name,&sample_spec,NULL))){
printf("Failed to create monitoring stream\n");
goto quit;
}
pa_stream_set_monitor_stream(stream,atoi((*td).sink_input_index));
pa_stream_set_read_callback(stream,read_callback,&fd);
uint32_t monitor_source_index=get_monitor_source_index(context,pa_ml,atoi((*td).sink_input_index));
snprintf(msi,sizeof(msi),"%u",monitor_source_index);
if(pa_stream_connect_record(stream,msi,&attr,(pa_stream_flags_t)(PA_STREAM_DONT_MOVE|PA_STREAM_PEAK_DETECT))<0){
printf("Failed to connect monitoring stream\n");
pa_stream_unref(stream);
goto quit;
}
if(end)
quit(pa_mlapi,0);
signal(SIGALRM,alarm_handler);
alarm(10);
if(pa_mainloop_run(pa_ml,&ret)<0){
printf("mainloop run failed.\n");
goto quit;
}
quit:
if(stream)
pa_stream_unref(stream);
if(context)
pa_context_unref(context);
if(pa_ml){
pa_signal_done();
pa_mainloop_free(pa_ml);
}
}
uint32_t get_monitor_source_index(pa_context *context,pa_mainloop
*pa_ml,uint32_t sink_input_index){
pa_operation *pa_op;
uint32_t sink_index;
uint32_t monitor_source_index;
int state = 0;
int pa_ready = 0;
pa_context_set_state_callback(context, pa_state_callback, &pa_ready);
for (;;) {
if (pa_ready == 0) {
pa_mainloop_iterate(pa_ml, 1, NULL);
continue;
}
if (pa_ready == 2) {
pa_context_disconnect(context);
pa_context_unref(context);
pa_mainloop_free(pa_ml);
return -1;
}
switch (state) {
case 0:
pa_op = pa_context_get_sink_input_info(context,
sink_input_index,
get_sink_index_callback,
&sink_index
);
printf("Getting sink index...\n");
state++;
break;
case 1:
if (pa_operation_get_state(pa_op) == PA_OPERATION_DONE) {
pa_operation_unref(pa_op);
pa_op = pa_context_get_sink_info_by_index(context,
sink_index,
get_monitor_source_index_callback,
&monitor_source_index
);
printf("Getting monitor source index...\n");
state++;
}
break;
case 2:
if (pa_operation_get_state(pa_op) == PA_OPERATION_DONE) {
pa_operation_unref(pa_op);
return monitor_source_index;
}
break;
default:
fprintf(stderr, "in state %d\n", state);
return -1;
}
pa_mainloop_iterate(pa_ml, 1, NULL);
}
}
void get_monitor_source_index_callback(pa_context *context,const
pa_sink_info *i,int eol,void *userdata){
uint32_t *monitor_source_index=userdata;
if (eol > 0) {
printf("Get monitor source index complete...\nmonitor source
index=%d\n\n",*(monitor_source_index));
return;
}
*(monitor_source_index)=i->monitor_source;
}
void get_sink_index_callback(pa_context *context,const
pa_sink_input_info *i,int eol,void *userdata){
uint32_t *sink_index=userdata;
if (eol > 0) {
printf("Get Sink index complete...\nsink index=%d\n\n",*(sink_index));
return;
}
*(sink_index)=i->sink;
}
void pa_state_callback(pa_context *c, void *userdata) {
pa_context_state_t state;
int *pa_ready = userdata;
state = pa_context_get_state(c);
switch (state) {
case PA_CONTEXT_UNCONNECTED:
case PA_CONTEXT_CONNECTING:
case PA_CONTEXT_AUTHORIZING:
case PA_CONTEXT_SETTING_NAME:
default:
break;
case PA_CONTEXT_FAILED:
case PA_CONTEXT_TERMINATED:
*pa_ready = 2;
break;
case PA_CONTEXT_READY:
*pa_ready = 1;
break;
}
}
void read_callback(pa_stream *stream,size_t length,void *userdata){
const void *data;
int *fd=userdata;
if(pa_stream_peek(stream,&data,&length)<0){
printf("Failed to read data from stream\n");
return;
}
if (write(*fd,data,length)<=0) {
printf("Failed to write data into file\n");
return;
}
pa_stream_drop(stream);
}
void quit(pa_mainloop_api *pa_mlapi,int ret){
assert(pa_mlapi);
pa_mlapi->quit(pa_mlapi,ret);
}
void alarm_handler(int sig){
end=1;
}
///////////////////////////////////////////////////////////////////
As before, it captures audio which combination of all radios.
How can I revise this code to capture audio which is from a single radio?
Thanks for your help again.
2010/11/19 Colin Guthrie <gmane at colin.guthr.ie>:
> 'Twas brillig, and Tsai Yu-Chin at 18/11/10 23:09 did gyre and gimble:
>> Excuse me.
>> When I play 3 radios at the same time,
>> how to capture one of them using PulseAudio?
>> Using Asynchronous API?
>>
>> I study PulseAudio Volume Control of PulsaAudio Device Chooser Project,
>> but I capture one audio which combine 3 radios.
>>
>> How can I capture one audio which is from one of three radios?
>
> Have a look at the pavucontrol source. It uses a sink input monitor to
> draw the vumeters on the "Playback" tab. This should allow you to locate
> the stream you want to record and open it's monitor.
>
> I've not done this myself, but I suspect that the code itself will lead
> the way. Let me know if you get stuck and I'll try and look it up for you.
>
> Col
>
> --
>
> Colin Guthrie
> gmane(at)colin.guthr.ie
> http://colin.guthr.ie/
>
> Day Job:
> Tribalogic Limited [http://www.tribalogic.net/]
> Open Source:
> Mageia Contributor [http://www.mageia.org/]
> PulseAudio Hacker [http://www.pulseaudio.org/]
> Trac Hacker [http://trac.edgewall.org/]
>
> _______________________________________________
> pulseaudio-discuss mailing list
> pulseaudio-discuss at mail.0pointer.de
> https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
>
More information about the pulseaudio-discuss
mailing list