예제 #1
0
파일: main.c 프로젝트: smatting/pulsemixer
void change_sel_vol(pa_context * c, vol_change_t vol_change)
{
    view_entry_t view_entry = view_selected_item();

    if(view_entry.type == VIEW_SINK) {
        sink_t * sink = (sink_t *) view_entry.ref;
        if(sink != NULL) {
            /* averge all channel volumes of local copy */
            pa_volume_t vol;
            vol = pa_cvolume_avg(&sink->volume);
            vol = modify_volume(vol, vol_change);
            pa_cvolume_set(&sink->volume, sink->volume.channels, vol);
            pa_context_set_sink_volume_by_index(c, sink->index, &sink->volume, NULL, NULL);
        }
    }

    if(view_entry.type == VIEW_SINK_INPUT) {
        sink_input_t * sink_input = (sink_input_t *) view_entry.ref;
        if(sink_input != NULL) {
            /* averge all channel volumes of local copy */
            pa_volume_t vol;
            vol = pa_cvolume_avg(&sink_input->volume);
            vol = modify_volume(vol, vol_change);
            pa_cvolume_set(&sink_input->volume, sink_input->volume.channels, vol);
            pa_context_set_sink_input_volume(c, sink_input->index, &sink_input->volume, NULL, NULL);
        }
    }
}
예제 #2
0
void CAESinkPULSE::UpdateInternalVolume(const pa_cvolume* nVol)
{
  if (!nVol)
    return;

  pa_volume_t o_vol = pa_cvolume_avg(&m_Volume);
  pa_volume_t n_vol = pa_cvolume_avg(nVol);

  if (o_vol != n_vol)
  {
    pa_cvolume_set(&m_Volume, m_Channels, n_vol);
    m_volume_needs_update = true;
  }
}
예제 #3
0
pa_volume_t pa_cvolume_avg_mask(const pa_cvolume *a, const pa_channel_map *cm, pa_channel_position_mask_t mask) {
    uint64_t sum = 0;
    unsigned c, n;

    pa_assert(a);

    if (!cm)
        return pa_cvolume_avg(a);

    pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(a, cm), PA_VOLUME_MUTED);

    for (c = n = 0; c < a->channels; c++) {

        if (!(PA_CHANNEL_POSITION_MASK(cm->map[c]) & mask))
            continue;

        sum += a->values[c];
        n ++;
    }

    if (n > 0)
        sum /= n;

    return (pa_volume_t) sum;
}
예제 #4
0
char * getpavolume(void)
{
	uint8_t ctr;
	char * result;
	pa_devicelist_t pa_output_devicelist[16];
	

	result = smprintf("vol: ");
	if (pa_get_devicelist(pa_output_devicelist) < 0) {
		return smprintf("ERR");
	}

	for (ctr = 0; ctr < 16; ctr++) {
		if (! pa_output_devicelist[ctr].initialized) {
			continue;
		}
		if ( pa_output_devicelist[ctr].mute )
		{
			char * tmp_res = result ;
			result = smprintf("%s mute", tmp_res) ;
			free(tmp_res);
		}
		else
		{
			char * tmp_res = result;
			result = smprintf("%s %d%%", tmp_res, (pa_cvolume_avg(&pa_output_devicelist[ctr].volume)*100)/PA_VOLUME_NORM);
			free(tmp_res);
		}
	}
	return result;
}
예제 #5
0
gint
xvd_get_readable_volume (const pa_cvolume *vol)
{
  guint new_vol = 0;

  new_vol = 100 * pa_cvolume_avg (vol) / PA_VOLUME_NORM;
  return MIN (new_vol, 100);
}
예제 #6
0
void PulseOutput::sink_info_callback(pa_context*, const pa_sink_input_info * info,int /*eol*/,void*userdata){
  PulseOutput * out = static_cast<PulseOutput*>(userdata);
  if (info) {
    pa_volume_t value = pa_cvolume_avg(&info->volume);
    if (out->pulsevolume!=value) {
      out->context->notify_volume((float)value / (float)PA_VOLUME_NORM);
      }
    }
  }
예제 #7
0
파일: pavol.c 프로젝트: lotrfan/pavolume
void pulse_get_default_sink_volume_cb(pa_context UNUSED *c, const pa_sink_info *i, int eol, void *raw) {
    if (eol)
        return;

    struct pulseaudio_t *pulse = (struct pulseaudio_t*)raw;

    pulse->muted = i->mute;
    pulse->cvolume = i->volume;
    pulse->volume = pa_cvolume_avg(&(i->volume));
}
예제 #8
0
static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
    struct userdata *u = PA_SOURCE(o)->userdata;
    int err;
    audio_info_t info;

    switch (code) {
        case PA_SOURCE_MESSAGE_GET_LATENCY: {
            pa_usec_t r = 0;

            if (u->fd) {
                err = ioctl(u->fd, AUDIO_GETINFO, &info);
                pa_assert(err >= 0);

                r += pa_bytes_to_usec(info.record.samples * u->frame_size, &PA_SOURCE(o)->sample_spec);
                r -= pa_bytes_to_usec(u->read_bytes, &PA_SOURCE(o)->sample_spec);
            }

            *((pa_usec_t*) data) = r;

            return 0;
        }

        case PA_SOURCE_MESSAGE_SET_VOLUME:
            if (u->fd >= 0) {
                AUDIO_INITINFO(&info);

                info.record.gain = pa_cvolume_avg((pa_cvolume*) data) * AUDIO_MAX_GAIN / PA_VOLUME_NORM;
                assert(info.record.gain <= AUDIO_MAX_GAIN);

                if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) {
                    if (errno == EINVAL)
                        pa_log("AUDIO_SETINFO: Unsupported volume.");
                    else
                        pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno));
                } else {
                    return 0;
                }
            }
            break;

        case PA_SOURCE_MESSAGE_GET_VOLUME:
            if (u->fd >= 0) {
                err = ioctl(u->fd, AUDIO_GETINFO, &info);
                pa_assert(err >= 0);

                pa_cvolume_set((pa_cvolume*) data, ((pa_cvolume*) data)->channels,
                    info.record.gain * PA_VOLUME_NORM / AUDIO_MAX_GAIN);

                return 0;
            }
            break;
    }

    return pa_source_process_msg(o, code, data, offset, chunk);
}
예제 #9
0
파일: pulsestream.cpp 프로젝트: KDE/phonon
void PulseStream::setVolume(const pa_cvolume *volume)
{
    if (mCachedVolume != -1)
        QMetaObject::invokeMethod(this, "applyCachedVolume", Qt::QueuedConnection);
    if (pa_cvolume_equal(&mVolume, volume) == 0) {
        memcpy(&mVolume, volume, sizeof(mVolume));
        qreal vol = (qreal)pa_cvolume_avg(volume) / PA_VOLUME_NORM;
        // AudioOutput expects the "backend" to supply values that have been
        // adjusted for Stephens' law, so we need to fudge them accordingly
        // so that the %ages match up in KMix/the application's own slider.
        emit volumeChanged(qPow(vol, VOLTAGE_TO_LOUDNESS_EXPONENT));
    }
}
예제 #10
0
pa_cvolume *pa_cvolume_remap(pa_cvolume *v, const pa_channel_map *from, const pa_channel_map *to) {
    int a, b;
    pa_cvolume result;

    pa_assert(v);
    pa_assert(from);
    pa_assert(to);

    pa_return_val_if_fail(pa_channel_map_valid(to), NULL);
    pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, from), NULL);

    if (pa_channel_map_equal(from, to))
        return v;

    result.channels = to->channels;

    for (b = 0; b < to->channels; b++) {
        pa_volume_t k = 0;
        int n = 0;

        for (a = 0; a < from->channels; a++)
            if (from->map[a] == to->map[b]) {
                k += v->values[a];
                n ++;
            }

        if (n <= 0) {
            for (a = 0; a < from->channels; a++)
                if ((on_left(from->map[a]) && on_left(to->map[b])) ||
                    (on_right(from->map[a]) && on_right(to->map[b])) ||
                    (on_center(from->map[a]) && on_center(to->map[b])) ||
                    (on_lfe(from->map[a]) && on_lfe(to->map[b]))) {

                    k += v->values[a];
                    n ++;
                }
        }

        if (n <= 0)
            k = pa_cvolume_avg(v);
        else
            k /= n;

        result.values[b] = k;
    }

    *v = result;
    return v;
}
static int control(int cmd, void *arg) {
    switch (cmd) {
        case AOCONTROL_GET_VOLUME: {
            ao_control_vol_t *vol = arg;
            uint32_t devidx = pa_stream_get_index(stream);
            pa_threaded_mainloop_lock(mainloop);
            if (!waitop(pa_context_get_sink_input_info(context, devidx, info_func, NULL))) {
                GENERIC_ERR_MSG(context, "pa_stream_get_sink_input_info() failed");
                return CONTROL_ERROR;
            }

            if (volume.channels != 2)
                vol->left = vol->right = pa_cvolume_avg(&volume)*100/PA_VOLUME_NORM;
            else {
                vol->left = volume.values[0]*100/PA_VOLUME_NORM;
                vol->right = volume.values[1]*100/PA_VOLUME_NORM;
            }

            return CONTROL_OK;
        }

        case AOCONTROL_SET_VOLUME: {
            const ao_control_vol_t *vol = arg;
            pa_operation *o;

            if (volume.channels != 2)
                pa_cvolume_set(&volume, volume.channels, (pa_volume_t)vol->left*PA_VOLUME_NORM/100);
            else {
                volume.values[0] = (pa_volume_t)vol->left*PA_VOLUME_NORM/100;
                volume.values[1] = (pa_volume_t)vol->right*PA_VOLUME_NORM/100;
            }

            pa_threaded_mainloop_lock(mainloop);
            o = pa_context_set_sink_input_volume(context, pa_stream_get_index(stream), &volume, NULL, NULL);
            if (!o) {
                pa_threaded_mainloop_unlock(mainloop);
                GENERIC_ERR_MSG(context, "pa_context_set_sink_input_volume() failed");
                return CONTROL_ERROR;
            }
            /* We don't wait for completion here */
            pa_operation_unref(o);
            pa_threaded_mainloop_unlock(mainloop);
            return CONTROL_OK;
        }

        default:
            return CONTROL_UNKNOWN;
    }
}
예제 #12
0
/**
 * @brief Callback function called when the information on the
 *        context's sink is retrieved.
 * @param ctx Context which operation has succeeded
 * @param info Structure containing the sink's information
 * @param this_gen pulse_driver_t pointer for the PulseAudio output
 *        instance.
 *
 * This function saves the volume field of the passed structure to the
 * @c cvolume variable of the output instance and send an update volume
 * event to the frontend.
 */
static void __xine_pa_sink_info_callback(pa_context *c, const pa_sink_input_info *info,
                                         int is_last, void *userdata) {

  pulse_driver_t *const this = (pulse_driver_t *) userdata;

  if (is_last < 0) {
    xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: Failed to get sink input info: %s\n",
             pa_strerror(pa_context_errno(this->context)));
    return;
  }

  if (!info)
      return;

  this->cvolume = info->volume;
  this->swvolume = pa_cvolume_avg(&info->volume);
#if PA_PROTOCOL_VERSION >= 11
  /* PulseAudio 0.9.7 and newer */
  this->muted = info->mute;
#else
  this->muted = pa_cvolume_is_muted (&this->cvolume);
#endif

  /* send update volume event to frontend */

  xine_event_t              event;
  xine_audio_level_data_t   data;
  xine_stream_t            *stream;
  xine_list_iterator_t      ite;

  data.right        = data.left = (int) (pa_sw_volume_to_linear(this->swvolume)*100);

  data.mute         = this->muted;

  event.type        = XINE_EVENT_AUDIO_LEVEL;
  event.data        = &data;
  event.data_length = sizeof(data);

  pthread_mutex_lock(&this->xine->streams_lock);
  for(ite = xine_list_front(this->xine->streams); ite; ite =
    xine_list_next(this->xine->streams, ite)) {
    stream = xine_list_get_value(this->xine->streams, ite);
    event.stream = stream;
    xine_event_send(stream, &event);
  }
  pthread_mutex_unlock(&this->xine->streams_lock);
}
예제 #13
0
static void pulse_get_volume (int * l, int * r)
{
    * l = * r = 0;

    if (! connected || ! volume_valid)
        return;

    pa_threaded_mainloop_lock (mainloop);
    CHECK_DEAD_GOTO (fail, 1);

    if (volume.channels == 2)
    {
        * l = (volume.values[0] * 100 + PA_VOLUME_NORM / 2) / PA_VOLUME_NORM;
        * r = (volume.values[1] * 100 + PA_VOLUME_NORM / 2) / PA_VOLUME_NORM;
    }
    else
        * l = * r = (pa_cvolume_avg (& volume) * 100 + PA_VOLUME_NORM / 2) /
         PA_VOLUME_NORM;

fail:
    pa_threaded_mainloop_unlock (mainloop);
}
예제 #14
0
void CAESinkPULSE::SetVolume(float volume)
{
  if (m_IsAllocated && !m_passthrough)
  {
    pa_threaded_mainloop_lock(m_MainLoop);
    // clamp possibly too large / low values
    float per_cent_volume = std::max(0.0f, std::min(volume, 1.0f));
    
    if (m_volume_needs_update)
    {
       m_volume_needs_update = false;
       pa_volume_t n_vol = pa_cvolume_avg(&m_Volume); 
       n_vol = std::min(n_vol, PA_VOLUME_NORM);
       per_cent_volume = (float) n_vol / PA_VOLUME_NORM; 
       // only update internal volume
       pa_threaded_mainloop_unlock(m_MainLoop);
       g_application.SetVolume(per_cent_volume, false);
       return;
    }
    
    pa_volume_t pavolume = per_cent_volume * PA_VOLUME_NORM;
    unsigned int sink_input_idx = pa_stream_get_index(m_Stream);
    
    if ( pavolume <= 0 )
      pa_cvolume_mute(&m_Volume, m_Channels);
    else
      pa_cvolume_set(&m_Volume, m_Channels, pavolume);
        
      pa_operation *op = pa_context_set_sink_input_volume(m_Context, sink_input_idx, &m_Volume, NULL, NULL);
      if (op == NULL)
        CLog::Log(LOGERROR, "PulseAudio: Failed to set volume");
      else
        pa_operation_unref(op);

    pa_threaded_mainloop_unlock(m_MainLoop);
  }
}
예제 #15
0
파일: ui.c 프로젝트: KoviRobi/pasystray
void ui_update_statusicon(menu_info_item_t* mii)
{
#ifdef DEBUG
    g_message("pulseaudio_update_status_icon(%s)", mii->name);
#endif

    pa_volume_t volume = pa_cvolume_avg(mii->volume);

    g_message("volume:%u%s", volume, mii->mute ? " muted" : "");

    const char* icon_name = NULL;

    if(volume == PA_VOLUME_MUTED || mii->mute)
        icon_name = "stock_volume-mute";
    else if(volume < (PA_VOLUME_NORM / 3))
        icon_name = "stock_volume-min";
    else if(volume < (PA_VOLUME_NORM / 3 * 2))
        icon_name = "stock_volume-med";
    else
        icon_name = "stock_volume-max";

    menu_infos_t* mis = mii->menu_info->menu_infos;
    gtk_status_icon_set_from_icon_name(mis->icon, icon_name);
}
예제 #16
0
static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
    struct userdata *u = PA_SINK(o)->userdata;
    int err;
    audio_info_t info;

    switch (code) {
    case PA_SINK_MESSAGE_GET_LATENCY: {
        pa_usec_t r = 0;

        if (u->fd >= 0) {

            err = ioctl(u->fd, AUDIO_GETINFO, &info);
            pa_assert(err >= 0);

            r += pa_bytes_to_usec(u->written_bytes, &PA_SINK(o)->sample_spec);
            r -= pa_bytes_to_usec(info.play.samples * u->frame_size, &PA_SINK(o)->sample_spec);

            if (u->memchunk.memblock)
                r += pa_bytes_to_usec(u->memchunk.length, &PA_SINK(o)->sample_spec);
        }

        *((pa_usec_t*) data) = r;

        return 0;
    }

    case PA_SINK_MESSAGE_SET_VOLUME:
        if (u->fd >= 0) {
            AUDIO_INITINFO(&info);

            info.play.gain = pa_cvolume_avg((pa_cvolume*)data) * AUDIO_MAX_GAIN / PA_VOLUME_NORM;
            assert(info.play.gain <= AUDIO_MAX_GAIN);

            if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) {
                if (errno == EINVAL)
                    pa_log("AUDIO_SETINFO: Unsupported volume.");
                else
                    pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno));
            } else {
                return 0;
            }
        }
        break;

    case PA_SINK_MESSAGE_GET_VOLUME:
        if (u->fd >= 0) {
            err = ioctl(u->fd, AUDIO_GETINFO, &info);
            assert(err >= 0);

            pa_cvolume_set((pa_cvolume*) data, ((pa_cvolume*) data)->channels,
                info.play.gain * PA_VOLUME_NORM / AUDIO_MAX_GAIN);

            return 0;
        }
        break;

    case PA_SINK_MESSAGE_SET_MUTE:
        if (u->fd >= 0) {
            AUDIO_INITINFO(&info);

            info.output_muted = !!PA_PTR_TO_UINT(data);

            if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0)
                pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno));
            else
                return 0;
        }
        break;

    case PA_SINK_MESSAGE_GET_MUTE:
        if (u->fd >= 0) {
            err = ioctl(u->fd, AUDIO_GETINFO, &info);
            pa_assert(err >= 0);

            *(int*)data = !!info.output_muted;

            return 0;
        }
        break;
    }

    return pa_sink_process_msg(o, code, data, offset, chunk);
}
예제 #17
0
static int control(struct ao *ao, enum aocontrol cmd, void *arg)
{
    struct priv *priv = ao->priv;
    switch (cmd) {
    case AOCONTROL_GET_MUTE:
    case AOCONTROL_GET_VOLUME: {
        uint32_t devidx = pa_stream_get_index(priv->stream);
        pa_threaded_mainloop_lock(priv->mainloop);
        if (!waitop(priv, pa_context_get_sink_input_info(priv->context, devidx,
                                                         info_func, ao))) {
            GENERIC_ERR_MSG(priv->context,
                            "pa_stream_get_sink_input_info() failed");
            return CONTROL_ERROR;
        }
        // Warning: some information in pi might be unaccessible, because
        // we naively copied the struct, without updating pointers etc.
        // Pointers might point to invalid data, accessors might fail.
        if (cmd == AOCONTROL_GET_VOLUME) {
            ao_control_vol_t *vol = arg;
            if (priv->pi.volume.channels != 2)
                vol->left = vol->right =
                    pa_cvolume_avg(&priv->pi.volume) * 100 / PA_VOLUME_NORM;
            else {
                vol->left = priv->pi.volume.values[0] * 100 / PA_VOLUME_NORM;
                vol->right = priv->pi.volume.values[1] * 100 / PA_VOLUME_NORM;
            }
        } else if (cmd == AOCONTROL_GET_MUTE) {
            bool *mute = arg;
            *mute = priv->pi.mute;
        }
        return CONTROL_OK;
    }

    case AOCONTROL_SET_MUTE:
    case AOCONTROL_SET_VOLUME: {
        pa_operation *o;

        pa_threaded_mainloop_lock(priv->mainloop);
        uint32_t stream_index = pa_stream_get_index(priv->stream);
        if (cmd == AOCONTROL_SET_VOLUME) {
            const ao_control_vol_t *vol = arg;
            struct pa_cvolume volume;

            pa_cvolume_reset(&volume, ao->channels);
            if (volume.channels != 2)
                pa_cvolume_set(&volume, volume.channels,
                               vol->left * PA_VOLUME_NORM / 100);
            else {
                volume.values[0] = vol->left * PA_VOLUME_NORM / 100;
                volume.values[1] = vol->right * PA_VOLUME_NORM / 100;
            }
            o = pa_context_set_sink_input_volume(priv->context, stream_index,
                                                 &volume, NULL, NULL);
            if (!o) {
                pa_threaded_mainloop_unlock(priv->mainloop);
                GENERIC_ERR_MSG(priv->context,
                                "pa_context_set_sink_input_volume() failed");
                return CONTROL_ERROR;
            }
        } else if (cmd == AOCONTROL_SET_MUTE) {
            const bool *mute = arg;
            o = pa_context_set_sink_input_mute(priv->context, stream_index,
                                               *mute, NULL, NULL);
            if (!o) {
                pa_threaded_mainloop_unlock(priv->mainloop);
                GENERIC_ERR_MSG(priv->context,
                                "pa_context_set_sink_input_mute() failed");
                return CONTROL_ERROR;
            }
        } else
            abort();
        /* We don't wait for completion here */
        pa_operation_unref(o);
        pa_threaded_mainloop_unlock(priv->mainloop);
        return CONTROL_OK;
    }
    default:
        return CONTROL_UNKNOWN;
    }
}