diff --git a/lib/native/linux-64/libjportaudio.so b/lib/native/linux-64/libjportaudio.so index 700754c24..8f01f0789 100755 Binary files a/lib/native/linux-64/libjportaudio.so and b/lib/native/linux-64/libjportaudio.so differ diff --git a/lib/native/linux/libjportaudio.so b/lib/native/linux/libjportaudio.so index cc6a5a1bd..3fd7e3d8b 100755 Binary files a/lib/native/linux/libjportaudio.so and b/lib/native/linux/libjportaudio.so differ diff --git a/lib/native/mac/libjportaudio.jnilib b/lib/native/mac/libjportaudio.jnilib index f66b56dbb..fb249d3f2 100755 Binary files a/lib/native/mac/libjportaudio.jnilib and b/lib/native/mac/libjportaudio.jnilib differ diff --git a/src/native/portaudio/Makefile b/src/native/portaudio/Makefile index 89d8912e6..00749bd76 100644 --- a/src/native/portaudio/Makefile +++ b/src/native/portaudio/Makefile @@ -10,7 +10,7 @@ CPPFLAGS=-DJNI_IMPLEMENTATION \ -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux \ -I$(PORTAUDIO_HOME)/include LDFLAGS=-shared -fPIC -LIBS=-L$(PORTAUDIO_HOME)/lib/.libs -lportaudio +LIBS=-L$(PORTAUDIO_HOME)/lib/.libs -static -lportaudio $(TARGET): net_java_sip_communicator_impl_media_protocol_portaudio_PortAudio.c net_java_sip_communicator_impl_media_protocol_portaudio_PortAudio.h $(CC) $(CPPFLAGS) $< $(LDFLAGS) -o $@ $(LIBS) diff --git a/src/net/java/sip/communicator/impl/media/MediaConfigurationPanel.java b/src/net/java/sip/communicator/impl/media/MediaConfigurationPanel.java index 719d4d21c..828ff7c4b 100644 --- a/src/net/java/sip/communicator/impl/media/MediaConfigurationPanel.java +++ b/src/net/java/sip/communicator/impl/media/MediaConfigurationPanel.java @@ -100,37 +100,56 @@ private void controllerUpdateForPreview(ControllerEvent event, } } - private void createPortAudioControls(Container portAudioPanel) + private void createPortAudioControls( + JPanel portAudioPanel, JPanel parentPanel) { + GridBagConstraints constraints = new GridBagConstraints(); + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.anchor = GridBagConstraints.NORTHWEST; + constraints.gridx = 0; + constraints.weightx = 0; + constraints.weighty = 0; + constraints.gridy = 0; + + portAudioPanel.add(new JLabel(getLabelText( + DeviceConfigurationComboBoxModel.AUDIO_CAPTURE)), constraints); + constraints.gridy = 1; portAudioPanel.add(new JLabel(getLabelText( - DeviceConfigurationComboBoxModel.AUDIO_CAPTURE))); + DeviceConfigurationComboBoxModel.AUDIO_PLAYBACK)), constraints); + constraints.gridy = 2; + portAudioPanel.add(new JLabel(getLabelText( + DeviceConfigurationComboBoxModel.AUDIO_NOTIFY)), constraints); + + constraints.weightx = 1; + constraints.gridx = 1; + constraints.gridy = 0; JComboBox captureCombo = new JComboBox(); captureCombo.setEditable(false); captureCombo.setModel( new DeviceConfigurationComboBoxModel( mediaService.getDeviceConfiguration(), DeviceConfigurationComboBoxModel.AUDIO_CAPTURE)); - portAudioPanel.add(captureCombo); + portAudioPanel.add(captureCombo, constraints); - portAudioPanel.add(new JLabel(getLabelText( - DeviceConfigurationComboBoxModel.AUDIO_PLAYBACK))); + constraints.gridy = 1; JComboBox playbackCombo = new JComboBox(); playbackCombo.setEditable(false); playbackCombo.setModel( new DeviceConfigurationComboBoxModel( mediaService.getDeviceConfiguration(), DeviceConfigurationComboBoxModel.AUDIO_PLAYBACK)); - portAudioPanel.add(playbackCombo); + portAudioPanel.add(playbackCombo, constraints); - portAudioPanel.add(new JLabel(getLabelText( - DeviceConfigurationComboBoxModel.AUDIO_NOTIFY))); + constraints.gridy = 2; JComboBox notifyCombo = new JComboBox(); notifyCombo.setEditable(false); notifyCombo.setModel( new DeviceConfigurationComboBoxModel( mediaService.getDeviceConfiguration(), DeviceConfigurationComboBoxModel.AUDIO_NOTIFY)); - portAudioPanel.add(notifyCombo); + portAudioPanel.add(notifyCombo, constraints); + parentPanel.setBorder( + BorderFactory.createTitledBorder("Devices")); } private Component createControls(int type) @@ -148,11 +167,13 @@ private Component createControls(int type) * input audio device, output audio device and audio device for playback * of notifications. */ - final Container portAudioPanel; + final JPanel portAudioPanel; + final JPanel portAudioParentPanel; if (type == DeviceConfigurationComboBoxModel.AUDIO) { portAudioPanel - = new TransparentPanel(new GridLayout(3, 2, HGAP, VGAP)); + = new TransparentPanel(new GridBagLayout()); + portAudioParentPanel = new TransparentPanel(new BorderLayout()); comboBox.addItemListener(new ItemListener() { @@ -163,11 +184,13 @@ public void itemStateChanged(ItemEvent e) if(DeviceConfiguration .AUDIO_SYSTEM_PORTAUDIO.equals(e.getItem())) { - createPortAudioControls(portAudioPanel); + createPortAudioControls( + portAudioPanel, portAudioParentPanel); } else { portAudioPanel.removeAll(); + portAudioParentPanel.setBorder(null); revalidate(); repaint(); @@ -178,10 +201,13 @@ public void itemStateChanged(ItemEvent e) if(comboBox .getSelectedItem() .equals(DeviceConfiguration.AUDIO_SYSTEM_PORTAUDIO)) - createPortAudioControls(portAudioPanel); + createPortAudioControls(portAudioPanel, portAudioParentPanel); } else + { portAudioPanel = null; + portAudioParentPanel = null; + } JLabel label = new JLabel(getLabelText(type)); label.setDisplayedMnemonic(getDisplayedMnemonic(type)); @@ -198,19 +224,22 @@ public void itemStateChanged(ItemEvent e) firstConstraints.weightx = 1; firstContainer.add(comboBox, firstConstraints); + Container secondContainer = + new TransparentPanel(new GridLayout(1, 0, HGAP, VGAP)); + + // if creating controls for audio will add devices panel + // otherwise it is video controls and will add preview panel if (portAudioPanel != null) { - firstConstraints.gridx = 0; - firstConstraints.gridy = 1; - firstConstraints.weightx = 1; - firstConstraints.gridwidth = 2; - firstConstraints.insets = new Insets(VGAP, 0, 0, 0); - firstContainer.add(portAudioPanel, firstConstraints); + // add portAudioPanel in new panel on north, as for some reason + // anchor = GridBagConstraints.NORTHWEST doesn't work + // and all components are vertically centered + portAudioParentPanel.add(portAudioPanel, BorderLayout.NORTH); + secondContainer.add(portAudioParentPanel); } + else + secondContainer.add(createPreview(type, comboBox)); - Container secondContainer = - new TransparentPanel(new GridLayout(1, 0, HGAP, VGAP)); - secondContainer.add(createPreview(type, comboBox)); secondContainer.add(createEncodingControls(type)); Container container = new TransparentPanel(new GridBagLayout()); diff --git a/src/net/java/sip/communicator/impl/media/device/DeviceConfiguration.java b/src/net/java/sip/communicator/impl/media/device/DeviceConfiguration.java index a4b8cc6cc..97bd8d8f8 100644 --- a/src/net/java/sip/communicator/impl/media/device/DeviceConfiguration.java +++ b/src/net/java/sip/communicator/impl/media/device/DeviceConfiguration.java @@ -221,6 +221,12 @@ else if (audioCaptureDevices.length < 1) } } + /** + * Returns the configured video capture device with the specified + * output format. + * @param format the output format of the video format. + * @return CaptureDeviceInfo for the video device. + */ private CaptureDeviceInfo extractConfiguredVideoCaptureDevice(String format) { List videoCaptureDevices = @@ -265,6 +271,15 @@ public CaptureDeviceInfo getAudioCaptureDevice() return audioCaptureDevice; } +// /** +// * Returns the default capture device used by the portaudio system. +// * @return the default capture device. +// */ +// public CaptureDeviceInfo getDefaultAudioCaptureDevice() +// { +// return PortAudioAuto.defaultCaptureDevice; +// } + /** * Gets the list of audio capture devices which are available through this * DeviceConfiguration, amongst which is @@ -473,6 +488,11 @@ public String getAudioSystem() return audioSystem; } + /** + * Extracts the audio system for the given device info. + * @param cdi the device + * @return the audio system used by the device. + */ private String getAudioSystem(CaptureDeviceInfo cdi) { String res = null; @@ -561,13 +581,10 @@ else if(name.equals(AUDIO_SYSTEM_JAVASOUND)) } else if(name.equals(AUDIO_SYSTEM_PORTAUDIO)) { - // changed to portaudio, so lets clear current device selection - // as we must select them - // if this is first time call devices will be already null - // and nothing will happen - setAudioCaptureDevice(null); - setAudioNotifyDevice(null); - setAudioPlaybackDevice(null); + // changed to portaudio, so lets set the default devices + setAudioCaptureDevice(PortAudioAuto.defaultCaptureDevice); + setAudioNotifyDevice(PortAudioAuto.defaultPlaybackDevice); + setAudioPlaybackDevice(PortAudioAuto.defaultPlaybackDevice); // we don't save anything cause it will be saved // when the devices are stored @@ -640,6 +657,9 @@ protected static void initPortAudioRenderer() PlugInManager.RENDERER); } + /** + * Removes javasound renderer. + */ private void removeJavaSoundRenderer() { PlugInManager.removePlugIn( @@ -647,6 +667,9 @@ private void removeJavaSoundRenderer() PlugInManager.RENDERER); } + /** + * Removed portaudio renderer. + */ private void removePortAudioRenderer() { PlugInManager.removePlugIn( @@ -654,6 +677,9 @@ private void removePortAudioRenderer() PlugInManager.RENDERER); } + /** + * Registers javasound renderer. + */ private void initJavaSoundRenderer() { try @@ -672,6 +698,10 @@ private void initJavaSoundRenderer() } } + /** + * Sets the device to be used by portaudio renderer. + * @param devInfo + */ private void setDeviceToRenderer(CaptureDeviceInfo devInfo) { // no need to change device to renderer it will not be used anyway @@ -697,6 +727,15 @@ public CaptureDeviceInfo getAudioPlaybackDevice() return audioPlaybackDevice; } +// /** +// * Returns the default playback device used by the portaudio system. +// * @return the default playback device. +// */ +// public CaptureDeviceInfo getDefaultAudioPlaybackDevice() +// { +// return PortAudioAuto.defaultCaptureDevice; +// } + /** * @return the audioNotifyDevice */ @@ -705,6 +744,15 @@ public CaptureDeviceInfo getAudioNotifyDevice() return audioNotifyDevice; } +// /** +// * Returns the default notify device used by the portaudio system. +// * @return the default notify device. +// */ +// public CaptureDeviceInfo getDefaultAudioNotifyDevice() +// { +// return PortAudioAuto.defaultPlaybackDevice; +// } + /** * @param audioPlaybackDevice the audioPlaybackDevice to set */ diff --git a/src/net/java/sip/communicator/impl/media/device/PortAudioAuto.java b/src/net/java/sip/communicator/impl/media/device/PortAudioAuto.java index ca394b948..64269d7bb 100644 --- a/src/net/java/sip/communicator/impl/media/device/PortAudioAuto.java +++ b/src/net/java/sip/communicator/impl/media/device/PortAudioAuto.java @@ -23,6 +23,16 @@ public class PortAudioAuto */ public static CaptureDeviceInfo[] playbackDevices = null; + /** + * The default playback device. + */ + public static CaptureDeviceInfo defaultPlaybackDevice = null; + + /** + * The default capture device. + */ + public static CaptureDeviceInfo defaultCaptureDevice = null; + PortAudioAuto() throws Exception { // if PortAudio has a problem initializing like missing native @@ -33,6 +43,9 @@ public class PortAudioAuto int deviceCount = PortAudio.Pa_GetDeviceCount(); int deviceIndex = 0; + int defaultInputDeviceIx = PortAudio.Pa_GetDefaultInputDevice(); + int defaultOutputDeviceIx = PortAudio.Pa_GetDefaultOutputDevice(); + Vector playbackDevVector = new Vector(); @@ -60,6 +73,12 @@ public class PortAudioAuto { playbackDevVector.add(jmfInfo); } + + if(deviceIndex == defaultInputDeviceIx) + defaultCaptureDevice = jmfInfo; + + if(deviceIndex == defaultOutputDeviceIx) + defaultPlaybackDevice = jmfInfo; } playbackDevices = playbackDevVector.toArray(new CaptureDeviceInfo[0]); diff --git a/src/net/java/sip/communicator/impl/media/notify/PortAudioClipImpl.java b/src/net/java/sip/communicator/impl/media/notify/PortAudioClipImpl.java index 55ce2ba0f..5505556ba 100644 --- a/src/net/java/sip/communicator/impl/media/notify/PortAudioClipImpl.java +++ b/src/net/java/sip/communicator/impl/media/notify/PortAudioClipImpl.java @@ -131,6 +131,9 @@ public void run() { while(true) { + AudioInputStream audioStream = + AudioSystem.getAudioInputStream(url); + if (portAudioStream == 0) { int deviceIndex = @@ -140,17 +143,27 @@ public void run() long devInfo = PortAudio.Pa_GetDeviceInfo(deviceIndex); int maxOutChannels = PortAudio.PaDeviceInfo_getMaxOutputChannels(devInfo); - if(maxOutChannels > 2) - maxOutChannels = 2; + + + int outChannels = audioStream.getFormat().getChannels(); + if(outChannels > maxOutChannels) + outChannels = maxOutChannels; double sampleRate = - PortAudio.PaDeviceInfo_getDefaultSampleRate(devInfo); + audioStream.getFormat().getSampleRate(); long streamParameters = PortAudio.PaStreamParameters_new( deviceIndex, - maxOutChannels, + outChannels, PortAudio.SAMPLE_FORMAT_INT16); + // check if file samplerate is supported + // if it is use it and not resample + if(!PortAudio.Pa_IsFormatSupported( + 0, streamParameters, sampleRate)) + sampleRate = + PortAudio.PaDeviceInfo_getDefaultSampleRate( + devInfo); portAudioStream = PortAudio.Pa_OpenStream( @@ -164,9 +177,6 @@ public void run() PortAudio.Pa_StartStream(portAudioStream); } - AudioInputStream audioStream = - AudioSystem.getAudioInputStream(url); - if(!started) { PortAudio.Pa_CloseStream(portAudioStream); diff --git a/src/net/java/sip/communicator/impl/media/renderer/audio/PortAudioRenderer.java b/src/net/java/sip/communicator/impl/media/renderer/audio/PortAudioRenderer.java index 48a6bc4cd..8bb04d34f 100644 --- a/src/net/java/sip/communicator/impl/media/renderer/audio/PortAudioRenderer.java +++ b/src/net/java/sip/communicator/impl/media/renderer/audio/PortAudioRenderer.java @@ -86,8 +86,8 @@ public void start() { try { - started = true; PortAudio.Pa_StartStream(stream); + started = true; } catch (PortAudioException e) { @@ -104,9 +104,9 @@ public void stop() { try { + started = false; PortAudio.Pa_CloseStream(stream); writerThread = null; - started = false; } catch (PortAudioException e) {