Take the 2-minute tour ×
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free, no registration required.

What I want is the following:

  • When I plug in my headphones, I want the sound to be un-muted and set to a specific volume level.
  • When I unplug my headphones, I want the sound to be muted (or set to a specific volume level).

Setting the volume levels isn't the problem, but I somehow need to do this when un-/plugging the headphones, so I'm looking for a way to get notified of those events.

I quickly found /proc/asound/card0/codec#0 to indicate whether headphones are plugged in or not, so I tried to monitor it using inotifywait and change the volume level based on modified notifications. Unfortunately inotifywait failed because proc isn't an ordinary filesystem.

Are there other ways to do this (maybe via PulseAudio)?

Audio device: Intel HDA, audio codec: Conexant CX20585.


To summarize what I've tried so far:

  • Ear Candy: didn't run at all on my system. Seems to be an abandoned project?
  • The code posted by Karl Bielefeldt might work on some hardware, it doesn't on mine.
  • The idea from StephenPaulger fails due to the lack of a 'Speaker' channel.
  • Motivated by aking1012 I made it work by hacking around in the kernel code (after finding the jack sensing code of the codec), but that's a rather cumbersome solution.

So, I'm still looking for an easy way to do this.

share|improve this question
    
Excellent question, I want to do this too! –  StephenPaulger Feb 3 '11 at 17:32
    
nice...but i think a patch to alsa will be necessary for the desired "instant" response on plug/unplug. otherwise it would work or seem to work, but under load or other conditions, the response could lag. think you have to get in between the plug event and the output toggle. probably possible, but sooooo not worth an individual patch basis unless an alsa dev says it will be committed to trunk. –  hbdgaf Feb 6 '11 at 5:37
    
one approach would be to load the module up in gdb, wait for the "normal" sound events to stop, use the record option, plug and unplug the head phones, and see what happened in the debug recording. –  hbdgaf Feb 8 '11 at 17:38
    
how much delay are you comfortable with? –  hbdgaf Feb 8 '11 at 23:30

8 Answers 8

I think you might achieve what you need using this: https://bbs.archlinux.org/viewtopic.php?pid=1105458#p1105458

share|improve this answer
    
Welcome to Ask Ubuntu! Whilst this may theoretically answer the question, it would be preferable to include the essential parts of the answer here, and provide the link for reference. –  Kevin Bowen Jun 5 '13 at 1:53
up vote 3 down vote accepted

During the UDS for Oneiric there has been a session about jack detection. See the blueprint for details. It sounds like this will exactly do what I'm looking for: different volume levels for different devices - just not on every hardware:

<htorque> something i'm curious about: will i be able to have different volume levels for different devices (eg., internal sound muted, headphones 75%) anytime soon?

<coling> this will be supported (on some h/w) yes. Timescales are "soonish" :p
<coling> (I'd also expect OSD to be shown (with current volume) when jacks are plugged/unplugged)

Update for 11.10

This should now be working in Oneiric - unfortunately my ThinkPad T510 seems to be one of the systems that's currently not supported.

Another follow-up from David Henningsson:

Long story short, it’s a desirable feature, and we’re moving in that direction, but slowly, as the feature is more complex than it seems like at first glance.

The good news: in the upcoming Ubuntu Oneiric (11.10), this is actually working. The bad news: it isn’t working for everyone.

More here.

Update for 12.04

It's now working with my ThinkPad T510 (and many other models) in Ubuntu 12.04 (development version).

share|improve this answer
    
Is there anything tracking which hardware is currently supported, or something to that effect? –  Mu Mind Oct 5 '12 at 23:15

Pulseaudio has a module shipped by default that is designed to achieve exactly this:

http://pulseaudio.org/wiki/Modules#module-device-restore

share|improve this answer
    
I don't see how this module is supposed to help me. –  htorque Feb 10 '11 at 10:45

If you do

amixer sset 'Speaker' playback 0%

the speaker volume will be muted but headphones will carry on working. Unplugging the headphones means no sound. Which is almost what you want...

However...

If you alter the volume control the 'Speaker' volume setting will be set up again. This is because pulseaudio tries to be clever with setting volumes (See http://pulseaudio.org/wiki/PulseAudioStoleMyVolumes for more information). We can stop it from messing with the volumes though.

Open /etc/pulse/default.pa

and find the line

load-module module-udev-detect

and change it to

load-module module-udev-detect ignore_dB=1

Restart pulseaudio.

killall pulseaudio

Now if you mute the speaker volume changing the master volume will not affect it. So headphones will work but the speaker will remain silent.

share|improve this answer
    
Would be a different approach, but unfortunately I don't have a Speaker volume channel, only Master and PCM. –  htorque Feb 8 '11 at 18:59

I don't know how much coding experience you have, but you mentioned inotifywait so I'm going to assume you're at least comfortable with shell scripting. The following C program, based on this article, should be able to detect your headphones being plugged or unplugged, after which you can perform whatever actions you want.

#include <linux/input.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>

int main(int argc, char* argv[])
{
    int fd = -1;
    char name[256]= "Unknown";
    struct input_event event;

    if ((fd = open(argv[1], O_RDONLY)) < 0) {
        perror("evdev open");
        exit(1);
    }

    if(ioctl(fd, EVIOCGNAME(sizeof(name)), name) < 0) {
        perror("evdev ioctl");
    }

    printf("The device on %s says its name is %s\n",
            argv[1], name);

    read(fd, &event, sizeof(struct input_event));
    printf("Event type is %d\n", event.type);
    printf("Event code is %d\n", event.code);
    printf("Event value is %d\n", event.value);

    close(fd);
    return 0;
}

The program takes one argument, which should be a path to the input event device for your headphones. This is /dev/input/event7 for me, but you may have to try a few to find which it is on your system. You will need read permissions on that device. The program will print the name of the device, and the type, code, and value of the first event before exiting.

share|improve this answer
    
Unfortunately none of the event* turned out to be connected to my headphone. Anyways, +1 - maybe it is of help to other users. –  htorque Feb 3 '11 at 19:53
    
+1, works for me, event.value is indeed switched ... but the read operation only returns when the value changes ... maybe you know how to make it not blocking? thanks anyway! –  Kevin Jun 28 '13 at 15:57
    
You add O_NONBLOCK when you open the device, and check the return value of the read. If it's negative, the read either would have blocked, or some other error occurred. There are other more complicated ways to do it without polling if you are incorporating this into a larger program. –  Karl Bielefeldt Jun 28 '13 at 16:29

Check dmesg and other log files. Probably plugging in/out fires some particular messages.

Then, you could use a daemon to parse that log file and detect the events. I think you know what to do from this point :)

share|improve this answer

Ear Candy has some functionality for dealing with headphone insertion/removal.

share|improve this answer
    
Looks like this is just for USB headphones... is that correct? –  Mu Mind Oct 5 '12 at 22:55

To set volume level from console use the command amixer. For example:

amixer sset Master playback 0%

Will set your level to 0%

I don't know how to change this when you plug in your headphones... but maybe someone can help you with that

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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