[sip-comm-dev] Re: svn commit: r7675 - trunk: resources/sounds src/net/java/sip/communicator/impl/gui/main/presence/avatar src/net/java/sip/communicator/impl/gui/main...


#1

Hi Damien and Damencho :),

Just wanted to thank you for the nice feature and give you some feedback :slight_smile:

I really like the animation and the little arrow on mouse over! The popup menu looks also great. I was just thinking that we could change the default cursor to a hand cursor, when over the "Choose..." and "Clear..." items.

Another small issue is that in the "Image picker" window my image isn't centered, but appears on the left (see attached screenshot). In addition the slider below the image won't resize the square, but the image and it's impossible to adjust the image to the square because neither the image nor the square could be moved.

Also, I'm not very comfortable having two lines of buttons. May be we could think of some icons that could represent the "Choose...", "Take a photo" and "Reset" buttons in order to put them on the left of the same line as "Cancel" and "Set".

In the "Take photo" dialog I was thinking that the buttons should probably be aligned on the right as all other dialogs.

That's all for now:) Thanks again for the nice feature!

Cheers,
Yana


#2

Hi Yana,

I've fixed most of the issues (r7701), see inline.

Hi Damien and Damencho :),

Just wanted to thank you for the nice feature and give you some feedback :slight_smile:

I really like the animation and the little arrow on mouse over! The popup menu looks also great. I was just thinking that we could change the default cursor to a hand cursor, when over the "Choose..." and "Clear..." items.

This seems to be some kind of a problem only under macosx and I didn't
managed to find a resolution for it. Under Linux and Windows its ok.

Another small issue is that in the "Image picker" window my image isn't centered, but appears on the left (see attached screenshot). In addition the slider below the image won't resize the square, but the image and it's impossible to adjust the image to the square because neither the image nor the square could be moved.

The image cropping was not made to reflect changes in windows size,
but its fixed now and the image must be centered.
Actually you can move the image by dragging it with the mouse and the
zoom buttons are only enabled when new image is inserted(from file ot
webcam). Also I made the zoom images to also zoom in and out the
image, not only through the slider.

Also, I'm not very comfortable having two lines of buttons. May be we could think of some icons that could represent the "Choose...", "Take a photo" and "Reset" buttons in order to put them on the left of the same line as "Cancel" and "Set".

The reset button is now a picture and is next to the zoom buttons,
where it belongs and now all the buttons are in one row, later when we
have pictures we can replace and Choose and "Take a photo" buttons.

In the "Take photo" dialog I was thinking that the buttons should probably be aligned on the right as all other dialogs.

Done.

···

On Thu, Sep 9, 2010 at 6:07 PM, Yana Stamcheva <yana@sip-communicator.org> wrote:

That's all for now:) Thanks again for the nice feature!

Cheers,
Yana

)

On Sep 8, 2010, at 6:01 PM, damencho@dev.java.net wrote:

Author: damencho
Date: 2010-09-08 16:01:37+0000
New Revision: 7675

Added:
trunk/resources/sounds/webcamSnapshot.wav (contents, props changed)
Modified:
trunk/resources/sounds/sounds.properties
trunk/src/net/java/sip/communicator/impl/gui/main/presence/avatar/SelectAvatarMenu.java
trunk/src/net/java/sip/communicator/impl/gui/main/presence/avatar/imagepicker/ImagePickerDialog.java
trunk/src/net/java/sip/communicator/impl/gui/main/presence/avatar/imagepicker/WebcamDialog.java
trunk/src/net/java/sip/communicator/impl/neomedia/MediaConfiguration.java
trunk/src/net/java/sip/communicator/impl/neomedia/MediaServiceImpl.java
trunk/src/net/java/sip/communicator/impl/protocol/msn/OperationSetServerStoredAccountInfoMsnImpl.java
trunk/src/net/java/sip/communicator/service/neomedia/MediaService.java

Log:
Use camera to grab avatar image.

Modified: trunk/resources/sounds/sounds.properties
Url: https://sip-communicator.dev.java.net/source/browse/sip-communicator/trunk/resources/sounds/sounds.properties?view=diff&rev=7675&p1=trunk/resources/sounds/sounds.properties&p2=trunk/resources/sounds/sounds.properties&r1=7674&r2=7675

--- trunk/resources/sounds/sounds.properties (original)
+++ trunk/resources/sounds/sounds.properties 2010-09-08 16:01:37+0000
@@ -20,4 +20,6 @@
HANG_UP=resources/sounds/hangup.wav

CALL_SECURITY_ON=resources/sounds/zrtpSecure.wav
-CALL_SECURITY_ERROR=resources/sounds/zrtpAlert.wav
\ No newline at end of file
+CALL_SECURITY_ERROR=resources/sounds/zrtpAlert.wav
+
+WEBCAM_SNAPSHOT=resources/sounds/webcamSnapshot.wav

Added: trunk/resources/sounds/webcamSnapshot.wav
Url: https://sip-communicator.dev.java.net/source/browse/sip-communicator/trunk/resources/sounds/webcamSnapshot.wav?view=auto&rev=7675

Binary file. No diff available.

Modified: trunk/src/net/java/sip/communicator/impl/gui/main/presence/avatar/SelectAvatarMenu.java
Url: https://sip-communicator.dev.java.net/source/browse/sip-communicator/trunk/src/net/java/sip/communicator/impl/gui/main/presence/avatar/SelectAvatarMenu.java?view=diff&rev=7675&p1=trunk/src/net/java/sip/communicator/impl/gui/main/presence/avatar/SelectAvatarMenu.java&p2=trunk/src/net/java/sip/communicator/impl/gui/main/presence/avatar/SelectAvatarMenu.java&r1=7674&r2=7675

--- trunk/src/net/java/sip/communicator/impl/gui/main/presence/avatar/SelectAvatarMenu.java (original)
+++ trunk/src/net/java/sip/communicator/impl/gui/main/presence/avatar/SelectAvatarMenu.java 2010-09-08 16:01:37+0000
@@ -260,7 +260,8 @@
= GuiActivator.getRegisteredProviderForAccount(
accountID);

- if(protocolProvider != null)
+ if(protocolProvider != null
+ && protocolProvider.isRegistered())
{
OperationSetAvatar opSetAvatar
= protocolProvider

Modified: trunk/src/net/java/sip/communicator/impl/gui/main/presence/avatar/imagepicker/ImagePickerDialog.java
Url: https://sip-communicator.dev.java.net/source/browse/sip-communicator/trunk/src/net/java/sip/communicator/impl/gui/main/presence/avatar/imagepicker/ImagePickerDialog.java?view=diff&rev=7675&p1=trunk/src/net/java/sip/communicator/impl/gui/main/presence/avatar/imagepicker/ImagePickerDialog.java&p2=trunk/src/net/java/sip/communicator/impl/gui/main/presence/avatar/imagepicker/ImagePickerDialog.java&r1=7674&r2=7675

--- trunk/src/net/java/sip/communicator/impl/gui/main/presence/avatar/imagepicker/ImagePickerDialog.java (original)
+++ trunk/src/net/java/sip/communicator/impl/gui/main/presence/avatar/imagepicker/ImagePickerDialog.java 2010-09-08 16:01:37+0000
@@ -96,8 +96,6 @@

    this\.webcamButton = new JButton\(GuiActivator\.getResources\(\)
            \.getI18NString\(&quot;service\.gui\.avatar\.imagepicker\.TAKE\_PHOTO&quot;\)\);

- // disable it till we support it
- this.webcamButton.setEnabled(false);

    this\.webcamButton\.addActionListener\(this\);
    this\.webcamButton\.setName\(&quot;webcamButton&quot;\);

@@ -158,17 +156,17 @@
{
this.editPanel.reset();
}
- else
+ else if (name.equals("webcamButton"))
{
-// WebcamDialog dialog = new WebcamDialog(this);
-// dialog.setVisible(true);
-// byte[] bimage = dialog.getGrabbedImage();
-//
-// if (bimage != null)
-// {
-// Image i = new ImageIcon(bimage).getImage();
-// editPanel.setImage(ImageUtils.getBufferedImage(i));
-// }
+ WebcamDialog dialog = new WebcamDialog(this);
+ dialog.setVisible(true);
+ byte[] bimage = dialog.getGrabbedImage();
+
+ if (bimage != null)
+ {
+ Image i = new ImageIcon(bimage).getImage();
+ editPanel.setImage(ImageUtils.getBufferedImage(i));
+ }
}
}

Modified: trunk/src/net/java/sip/communicator/impl/gui/main/presence/avatar/imagepicker/WebcamDialog.java
Url: https://sip-communicator.dev.java.net/source/browse/sip-communicator/trunk/src/net/java/sip/communicator/impl/gui/main/presence/avatar/imagepicker/WebcamDialog.java?view=diff&rev=7675&p1=trunk/src/net/java/sip/communicator/impl/gui/main/presence/avatar/imagepicker/WebcamDialog.java&p2=trunk/src/net/java/sip/communicator/impl/gui/main/presence/avatar/imagepicker/WebcamDialog.java&r1=7674&r2=7675

--- trunk/src/net/java/sip/communicator/impl/gui/main/presence/avatar/imagepicker/WebcamDialog.java (original)
+++ trunk/src/net/java/sip/communicator/impl/gui/main/presence/avatar/imagepicker/WebcamDialog.java 2010-09-08 16:01:37+0000
@@ -8,36 +8,38 @@

import java.awt.*;
import java.awt.event.*;
+import java.awt.image.*;

import javax.swing.*;

import net.java.sip.communicator.impl.gui.*;
import net.java.sip.communicator.service.audionotifier.*;
-//import net.java.sip.communicator.service.media.*;
-import net.java.sip.communicator.service.protocol.event.*;
+import net.java.sip.communicator.service.neomedia.*;
+import net.java.sip.communicator.util.*;
import net.java.sip.communicator.util.swing.*;

/**
* A dialog showing the webcam and allowing the user to grap a snapshot
*
* @author Damien Roth
+ * @author Damian Minkov
*/
public class WebcamDialog
extends SIPCommDialog
implements ActionListener
-// , VideoListener
{
+ /**
+ * The <tt>Logger</tt> used by the <tt>WebcamDialog</tt> class and its
+ * instances for logging output.
+ */
+ private static final Logger logger = Logger.getLogger(WebcamDialog.class);
+
private VideoContainer videoContainer;
- private Component videoComponent = null;
-
- private JButton cancelButton;
+
private JButton grabSnapshot;
-
+
private byte[] grabbedImage = null;

- private TransparentPanel southPanel;
-
- private TransparentPanel timerPanel;
private TimerImage[] timerImages = new TimerImage[3];

/\*\*

@@ -66,40 +68,40 @@
this.grabSnapshot.addActionListener(this);
this.grabSnapshot.setEnabled(false);

- this.cancelButton = new JButton(GuiActivator.getResources()
+ JButton cancelButton = new JButton(GuiActivator.getResources()
.getI18NString("service.gui.avatar.imagepicker.CANCEL"));
- this.cancelButton.setName("cancel");
- this.cancelButton.addActionListener(this);
+ cancelButton.setName("cancel");
+ cancelButton.addActionListener(this);

    initAccessWebcam\(\);

-
// Timer Panel
- this.timerPanel = new TransparentPanel();
- this.timerPanel.setLayout(new GridLayout(0, 3));
+ TransparentPanel timerPanel = new TransparentPanel();
+ timerPanel.setLayout(new GridLayout(0, timerImages.length));

    TransparentPanel tp;
    for \(int i = 0; i &lt; this\.timerImages\.length; i\+\+\)
    \{

- this.timerImages[i] = new TimerImage("" + (3-i));
+ this.timerImages[i] = new TimerImage("" + (timerImages.length - i));

        tp = new TransparentPanel\(\);
        tp\.add\(this\.timerImages\[i\], BorderLayout\.CENTER\);

- this.timerPanel.add(tp);
+ timerPanel.add(tp);
}

- TransparentPanel buttonsPanel = new TransparentPanel(new GridLayout(1, 2));
+ TransparentPanel buttonsPanel
+ = new TransparentPanel(new GridLayout(1, 2));
buttonsPanel.add(this.grabSnapshot);
- buttonsPanel.add(this.cancelButton);
+ buttonsPanel.add(cancelButton);

    // South Panel

- this.southPanel = new TransparentPanel(new BorderLayout());
- this.southPanel.add(this.timerPanel, BorderLayout.CENTER);
- this.southPanel.add(buttonsPanel, BorderLayout.SOUTH);
+ TransparentPanel southPanel = new TransparentPanel(new BorderLayout());
+ southPanel.add(timerPanel, BorderLayout.CENTER);
+ southPanel.add(buttonsPanel, BorderLayout.SOUTH);

    this\.add\(this\.videoContainer, BorderLayout\.CENTER\);

- this.add(this.southPanel, BorderLayout.SOUTH);
+ this.add(southPanel, BorderLayout.SOUTH);
}

/\*\*

@@ -107,46 +109,39 @@
*/
private void initAccessWebcam()
{
- Dimension d = new Dimension(320, 240);
-
- // Create a container for the video
- this.videoContainer = new VideoContainer(new JLabel(
- GuiActivator.getResources()
- .getI18NString("service.gui.avatar.imagepicker.INITIALIZING"),
- JLabel.CENTER));
- this.videoContainer.setPreferredSize(d);
- this.videoContainer.setMinimumSize(d);
- this.videoContainer.setMaximumSize(d);
-
-// try
-// {
-// // Call the method in the media service
-// GuiActivator.getMediaService().createLocalVideoComponent(this);
-// } catch (MediaException e)
-// {
-// //todo: In what scenarios are exceptions thrown and how to manage them?
-// this.videoContainer = new VideoContainer(new JLabel(
-// GuiActivator.getResources()
-// .getI18NString("service.gui.avatar.imagepicker.WEBCAM_ERROR")));
-// e.printStackTrace();
-// }
+ //Call the method in the media service
+ this.videoContainer =
+ (VideoContainer)GuiActivator.getMediaService()
+ .getVideoPreviewComponent(
+ GuiActivator.getMediaService().getDefaultDevice(
+ MediaType.VIDEO,
+ MediaUseCase.CALL
+ ), 320, 240);
+ this.grabSnapshot.setEnabled(true);
}

/\*\*

- * Grap the current image of the webcam throught the MediaService
+ * Grab the current image of the webcam through the MediaService
*/
private void grabSnapshot()
{
- // Just call the method "grabSnapshot" from the MediaService with the component
-// try
-// {
-// this.grabbedImage = GuiActivator.getMediaService()
-// .grabSnapshot(this.videoComponent);
-// }
-// catch (Exception e)
-// {
-// e.printStackTrace();
-// }
+ try
+ {
+ Robot robot = new Robot();
+ Point location = videoContainer.getLocationOnScreen();
+
+ BufferedImage bi = robot.createScreenCapture(new Rectangle(
+ location.x,
+ location.y,
+ videoContainer.getWidth(),
+ videoContainer.getHeight()));
+ this.grabbedImage = ImageUtils.toByteArray(bi);
+ }
+ catch (Throwable e)
+ {
+ logger.error("Cannot create snapshot!", e);
+ }
+
close(false);
this.setVisible(false);
}
@@ -177,41 +172,8 @@

protected void close\(boolean isEscaped\)
\{

-// try
-// {
-// if (this.videoComponent != null)
-// {
-// GuiActivator.getMediaService()
-// .disposeLocalVideoComponent(this.videoComponent);
-// this.videoComponent = null;
-// }
-// }
-// catch (MediaException e)
-// {
-// // Better manager the exception !
-// e.printStackTrace();
-// }
- }
-
- public void videoAdded(VideoEvent event)
- {
- // Here is the important part. With this event, you get the component
- // containing the video !
-
- // You need to keep it. The returned componant is the key for all
- // the other methods !
- this.videoComponent = event.getVisualComponent();
-
- // Add the component in the container
- this.videoContainer.add(this.videoComponent);
-
- this.grabSnapshot.setEnabled(true);
- }
-
- public void videoRemoved(VideoEvent event)
- {
- // In case of the video is removed elsewhere
- this.videoComponent = null;
+ this.videoContainer = null;
+ dispose();
}

public void actionPerformed\(ActionEvent e\)

@@ -220,21 +182,21 @@

    if \(actName\.equals\(&quot;grab&quot;\)\)
    \{

- if (this.videoComponent == null)
- return;
-
this.grabSnapshot.setEnabled(false);
new SnapshotTimer().start();
}
else
{
close(false);
- this.setVisible(false);
+ dispose();
}
}
-
+
+ /**
+ * This thread grabs the snapshot by counting down.
+ */
private class SnapshotTimer
- extends Thread
+ extends Thread
{
@Override
public void run()
@@ -250,7 +212,7 @@
}
catch (InterruptedException e)
{
- e.printStackTrace();
+ logger.error("", e);
}
}

@@ -262,7 +224,10 @@

    \}
\}

-
+
+ /**
+ * These are the images shown as timer while grabbing the snapshot.
+ */
private class TimerImage
extends JComponent
{

Modified: trunk/src/net/java/sip/communicator/impl/neomedia/MediaConfiguration.java
Url: https://sip-communicator.dev.java.net/source/browse/sip-communicator/trunk/src/net/java/sip/communicator/impl/neomedia/MediaConfiguration.java?view=diff&rev=7675&p1=trunk/src/net/java/sip/communicator/impl/neomedia/MediaConfiguration.java&p2=trunk/src/net/java/sip/communicator/impl/neomedia/MediaConfiguration.java&r1=7674&r2=7675

--- trunk/src/net/java/sip/communicator/impl/neomedia/MediaConfiguration.java (original)
+++ trunk/src/net/java/sip/communicator/impl/neomedia/MediaConfiguration.java 2010-09-08 16:01:37+0000
@@ -5,20 +5,21 @@
*/
package net.java.sip.communicator.impl.neomedia;

+import java.util.*;
+
import java.awt.*;
import java.awt.event.*;
import java.io.*;

import javax.media.*;
import javax.media.MediaException;
-import javax.media.control.*;
-import javax.media.protocol.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;

-import net.java.sip.communicator.impl.neomedia.codec.video.*;
import net.java.sip.communicator.impl.neomedia.device.*;
+import net.java.sip.communicator.service.neomedia.*;
+import net.java.sip.communicator.service.neomedia.device.*;
import net.java.sip.communicator.service.resources.*;
import net.java.sip.communicator.util.*;
import net.java.sip.communicator.util.swing.*;
@@ -59,12 +60,6 @@
private static CaptureDeviceInfo videoDeviceInPreview;

/\*\*

- * The <code>Player</code> depicting the preview of the currently selected
- * <code>CaptureDeviceInfo</code>.
- */
- private static Player videoPlayerInPreview;
-
- /**
* Returns the audio configuration panel.
* @return the audio configuration panel
*/
@@ -83,65 +78,6 @@
}

/\*\*

- * Listens and shows the video in the video container when needed.
- * @param event the event when player has ready visual component.
- * @param videoContainer the container.
- */
- private static void controllerUpdateForPreview(ControllerEvent event,
- Container videoContainer)
- {
- if (event instanceof ConfigureCompleteEvent)
- {
- Processor player = (Processor) event.getSourceController();
-
- /*
- * Use SwScaler for the scaling since it produces an image with
- * better quality.
- */
- TrackControl[] trackControls = player.getTrackControls();
-
- if ((trackControls != null) && (trackControls.length != 0))
- try
- {
- for (TrackControl trackControl : trackControls)
- {
- SwScaler playerScaler = new SwScaler();
-
- trackControl.setCodecChain(
- new Codec[] { playerScaler });
- break;
- }
- }
- catch (UnsupportedPlugInException upiex)
- {
- logger.warn("Failed to add SwScaler to codec chain", upiex);
- }
-
- // Turn the Processor into a Player.
- try
- {
- player.setContentDescriptor(null);
- }
- catch (NotConfiguredError nce)
- {
- logger.error(
- "Failed to set ContentDescriptor of Processor",
- nce);
- }
-
- player.realize();
- }
- else if (event instanceof RealizeCompleteEvent)
- {
- Player player = (Player) event.getSourceController();
- Component video = player.getVisualComponent();
-
- showPreview(videoContainer, video, player);
- player.start();
- }
- }
-
- /**
* Creates the ui controls for portaudio.
* @param portAudioPanel the panel
*/
@@ -439,47 +375,38 @@
* @throws MediaException a problem getting preview.
*/
private static void createPreview(CaptureDeviceInfo device,
- final Container videoContainer)
+ final JComponent videoContainer)
throws IOException,
MediaException
{
videoContainer.removeAll();
- if (videoPlayerInPreview != null)
- disposePlayer(videoPlayerInPreview);
+
+ videoContainer.revalidate();
+ videoContainer.repaint();

    if \(device == null\)
        return;

- DataSource dataSource = Manager.createDataSource(device.getLocator());
- Dimension size = videoContainer.getPreferredSize();
-
- /*
- * Don't let the size be uselessly small just because the videoContainer
- * has too small a preferred size.
- */
- if ((size.width < 128) || (size.height < 96))
- {
- size.width = 128;
- size.height = 96;
- }
- VideoMediaStreamImpl
- .selectVideoSize(dataSource, size.width, size.height);
-
- // A Player is documented to be created on a connected DataSource.
- dataSource.connect();
+ Iterator<MediaDevice> mDevsIter =
+ NeomediaActivator.getMediaServiceImpl()
+ .getDevices(MediaType.VIDEO, MediaUseCase.ANY)
+ .iterator();
+ while(mDevsIter.hasNext())
+ {
+ MediaDeviceImpl dev = (MediaDeviceImpl)mDevsIter.next();
+ if(dev.getCaptureDeviceInfo().equals(device))
+ {
+ Component c = (Component)NeomediaActivator.getMediaServiceImpl()
+ .getVideoPreviewComponent(
+ dev,
+ videoContainer.getSize().width,
+ videoContainer.getSize().height);

- Processor player = Manager.createProcessor(dataSource);
+ videoContainer.add(c);

- videoPlayerInPreview = player;
-
- player.addControllerListener(new ControllerListener()
- {
- public void controllerUpdate(ControllerEvent event)
- {
- controllerUpdateForPreview(event, videoContainer);
+ break;
}
- });
- player.configure();
+ }
}

/\*\*

@@ -490,7 +417,7 @@
*/
private static Component createPreview(int type, final JComboBox comboBox)
{
- final Container preview;
+ final JComponent preview;
if (type == DeviceConfigurationComboBoxModel.VIDEO)
{
JLabel noPreview =
@@ -523,7 +450,7 @@

                Exception exception;
                try

- {
+ {
createPreview(device, preview);
exception = null;
}
@@ -566,7 +493,21 @@
& HierarchyEvent.DISPLAYABILITY_CHANGED)
!= 0)
&& comboBox.isDisplayable())
- comboBoxListener.actionPerformed(null);
+ {
+ // let current changes end their execution
+ // and after that trigger action on combobox
+ SwingUtilities.invokeLater(new Runnable(){
+ public void run()
+ {
+ comboBoxListener.actionPerformed(null);
+ }
+ });
+ }
+ else
+ {
+ if(!comboBox.isDisplayable())
+ videoDeviceInPreview = null;
+ }
}
});
} else
@@ -580,27 +521,12 @@
* @param noVideoComponent the container component.
* @return the video container.
*/
- private static Container createVideoContainer(Component noVideoComponent)
+ private static JComponent createVideoContainer(Component noVideoComponent)
{
return new VideoContainer(noVideoComponent);
}

/\*\*

- * Dispose the player used for the preview.
- * @param player the player.
- */
- private static void disposePlayer(Player player)
- {
- player.stop();
- player.deallocate();
- player.close();
-
- if ((videoPlayerInPreview != null)
- && videoPlayerInPreview.equals(player))
- videoPlayerInPreview = null;
- }
-
- /**
* The mnemonic for a type.
* @param type audio or video type.
* @return the mnemonic.
@@ -661,101 +587,4 @@
.getSelectedRow(), up);
table.getSelectionModel().setSelectionInterval(index, index);
}
-
- /**
- * Shows the preview panel.
- * @param previewContainer the container
- * @param preview the preview component.
- * @param player the player.
- */
- private static void showPreview(final Container previewContainer,
- final Component preview, final Player player)
- {
- if (!SwingUtilities.isEventDispatchThread())
- {
- SwingUtilities.invokeLater(new Runnable()
- {
- public void run()
- {
- showPreview(previewContainer, preview, player);
- }
- });
- return;
- }
-
- previewContainer.removeAll();
-
- if (preview != null)
- {
- HierarchyListener hierarchyListener = new HierarchyListener()
- {
- private Window window;
-
- private WindowListener windowListener;
-
- public void dispose()
- {
- if (windowListener != null)
- {
- if (window != null)
- {
- window.removeWindowListener(windowListener);
- window = null;
- }
- windowListener = null;
- }
- preview.removeHierarchyListener(this);
-
- disposePlayer(player);
- videoDeviceInPreview = null;
-
- /*
- * We've just disposed the player which created the preview
- * component so the preview component is of no use
- * regardless of whether the Media configuration form will
- * be redisplayed or not. And since the preview component
- * appears to be a huge object even after its player is
- * disposed, make sure to not reference it.
- */
- previewContainer.remove(preview);
- }
-
- public void hierarchyChanged(HierarchyEvent event)
- {
- if ((event.getChangeFlags()
- & HierarchyEvent.DISPLAYABILITY_CHANGED)
- == 0)
- return;
-
- if (!preview.isDisplayable())
- {
- dispose();
- return;
- }
-
- if (windowListener == null)
- {
- window = SwingUtilities.windowForComponent(preview);
- if (window != null)
- {
- windowListener = new WindowAdapter()
- {
- @Override
- public void windowClosing(WindowEvent event)
- {
- dispose();
- }
- };
- window.addWindowListener(windowListener);
- }
- }
- }
- };
- preview.addHierarchyListener(hierarchyListener);
-
- previewContainer.add(preview);
- }
- else
- disposePlayer(player);
- }
}

Modified: trunk/src/net/java/sip/communicator/impl/neomedia/MediaServiceImpl.java
Url: https://sip-communicator.dev.java.net/source/browse/sip-communicator/trunk/src/net/java/sip/communicator/impl/neomedia/MediaServiceImpl.java?view=diff&rev=7675&p1=trunk/src/net/java/sip/communicator/impl/neomedia/MediaServiceImpl.java&p2=trunk/src/net/java/sip/communicator/impl/neomedia/MediaServiceImpl.java&r1=7674&r2=7675

--- trunk/src/net/java/sip/communicator/impl/neomedia/MediaServiceImpl.java (original)
+++ trunk/src/net/java/sip/communicator/impl/neomedia/MediaServiceImpl.java 2010-09-08 16:01:37+0000
@@ -6,16 +6,25 @@
*/
package net.java.sip.communicator.impl.neomedia;

+import java.awt.*;
+import java.awt.event.*;
import java.util.*;
+import java.util.List;

import javax.media.*;
+import javax.media.control.*;
+import javax.media.protocol.*;
+import javax.swing.*;

import net.java.sip.communicator.impl.neomedia.codec.*;
+import net.java.sip.communicator.impl.neomedia.codec.video.*;
import net.java.sip.communicator.impl.neomedia.device.*;
import net.java.sip.communicator.impl.neomedia.format.*;
import net.java.sip.communicator.service.neomedia.*;
import net.java.sip.communicator.service.neomedia.device.*;
import net.java.sip.communicator.service.neomedia.format.*;
+import net.java.sip.communicator.util.*;
+import net.java.sip.communicator.util.swing.*;

/**
* Implements <tt>MediaService</tt> for JMF.
@@ -26,6 +35,11 @@
public class MediaServiceImpl
implements MediaService
{
+ /**
+ * The logger.
+ */
+ private static final Logger logger
+ = Logger.getLogger(MediaServiceImpl.class);

/\*\*
 \* With this property video support can be disabled \(enabled by default\)\.

@@ -608,4 +622,246 @@
}
return dynamicPayloadTypePreferences;
}
+
+ /**
+ * Creates a preview component for the specified device(video device) used
+ * to show video preview from that device.
+ *
+ * @param device the video device
+ * @param preferredWidth the width we prefer for the component
+ * @param preferredHeight the height we prefer for the component
+ * @return the preview component.
+ */
+ public Object getVideoPreviewComponent(MediaDevice device
+ , int preferredWidth, int preferredHeight)
+ {
+ JLabel noPreview =
+ new JLabel(NeomediaActivator.getResources().getI18NString(
+ "impl.media.configform.NO_PREVIEW"));
+ noPreview.setHorizontalAlignment(SwingConstants.CENTER);
+ noPreview.setVerticalAlignment(SwingConstants.CENTER);
+ final JComponent videoContainer
+ = new VideoContainer(noPreview);
+
+ videoContainer.setPreferredSize(
+ new Dimension(preferredWidth, preferredHeight));
+ videoContainer.setMaximumSize(
+ new Dimension(preferredWidth, preferredHeight));
+
+ try
+ {
+ if (device == null ||
+ ((MediaDeviceImpl)device).getCaptureDeviceInfo() == null)
+ {
+ return videoContainer;
+ }
+
+ DataSource dataSource = Manager.createDataSource(
+ ((MediaDeviceImpl)device).getCaptureDeviceInfo().getLocator());
+
+ /*
+ * Don't let the size be uselessly small just because the videoContainer
+ * has too small a preferred size.
+ */
+ if ((preferredWidth < 128) || (preferredHeight < 96))
+ {
+ preferredHeight = 128;
+ preferredWidth = 96;
+ }
+ VideoMediaStreamImpl
+ .selectVideoSize(dataSource, preferredWidth, preferredHeight);
+
+ // A Player is documented to be created on a connected DataSource.
+ dataSource.connect();
+
+ Processor player = Manager.createProcessor(dataSource);
+
+ player.addControllerListener(new ControllerListener()
+ {
+ public void controllerUpdate(ControllerEvent event)
+ {
+ controllerUpdateForPreview(event, videoContainer);
+ }
+ });
+ player.configure();
+
+ return videoContainer;
+ }
+ catch(Exception e)
+ {
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+
+ /**
+ * Listens and shows the video in the video container when needed.
+ * @param event the event when player has ready visual component.
+ * @param videoContainer the container.
+ */
+ private static void controllerUpdateForPreview(ControllerEvent event,
+ JComponent videoContainer)
+ {
+ if (event instanceof ConfigureCompleteEvent)
+ {
+ Processor player = (Processor) event.getSourceController();
+
+ /*
+ * Use SwScaler for the scaling since it produces an image with
+ * better quality.
+ */
+ TrackControl[] trackControls = player.getTrackControls();
+
+ if ((trackControls != null) && (trackControls.length != 0))
+ try
+ {
+ for (TrackControl trackControl : trackControls)
+ {
+ trackControl.setCodecChain(
+ new Codec[] { new SwScaler() });
+ break;
+ }
+ }
+ catch (UnsupportedPlugInException upiex)
+ {
+ logger.warn("Failed to add SwScaler to codec chain", upiex);
+ }
+
+ // Turn the Processor into a Player.
+ try
+ {
+ player.setContentDescriptor(null);
+ }
+ catch (NotConfiguredError nce)
+ {
+ logger.error(
+ "Failed to set ContentDescriptor of Processor",
+ nce);
+ }
+
+ player.realize();
+ }
+ else if (event instanceof RealizeCompleteEvent)
+ {
+ Player player = (Player) event.getSourceController();
+ Component video = player.getVisualComponent();
+
+ showPreview(videoContainer, video, player);
+ }
+ }
+
+ /**
+ * Shows the preview panel.
+ * @param previewContainer the container
+ * @param preview the preview component.
+ * @param player the player.
+ */
+ private static void showPreview(final JComponent previewContainer,
+ final Component preview, final Player player)
+ {
+ if (!SwingUtilities.isEventDispatchThread())
+ {
+ SwingUtilities.invokeLater(new Runnable()
+ {
+ public void run()
+ {
+ showPreview(previewContainer, preview, player);
+ }
+ });
+ return;
+ }
+
+ previewContainer.removeAll();
+
+ if (preview != null)
+ {
+ HierarchyListener hierarchyListener = new HierarchyListener()
+ {
+ private Window window;
+
+ private WindowListener windowListener;
+
+ public void dispose()
+ {
+ if (windowListener != null)
+ {
+ if (window != null)
+ {
+ window.removeWindowListener(windowListener);
+ window = null;
+ }
+ windowListener = null;
+ }
+ preview.removeHierarchyListener(this);
+
+ disposePlayer(player);
+
+ /*
+ * We've just disposed the player which created the preview
+ * component so the preview component is of no use
+ * regardless of whether the Media configuration form will
+ * be redisplayed or not. And since the preview component
+ * appears to be a huge object even after its player is
+ * disposed, make sure to not reference it.
+ */
+ previewContainer.remove(preview);
+ }
+
+ public void hierarchyChanged(HierarchyEvent event)
+ {
+ if ((event.getChangeFlags()
+ & HierarchyEvent.DISPLAYABILITY_CHANGED)
+ == 0)
+ return;
+
+ if (!preview.isDisplayable())
+ {
+ dispose();
+ return;
+ }
+ else
+ {
+ player.start();
+ }
+
+ if (windowListener == null)
+ {
+ window = SwingUtilities.windowForComponent(preview);
+ if (window != null)
+ {
+ windowListener = new WindowAdapter()
+ {
+ @Override
+ public void windowClosing(WindowEvent event)
+ {
+ dispose();
+ }
+ };
+ window.addWindowListener(windowListener);
+ }
+ }
+ }
+ };
+ preview.addHierarchyListener(hierarchyListener);
+
+ previewContainer.add(preview);
+
+ previewContainer.revalidate();
+ previewContainer.repaint();
+ }
+ else
+ disposePlayer(player);
+ }
+
+ /**
+ * Dispose the player used for the preview.
+ * @param player the player.
+ */
+ private static void disposePlayer(Player player)
+ {
+ player.stop();
+ player.deallocate();
+ player.close();
+ }
}

Modified: trunk/src/net/java/sip/communicator/impl/protocol/msn/OperationSetServerStoredAccountInfoMsnImpl.java
Url: https://sip-communicator.dev.java.net/source/browse/sip-communicator/trunk/src/net/java/sip/communicator/impl/protocol/msn/OperationSetServerStoredAccountInfoMsnImpl.java?view=diff&rev=7675&p1=trunk/src/net/java/sip/communicator/impl/protocol/msn/OperationSetServerStoredAccountInfoMsnImpl.java&p2=trunk/src/net/java/sip/communicator/impl/protocol/msn/OperationSetServerStoredAccountInfoMsnImpl.java&r1=7674&r2=7675

--- trunk/src/net/java/sip/communicator/impl/protocol/msn/OperationSetServerStoredAccountInfoMsnImpl.java (original)
+++ trunk/src/net/java/sip/communicator/impl/protocol/msn/OperationSetServerStoredAccountInfoMsnImpl.java 2010-09-08 16:01:37+0000
@@ -34,7 +34,7 @@
Logger.getLogger(OperationSetServerStoredAccountInfoMsnImpl.class);

/\*\*

- * The jabber provider that created us.
+ * The msn provider that created us.
*/
private ProtocolProviderServiceMsnImpl msnProvider = null;
/**
@@ -499,14 +499,14 @@
if (msnProvider == null)
{
throw new IllegalStateException(
- "The jabber provider must be non-null and signed on "
+ "The msn provider must be non-null and signed on "
+ "before being able to communicate.");
}

    if \(\!msnProvider\.isRegistered\(\)\)
    \{
        throw new IllegalStateException\(

- "The jabber provider must be signed on before "
+ "The msn provider must be signed on before "
+ "being able to communicate.");
}
}

Modified: trunk/src/net/java/sip/communicator/service/neomedia/MediaService.java
Url: https://sip-communicator.dev.java.net/source/browse/sip-communicator/trunk/src/net/java/sip/communicator/service/neomedia/MediaService.java?view=diff&rev=7675&p1=trunk/src/net/java/sip/communicator/service/neomedia/MediaService.java&p2=trunk/src/net/java/sip/communicator/service/neomedia/MediaService.java&r1=7674&r2=7675

--- trunk/src/net/java/sip/communicator/service/neomedia/MediaService.java (original)
+++ trunk/src/net/java/sip/communicator/service/neomedia/MediaService.java 2010-09-08 16:01:37+0000
@@ -6,7 +6,9 @@
*/
package net.java.sip.communicator.service.neomedia;

+import java.awt.*;
import java.util.*;
+import java.util.List;

import net.java.sip.communicator.service.neomedia.device.*;
import net.java.sip.communicator.service.neomedia.format.*;
@@ -178,4 +180,16 @@
* payload type number.
*/
public Map<MediaFormat, Byte> getDynamicPayloadTypePreferences();
+
+ /**
+ * Creates a preview component for the specified device(video device) used
+ * to show video preview from it.
+ *
+ * @param device the video device
+ * @param preferredWidth the width we prefer for the component
+ * @param preferredHeight the height we prefer for the component
+ * @return the preview component.
+ */
+ public Object getVideoPreviewComponent(
+ MediaDevice device, int preferredWidth, int preferredHeight);
}

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: commits-help@sip-communicator.dev.java.net

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net