如何在默认声卡的主通道上收听音量变化?我希望通过dbus或回调或音量已更改的内容收到通知。
我已经尝试过查看ALSA和PulseAudio API,它们似乎只允许您设置和获取音量,但不能监听以查看音量的变化。
任何编程语言都可以。
答案 0 :(得分:6)
使用ALSA API可以实现这一点。
如果您有控制设备,请致电snd_ctl_subscribe_events()
以启用事件。
然后使用snd_ctl_read()
来读取事件;要等待它们,请使用阻止模式或poll()
。
如果事件的类型为SND_CTL_EVENT_ELEM
,并且其事件位掩码包含SND_CTL_EVENT_MASK_VALUE
,则该元素的值已更改。
有关示例,请参阅the implementation of amixer monitor
。
答案 1 :(得分:2)
修改:在第二个示例中,当音量低于5%或高于100%时,不会为我生成事件。就我所知,第一个例子完美无缺。
pactl subscribe
会在音量变化时打印出有关接收器的数据。我现在正在做的是将输出传递给一个运行脚本的小型C程序。
run.sh:
pactl subscribe | grep --line-buffered "sink" | ./prog
或特定的水槽,例如3:
pactl subscribe | grep --line-buffered "sink #3" | ./prog
prog.c中:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[]){
while(1){
while(getchar() != '\n');
system("./volume_notify.sh");
}
}
当接收器的音量改变时,pactl
将打印一行,这将导致程序运行该脚本。
-OR -
这是一个基于amixer monitor的示例,由CL引用。 while循环将在每次音量改变时进行迭代,因此将回调放在那里。
#include <stdio.h>
#include <alsa/asoundlib.h>
#define MAX_CARDS 256
int monitor_native(char const *name);
int open_ctl(const char *name, snd_ctl_t **ctlp);
void close_all(snd_ctl_t* ctls[], int ncards);
int main(int argc, char* argv[]){
const char *ctl_name = "hw:0";
while(monitor_native(ctl_name) == 1){
//volume has been changed, do something
system("~/.volume_notify.sh");
}
return 0;
}
int monitor_native(char const *name) {
snd_ctl_t *ctls[MAX_CARDS];
int ncards = 0;
int i, err = 0;
if (!name) {
int card = -1;
while (snd_card_next(&card) >= 0 && card >= 0) {
char cardname[16];
if (ncards >= MAX_CARDS) {
fprintf(stderr, "alsactl: too many cards\n");
close_all(ctls, ncards);
return -E2BIG;
}
sprintf(cardname, "hw:%d", card);
err = open_ctl(cardname, &ctls[ncards]);
if (err < 0) {
close_all(ctls, ncards);
return err;
}
ncards++;
}
} else {
err = open_ctl(name, &ctls[0]);
if (err < 0) {
close_all(ctls, ncards);
return err;
}
ncards++;
}
for (;ncards > 0;) {
pollfd* fds = new pollfd[ncards];
for (i = 0; i < ncards; i++) {
snd_ctl_poll_descriptors(ctls[i], &fds[i], 1);
}
err = poll(fds, ncards, -1);
if (err <= 0) {
err = 0;
break;
}
for (i = 0; i < ncards; i++) {
unsigned short revents;
snd_ctl_poll_descriptors_revents(ctls[i], &fds[i], 1, &revents);
if (revents & POLLIN) {
snd_ctl_event_t *event;
snd_ctl_event_alloca(&event);
if (snd_ctl_read(ctls[i], event) < 0) {
continue;
}
if (snd_ctl_event_get_type(event) != SND_CTL_EVENT_ELEM) {
continue;
}
unsigned int mask = snd_ctl_event_elem_get_mask(event);
if (mask & SND_CTL_EVENT_MASK_VALUE) {
close_all(ctls, ncards);
return 1;
}
}
}
}
close_all(ctls, ncards);
return 0;
}
int open_ctl(const char *name, snd_ctl_t **ctlp) {
snd_ctl_t *ctl;
int err;
err = snd_ctl_open(&ctl, name, SND_CTL_READONLY);
if (err < 0) {
fprintf(stderr, "Cannot open ctl %s\n", name);
return err;
}
err = snd_ctl_subscribe_events(ctl, 1);
if (err < 0) {
fprintf(stderr, "Cannot open subscribe events to ctl %s\n", name);
snd_ctl_close(ctl);
return err;
}
*ctlp = ctl;
return 0;
}
void close_all(snd_ctl_t* ctls[], int ncards) {
for (ncards -= 1; ncards >= 0; --ncards) {
snd_ctl_close(ctls[ncards]);
}
}
答案 2 :(得分:2)
类似于@ sealj553的答案,但不需要C程序:
org.springframework.dao.DataAccessResourceFailureException: Operation on server 127.0.0.1:27017 failed; nested exception is com.mongodb.MongoException$Network: Operation on server 127.0.0.1:27017 failed
at org.springframework.data.mongodb.core.MongoExceptionTranslator.translateExceptionIfPossible(MongoExceptionTranslator.java:59)
at org.springframework.data.mongodb.core.MongoTemplate.potentiallyConvertRuntimeException(MongoTemplate.java:1920)
at org.springframework.data.mongodb.core.MongoTemplate.execute(MongoTemplate.java:412)
...
Caused by: com.mongodb.MongoException$Network: Operation on server 127.0.0.1:27017 failed
at com.mongodb.DBTCPConnector.doOperation(DBTCPConnector.java:214)
at com.mongodb.DBCollectionImpl.writeWithCommandProtocol(DBCollectionImpl.java:424)
at com.mongodb.DBCollectionImpl.removeWithCommandProtocol(DBCollectionImpl.java:409)
at com.mongodb.DBCollectionImpl.remove(DBCollectionImpl.java:223)
at com.mongodb.DBCollectionImpl.remove(DBCollectionImpl.java:203)
at com.mongodb.DBCollection.remove(DBCollection.java:274)
at org.springframework.data.mongodb.core.MongoTemplate$12.doInCollection(MongoTemplate.java:1194)
at org.springframework.data.mongodb.core.MongoTemplate$12.doInCollection(MongoTemplate.java:1178)
at org.springframework.data.mongodb.core.MongoTemplate.execute(MongoTemplate.java:410)
... 8 more
Caused by: java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:170)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:286)
at java.io.BufferedInputStream.read(BufferedInputStream.java:345)
at org.bson.io.Bits.readFully(Bits.java:48)
at org.bson.io.Bits.readFully(Bits.java:35)
at org.bson.io.Bits.readFully(Bits.java:30)
at com.mongodb.Response.<init>(Response.java:42)
at com.mongodb.DBCollectionImpl.receiveWriteCommandMessage(DBCollectionImpl.java:495)
at com.mongodb.DBCollectionImpl.access$300(DBCollectionImpl.java:48)
at com.mongodb.DBCollectionImpl$2.execute(DBCollectionImpl.java:437)
at com.mongodb.DBCollectionImpl$2.execute(DBCollectionImpl.java:424)
at com.mongodb.DBPort.doOperation(DBPort.java:164)
at com.mongodb.DBTCPConnector.doOperation(DBTCPConnector.java:207)
... 16 more