diff --git a/src/net/java/sip/communicator/impl/gui/main/call/RecordButton.java b/src/net/java/sip/communicator/impl/gui/main/call/RecordButton.java index d5bada812..c396cfadc 100644 --- a/src/net/java/sip/communicator/impl/gui/main/call/RecordButton.java +++ b/src/net/java/sip/communicator/impl/gui/main/call/RecordButton.java @@ -137,6 +137,27 @@ public void actionPerformed(ActionEvent evt) } setSelected(startedRecording); } + /* + * Notify the user the call has been successfully saved upon the + * recorder stopping. + */ + if (startedRecording && (recorder != null)) + { + recorder.addListener( + new Recorder.Listener() + { + public void recorderStopped(Recorder recorder) + { + NotificationManager.fireNotification( + NotificationManager.CALL_SAVED, + resources.getI18NString( + "plugin.callrecordingconfig.CALL_SAVED"), + resources.getI18NString( + "plugin.callrecordingconfig.CALL_SAVED_TO", + new String[] { callFilename })); + } + }); + } } // stop recording else if (recorder != null) @@ -144,13 +165,6 @@ else if (recorder != null) try { recorder.stop(); - NotificationManager.fireNotification( - NotificationManager.CALL_SAVED, - resources.getI18NString( - "plugin.callrecordingconfig.CALL_SAVED"), - resources.getI18NString( - "plugin.callrecordingconfig.CALL_SAVED_TO", - new String[] { callFilename })); } finally { @@ -189,7 +203,7 @@ private String createDefaultFilename(String savedCallsPath) } } - String ext = configuration.getString(Recorder.CALL_FORMAT); + String ext = configuration.getString(Recorder.FORMAT); // Use a default format when the configured one seems invalid. if ((ext == null) @@ -298,6 +312,7 @@ private boolean startRecording() { String savedCallsPath = configuration.getString(Recorder.SAVED_CALLS_PATH); + String callFormat; // Ask the user where to save the call. if ((savedCallsPath == null) || (savedCallsPath.length() == 0)) @@ -381,7 +396,7 @@ public String getDescription() * OS X at least) i.e. no format, then it is not obvious that we * have to override the set Recorder.CALL_FORMAT. */ - String callFormat = SoundFileUtils.getExtension(selectedFile); + callFormat = SoundFileUtils.getExtension(selectedFile); if ((callFormat != null) && (callFormat.length() != 0)) { @@ -407,7 +422,7 @@ public String getDescription() = SoundFileUtils.DEFAULT_CALL_RECORDING_FORMAT; callFilename += '.' + callFormat; } - configuration.setProperty(Recorder.CALL_FORMAT, callFormat); + configuration.setProperty(Recorder.FORMAT, callFormat); } } else @@ -417,7 +432,10 @@ public String getDescription() } } else + { callFilename = createDefaultFilename(savedCallsPath); + callFormat = SoundFileUtils.getExtension(new File(callFilename)); + } Throwable exception = null; @@ -426,7 +444,12 @@ public String getDescription() Recorder recorder = getRecorder(); if (recorder != null) - recorder.start(callFilename); + { + if ((callFormat == null) || (callFormat.length() <= 0)) + callFormat = SoundFileUtils.DEFAULT_CALL_RECORDING_FORMAT; + + recorder.start(callFormat, callFilename); + } this.recorder = recorder; } diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/ChatConversationPanel.java b/src/net/java/sip/communicator/impl/gui/main/chat/ChatConversationPanel.java index c993f0e18..26f4d7d61 100755 --- a/src/net/java/sip/communicator/impl/gui/main/chat/ChatConversationPanel.java +++ b/src/net/java/sip/communicator/impl/gui/main/chat/ChatConversationPanel.java @@ -46,6 +46,10 @@ public class ChatConversationPanel MouseListener, ClipboardOwner { + /** + * The Logger used by the ChatConversationPanel class and + * its instances for logging output. + */ private static final Logger logger = Logger.getLogger(ChatConversationPanel.class); @@ -335,7 +339,8 @@ public void setBounds(int x, int y, int width, int height) * Processes the message given by the parameters. * * @param chatMessage the message - * @param keyword + * @param keyword a substring of chatMessage to be highlighted upon + * display of chatMessage in the UI * @return the processed message */ public String processMessage(ChatMessage chatMessage, String keyword) @@ -1266,12 +1271,13 @@ private class MyTextPane * @param event the MouseEvent * @return the string to be used as the tooltip for event. */ + @Override public String getToolTipText(MouseEvent event) { - if(currentHref != null && currentHref.length() != 0) - return currentHref; - else - return null; + return + ((currentHref != null) && (currentHref.length() != 0)) + ? currentHref + : null; } } diff --git a/src/net/java/sip/communicator/impl/neomedia/CallRecordingConfigForm.java b/src/net/java/sip/communicator/impl/neomedia/CallRecordingConfigForm.java index a3b88a984..dfb49c659 100644 --- a/src/net/java/sip/communicator/impl/neomedia/CallRecordingConfigForm.java +++ b/src/net/java/sip/communicator/impl/neomedia/CallRecordingConfigForm.java @@ -88,18 +88,16 @@ public CallRecordingConfigForm() */ private void loadValues() { - ConfigurationService configurationService + ConfigurationService configuration = NeomediaActivator.getConfigurationService(); - String callFormat - = configurationService.getString(Recorder.CALL_FORMAT); + String format = configuration.getString(Recorder.FORMAT); formatsComboBox.setSelectedItem( - (callFormat == null) + (format == null) ? SoundFileUtils.DEFAULT_CALL_RECORDING_FORMAT - : callFormat); + : format); - savedCallsDir - = configurationService.getString(Recorder.SAVED_CALLS_PATH); + savedCallsDir = configuration.getString(Recorder.SAVED_CALLS_PATH); saveCallsToCheckBox.setSelected(savedCallsDir != null); callDirTextField.setText(savedCallsDir); callDirTextField.setEnabled(saveCallsToCheckBox.isSelected()); @@ -192,7 +190,7 @@ public void itemStateChanged(ItemEvent event) { NeomediaActivator .getConfigurationService() - .setProperty(Recorder.CALL_FORMAT, event.getItem()); + .setProperty(Recorder.FORMAT, event.getItem()); } } }); diff --git a/src/net/java/sip/communicator/impl/neomedia/RecorderImpl.java b/src/net/java/sip/communicator/impl/neomedia/RecorderImpl.java index aa3758822..c8ab59c44 100644 --- a/src/net/java/sip/communicator/impl/neomedia/RecorderImpl.java +++ b/src/net/java/sip/communicator/impl/neomedia/RecorderImpl.java @@ -13,7 +13,6 @@ import javax.media.protocol.*; import net.java.sip.communicator.impl.neomedia.device.*; -import net.java.sip.communicator.service.configuration.*; import net.java.sip.communicator.service.neomedia.*; import net.java.sip.communicator.service.neomedia.MediaException; // disambiguation import net.java.sip.communicator.util.*; @@ -28,11 +27,6 @@ public class RecorderImpl implements Recorder { - /** - * The Logger used by the RecorderImpl class and its - * instances for logging output. - */ - private static final Logger logger = Logger.getLogger(RecorderImpl.class); /** * The list of formats in which RecorderImpl instances support @@ -48,16 +42,23 @@ public class RecorderImpl SoundFileUtils.wav }; + /** + * The AudioMixerMediaDevice which is to be or which is already + * being recorded by this Recorder. + */ + private final AudioMixerMediaDevice device; + /** * The MediaDeviceSession is used to create an output data source. */ private MediaDeviceSession deviceSession; /** - * The format of {@link #deviceSession} in particular and of the recording - * produced by this Recorder in general. + * The List of Recorder.Listeners interested in + * notifications from this Recorder. */ - private final String format; + private final List listeners + = new ArrayList(); /** * DataSink used to save the output data. @@ -75,39 +76,27 @@ public RecorderImpl(AudioMixerMediaDevice device) if (device == null) throw new NullPointerException("device"); - ConfigurationService configuration - = NeomediaActivator.getConfigurationService(); - String format = configuration.getString(Recorder.CALL_FORMAT); + this.device = device; + } - if (format == null) - format = SoundFileUtils.DEFAULT_CALL_RECORDING_FORMAT; + /** + * Adds a new Recorder.Listener to the list of listeners interested + * in notifications from this Recorder. + * + * @param listener the new Recorder.Listener to be added to the + * list of listeners interested in notifications from this Recorder + * @see Recorder#addListener(Recorder.Listener) + */ + public void addListener(Recorder.Listener listener) + { + if (listener == null) + throw new NullPointerException("listener"); - try - { - deviceSession - = device.createRecordingSession(getContentDescriptor( - format)); - } - catch (IllegalArgumentException iaex) + synchronized (listeners) { - //seems like we had an illegal format stored in the configuration - //service - logger.debug( - "Unable to crate a " - + format - + " record. Will retry default format"); - - format = SoundFileUtils.DEFAULT_CALL_RECORDING_FORMAT; - - //make sure we don't try the faulty format again. - configuration.setProperty(Recorder.CALL_FORMAT, null); - - deviceSession - = device.createRecordingSession(getContentDescriptor( - format)); + if (!listeners.contains(listener)) + listeners.add(listener); } - - this.format = format; } /** @@ -156,25 +145,49 @@ public List getSupportedFormats() return Arrays.asList(SUPPORTED_FORMATS); } + /** + * Removes a existing Recorder.Listener from the list of listeners + * interested in notifications from this Recorder. + * + * @param listener the existing Recorder.Listener to be removed + * from the list of listeners interested in notifications from this + * Recorder + * @see Recorder#removeListener(Recorder.Listener) + */ + public void removeListener(Recorder.Listener listener) + { + if (listener != null) + { + synchronized (listeners) + { + listeners.remove(listener); + } + } + } + /** * Starts the recording of the media associated with this Recorder * (e.g. the media being sent and received in a Call) into a file * with a specific name. * + * @param format the format into which the media associated with this + * Recorder is to be recorded into the specified file * @param filename the name of the file into which the media associated with * this Recorder is to be recorded * @throws IOException if anything goes wrong with the input and/or output * performed by this Recorder * @throws MediaException if anything else goes wrong while starting the * recording of media performed by this Recorder - * @see Recorder#start(String) + * @see Recorder#start(String, String) */ - public void start(String filename) + public void start(String format, String filename) throws IOException, MediaException { if (this.sink == null) { + if (format == null) + throw new NullPointerException("format"); if (filename == null) throw new NullPointerException("filename"); @@ -186,18 +199,48 @@ public void start(String filename) int extensionBeginIndex = filename.lastIndexOf('.'); if (extensionBeginIndex < 0) - filename += '.' + this.format; + filename += '.' + format; else if (extensionBeginIndex == filename.length() - 1) - filename += this.format; + filename += format; + + MediaDeviceSession deviceSession = device.createSession(); + + try + { + deviceSession.setContentDescriptor(getContentDescriptor(format)); + + /* + * This RecorderImpl will use deviceSession to get a hold of the + * media being set to the remote peers associated with the same + * AudioMixerMediaDevice i.e. this RecorderImpl needs + * deviceSession to only capture and not play back. + */ + deviceSession.start(MediaDirection.SENDONLY); + + this.deviceSession = deviceSession; + } + finally + { + if (this.deviceSession == null) + { + throw new MediaException( + "Failed to create MediaDeviceSession from" + + " AudioMixerMediaDevice for the purposes of" + + " recording"); + } + } - DataSource outputDataSource = deviceSession.getOutputDataSource(); + Throwable exception = null; try { + DataSource outputDataSource + = deviceSession.getOutputDataSource(); DataSink sink = Manager.createDataSink( outputDataSource, new MediaLocator("file:" + filename)); + sink.open(); sink.start(); @@ -205,10 +248,18 @@ else if (extensionBeginIndex == filename.length() - 1) } catch (NoDataSinkException ndsex) { - throw - new MediaException( + exception = ndsex; + } + finally + { + if ((this.sink == null) || (exception != null)) + { + stop(); + + throw new MediaException( "Failed to start recording into file " + filename, - ndsex); + exception); + } } } } @@ -232,6 +283,23 @@ public void stop() { sink.close(); sink = null; + + /* + * RecorderImpl creates the sink upon start() and it does it only if + * it is null so this RecorderImpl has really stopped only if it has + * managed to close() the (existing) sink. Notify the registered + * listeners. + */ + Recorder.Listener[] listeners; + + synchronized (this.listeners) + { + listeners + = this.listeners.toArray( + new Recorder.Listener[this.listeners.size()]); + } + for (Recorder.Listener listener : listeners) + listener.recorderStopped(this); } } } diff --git a/src/net/java/sip/communicator/impl/neomedia/device/AudioMixerMediaDevice.java b/src/net/java/sip/communicator/impl/neomedia/device/AudioMixerMediaDevice.java index 307bab1a2..2d92cfab1 100644 --- a/src/net/java/sip/communicator/impl/neomedia/device/AudioMixerMediaDevice.java +++ b/src/net/java/sip/communicator/impl/neomedia/device/AudioMixerMediaDevice.java @@ -205,83 +205,6 @@ public synchronized MediaDeviceSession createSession() return new MediaStreamMediaDeviceSession(deviceSession); } - /** - * Create a new recording session. - * - * @param contentDescriptor the content descriptor for the session. - * @return a new MediaDeviceSession - */ - public synchronized MediaDeviceSession createRecordingSession( - final ContentDescriptor contentDescriptor) - { - if (deviceSession == null) - deviceSession = new AudioMixerMediaDeviceSession(); - - return new MediaStreamMediaDeviceSession(deviceSession) - { - /** - * Starts a specific Processor if this - * MediaDeviceSession has been started and the specified - * Processor is not started. Does not check the - * MediaDirection of this session when starting. - * - * @param processor the Processor to start - */ - @Override - protected void startProcessorInAccordWithDirection( - Processor processor) - { - if (processor.getState() != Processor.Started) - { - processor.start(); - if (logger.isTraceEnabled()) - { - logger.trace( - "Started Processor with hashCode " - + processor.hashCode()); - } - } - } - - /** - * Overrides the method to set the processor's content descriptor - * to FileTypeDescriptor.MPEG_AUDIO. - * - * @param event the ControllerEvent specifying the - * Controller which is the source of the event and the very - * type of the event - */ - @Override - protected void processorControllerUpdate(ControllerEvent event) - { - super.processorControllerUpdate(event); - - if (event instanceof ConfigureCompleteEvent) - { - Processor processor = (Processor) event. - getSourceController(); - - if (processor != null) - { - try - { - processor.setContentDescriptor(contentDescriptor); - } - catch (NotConfiguredError nce) - { - logger.error( - "Failed to set ContentDescriptor to Processor.", - nce); - } - - if (format != null) - setProcessorFormat(processor, format); - } - } - } - }; - } - /** * Notifies all currently registered SimpleAudioLevelListeners * that our local media now has audio level level. diff --git a/src/net/java/sip/communicator/impl/neomedia/device/MediaDeviceSession.java b/src/net/java/sip/communicator/impl/neomedia/device/MediaDeviceSession.java index 6bdc0d107..06af08350 100644 --- a/src/net/java/sip/communicator/impl/neomedia/device/MediaDeviceSession.java +++ b/src/net/java/sip/communicator/impl/neomedia/device/MediaDeviceSession.java @@ -70,6 +70,13 @@ public class MediaDeviceSession */ private boolean captureDeviceIsConnected; + /** + * The ContentDescriptor which specifies the content type in which + * this MediaDeviceSession is to output the media captured by its + * MediaDevice. + */ + private ContentDescriptor contentDescriptor; + /** * The MediaDevice used by this instance to capture and play back * media. @@ -497,6 +504,27 @@ public void controllerUpdate(ControllerEvent event) return null; } + /** + * Creates a ContentDescriptor to be set on a specific + * Processor of captured media to be sent to the remote peer. + * Allows extenders to override. The default implementation returns + * {@link ContentDescriptor#RAW_RTP}. + * + * @param processor the Processor of captured media to be sent to + * the remote peer which is to have its contentDescriptor set to + * the returned ContentDescriptor + * @return a ContentDescriptor to be set on the specified + * processor of captured media to be sent to the remote peer + */ + protected ContentDescriptor createProcessorContentDescriptor( + Processor processor) + { + return + (contentDescriptor == null) + ? new ContentDescriptor(ContentDescriptor.RAW_RTP) + : contentDescriptor; + } + /** * Makes sure {@link #captureDevice} is disconnected. */ @@ -705,13 +733,13 @@ public Format getProcessorFormat() continue; Format jmfFormat = trackControl.getFormat(); - MediaType type = jmfFormat instanceof VideoFormat - ? MediaType.VIDEO : MediaType.AUDIO; + MediaType type + = (jmfFormat instanceof VideoFormat) + ? MediaType.VIDEO + : MediaType.AUDIO; - if(mediaType.equals((type))) - { + if(mediaType.equals(type)) return jmfFormat; - } } } return null; @@ -1113,10 +1141,8 @@ protected void processorControllerUpdate(ControllerEvent event) { try { - processor - .setContentDescriptor( - new ContentDescriptor( - ContentDescriptor.RAW_RTP)); + processor.setContentDescriptor( + createProcessorContentDescriptor(processor)); } catch (NotConfiguredError nce) { @@ -1219,6 +1245,25 @@ protected void receiveStreamChanged( { } + /** + * Sets the ContentDescriptor which specifies the content type in + * which this MediaDeviceSession is to output the media captured by + * its MediaDevice. The default content type in which + * MediaDeviceSession outputs the media captured by its + * MediaDevice is {@link ContentDescriptor#RAW_RTP}. + * + * @param contentDescriptor the ContentDescriptor which specifies + * the content type in which this MediaDeviceSession is to output + * the media captured by its MediaDevice + */ + public void setContentDescriptor(ContentDescriptor contentDescriptor) + { + if (contentDescriptor == null) + throw new NullPointerException("contentDescriptor"); + + this.contentDescriptor = contentDescriptor; + } + /** * Sets the MediaFormat in which this MediaDeviceSession * outputs the media captured by its MediaDevice. diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java index b40c9cec1..2b4092ba1 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java @@ -1189,6 +1189,15 @@ protected XMPPConnection getConnection() return connection; } + /** + * Determines whether a specific XMPPException signals that + * attempted authentication has failed. + * + * @param ex the XMPPException which is to be determined whether it + * signals that attempted authentication has failed + * @return true if the specified ex signals that attempted + * authentication has failed; otherwise, false + */ private boolean isAuthenticationFailed(XMPPException ex) { String exMsg = ex.getMessage().toLowerCase(); @@ -1196,16 +1205,12 @@ private boolean isAuthenticationFailed(XMPPException ex) // as there are no types or reasons for XMPPException // we try determine the reason according to their message // all messages that were found in smack 3.1.0 were took in count - if(exMsg.indexOf("authentication failed") != -1 - || (exMsg.indexOf("authentication") != -1 - && exMsg.indexOf("failed") != -1) - || exMsg.indexOf("login failed") != -1 - || exMsg.indexOf("unable to determine password") != -1) - { - return true; - } - else - return false; + return + (exMsg.indexOf("authentication failed") != -1) + || ((exMsg.indexOf("authentication") != -1) + && (exMsg.indexOf("failed") != -1)) + || (exMsg.indexOf("login failed") != -1) + || (exMsg.indexOf("unable to determine password") != -1); } /** diff --git a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetPresenceSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetPresenceSipImpl.java index 143d28e02..2f30fe585 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetPresenceSipImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetPresenceSipImpl.java @@ -3176,7 +3176,7 @@ protected void processSuccessResponse( /** * Implements the corresponding SipListener method by - * terminating the corresponding subsctiption and polling the related + * terminating the corresponding subscription and polling the related * contact. * * @param requestEvent the event containing the request that was \ diff --git a/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java index 0478c5712..7e0fff4ca 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java @@ -301,7 +301,26 @@ public List getKnownEventsList() return this.registeredEvents; } - + /** + * Overrides + * {@link AbstractProtocolProviderService#fireRegistrationStateChanged( + * RegistrationState, RegistrationState, int, String)} in order to add + * enabling/disabling XCAP functionality in accord with the current + * RegistrationState of this + * ProtocolProviderServiceSipImpl. + * + * @param oldState the state that the provider had before the change + * occurred + * @param newState the state that the provider is currently in + * @param reasonCode a value corresponding to one of the REASON_XXX fields + * of the RegistrationStateChangeEvent class, indicating the reason + * for this state transition + * @param reason a String further explaining the reason code or + * null if no such explanation is necessary + * @see AbstractProtocolProviderService#fireRegistrationStateChanged( + * RegistrationState, RegistrationState, int, String) + */ + @Override public void fireRegistrationStateChanged(RegistrationState oldState, RegistrationState newState, int reasonCode, diff --git a/src/net/java/sip/communicator/service/neomedia/Recorder.java b/src/net/java/sip/communicator/service/neomedia/Recorder.java index 0122b0398..90b0e9ec3 100644 --- a/src/net/java/sip/communicator/service/neomedia/Recorder.java +++ b/src/net/java/sip/communicator/service/neomedia/Recorder.java @@ -31,8 +31,17 @@ public interface Recorder * format in which media is to be recorded by Recorder (e.g. the * media being sent and received in a Call). */ - public static final String CALL_FORMAT - = "net.java.sip.communicator.impl.neomedia.CALL_FORMAT"; + public static final String FORMAT + = "net.java.sip.communicator.impl.neomedia.Recorder.FORMAT"; + + /** + * Adds a new Listener to the list of listeners interested in + * notifications from this Recorder. + * + * @param listener the new Listener to be added to the list of + * listeners interested in notifications from this Recorder + */ + public void addListener(Listener listener); /** * Gets a list of the formats in which this Recorder supports @@ -43,11 +52,22 @@ public interface Recorder */ public List getSupportedFormats(); + /** + * Removes an existing Listener from the list of listeners + * interested in notifications from this Recorder. + * + * @param listener the existing Listener to be removed from the + * list of listeners interested in notifications from this Recorder + */ + public void removeListener(Listener listener); + /** * Starts the recording of the media associated with this Recorder * (e.g. the media being sent and received in a Call) into a file * with a specific name. * + * @param format the format into which the media associated with this + * Recorder is to be recorded into the specified file * @param filename the name of the file into which the media associated with * this Recorder is to be recorded * @throws IOException if anything goes wrong with the input and/or output @@ -55,7 +75,7 @@ public interface Recorder * @throws MediaException if anything else goes wrong while starting the * recording of media performed by this Recorder */ - public void start(String filename) + public void start(String format, String filename) throws IOException, MediaException; @@ -65,4 +85,21 @@ public void start(String filename) * been started and prepares this Recorder for garbage collection. */ public void stop(); + + /** + * Represents a listener interested in notifications from a Recorder. + * + * @author Lubomir Marinov + */ + public interface Listener + { + /** + * Notifies this Listener that a specific Recorder has + * stopped recording the media associated with it. + * + * @param recorder the Recorder which has stopped recording its + * associated media + */ + public void recorderStopped(Recorder recorder); + } } diff --git a/src/net/java/sip/communicator/service/protocol/media/MediaAwareCall.java b/src/net/java/sip/communicator/service/protocol/media/MediaAwareCall.java index 6500a3881..db7f24a9e 100644 --- a/src/net/java/sip/communicator/service/protocol/media/MediaAwareCall.java +++ b/src/net/java/sip/communicator/service/protocol/media/MediaAwareCall.java @@ -570,8 +570,40 @@ public void removeVideoPropertyChangeListener( public Recorder createRecorder() throws OperationFailedException { - return - ProtocolMediaActivator.getMediaService().createRecorder( + final Recorder recorder + = ProtocolMediaActivator.getMediaService().createRecorder( getDefaultDevice(MediaType.AUDIO)); + + if (recorder != null) + { + // Make sure the recorder is stopped when this call ends. + final CallChangeListener callChangeListener + = new CallChangeAdapter() + { + @Override + public void callStateChanged(CallChangeEvent evt) + { + if (CallState.CALL_ENDED.equals(evt.getNewValue())) + recorder.stop(); + } + }; + + addCallChangeListener(callChangeListener); + + /* + * If the recorder gets stopped earlier than this call ends, don't + * wait for the end of the call because callChangeListener will keep + * a reference to the stopped recorder. + */ + recorder.addListener( + new Recorder.Listener() + { + public void recorderStopped(Recorder recorder) + { + removeCallChangeListener(callChangeListener); + } + }); + } + return recorder; } } diff --git a/src/net/java/sip/communicator/util/NetworkUtils.java b/src/net/java/sip/communicator/util/NetworkUtils.java index 2012d7eb8..9a09d1bec 100644 --- a/src/net/java/sip/communicator/util/NetworkUtils.java +++ b/src/net/java/sip/communicator/util/NetworkUtils.java @@ -21,8 +21,11 @@ */ public class NetworkUtils { - private static final Logger logger - = Logger.getLogger(NetworkUtils.class); + /** + * The Logger used by the NetworkUtils class for logging + * output. + */ + private static final Logger logger = Logger.getLogger(NetworkUtils.class); /** * A string containing the "any" local address for IPv6. @@ -436,7 +439,7 @@ public static InetAddress getInetAddress(String hostAddress) * The records are ordered against the SRV record priority * @param domain the name of the domain we'd like to resolve (_proto._tcp * included). - * @param port + * @param port the port number of the returned InetSocketAddress * @return an array of InetSocketAddress containing records returned by the DNS * server - address and port . * @throws ParseException if domain is not a valid domain name. @@ -472,7 +475,7 @@ public static InetSocketAddress getARecord(String domain, int port) * The records are ordered against the SRV record priority * @param domain the name of the domain we'd like to resolve (_proto._tcp * included). - * @param port + * @param port the port number of the returned InetSocketAddress * @return an array of InetSocketAddress containing records returned by the DNS * server - address and port . * @throws ParseException if domain is not a valid domain name. diff --git a/src/net/java/sip/communicator/util/swing/SipCommFileDialogImpl.java b/src/net/java/sip/communicator/util/swing/SipCommFileDialogImpl.java index 112fe9f5f..bf6a30b12 100644 --- a/src/net/java/sip/communicator/util/swing/SipCommFileDialogImpl.java +++ b/src/net/java/sip/communicator/util/swing/SipCommFileDialogImpl.java @@ -18,6 +18,12 @@ public class SipCommFileDialogImpl extends FileDialog implements SipCommFileChooser { + /** + * The serialization-related version of the SipCommFileDialogImpl + * class explicitly defined to silence a related warning (e.g. in Eclipse + * IDE) since the SipCommFileDialogImpl class does not add instance + * fields. + */ private static final long serialVersionUID = 0L; /** @@ -67,7 +73,7 @@ public void setStartPath(String path) if ((file != null) && !file.isDirectory()) { setDirectory(file.getParent()); - setFile(path); + setFile(file.getName()); } else setDirectory(path);