QList<DeviceFinder::Device> PulseDeviceFinder::ListDevices() {
  if (!context_ || pa_context_get_state(context_) != PA_CONTEXT_READY) {
    return QList<Device>();
  }

retry:
  ListDevicesState state;
  pa_context_get_sink_info_list(
      context_, &PulseDeviceFinder::GetSinkInfoCallback, &state);

  forever {
    if (state.finished) {
      return state.devices;
    }

    switch (pa_context_get_state(context_)) {
    case PA_CONTEXT_READY:
      break;
    case PA_CONTEXT_FAILED:
    case PA_CONTEXT_TERMINATED:
      // Maybe pulseaudio died.  Try reconnecting.
      if (Reconnect()) {
        goto retry;
      }
      return state.devices;
    default:
      return state.devices;
    }

    pa_mainloop_iterate(mainloop_, true, nullptr);
  }
}
Beispiel #2
0
void _cb_state_changed(pa_context *context, void *userdata) {
    callback_t *callback = (callback_t*)userdata;
    pa_context_state_t state = pa_context_get_state(context);
    PACMIXER_LOG("B:server state changed to %d", state);
    switch(state) {
        case PA_CONTEXT_READY:
            pa_context_set_subscribe_callback(context, _cb_event, callback);
            pa_context_subscribe(context, PA_SUBSCRIPTION_MASK_ALL, NULL, NULL);
            pa_context_get_sink_input_info_list(context, _cb_sink_input, callback);
            pa_context_get_sink_info_list(context, _cb_sink, callback);
            pa_context_get_source_info_list(context, _cb_source, callback);
            pa_context_get_source_output_info_list(context, _cb_source_output, callback);
            pa_context_get_card_info_list(context, _cb_card, callback);
            pa_context_get_server_info(context, _cb_server, callback);
            ((tstate_callback_func)(callback->state))(callback->self, S_CAME);
            break;
        case PA_CONTEXT_FAILED:
        case PA_CONTEXT_TERMINATED:
            pa_context_unref(context);
            ((tstate_callback_func)(callback->state))(callback->self, S_GONE);
            break;
        default:
            break;
    }
}
void QPulseAudioEngine::updateDevices()
{
    lock();

    // Get default input and output devices
    pa_operation *operation = pa_context_get_server_info(m_context, serverInfoCallback, this);
    while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING)
        pa_threaded_mainloop_wait(m_mainLoop);
    pa_operation_unref(operation);

    // Get output devices
    operation = pa_context_get_sink_info_list(m_context, sinkInfoCallback, this);
    while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING)
        pa_threaded_mainloop_wait(m_mainLoop);
    pa_operation_unref(operation);

    // Get input devices
    operation = pa_context_get_source_info_list(m_context, sourceInfoCallback, this);
    while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING)
        pa_threaded_mainloop_wait(m_mainLoop);
    pa_operation_unref(operation);

    unlock();

    // Swap the default output to index 0
    m_sinks.removeOne(m_defaultSink);
    m_sinks.prepend(m_defaultSink);

    // Swap the default input to index 0
    m_sources.removeOne(m_defaultSource);
    m_sources.prepend(m_defaultSource);
}
Beispiel #4
0
static void m_context_state_cb(pa_context *c, void *user_data)                   
{                                                                               
    if (!c) {
        printf("m_context_state_cb() invalid arguement\n");
        return;
    }

    pa_operation *pa_op = NULL;

    switch (pa_context_get_state(c)) {
        case PA_CONTEXT_UNCONNECTED:                                            
        case PA_CONTEXT_CONNECTING:                                             
        case PA_CONTEXT_AUTHORIZING:                                            
        case PA_CONTEXT_SETTING_NAME:                                           
            break;                                                              
                                                                                
        case PA_CONTEXT_READY:                                                  
            pa_context_set_subscribe_callback(c, m_pa_context_subscribe_cb, NULL);
                                                                                
            pa_op = pa_context_subscribe(c, (pa_subscription_mask_t)      
                                           (PA_SUBSCRIPTION_MASK_SINK|          
                                            PA_SUBSCRIPTION_MASK_SOURCE|        
                                            PA_SUBSCRIPTION_MASK_SINK_INPUT|    
                                            PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT| 
                                            PA_SUBSCRIPTION_MASK_CLIENT|        
                                            PA_SUBSCRIPTION_MASK_SERVER|        
                                            PA_SUBSCRIPTION_MASK_CARD), NULL, NULL);
            if (!pa_op) {
                printf("pa_context_subscribe() failed\n");
                return;
            }
            pa_operation_unref(pa_op);

            pa_op = pa_context_get_sink_info_list(c, m_pa_sink_info_cb, NULL);
            if (!pa_op) {
                printf("pa_context_get_sink_info_list() failed\n");
                return;
            }
            pa_operation_unref(pa_op);
            break;                                                              
                                                                                
        case PA_CONTEXT_FAILED:                                                 
            if (m_pa_ctx) {
                pa_context_unref(m_pa_ctx);                                     
                m_pa_ctx = NULL;
            }            
                                                                                
            printf("Connection failed, attempting reconnect\n");                
            g_timeout_add_seconds(13, m_connect_to_pulse, NULL);                                           
            return;                                                             
                                                                                
        case PA_CONTEXT_TERMINATED:                                             
        default:                                                                
            printf("pa_context terminated\n");                                  
            return;                                                             
    }                                                                           
}
int pa_get_devicelist(pa_devicelist_t *output)
{
	pa_mainloop *pa_ml = NULL;
	pa_mainloop_api *pa_mlapi = NULL;
	pa_operation *pa_op = NULL;
	pa_context *pa_ctx = NULL;

	uint8_t state = 0;
	int pa_ready = 0;

	memset(output, 0, sizeof(pa_devicelist_t) * 16);

	if ( (pa_ml = pa_mainloop_new()) == NULL) return -1;
	if ( (pa_mlapi = pa_mainloop_get_api(pa_ml)) == NULL ) return -2;
	if ( (pa_ctx = pa_context_new(pa_mlapi, "test")) == NULL) return -3;

	pa_context_connect(pa_ctx, NULL, 0, NULL);

	pa_context_set_state_callback(pa_ctx, pa_state_cb, &pa_ready);

	while (1) {
		if (pa_ready == 0) {
			pa_mainloop_iterate(pa_ml, 1, NULL);
			continue;
		}
		if (pa_ready == 2) {
			pa_context_disconnect(pa_ctx);
			pa_context_unref(pa_ctx);
			pa_mainloop_free(pa_ml);
			return -1;
		}
		switch (state) {
			case 0:
				pa_op = pa_context_get_sink_info_list(pa_ctx, pa_sinklist_cb, output);

				state++;
				break;
			case 1:
				if (pa_operation_get_state(pa_op) == PA_OPERATION_DONE) {
					pa_operation_unref(pa_op);
					pa_context_disconnect(pa_ctx);
					pa_context_unref(pa_ctx);
					pa_mainloop_free(pa_ml);
					return 0;
				}
				break;
			default:
				return -1;
		}
		pa_mainloop_iterate(pa_ml, 1, NULL);
	}
}
Beispiel #6
0
static void get_source_info_callback(pa_context *c, const pa_source_info *i, int is_last, void *userdata) {
    if ( is_last )
    {
        pa_operation_unref(pa_context_get_sink_info_list(c, get_sink_info_callback, userdata));
        return;
    }
    printf("Source: %s - name: %s\n",i->description,i->name);
    if ( i->monitor_of_sink != PA_INVALID_INDEX )
    {
        printf("[ISMONITOR] of %s\n",i->monitor_of_sink_name);
        ((MediaRecorder*)userdata)->monitorsources.insert(std::pair<std::string,std::string>(i->monitor_of_sink_name,i->name));
    }
}
Beispiel #7
0
void PulseAudioSystem::query() {
	bSourceDone=bSinkDone=bServerDone = false;
	qhInput.clear();
	qhOutput.clear();
	qhEchoMap.clear();
	qhSpecMap.clear();
	qhChanMap.clear();
	qhInput.insert(QString(), tr("Default Input"));
	qhOutput.insert(QString(), tr("Default Output"));
	pa_operation_unref(pa_context_get_server_info(pacContext, server_callback, this));
	pa_operation_unref(pa_context_get_sink_info_list(pacContext, sink_callback, this));
	pa_operation_unref(pa_context_get_source_info_list(pacContext, source_callback, this));
	wakeup();
}
/**
 * Callback to retrieve server infos (mostly, the default sink).
 */
static void
xvd_server_info_callback (pa_context           *c,
                          const pa_server_info *info,
                          void                 *userdata)
{
  pa_operation *op = NULL;

  if (!c || !userdata)
    {
      g_warning ("xvd_server_info_callback: invalid argument");
      return;
    }

  if (!info)
    {
      g_warning("xvd_server_info_callback: No PulseAudio server");
      return;
    }

  if (info->default_sink_name)
    {
      op = pa_context_get_sink_info_by_name (c,
                                             info->default_sink_name,
                                             xvd_default_sink_info_callback,
                                             userdata);

      if (!op)
        {
          g_warning("xvd_server_info_callback: pa_context_get_sink_info_by_name() failed");
          return;
        }
      pa_operation_unref (op);
    }
  else
    {
      /* when PulseAudio doesn't set a default sink, look at all of them
         and hope to find a usable one */
      op = pa_context_get_sink_info_list(c,
                                         xvd_sink_info_callback,
                                         userdata);

      if (!op)
        {
          g_warning("xvd_server_info_callback: pa_context_get_sink_info_list() failed");
          return;
        }
      pa_operation_unref (op);
    }
}
void context_state_cb(pa_context *c, void *userdata) {

    switch (pa_context_get_state(c)) {
    case PA_CONTEXT_UNCONNECTED:
    case PA_CONTEXT_CONNECTING:
    case PA_CONTEXT_AUTHORIZING:
    case PA_CONTEXT_SETTING_NAME:
	break;

    case PA_CONTEXT_READY: {
	pa_operation *o;

	if (!(o = pa_context_get_source_info_list(c,
						  source_cb,
						  NULL
						  ))) {
	    show_error(_("pa_context_subscribe() failed"));
	    return;
	}
	pa_operation_unref(o);

	if (!(o = pa_context_get_sink_info_list(c,
						sink_cb,
						NULL
						))) {
	    show_error(_("pa_context_subscribe() failed"));
	    return;
	}
	pa_operation_unref(o);

	pa_context_set_subscribe_callback(c, subscribe_cb, NULL);

	if (!(o = pa_context_subscribe(c, (pa_subscription_mask_t)
				       (PA_SUBSCRIPTION_MASK_SINK|
					PA_SUBSCRIPTION_MASK_SOURCE), NULL, NULL))) {
	    show_error(_("pa_context_subscribe() failed"));
	    return;
	}
	pa_operation_unref(o);

	break;
    }

    case PA_CONTEXT_FAILED:
    case PA_CONTEXT_TERMINATED:
    default:
	return;
    }
}
void processContextState( pa_context* context, void* userData )
{
	StateData* stateData = static_cast<StateData*>( userData );
	pa_context_state_t state = ::pa_context_get_state( context );
	switch( state ) {
		case PA_CONTEXT_READY: {
			switch( stateData->request ) {
				case StateData::GET_SINKS:
					pa_operation_unref( pa_context_get_sink_info_list( context, processSinkInfo, userData ) );
				break;

				case StateData::GET_SOURCES:
					pa_operation_unref( pa_context_get_source_info_list( context, processSourceInfo, userData ) );
				break;

				case StateData::GET_DEFAULT_SINK_NAME:
					pa_operation_unref( pa_context_get_server_info( context, processServerInfo, userData ) );
				break;

				case StateData::GET_DEFAULT_SOURCE_NAME:
					pa_operation_unref( pa_context_get_server_info( context, processServerInfo, userData ) );
				break;

				case StateData::DONE:
					stateData->mainLoopApi->quit( stateData->mainLoopApi, 0 );
				break;

				case StateData::INVALID:
					stateData->mainLoopApi->quit( stateData->mainLoopApi, -1 );
				break;
			}
		}
		break;

		case PA_CONTEXT_TERMINATED:
			stateData->mainLoopApi->quit( stateData->mainLoopApi, 0 );
		break;

		case PA_CONTEXT_FAILED:
			stateData->mainLoopApi->quit( stateData->mainLoopApi, -1 );
		break;
		
		default:
		break;
	}
}
Beispiel #11
0
static void cm_cardinfo_cb(pa_context *context, const pa_card_info *info, int is_last, void *user_data)
{
	struct luna_service_req_data *req = user_data;
	struct audio_service *service = req->user_data;
	pa_card_profile_info *voice_call = NULL, *highest = NULL;
	const char *name_to_set = NULL;
	const char *value_to_set = NULL;
	pa_operation *op;
	int i;

	for (i = 0; i < info->n_profiles; i++) {
		if (!highest || info->profiles[i].priority > highest->priority)
			highest = &info->profiles[i];
		if (!strcmp(info->profiles[i].name, "voicecall"))
			voice_call = &info->profiles[i];
	}

	if (is_last && !voice_call) {
		finish_set_call_mode(false, user_data);
		return;
	}

	if (!voice_call)
		return; /* Not the right card */

	if (service->in_call && (voice_call != info->active_profile)) {
		name_to_set = info->name;
		value_to_set = voice_call->name;
	}
	else if (!service->in_call && (voice_call == info->active_profile)) {
		name_to_set = info->name;
		value_to_set = highest->name;
	}

	if (name_to_set) {
		op = pa_context_set_card_profile_by_name(service->context, name_to_set, value_to_set,
											cm_card_profile_set_cb, req);
		pa_operation_unref(op);
	}
	else {
		op = pa_context_get_sink_info_list(context, cm_sinkinfo_cb, user_data);
		pa_operation_unref(op);
	}
}
Beispiel #12
0
void CPulseAE::EnumerateOutputDevices(AEDeviceList &devices, bool passthrough)
{
  if (!m_MainLoop || ! m_Context)
    return;

  pa_threaded_mainloop_lock(m_MainLoop);

  SinkInfoStruct sinkStruct;
  sinkStruct.passthrough = passthrough;
  sinkStruct.mainloop = m_MainLoop;
  sinkStruct.list = &devices;
  CStdString def;
  def.Format("%s (PulseAudio)",g_localizeStrings.Get(409).c_str());
  devices.push_back(AEDevice(def, "pulse:default@default"));
  WaitForOperation(pa_context_get_sink_info_list(m_Context,
                   SinkInfo, &sinkStruct), m_MainLoop, "EnumerateAudioSinks");

  pa_threaded_mainloop_unlock(m_MainLoop);
}
Beispiel #13
0
void context_state_cb(pa_context *c, void *userdata) {

    switch (pa_context_get_state(c)) {
    case PA_CONTEXT_UNCONNECTED:
    case PA_CONTEXT_CONNECTING:
    case PA_CONTEXT_AUTHORIZING:
    case PA_CONTEXT_SETTING_NAME:
	break;

    case PA_CONTEXT_READY: {
    printf("func = %s , LINE = %d \n",__func__,__LINE__);
	pa_operation *o;

	// set up a callback to tell us about source devices
	if (!(o = pa_context_get_source_info_list(c,
					    sourcelist_cb,
					    NULL
						  ))) {
	    show_error(_("pa_context_subscribe() failed"));
	    return;
	}
	pa_operation_unref(o);

	// set up a callback to tell us about sink devices
	if (!(o = pa_context_get_sink_info_list(c,
					    sinklist_cb,
					    NULL
						  ))) {
	    show_error(_("pa_context_subscribe() failed"));
	    return;
	}
	pa_operation_unref(o);

	break;
    }

    case PA_CONTEXT_FAILED:
    case PA_CONTEXT_TERMINATED:
    default:
	return;
    }
}
JNIEXPORT jlong JNICALL
Java_org_jitsi_impl_neomedia_pulseaudio_PA_context_1get_1sink_1info_1list
    (JNIEnv *env, jclass clazz, jlong c, jobject cb)
{
    jweak weakCb = cb ? (*env)->NewWeakGlobalRef(env, cb) : NULL;
    pa_operation *o;

    if ((*env)->ExceptionCheck(env))
        o = NULL;
    else
    {
        o
            = pa_context_get_sink_info_list(
                    (pa_context *) (intptr_t) c,
                    weakCb ? PulseAudio_sinkInfoCallback : NULL,
                    (void *) weakCb);
    }

    return (intptr_t) o;
}
Beispiel #15
0
static void probe_devices(ALboolean capture)
{
    pa_threaded_mainloop *loop;

    if(capture == AL_FALSE)
        allDevNameMap = malloc(sizeof(DevMap) * 1);
    else
        allCaptureDevNameMap = malloc(sizeof(DevMap) * 1);

    if((loop=pa_threaded_mainloop_new()) &&
       pa_threaded_mainloop_start(loop) >= 0)
    {
        pa_context *context;

        pa_threaded_mainloop_lock(loop);
        context = connect_context(loop, AL_FALSE);
        if(context)
        {
            pa_operation *o;

            if(capture == AL_FALSE)
                o = pa_context_get_sink_info_list(context, sink_device_callback, loop);
            else
                o = pa_context_get_source_info_list(context, source_device_callback, loop);
            while(pa_operation_get_state(o) == PA_OPERATION_RUNNING)
                pa_threaded_mainloop_wait(loop);
            pa_operation_unref(o);

            pa_context_disconnect(context);
            pa_context_unref(context);
        }
        pa_threaded_mainloop_unlock(loop);
        pa_threaded_mainloop_stop(loop);
    }
    if(loop)
        pa_threaded_mainloop_free(loop);
}
Beispiel #16
0
void CAESinkPULSE::EnumerateDevicesEx(AEDeviceInfoList &list, bool force)
{
  pa_context *context;
  pa_threaded_mainloop *mainloop;

  if (!SetupContext(NULL, &context, &mainloop))
  {
    CLog::Log(LOGNOTICE, "PulseAudio might not be running. Context was not created.");
    return;
  }

  pa_threaded_mainloop_lock(mainloop);

  SinkInfoStruct sinkStruct;
  sinkStruct.mainloop = mainloop;
  sinkStruct.list = &list;
  WaitForOperation(pa_context_get_sink_info_list(context, SinkInfoRequestCallback, &sinkStruct), mainloop, "EnumerateAudioSinks");

  pa_threaded_mainloop_unlock(mainloop);

  if (mainloop)
    pa_threaded_mainloop_stop(mainloop);

  if (context)
  {
    pa_context_disconnect(context);
    pa_context_unref(context);
    context = NULL;
  }

  if (mainloop)
  {
    pa_threaded_mainloop_free(mainloop);
    mainloop = NULL;
  }
}
Beispiel #17
0
/*
 * iterate the main loop until all devices are listed
 * args:
 *    audio_ctx - pointer to audio context
 *
 * asserts:
 *    audio_ctx is not null
 *
 * returns: error code
 */
static int pa_get_devicelist(audio_context_t *audio_ctx)
{
	/*assertions*/
	assert(audio_ctx != NULL);

	/* Define our pulse audio loop and connection variables */
	pa_mainloop *pa_ml;
	pa_mainloop_api *pa_mlapi;
	pa_operation *pa_op = NULL;
	pa_context *pa_ctx;

	/* We'll need these state variables to keep track of our requests */
    int state = 0;
    int pa_ready = 0;

    /* Create a mainloop API and connection to the default server */
    pa_ml = pa_mainloop_new();
    pa_mlapi = pa_mainloop_get_api(pa_ml);
    pa_ctx = pa_context_new(pa_mlapi, "getDevices");

    /* This function connects to the pulse server */
    if(pa_context_connect(pa_ctx, NULL, 0, NULL) < 0)
    {
		fprintf(stderr,"AUDIO: PULSE - unable to connect to server: pa_context_connect failed\n");
		finish(pa_ctx, pa_ml);
		return -1;
	}

    /*
	 * This function defines a callback so the server will tell us
	 * it's state.
     * Our callback will wait for the state to be ready.
     * The callback will modify the variable to 1 so we know when we
     * have a connection and it's ready.
     * If there's an error, the callback will set pa_ready to 2
	 */
    pa_context_set_state_callback(pa_ctx, pa_state_cb, &pa_ready);

    /*
	 * Now we'll enter into an infinite loop until we get the data
	 * we receive or if there's an error
	 */
    for (;;)
	{
        /*
		 * We can't do anything until PA is ready,
		 * so just iterate the mainloop and continue
		 */
        if (pa_ready == 0)
		{
            pa_mainloop_iterate(pa_ml, 1, NULL);
            continue;
        }
        /* We couldn't get a connection to the server, so exit out */
        if (pa_ready == 2)
		{
            finish(pa_ctx, pa_ml);
            return -1;
        }
        /*
		 * At this point, we're connected to the server and ready
		 * to make requests
		 */
        switch (state)
		{
            /* State 0: we haven't done anything yet */
            case 0:
                /*
				 * This sends an operation to the server.
				 * pa_sinklist_cb is our callback function and a pointer
				 * o our devicelist will be passed to the callback
				 * (audio_ctx) The operation ID is stored in the
                 * pa_op variable
				 */
                pa_op = pa_context_get_sink_info_list(
						  pa_ctx,
                          pa_sinklist_cb,
                          (void *) audio_ctx);

                /* Update state for next iteration through the loop */
                state++;
                break;
            case 1:
                /*
				 * Now we wait for our operation to complete.
				 * When it's complete our pa_output_devicelist is
				 * filled out, and we move along to the next state
				 */
                if (pa_operation_get_state(pa_op) == PA_OPERATION_DONE)
				{
                    pa_operation_unref(pa_op);

                    /*
					 * Now we perform another operation to get the
					 * source(input device) list just like before.
					 * This time we pass a pointer to our input structure
					 */
                    pa_op = pa_context_get_source_info_list(
							  pa_ctx,
                              pa_sourcelist_cb,
                              (void *) audio_ctx);
                    /* Update the state so we know what to do next */
                    state++;
                }
                break;
            case 2:
                if (pa_operation_get_state(pa_op) == PA_OPERATION_DONE)
				{
                    /*
                     * Now we're done,
                     * clean up and disconnect and return
                     */
                    pa_operation_unref(pa_op);
                    finish(pa_ctx, pa_ml);
                    return 0;
                }
                break;
            default:
                /* We should never see this state */
                printf("AUDIO: Pulseaudio in state %d\n", state);
                return -1;
        }
        /*
		 * Iterate the main loop and go again.  The second argument is whether
         * or not the iteration should block until something is ready to be
         * done.  Set it to zero for non-blocking.
		 */
        pa_mainloop_iterate(pa_ml, 1, NULL);
    }

    return 0;
}
Beispiel #18
0
static int pulseaudio_open(void)
{
   /* Use PA_CONTEXT_NOAUTOSPAWN to see if a PA server is running.
    * If not, fail - we're better off using ALSA/OSS.
    * 
    * Also check for suspended PA - again better using ALSA/OSS in
    * that case (pa_simple_write just blocks until PA is unsuspended
    * otherwise).
    * 
    * TODO: Maybe we should have a force flag to the audio driver
    * open method, which in the case of PA would spawn a server if
    * none is running (and also unsuspend?).
    */

   pa_mainloop *mainloop = pa_mainloop_new();
   pa_context *c = pa_context_new(pa_mainloop_get_api(mainloop),
      al_get_app_name());
   if (!c) {
      pa_mainloop_free(mainloop);
      return 1;
   }

   pa_context_connect(c, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL);

   while (1) {
      /* Don't block or it will hang if there is no server to connect to. */
      const int blocking = 0;
      if (pa_mainloop_iterate(mainloop, blocking, NULL) < 0) {
         ALLEGRO_ERROR("pa_mainloop_iterate failed\n");
         pa_context_disconnect(c);
         pa_mainloop_free(mainloop);
         break;
      }
      pa_context_state_t s = pa_context_get_state(c);
      if (s == PA_CONTEXT_READY) {
         ALLEGRO_DEBUG("PA_CONTEXT_READY\n");
         break;
      }
      if (s == PA_CONTEXT_FAILED) {
         ALLEGRO_ERROR("PA_CONTEXT_FAILED\n");
         pa_context_disconnect(c);
         pa_mainloop_free(mainloop);
         return 1;
      }
   }

   pa_sink_state_t state = 0;
   pa_operation *op = pa_context_get_sink_info_list(c, sink_info_cb, &state);
   while (pa_operation_get_state(op) == PA_OPERATION_RUNNING) {
      pa_mainloop_iterate(mainloop, 1, NULL);
   }
   /*if (state == PA_SINK_SUSPENDED) {
      pa_context_disconnect(c);
      pa_mainloop_free(mainloop);
      return 1;
   }*/
   pa_operation_unref(op);
   pa_context_disconnect(c);
   pa_context_unref(c);
   pa_mainloop_free(mainloop);
   return 0;
}
PyObject * quisk_pa_sound_devices(PyObject * self, PyObject * args)
{	// Return a list of PulseAudio device names [pycapt, pyplay]
	PyObject * pylist, * pycapt, * pyplay;
	pa_mainloop *pa_names_ml;
	pa_mainloop_api *pa_names_mlapi;
	pa_operation *pa_op=NULL;
	pa_context *pa_names_ctx;
	int state = 0;

	if (!PyArg_ParseTuple (args, ""))
		return NULL;
	// Each pycapt and pyplay is (dev name, description, alsa name)
	pylist = PyList_New(0);		// list [pycapt, pyplay]
	pycapt = PyList_New(0);		// list of capture devices
	pyplay = PyList_New(0);		// list of play devices
	PyList_Append(pylist, pycapt);
	PyList_Append(pylist, pyplay);
    
    //printf("Starting name loop\n");

	// Create a mainloop API and connection to the default server
	pa_names_ml = pa_mainloop_new();
	pa_names_mlapi = pa_mainloop_get_api(pa_names_ml);
	pa_names_ctx = pa_context_new(pa_names_mlapi, "DeviceNames");
 
	// This function connects to the pulse server
	if (pa_context_connect(pa_names_ctx, NULL, 0, NULL) < 0) {
	   if (quisk_sound_state.verbose_pulse)
	      printf("No local daemon to connect to for show_pulse_audio_devices option\n");
	   return pylist;
	}

	// This function defines a callback so the server will tell us it's state.
	pa_context_set_state_callback(pa_names_ctx, pa_names_state_cb, &state);

	// Now we'll enter into an infinite loop until we get the data we receive or if there's an error
	while (state < 10) {
		switch (state) {
		case 0:	// We can't do anything until PA is ready
			pa_mainloop_iterate(pa_names_ml, 1, NULL);
			break;
		case 1:
			// This sends an operation to the server.  pa_sinklist_info is
			// our callback function and a pointer to our devicelist will
			// be passed to the callback.
			pa_op = pa_context_get_sink_info_list(pa_names_ctx, pa_sinklist_cb, pyplay);
			// Update state for next iteration through the loop
			state++;
			pa_mainloop_iterate(pa_names_ml, 1, NULL);
			break;
		case 2:
			// Now we wait for our operation to complete.  When it's
			// complete our pa_output_devicelist is filled out, and we move
			// along to the next state
			if (pa_operation_get_state(pa_op) == PA_OPERATION_DONE) {
				pa_operation_unref(pa_op);
				// Now we perform another operation to get the source
				// (input device) list just like before.
				pa_op = pa_context_get_source_info_list(pa_names_ctx, pa_sourcelist_cb, pycapt);
				// Update the state so we know what to do next
				state++;
			}
			pa_mainloop_iterate(pa_names_ml, 1, NULL);
			break;
		case 3:
			if (pa_operation_get_state(pa_op) == PA_OPERATION_DONE) {
				pa_operation_unref(pa_op);
				state = 9;
			}
			else
				pa_mainloop_iterate(pa_names_ml, 1, NULL);
			break;
		case 9:				// Now we're done, clean up and disconnect and return
			pa_context_disconnect(pa_names_ctx);
			pa_context_unref(pa_names_ctx);
			pa_mainloop_free(pa_names_ml);
			state = 99;
			break;
		}
	}
    //printf("Finished with name loop\n");
	return pylist;
}
AudioDevPulseAudio::AudioDevPulseAudio(QObject *parent):
    AudioDev(parent)
{
    this->d = new AudioDevPulseAudioPrivate(this);

    // Create a threaded main loop for PulseAudio
    this->d->m_mainLoop = pa_threaded_mainloop_new();

    if (!this->d->m_mainLoop)
        return;

    // Start main loop.
    if (pa_threaded_mainloop_start(this->d->m_mainLoop) != 0) {
        pa_threaded_mainloop_free(this->d->m_mainLoop);
        this->d->m_mainLoop = nullptr;

        return;
    }

    pa_threaded_mainloop_lock(this->d->m_mainLoop);

    // Get main loop abstration layer.
    auto mainLoopApi = pa_threaded_mainloop_get_api(this->d->m_mainLoop);

    if (!mainLoopApi) {
        pa_threaded_mainloop_unlock(this->d->m_mainLoop);
        pa_threaded_mainloop_stop(this->d->m_mainLoop);
        pa_threaded_mainloop_free(this->d->m_mainLoop);
        this->d->m_mainLoop = nullptr;

        return;
    }

    // Get a PulseAudio context.
    this->d->m_context = pa_context_new(mainLoopApi,
                                        QCoreApplication::applicationName()
                                           .toStdString()
                                           .c_str());

    if (!this->d->m_context) {
        pa_threaded_mainloop_unlock(this->d->m_mainLoop);
        pa_threaded_mainloop_stop(this->d->m_mainLoop);
        pa_threaded_mainloop_free(this->d->m_mainLoop);
        this->d->m_mainLoop = nullptr;

        return;
    }

    // We need to set a state callback in order to connect to the server.
    pa_context_set_state_callback(this->d->m_context,
                                  AudioDevPulseAudioPrivate::contextStateCallbackInit,
                                  this);

    // Connect to PulseAudio server.
    if (pa_context_connect(this->d->m_context,
                           nullptr,
                           PA_CONTEXT_NOFLAGS,
                           nullptr) < 0) {
        pa_context_unref(this->d->m_context);
        this->d->m_context = nullptr;
        pa_threaded_mainloop_unlock(this->d->m_mainLoop);
        pa_threaded_mainloop_stop(this->d->m_mainLoop);
        pa_threaded_mainloop_free(this->d->m_mainLoop);
        this->d->m_mainLoop = nullptr;

        return;
    }

    static const QList<pa_context_state_t> expectedStates = {
        PA_CONTEXT_READY,
        PA_CONTEXT_FAILED,
        PA_CONTEXT_TERMINATED
    };

    pa_context_state_t state;

    // Wait until the connection to the server is stablished.
    forever {
        state = pa_context_get_state(this->d->m_context);

        if (expectedStates.contains(state))
            break;

        pa_threaded_mainloop_wait(this->d->m_mainLoop);
    }

    if (state != PA_CONTEXT_READY) {
        pa_context_disconnect(this->d->m_context);
        pa_context_unref(this->d->m_context);
        this->d->m_context = nullptr;
        pa_threaded_mainloop_unlock(this->d->m_mainLoop);
        pa_threaded_mainloop_stop(this->d->m_mainLoop);
        pa_threaded_mainloop_free(this->d->m_mainLoop);
        this->d->m_mainLoop = nullptr;

        return;
    }

    // Get server information.
    auto operation =
            pa_context_get_server_info(this->d->m_context,
                                       AudioDevPulseAudioPrivate::serverInfoCallback,
                                       this);

    while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING)
        pa_threaded_mainloop_wait(this->d->m_mainLoop);

    pa_operation_unref(operation);

    // Get sources information.
    operation = pa_context_get_source_info_list(this->d->m_context,
                                                AudioDevPulseAudioPrivate::sourceInfoCallback,
                                                this);

    while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING)
        pa_threaded_mainloop_wait(this->d->m_mainLoop);

    pa_operation_unref(operation);

    // Get sinks information.
    operation = pa_context_get_sink_info_list(this->d->m_context,
                                              AudioDevPulseAudioPrivate::sinkInfoCallback,
                                              this);

    while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING)
        pa_threaded_mainloop_wait(this->d->m_mainLoop);

    pa_operation_unref(operation);

    pa_context_set_subscribe_callback(this->d->m_context,
                                      AudioDevPulseAudioPrivate::deviceUpdateCallback,
                                      this);

    pa_operation_unref(pa_context_subscribe(this->d->m_context,
                                            pa_subscription_mask_t(PA_SUBSCRIPTION_MASK_SINK
                                                                   | PA_SUBSCRIPTION_MASK_SOURCE
                                                                   | PA_SUBSCRIPTION_MASK_SERVER),
                                            nullptr,
                                            this));

    pa_threaded_mainloop_unlock(this->d->m_mainLoop);
}
Beispiel #21
0
static void probe_devices(ALboolean capture)
{
    pa_threaded_mainloop *loop;

    if(capture == AL_FALSE)
        allDevNameMap = malloc(sizeof(DevMap) * 1);
    else
        allCaptureDevNameMap = malloc(sizeof(DevMap) * 1);

    if((loop=pa_threaded_mainloop_new()) &&
       pa_threaded_mainloop_start(loop) >= 0)
    {
        pa_context *context;

        pa_threaded_mainloop_lock(loop);
        context = connect_context(loop, AL_FALSE);
        if(context)
        {
            pa_operation *o;

            if(capture == AL_FALSE)
            {
                pa_stream_flags_t flags;
                pa_sample_spec spec;
                pa_stream *stream;

                flags = PA_STREAM_FIX_FORMAT | PA_STREAM_FIX_RATE |
                        PA_STREAM_FIX_CHANNELS | PA_STREAM_DONT_MOVE;

                spec.format = PA_SAMPLE_S16NE;
                spec.rate = 44100;
                spec.channels = 2;

                stream = connect_playback_stream(NULL, loop, context, flags,
                                                 NULL, &spec, NULL);
                if(stream)
                {
                    o = pa_context_get_sink_info_by_name(context, pa_stream_get_device_name(stream), sink_device_callback, loop);
                    WAIT_FOR_OPERATION(o, loop);

                    pa_stream_disconnect(stream);
                    pa_stream_unref(stream);
                    stream = NULL;
                }

                o = pa_context_get_sink_info_list(context, sink_device_callback, loop);
            }
            else
            {
                pa_stream_flags_t flags;
                pa_sample_spec spec;
                pa_stream *stream;

                flags = PA_STREAM_FIX_FORMAT | PA_STREAM_FIX_RATE |
                        PA_STREAM_FIX_CHANNELS | PA_STREAM_DONT_MOVE;

                spec.format = PA_SAMPLE_S16NE;
                spec.rate = 44100;
                spec.channels = 1;

                stream = connect_record_stream(NULL, loop, context, flags,
                                               NULL, &spec, NULL);
                if(stream)
                {
                    o = pa_context_get_source_info_by_name(context, pa_stream_get_device_name(stream), source_device_callback, loop);
                    WAIT_FOR_OPERATION(o, loop);

                    pa_stream_disconnect(stream);
                    pa_stream_unref(stream);
                    stream = NULL;
                }

                o = pa_context_get_source_info_list(context, source_device_callback, loop);
            }
            WAIT_FOR_OPERATION(o, loop);

            pa_context_disconnect(context);
            pa_context_unref(context);
        }
        pa_threaded_mainloop_unlock(loop);
        pa_threaded_mainloop_stop(loop);
    }
    if(loop)
        pa_threaded_mainloop_free(loop);
}
Beispiel #22
0
int main(int argc, char **argv)
{
    int retval = 0;

    struct timeval timeout, timeout_def;

    pa_mainloop * ml = pa_mainloop_new();
    pa_mainloop_api * api = pa_mainloop_get_api(ml);
    pa_context_state_t pa_state;

    pa_context * context = pa_context_new(api, "pa-mixer");
    pa_context_connect(context, NULL, 0, NULL);
    pa_context_set_state_callback(context, pa_state_changed, &pa_state);

    /*
    struct sigaction sigint_handler;
    sigint_handler.sa_handler = handle_sig_int;
    sigemptyset(&sigint_handler.sa_mask);
    sigint_handler.sa_flags = 0;
    sigaction(SIGINT, &sigint_handler, NULL);
    */

    int init_done = 0;

    initscr();
    keypad(stdscr, TRUE);
    start_color();
    curs_set(0);
    cbreak();
    noecho();
    init_pair(1, COLOR_WHITE, COLOR_BLACK);
    init_pair(2, COLOR_WHITE, COLOR_BLUE);

    fd_set read_set, test_set;
    FD_ZERO(&read_set);
    FD_SET(0, &read_set);
    timeout_def.tv_sec = 0;
    timeout_def.tv_usec = 1000;

    view_init();

    while(running) {
        if(pa_state == PA_CONTEXT_UNCONNECTED) {
            pa_mainloop_iterate(ml, 1, NULL);
            continue;
        }
        if(pa_state == PA_CONTEXT_FAILED || pa_state == PA_CONTEXT_TERMINATED) {
            running = 0;
            retval = -1;
        }
        if(pa_state == PA_CONTEXT_READY) {
            if(!init_done) {
                pa_context_set_subscribe_callback(context, on_event, NULL);
                pa_context_subscribe(context, PA_SUBSCRIPTION_MASK_ALL, NULL, NULL);
                pa_context_get_sink_input_info_list(context, on_sink_input_update, context);
                pa_context_get_sink_info_list(context, on_sink_update, context);
            }
            init_done = 1;
        }

        test_set = read_set;
        timeout = timeout_def;
        int r = select(1, &test_set, NULL, NULL, &timeout);
        if(r == 0) {
            /* timeout */
            pa_mainloop_iterate(ml, 0, NULL);
        }
        if(FD_ISSET(0, &test_set)) {
            /* stdin ready */

            int key = getch();
            switch(key) {
                case KEY_UP:
                    view_select_prev();
                    view_show();
                    break;
                case KEY_DOWN:
                    view_select_next();
                    view_show();
                    break;
                case KEY_LEFT:
                    change_sel_vol(context, VOL_DOWN);
                    break;
                case KEY_RIGHT:
                    change_sel_vol(context, VOL_UP);
                    break;
                case 'n':
                    change_sel_vol(context, VOL_NORM);
                    break;
                case 'm':
                    change_sel_vol(context, VOL_MUTE);
                    break;
                case 'q':
                    running = 0;
                    break;
                case KEY_RESIZE:
                    view_show();
                    refresh();
                    break;
            }
        }

    }

    pa_context_disconnect(context);
    pa_context_unref(context);
    pa_mainloop_free(ml);

    endwin();

    return retval;
}
PulseAudioWrapper::PulseAudioWrapper(QObject *parent)
    : QObject(parent),
      d(new PulseAudioWrapperPrivate(this))
{
    PulseAudioWrapperPrivate::paMainLoop = pa_threaded_mainloop_new();
    pa_threaded_mainloop_start(PulseAudioWrapperPrivate::paMainLoop);

    PulseAudioWrapperPrivate::paMainLoopApi = pa_threaded_mainloop_get_api(PulseAudioWrapperPrivate::paMainLoop);

    pa_threaded_mainloop_lock(PulseAudioWrapperPrivate::paMainLoop);

    PulseAudioWrapperPrivate::paContext = pa_context_new(PulseAudioWrapperPrivate::paMainLoopApi,
                                                         qApp->applicationName().toUtf8().data());

    pa_context_set_state_callback(PulseAudioWrapperPrivate::paContext, &PulseAudioWrapperPrivate::onContextNotify, NULL);
    pa_context_connect(PulseAudioWrapperPrivate::paContext, NULL, PA_CONTEXT_NOFLAGS, NULL);

    bool done = false;
    pa_context_state_t contextState;

    while (!done)
    {
        switch (contextState = pa_context_get_state(d->paContext))
        {
            case PA_CONTEXT_UNCONNECTED: qDebug() << "Context state: PA_CONTEXT_UNCONNECTED"; break;
            case PA_CONTEXT_CONNECTING: qDebug() << "Context state: PA_CONTEXT_CONNECTING"; break;
            case PA_CONTEXT_AUTHORIZING: qDebug() << "Context state: PA_CONTEXT_AUTHORIZING"; break;
            case PA_CONTEXT_SETTING_NAME: qDebug() << "Context state: PA_CONTEXT_SETTING_NAME"; break;
            case PA_CONTEXT_READY: qDebug() << "Context state: PA_CONTEXT_READY"; done = true; break;
            case PA_CONTEXT_FAILED: qDebug() << "Context state: PA_CONTEXT_FAILED"; done = true; break;
            case PA_CONTEXT_TERMINATED: qDebug() << "Context state: PA_CONTEXT_TERMINATED"; done = true; break;
        }

        if (!done)
            pa_threaded_mainloop_wait(PulseAudioWrapperPrivate::paMainLoop);
    }

    if (contextState != PA_CONTEXT_READY)
        throw CallRecorderException("Unable to connect PulseAudio context!");

    pa_operation* listCardsOp = pa_context_get_card_info_list(PulseAudioWrapperPrivate::paContext,
                                                         &PulseAudioWrapperPrivate::onCardInfoList,
                                                         d.data());
    pa_threaded_mainloop_wait(PulseAudioWrapperPrivate::paMainLoop);
    pa_operation_unref(listCardsOp);

    pa_operation* listSinksOp = pa_context_get_sink_info_list(PulseAudioWrapperPrivate::paContext,
                                                             &PulseAudioWrapperPrivate::onSinkInfoList,
                                                             d.data());
    pa_threaded_mainloop_wait(PulseAudioWrapperPrivate::paMainLoop);
    pa_operation_unref(listSinksOp);

    pa_operation* listSourcesOp = pa_context_get_source_info_list(PulseAudioWrapperPrivate::paContext,
                                                                  &PulseAudioWrapperPrivate::onSourceInfoList,
                                                                  d.data());
    pa_threaded_mainloop_wait(PulseAudioWrapperPrivate::paMainLoop);
    pa_operation_unref(listSourcesOp);

    pa_context_set_subscribe_callback(PulseAudioWrapperPrivate::paContext,
                                      &PulseAudioWrapperPrivate::onContextSubscription,
                                      d.data());

    pa_operation* subscriptionOp = pa_context_subscribe(PulseAudioWrapperPrivate::paContext,
                                                        static_cast< pa_subscription_mask_t >(
                                                            PA_SUBSCRIPTION_MASK_CARD |
                                                            PA_SUBSCRIPTION_MASK_SINK |
                                                            PA_SUBSCRIPTION_MASK_SOURCE),
                                                        &PulseAudioWrapperPrivate::onContextSubscriptionSuccess,
                                                        d.data());
    pa_threaded_mainloop_wait(PulseAudioWrapperPrivate::paMainLoop);
    pa_operation_unref(subscriptionOp);


    pa_threaded_mainloop_unlock(PulseAudioWrapperPrivate::paMainLoop);
}
void PulseAudioSinksManager::retrieveSinksInfo()
{
    PaOperation op;
    op=pa_context_get_sink_info_list(pa_ctx.get(),PulseAudioSinksManager::pulseAudioSinklistCallback,this);
}
Beispiel #25
0
void Context::contextStateCallback(pa_context *c)
{
    qCDebug(PLASMAPA) << "state callback";
    pa_context_state_t state = pa_context_get_state(c);
    if (state == PA_CONTEXT_READY) {
        qCDebug(PLASMAPA) << "ready";

        // 1. Register for the stream changes (except during probe)
        if (m_context == c) {
            pa_context_set_subscribe_callback(c, subscribe_cb, this);

            if (!PAOperation(pa_context_subscribe(c, (pa_subscription_mask_t)
                                           (PA_SUBSCRIPTION_MASK_SINK|
                                            PA_SUBSCRIPTION_MASK_SOURCE|
                                            PA_SUBSCRIPTION_MASK_CLIENT|
                                            PA_SUBSCRIPTION_MASK_SINK_INPUT|
                                            PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT|
                                            PA_SUBSCRIPTION_MASK_CARD|
                                            PA_SUBSCRIPTION_MASK_SERVER), nullptr, nullptr))) {
                qCWarning(PLASMAPA) << "pa_context_subscribe() failed";
                return;
            }
        }

        if (!PAOperation(pa_context_get_sink_info_list(c, sink_cb, this))) {
            qCWarning(PLASMAPA) << "pa_context_get_sink_info_list() failed";
            return;
        }

        if (!PAOperation(pa_context_get_source_info_list(c, source_cb, this))) {
            qCWarning(PLASMAPA) << "pa_context_get_source_info_list() failed";
            return;
        }

        if (!PAOperation(pa_context_get_client_info_list(c, client_cb, this))) {
            qCWarning(PLASMAPA) << "pa_context_client_info_list() failed";
            return;
        }

        if (!PAOperation(pa_context_get_card_info_list(c, card_cb, this))) {
            qCWarning(PLASMAPA) << "pa_context_get_card_info_list() failed";
            return;
        }

        if (!PAOperation(pa_context_get_sink_input_info_list(c, sink_input_callback, this))) {
            qCWarning(PLASMAPA) << "pa_context_get_sink_input_info_list() failed";
            return;
        }

        if (!PAOperation(pa_context_get_source_output_info_list(c, source_output_cb, this))) {
            qCWarning(PLASMAPA) << "pa_context_get_source_output_info_list() failed";
            return;
        }

        if (!PAOperation(pa_context_get_server_info(c, server_cb, this))) {
            qCWarning(PLASMAPA) << "pa_context_get_server_info() failed";
            return;
        }

        if (PAOperation(pa_ext_stream_restore_read(c, ext_stream_restore_read_cb, this))) {
            pa_ext_stream_restore_set_subscribe_cb(c, ext_stream_restore_subscribe_cb, this);
            PAOperation(pa_ext_stream_restore_subscribe(c, 1, nullptr, this));
        } else {
            qCWarning(PLASMAPA) << "Failed to initialize stream_restore extension";
        }
    } else if (!PA_CONTEXT_IS_GOOD(state)) {
        qCWarning(PLASMAPA) << "context kaput";
        if (m_context) {
            pa_context_unref(m_context);
            m_context = nullptr;
        }
        reset();
        QTimer::singleShot(1000, this, &Context::connectToDaemon);
    }
}
Beispiel #26
0
// call this while holding the main loop lock
static int refresh_devices(struct SoundIoPrivate *si) {
    struct SoundIo *soundio = &si->pub;
    struct SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;

    assert(!sipa->current_devices_info);
    sipa->current_devices_info = ALLOCATE(struct SoundIoDevicesInfo, 1);
    if (!sipa->current_devices_info)
        return SoundIoErrorNoMem;

    pa_operation *list_sink_op = pa_context_get_sink_info_list(sipa->pulse_context, sink_info_callback, si);
    pa_operation *list_source_op = pa_context_get_source_info_list(sipa->pulse_context, source_info_callback, si);
    pa_operation *server_info_op = pa_context_get_server_info(sipa->pulse_context, server_info_callback, si);

    int err;
    if ((err = perform_operation(si, list_sink_op))) {
        return err;
    }
    if ((err = perform_operation(si, list_source_op))) {
        return err;
    }
    if ((err = perform_operation(si, server_info_op))) {
        return err;
    }

    if (sipa->device_query_err) {
        return sipa->device_query_err;
    }

    // based on the default sink name, figure out the default output index
    // if the name doesn't match just pick the first one. if there are no
    // devices then we need to set it to -1.
    sipa->current_devices_info->default_output_index = -1;
    sipa->current_devices_info->default_input_index = -1;

    if (sipa->current_devices_info->input_devices.length > 0) {
        sipa->current_devices_info->default_input_index = 0;
        for (int i = 0; i < sipa->current_devices_info->input_devices.length; i += 1) {
            struct SoundIoDevice *device = SoundIoListDevicePtr_val_at(
                    &sipa->current_devices_info->input_devices, i);

            assert(device->aim == SoundIoDeviceAimInput);
            if (strcmp(device->id, sipa->default_source_name) == 0) {
                sipa->current_devices_info->default_input_index = i;
            }
        }
    }

    if (sipa->current_devices_info->output_devices.length > 0) {
        sipa->current_devices_info->default_output_index = 0;
        for (int i = 0; i < sipa->current_devices_info->output_devices.length; i += 1) {
            struct SoundIoDevice *device = SoundIoListDevicePtr_val_at(
                    &sipa->current_devices_info->output_devices, i);

            assert(device->aim == SoundIoDeviceAimOutput);
            if (strcmp(device->id, sipa->default_sink_name) == 0) {
                sipa->current_devices_info->default_output_index = i;
            }
        }
    }

    soundio_destroy_devices_info(sipa->ready_devices_info);
    sipa->ready_devices_info = sipa->current_devices_info;
    sipa->current_devices_info = NULL;
    pa_threaded_mainloop_signal(sipa->main_loop, 0);
    soundio->on_events_signal(soundio);

    return 0;
}
int pa_get_devicelist(pa_devicelist_t *input, pa_devicelist_t *output) {
    // Define our pulse audio loop and connection variables
    pa_mainloop *pa_ml;
    pa_mainloop_api *pa_mlapi;
    pa_operation *pa_op;
    pa_context *pa_ctx;

    // We'll need these state variables to keep track of our requests
    int state = 0;
    int pa_ready = 0;

    // Initialize our device lists
    memset(input, 0, sizeof(pa_devicelist_t) * 16);
    memset(output, 0, sizeof(pa_devicelist_t) * 16);

    // Create a mainloop API and connection to the default server
    pa_ml = pa_mainloop_new();
    pa_mlapi = pa_mainloop_get_api(pa_ml);
    pa_ctx = pa_context_new(pa_mlapi, "test");

    // This function connects to the pulse server
    pa_context_connect(pa_ctx, NULL, 0, NULL);

    // This function defines a callback so the server will tell us it's state.
    // Our callback will wait for the state to be ready.  The callback will
    // modify the variable to 1 so we know when we have a connection and it's
    // ready.
    // If there's an error, the callback will set pa_ready to 2
    pa_context_set_state_callback(pa_ctx, pa_state_cb, &pa_ready);

    // Now we'll enter into an infinite loop until we get the data we receive
    // or if there's an error
    for (;;) {
        // We can't do anything until PA is ready, so just iterate the mainloop
        // and continue
        if (pa_ready == 0) {
            pa_mainloop_iterate(pa_ml, 1, NULL);
            continue;
        }
        // We couldn't get a connection to the server, so exit out
        if (pa_ready == 2) {
            pa_context_disconnect(pa_ctx);
            pa_context_unref(pa_ctx);
            pa_mainloop_free(pa_ml);
            return -1;
        }
        // At this point, we're connected to the server and ready to make
        // requests
        switch (state) {
            // State 0: we haven't done anything yet
            case 0:
                // This sends an operation to the server.  pa_sinklist_info is
                // our callback function and a pointer to our devicelist will
                // be passed to the callback The operation ID is stored in the
                // pa_op variable
                pa_op = pa_context_get_sink_info_list(pa_ctx,
                        pa_sinklist_cb,
                        output
                        );

                // Update state for next iteration through the loop
                state++;
                break;
            
            case 1:
                // Now we wait for our operation to complete.  When it's
                // complete our pa_output_devicelist is filled out, and we move
                // along to the next state
                if (pa_operation_get_state(pa_op) == PA_OPERATION_DONE) {
                    pa_operation_unref(pa_op);

                    // Now we perform another operation to get the source
                    // (input device) list just like before.  This time we pass
                    // a pointer to our input structure
                    pa_op = pa_context_get_source_info_list(pa_ctx,
                            pa_sourcelist_cb,
                            input
                            );
                    // Update the state so we know what to do next
                    state++;
                }
                break;
            case 2:
                if (pa_operation_get_state(pa_op) == PA_OPERATION_DONE) {
                    // Now we're done, clean up and disconnect and return
                    pa_operation_unref(pa_op);
                    pa_context_disconnect(pa_ctx);
                    pa_context_unref(pa_ctx);
                    pa_mainloop_free(pa_ml);
                    return 0;
                }
                break;
            default:
                // We should never see this state
                fprintf(stderr, "in state %d\n", state);
                return -1;
        }
        // Iterate the main loop and go again.  The second argument is whether
        // or not the iteration should block until something is ready to be
        // done.  Set it to zero for non-blocking.
        pa_mainloop_iterate(pa_ml, 1, NULL);
    }
}
Beispiel #28
0
void PulseSink::make_device_description(pa_context* pulse_context) {
  devices_.clear();
  pa_operation_unref(pa_context_get_sink_info_list(pulse_context, get_sink_info_callback, this));
}
Beispiel #29
0
/* The implementation of create_output_device_name_list() is based on the
 * example code in
 * http://www.ypass.net/blog/2009/10/
 *    pulseaudio-an-async-example-to-get-device-lists/
 */
mbx_error_code mbx_create_output_device_name_list(char ***dev_names, size_t *n_devs)
{
    pa_mainloop *pa_ml = pa_mainloop_new();
    pa_mainloop_api *pa_mlapi = pa_mainloop_get_api(pa_ml);
    pa_context *pa_ctx = pa_context_new(pa_mlapi, "music box (listing output "
        "devices)");
    pa_operation *pa_op;
    pa_context_state_t pa_context_state = PA_CONTEXT_UNCONNECTED;
    int do_iterate = 1;
    int error = 0;

    pa_context_connect(pa_ctx, NULL, 0, NULL);
    /* The state callback will update the state when we are connected to the
     * PulseAudio server, or if an error occurs. */
    pa_context_set_state_callback(pa_ctx, pa_context_state_cb,
        &pa_context_state);

    while ( do_iterate ) {
        switch ( pa_context_state ) {
            case PA_CONTEXT_UNCONNECTED:
            case PA_CONTEXT_CONNECTING:
            case PA_CONTEXT_AUTHORIZING:
            case PA_CONTEXT_SETTING_NAME:
                pa_mainloop_iterate(pa_ml, 1, NULL); // we must wait.
                break;
            case PA_CONTEXT_READY:
                do_iterate = 0;
                break;
            case PA_CONTEXT_FAILED:
                mbx_log_error(MBX_LOG_AUDIO_OUTPUT, "Connection to PulseAudio server failed: "
                    "%s", pa_strerror(pa_context_errno(pa_ctx)));
                error = 1;
                break;
            case PA_CONTEXT_TERMINATED:
                mbx_log_error(MBX_LOG_AUDIO_OUTPUT, "Connection to PulseAudio server "
                    "terminated unexpectedly.");
                error = 1;
                break;
            default:
                mbx_log_error(MBX_LOG_AUDIO_OUTPUT, "The PulseAudio context has an unexpected "
                    "state: %d", pa_context_state);
                error = 1;
                break;
        }
        if ( error ) {
            do_iterate = 0;
        }
    }
    if ( ! error ) {
        struct list_of_strings result = { NULL, 0, 0 };
        pa_op = pa_context_get_sink_info_list(pa_ctx, pa_sinklist_cb, &result);
        while ( pa_operation_get_state(pa_op) == PA_OPERATION_RUNNING ) {
            pa_mainloop_iterate(pa_ml, 1, NULL); // wait.
        }
        pa_operation_unref(pa_op);
        *dev_names = result.strings;
        *n_devs = result.n_strings;
    }
    pa_context_disconnect(pa_ctx);
    pa_context_unref(pa_ctx);
    pa_mainloop_free(pa_ml);
    return error ? MBX_PULSEAUDIO_ERROR : MBX_SUCCESS;
}
Beispiel #30
0
static void cm_card_profile_set_cb(pa_context *context, int success, void *user_data)
{
	pa_operation *op;
	op = pa_context_get_sink_info_list(context, cm_sinkinfo_cb, user_data);
	pa_operation_unref(op);
}