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);