11

I have written a small 'daemon' in bash that will switch to the headphones if they are detected, and if not, switch to an external USB speaker with PulseAudio.

What I'm looking for is some way to get notification of changes on the file /proc/asound/card0/codec#0, just like inotifywait does on real files (considering files under /proc to be as "pseudo-files").

I find my code a bit insane, because it runs sleep 1 with awk for the whole day, that is 86400 times a day :)

while sleep 1; do
    _1=${_2:-}
    _2=$(awk '/Pin-ctls/{n++;if(n==4)print}' '/proc/asound/card0/codec#0')

    [[ ${_1:-} = $_2 ]] ||
        if [[ $_2 =~ OUT ]]; then
            use_speakers
        else
            use_internal
        fi
done

What I'm looking for is something like (this example doesn't work):

codec=/proc/asound/card0/codec#0
while inotifywait $codec; do
    if [[ $(awk '/Pin-ctls/{n++;if(n==4)print}' $codec) =~ OUT ]]; then
        use_speakers
    else
        use_internal
    fi
done

This way the commands inside the loop would be run only when there are real changes on the $codec file.

  • 1
    It's not insane -- things like top and GUI system monitors read a whole lot more than that from /proc at short intervals. Of course, they probably do it much more efficiently as compiled executables, but the point is: polling for information is a common task. – goldilocks Sep 14 '13 at 12:54
  • 2
    Since the underlying problem is not unique to you, I would expect there to be some ready-made solution (at least for some hardware) - have a look at unix.stackexchange.com/questions/25776/… and superuser.com/questions/339900/…. The ultimate source is of course the kernel tree (and hardware specs if you decide to implement it into some driver). – peterph Sep 14 '13 at 14:42
  • 1
    If this shows up in /proc, you can probably trigger your script with a udev rule, which would be pretty ideal. Less ideal is how tedious it can be coming up with udev rules ;) – goldilocks Sep 14 '13 at 16:31
  • @peterph From what I could gather, hda-verb provides an interface for setting or checking parameters, but it looks like I'll have to run it every second as well. – Teresa e Junior Sep 14 '13 at 16:55
  • @goldilocks Plugging the headphones doesn't send any udev-event. Or is there something more I am missing? – Teresa e Junior Sep 14 '13 at 17:02
10

What I'm looking for is some way to get notification of changes on the file [in proc]

You can't, because they aren't files. This is not quite a duplicate question, but the answer here explains why.

/proc is a kernel interface. There are no real files there, hence they can't change. Reading from the handles is a request and the data in the file when you read it is a reply to that.

The only way you could simulate something like this would be to read the file at intervals and compare the content to see if the reply from the kernel has changed -- looks like you've already done that.

If you stat procfs files, the atime and the mtime will be the same: for some files it is whenever the stat call was, for others a time from during system boot. In the first case, it will always seem to have changed, in the second, it will never seem to have changed.

  • Unfortunately, even polling it every second adds a considerable latency (eg. 500ms). I hoped there would be a faster/more efficient way of doing this, but since you've mentioned that apps like top do it the same way, I think I'll leave it that way. – Teresa e Junior Sep 14 '13 at 13:38
  • @TeresaeJunior If the latency is an issue (I think it isn't here), e.g., because the duration of the poll is used in a calculation, you would time the actual duration (and not just use the time you asked to sleep). That seems like a lot though; I've never profiled bash scripts so I don't know what would be normal here (hmm...good separate question). Invoking awk == fork() and stuff like that is expensive; utilities written all in C would, as mentioned, have faster methods. I still don't think you are adding much load to the system overall tho. – goldilocks Sep 14 '13 at 13:53
  • 1
    No, sorry, I actually meant: from the time I plug the headphones until the next sleep there is some noticeable delay. But I don't plan on decreasing the sleep time. Thanks for your help! – Teresa e Junior Sep 14 '13 at 16:19
4

If you are using PulseAudio, pactl subscribe does this.

  • Yes, indeed! I started using it after compiling PA 4.0 some months ago due to some audio problems. The version on Debian Stable is 2.0 (although they have uploaded 4.0 to backports recently), and there was no subscribe on 2.0. – Teresa e Junior Apr 26 '14 at 18:14
2

Also take in mind that some files under /proc/ permit to be monitored for changes via polling, for example if you do man proc you can read the following about /proc/self/mounts file:

/proc/[pid]/mounts (since Linux 2.4.19) This file lists all the filesystems currently mounted in the process's mount namespace (see mount_namespaces(7)). The format of this file is documented in fstab(5).

Since kernel version 2.6.15, this file is pollable: after opening the file for reading, a change in this file (i.e., a filesystem mount or unmount) causes select(2) to mark the file descriptor as having an exceptional condition, and poll(2) and epoll_wait(2) mark the file as having a priority event (POLLPRI). (Before Linux 2.6.30, a change in this file was indicated by the file descriptor being marked as readable for select(2), and being marked as having an error condition for poll(2) and epoll_wait(2).)

And that is exactly what is being implemented in the following question:

https://stackoverflow.com/questions/5070801/monitoring-mount-point-changes-via-proc-mounts

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.