3

ALSAライブラリを使用しようとしたときに、Cコードの奇妙な動作が発生しました。このコードを使用して、デバイスのsidを生成しました

snd_mixer_selem_id_t*
getSid(){
  snd_mixer_selem_id_t *sid;
  snd_mixer_selem_id_alloca(&sid);
  snd_mixer_selem_id_set_index(sid,0);
  snd_mixer_selem_id_set_name(sid, selem_name);

  return sid;
}

次に、この機能にアクセスしようとしました

snd_mixer_t *handle = getHandle();
snd_mixer_selem_id_t *sid = getSid();

snd_mixer_elem_t *elem = snd_mixer_find_selem(handle,sid);

getHandle()カードハンドラーを取得するための同等の関数ですが、これは機能しています。奇妙なことに、関数を使用する直前に関数のコードを使用すると、snd_mixer_find_selem関数が機能します。私はCに不慣れであり、これは私の最初のプロジェクトの1つであると言わざるを得ないので、それはポインターの初心者の間違いである可能性があります。

エラーメッセージはsimple.c:282: snd_mixer_selem_get_playback_volume_range: Assertion 'elem' failed.

それで、誰かが問題が何であるか知っていますか?

これが私が使用するコードの最小限の例です:

#include <alsa/asoundlib.h>

static const char *selem_name = "Master";
static const char *card = "default";

snd_mixer_t*
getHandle(){
  snd_mixer_t *handle;

  snd_mixer_open(&handle, 0);
  snd_mixer_attach(handle, card);
  snd_mixer_selem_register(handle, NULL, NULL);
  snd_mixer_load(handle);

  return handle;
}

snd_mixer_selem_id_t*
getSid(){
  snd_mixer_selem_id_t *sid;
  snd_mixer_selem_id_alloca(&sid);
  snd_mixer_selem_id_set_index(sid,0);
  snd_mixer_selem_id_set_name(sid, selem_name);

  return sid;
}

void
incMasterVol(long step){ // Step is a value in [-100,100]
  long min,max,curr;

  snd_mixer_t *handle = getHandle();

/*snd_mixer_open(&handle, 0);
  snd_mixer_attach(handle, card);
  snd_mixer_selem_register(handle, NULL, NULL);
  snd_mixer_load(handle);*/

  snd_mixer_selem_id_t *sid;
  snd_mixer_selem_id_alloca(&sid);
  snd_mixer_selem_id_set_index(sid,0);
  snd_mixer_selem_id_set_name(sid, selem_name);

  snd_mixer_elem_t *elem = snd_mixer_find_selem(handle,sid);

  snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
  snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_SIDE_LEFT, &curr);
  curr = curr * 100/max;
  if(curr + step > 100)
    curr = 100;
  else if(curr + step < 0)
    curr = 0;
  else
    curr += step;
  snd_mixer_selem_set_playback_volume_all(elem, curr * max / 100);

  snd_mixer_close(handle);
}

void
toggleMasterVol(){
 int swiVal;
 snd_mixer_t *handle = getHandle();
 snd_mixer_elem_t *elem = snd_mixer_find_selem(handle,getSid());

 snd_mixer_selem_get_playback_switch(elem, SND_MIXER_SCHN_SIDE_LEFT, &swiVal);
 snd_mixer_selem_set_playback_switch_all(elem, !swiVal);

 snd_mixer_close(handle);
}

int
main(int argc, char *argv[]){
  incMasterVol(5);
}
4

2 に答える 2

6

alloca()syscallに由来すると思います

allocaスタックフレームに割り当てるのでgetSid()、割り当てられた変数が返されると解放され、ポインタがぶら下がってしまいます...(メイン関数に配置するとalloca、メインのアクティベーションレコードにスペースが割り当てられるため機能します)

これは単なる提案ですが、使用する必要があると思いますmalloc(ヒープにスペースを割り当てるため、呼び出すまで動的メモリが割り当てられますfree()

snd_mixer_selem_id_malloc()代わりに試してみてください:)

于 2013-03-01T13:16:40.083 に答える