0

i am trying to write a program that detects when the headphones are plugged into the system and then run another piece of code when you remove the headphones. The code is working fine but the problem that i am facing is that the status of the device is getting cached so only 1 minute after i pull out the headphones does my program detect that it has been removed. This happens when i run the code is a endless while loop.

but if i run single instances not in a loop it shows the correct status immediately on the run

here is the code :

        public class Headphonecheck {

             public static int hpfound = 0;
             public static int hpnfound =0;

             public static void isHeadphoneAvailable() {
                while (true)
                    {
                  if     (!AudioSystem.isLineSupported(Port.Info.HEADPHONE) && hpnfound ==0) {
                        System.out.println("NO HEADPHONE FOUND");
                       System.out.println("Do something else");
                       hpfound = 0;
                       hpnfound = 1;

                    } else {
                    if(AudioSystem.isLineSupported(Port.Info.HEADPHONE) && hpfound ==0){
                       System.out.println("HEADPHONE FOUND");
                       System.out.println("Do something");
                       hpnfound = 0;
                       hpfound =1;
                    }
                }

                } //close while

            }

        public static void main (String[] args){
            isHeadphoneAvailable();
        }
}

if you remove the while loop and run the code it works perfectly for single run .. i.e. you plug in the headphones and run the code it shows HEADPHONE FOUND and then when you remove the headphones and run the code it shows NO HEADPHONE FOUND.

in the while loop once if you have the headphone in and run the code it shows HEADPHONE FOUND and then if you remove the headphone immediately it takes about 50 secs to show NO HEADPHONE FOUND. this is because it is caching it for 50 secs and then clearing the cache

HOW DO I STOP IT FROM CACHING OR CLEAR THE CACHE

user1492955
  • 1,728
  • 2
  • 12
  • 13
  • It seems my answer was wrong, and it is Java Sound itself that is caching the value - for around 50-55 second, in my test code. :( – Andrew Thompson Jul 05 '12 at 15:51
  • How neat is this! I didn't know one could check for headphone use via Java. Nice job getting this to work at all! I'm bookmarking for future reference. – Phil Freihofner Jul 05 '12 at 19:51
  • I do not think this works as expected in general. Running the given code always detects prints HEADPHONE FOUND when I run it, regardless of whether I have them plugged in or not. I am running Windows 7 and java 1.7.0_05. See [Detecting when head phones are plugged in](http://stackoverflow.com/q/861601/3340). – Jacob Schoen Jul 05 '12 at 20:40
  • Hi jschoen this works perfectly for me ... when i do single runs without the while loop it detects when the headphones have been plugged in and when they are pulled out – user1492955 Jul 06 '12 at 05:05
  • i read somewhere that 'com.sun.media.sound.JDK13Services.setCachingPeriod(0);' works ... but i am unable to implement this in my code since JDK13Services class is no longer available !! :( – user1492955 Jul 06 '12 at 05:08

2 Answers2

0

What is your goal latency?

Can you set up repeated "single runs"? (For example, via a Timer?)

I'd expect the while loop to run continuously for a "slice", and have it's response be related to the size and spacing of the "slices". But threads don't normally run 50 seconds in advance! Even 50 msec is a bit excessive. So that can't be the total explanation for the amount of caching you are getting.

In any event, running a while loop as you do seems costly in terms of cpu for an event that happens infrequently and may only require, say, 50 msec accuracy? (Currently, the while loop is testing contiguous microseconds or even nanoseconds, not a exactly a high-payoff test.) A Timer loop that repeats a single poll every 50 milliseconds should be a significantly better use of resources all around.

One additional note, if you take the Timer route: a ScheduledThreadPoolExecutor is being touted as superior to util.Timer, and to be preferred for Java 1.5 and beyond, by Goetz/Bloch/Lea/others in "Java Concurrency in Practice". They say it does a better job of handling unchecked exceptions.

Another possibility: put a Thread.sleep(50) or somesuch value in your while loop and that might help in a way equivalent to using TimerTasks.

I can't say for sure this will fix the problem, but at least the "cache" won't be so large as a result, and performance should improve overall, slightly.

Phil Freihofner
  • 7,645
  • 1
  • 20
  • 41
  • If the LineListener solution can be shown to work, that is much better than what I am suggesting here. – Phil Freihofner Jul 06 '12 at 03:08
  • Thanks for the reply Phil, i have tried putting in a timer and also tried to put the thread to sleep ... but the state seems to change only after 55 secs !! – user1492955 Jul 06 '12 at 05:00
  • i read somewhere that 'com.sun.media.sound.JDK13Services.setCachingPeriod(0);' works ... but i am unable to implement this in my code since JDK13Services class is no longer available !! :( – user1492955 Jul 06 '12 at 05:08
0

Seems like you need to add an event listener. You don't really want to loop looking for this information, you want to be notified when it changes. I haven't personally worked with this system before, but it looks like the Line interface allows you to add a LineListener for events.

The code would look something like this:

...

if(AudioSystem.isLineSupported(Port.Info.HEADPHONE) && hpfound ==0){ 
  Line line = AudioSystem.getLine(Port.Info.HEADPHONE);
  line.addLineListener(new LineListener() {
       public void update(LineEvent event) {
         switch (event.getType()) {
           CLOSE: doSomethingOnClose();
           STOP: doSomethingOnStop();
           // etc...
         }
       }
     });
}

...
bluejekyll
  • 155
  • 2
  • 8
  • If there is a LineListener that can be used, this is definitely superior to the answer I gave earlier! – Phil Freihofner Jul 06 '12 at 03:07
  • Thanks for the reply bluejekyll ! but we a AudioSystem.getLine does not take HEADPHONE as a valid argument as it is a targetdataline and not a sourcedataline. if not for this i am sure that the listener would have been a brilliant solution – user1492955 Jul 06 '12 at 05:00
  • i read somewhere that 'com.sun.media.sound.JDK13Services.setCachingPeriod(0);' works ... but i am unable to implement this in my code since JDK13Services class is no longer available !! :( – user1492955 Jul 06 '12 at 05:08
  • sorry, that was the best guess I had :) – bluejekyll Jul 09 '12 at 17:48