[Title] add screenshot dialog and hidden setting files
authorSon Hyunjun <hj79.son@samsung.com>
Mon, 26 Mar 2012 01:32:20 +0000 (10:32 +0900)
committerSon Hyunjun <hj79.son@samsung.com>
Mon, 26 Mar 2012 01:32:20 +0000 (10:32 +0900)
[Type] Feature
[Module] Skin
[Priority] Major
[CQ#]
[Redmine#]
[Problem]
[Cause]
[Solution]

Change-Id: I35b95540b02e02ca10ea2051dd813c49b58e0e61

16 files changed:
.cproject [new file with mode: 0644]
.project [new file with mode: 0644]
tizen/src/maru_sdl.c
tizen/src/maru_sdl.h
tizen/src/skin/client/.settings/org.eclipse.core.resources.prefs [new file with mode: 0644]
tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorSkin.java
tizen/src/skin/client/src/org/tizen/emulator/skin/comm/ICommunicator.java
tizen/src/skin/client/src/org/tizen/emulator/skin/comm/sock/SocketCommunicator.java
tizen/src/skin/client/src/org/tizen/emulator/skin/config/EmulatorConfig.java
tizen/src/skin/client/src/org/tizen/emulator/skin/exception/ScreenShotException.java [new file with mode: 0644]
tizen/src/skin/client/src/org/tizen/emulator/skin/screenshot/ScreenShotDialog.java
tizen/src/skin/client/src/org/tizen/emulator/skin/util/SkinRotation.java
tizen/src/skin/client/src/org/tizen/emulator/skin/util/SkinUtil.java
tizen/src/skin/maruskin_operation.c
tizen/src/skin/maruskin_operation.h
tizen/src/skin/maruskin_server.c

diff --git a/.cproject b/.cproject
new file mode 100644 (file)
index 0000000..85cfd90
--- /dev/null
+++ b/.cproject
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?fileVersion 4.0.0?>
+
+<cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
+       <storageModule moduleId="org.eclipse.cdt.core.settings">
+               <cconfiguration id="cdt.managedbuild.toolchain.gnu.base.599200627">
+                       <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.base.599200627" moduleId="org.eclipse.cdt.core.settings" name="Default">
+                               <externalSettings/>
+                               <extensions>
+                                       <extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+                                       <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+                                       <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+                                       <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+                                       <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+                                       <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+                               </extensions>
+                       </storageModule>
+                       <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+                               <configuration artifactName="${ProjName}" buildProperties="" description="" id="cdt.managedbuild.toolchain.gnu.base.599200627" name="Default" parent="org.eclipse.cdt.build.core.emptycfg">
+                                       <folderInfo id="cdt.managedbuild.toolchain.gnu.base.599200627.810909853" name="/" resourcePath="">
+                                               <toolChain id="cdt.managedbuild.toolchain.gnu.base.191848946" name="cdt.managedbuild.toolchain.gnu.base" superClass="cdt.managedbuild.toolchain.gnu.base">
+                                                       <targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.target.gnu.platform.base.1222568721" name="Debug Platform" osList="linux,hpux,aix,qnx" superClass="cdt.managedbuild.target.gnu.platform.base"/>
+                                                       <builder command="" id="cdt.managedbuild.target.gnu.builder.base.628599481" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.base"/>
+                                                       <tool id="cdt.managedbuild.tool.gnu.archiver.base.574770557" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
+                                                       <tool id="cdt.managedbuild.tool.gnu.cpp.compiler.base.2079317122" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.base"/>
+                                                       <tool id="cdt.managedbuild.tool.gnu.c.compiler.base.1922596436" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base">
+                                                               <option id="gnu.c.compiler.option.include.paths.507417315" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" valueType="includePath">
+                                                                       <listOptionValue builtIn="false" value="&quot;${workspace_loc:/qemu-develop/i386-softmmu}&quot;"/>
+                                                                       <listOptionValue builtIn="false" value="/usr/include/SDL"/>
+                                                               </option>
+                                                               <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.676204606" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
+                                                       </tool>
+                                                       <tool id="cdt.managedbuild.tool.gnu.c.linker.base.2026169100" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.base">
+                                                               <inputType id="cdt.managedbuild.tool.gnu.c.linker.input.1055445101" superClass="cdt.managedbuild.tool.gnu.c.linker.input">
+                                                                       <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+                                                                       <additionalInput kind="additionalinput" paths="$(LIBS)"/>
+                                                               </inputType>
+                                                       </tool>
+                                                       <tool id="cdt.managedbuild.tool.gnu.cpp.linker.base.1635507651" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.base"/>
+                                                       <tool id="cdt.managedbuild.tool.gnu.assembler.base.903060300" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.base">
+                                                               <inputType id="cdt.managedbuild.tool.gnu.assembler.input.1155102024" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
+                                                       </tool>
+                                               </toolChain>
+                                       </folderInfo>
+                               </configuration>
+                       </storageModule>
+                       <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+               </cconfiguration>
+       </storageModule>
+       <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+               <project id="qemu-develop.null.125981814" name="qemu-develop"/>
+       </storageModule>
+       <storageModule moduleId="refreshScope" versionNumber="1">
+               <resource resourceType="PROJECT" workspacePath="/qemu-develop"/>
+       </storageModule>
+       <storageModule moduleId="scannerConfiguration">
+               <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+               <scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.base.599200627;cdt.managedbuild.toolchain.gnu.base.599200627.810909853;cdt.managedbuild.tool.gnu.c.compiler.base.1922596436;cdt.managedbuild.tool.gnu.c.compiler.input.676204606">
+                       <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"/>
+               </scannerConfigBuildInfo>
+       </storageModule>
+</cproject>
diff --git a/.project b/.project
new file mode 100644 (file)
index 0000000..000aa18
--- /dev/null
+++ b/.project
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>qemu-develop</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
+                       <triggers>clean,full,incremental,</triggers>
+                       <arguments>
+                               <dictionary>
+                                       <key>?name?</key>
+                                       <value></value>
+                               </dictionary>
+                               <dictionary>
+                                       <key>org.eclipse.cdt.make.core.append_environment</key>
+                                       <value>true</value>
+                               </dictionary>
+                               <dictionary>
+                                       <key>org.eclipse.cdt.make.core.autoBuildTarget</key>
+                                       <value>all</value>
+                               </dictionary>
+                               <dictionary>
+                                       <key>org.eclipse.cdt.make.core.buildArguments</key>
+                                       <value></value>
+                               </dictionary>
+                               <dictionary>
+                                       <key>org.eclipse.cdt.make.core.buildCommand</key>
+                                       <value></value>
+                               </dictionary>
+                               <dictionary>
+                                       <key>org.eclipse.cdt.make.core.cleanBuildTarget</key>
+                                       <value>clean</value>
+                               </dictionary>
+                               <dictionary>
+                                       <key>org.eclipse.cdt.make.core.contents</key>
+                                       <value>org.eclipse.cdt.make.core.activeConfigSettings</value>
+                               </dictionary>
+                               <dictionary>
+                                       <key>org.eclipse.cdt.make.core.enableAutoBuild</key>
+                                       <value>false</value>
+                               </dictionary>
+                               <dictionary>
+                                       <key>org.eclipse.cdt.make.core.enableCleanBuild</key>
+                                       <value>true</value>
+                               </dictionary>
+                               <dictionary>
+                                       <key>org.eclipse.cdt.make.core.enableFullBuild</key>
+                                       <value>true</value>
+                               </dictionary>
+                               <dictionary>
+                                       <key>org.eclipse.cdt.make.core.fullBuildTarget</key>
+                                       <value>all</value>
+                               </dictionary>
+                               <dictionary>
+                                       <key>org.eclipse.cdt.make.core.stopOnError</key>
+                                       <value>true</value>
+                               </dictionary>
+                               <dictionary>
+                                       <key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>
+                                       <value>false</value>
+                               </dictionary>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
+                       <triggers>full,incremental,</triggers>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.cdt.core.cnature</nature>
+               <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
+               <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
+       </natures>
+       <filteredResources>
+               <filter>
+                       <id>1332425928400</id>
+                       <name></name>
+                       <type>22</type>
+                       <matcher>
+                               <id>org.eclipse.ui.ide.multiFilter</id>
+                               <arguments>1.0-name-matches-false-false-*.o</arguments>
+                       </matcher>
+               </filter>
+               <filter>
+                       <id>1332425928407</id>
+                       <name></name>
+                       <type>22</type>
+                       <matcher>
+                               <id>org.eclipse.ui.ide.multiFilter</id>
+                               <arguments>1.0-name-matches-false-false-*.d</arguments>
+                       </matcher>
+               </filter>
+       </filteredResources>
+</projectDescription>
index 9703c82..b69cc93 100644 (file)
@@ -59,6 +59,7 @@ static int sdl_thread_initialized = 0;
 #define SDL_FLAGS (SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL | SDL_NOFRAME)
 #define SDL_BPP 32
 
+DisplaySurface* qemu_display_surface = NULL;
 
 static void qemu_update(void)
 {
@@ -226,6 +227,9 @@ static void qemu_ds_refresh(DisplayState *ds)
 
     vga_hw_update();
 
+    // surface may be NULL in init func.
+    qemu_display_surface = ds->surface;
+
     while (maru_sdl_poll_event(ev)) {
         switch (ev->type) {
             case SDL_VIDEORESIZE:
@@ -353,3 +357,7 @@ void maruskin_sdl_resize(void)
     //This function is thread safe, and can be called from other threads safely.
     SDL_PushEvent(&ev);
 }
+
+DisplaySurface* get_qemu_display_surface( void ) {
+    return qemu_display_surface;
+}
index 442fc96..359a39a 100644 (file)
@@ -42,6 +42,7 @@
 
 #include <SDL.h>
 #include <SDL_syswm.h>
+#include "qemu-common.h"
 
 #define SDL_USER_EVENT_CODE_HARDKEY 1
 
@@ -49,4 +50,6 @@ void maruskin_display_init(DisplayState *ds);
 void maruskin_sdl_init(int swt_handle, int lcd_size_width, int lcd_size_height);
 void maruskin_sdl_resize(void);
 
+DisplaySurface* get_qemu_display_surface( void );
+
 #endif /* MARU_SDL_H_ */
diff --git a/tizen/src/skin/client/.settings/org.eclipse.core.resources.prefs b/tizen/src/skin/client/.settings/org.eclipse.core.resources.prefs
new file mode 100644 (file)
index 0000000..99f26c0
--- /dev/null
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
index 54486a2..3feb87f 100644 (file)
@@ -65,10 +65,10 @@ import org.eclipse.swt.widgets.Event;
 import org.eclipse.swt.widgets.Listener;
 import org.eclipse.swt.widgets.Menu;
 import org.eclipse.swt.widgets.MenuItem;
-import org.eclipse.swt.widgets.MessageBox;
 import org.eclipse.swt.widgets.Shell;
 import org.tizen.emulator.skin.comm.ICommunicator.KeyEventType;
 import org.tizen.emulator.skin.comm.ICommunicator.MouseEventType;
+import org.tizen.emulator.skin.comm.ICommunicator.RotationInfo;
 import org.tizen.emulator.skin.comm.ICommunicator.SendCommand;
 import org.tizen.emulator.skin.comm.sock.SocketCommunicator;
 import org.tizen.emulator.skin.comm.sock.data.BooleanData;
@@ -89,7 +89,6 @@ import org.tizen.emulator.skin.log.SkinLogger;
 import org.tizen.emulator.skin.screenshot.ScreenShotDialog;
 import org.tizen.emulator.skin.util.SkinRegion;
 import org.tizen.emulator.skin.util.SkinRotation;
-import org.tizen.emulator.skin.util.SkinRotation.RotationInfo;
 import org.tizen.emulator.skin.util.SkinUtil;
 import org.tizen.emulator.skin.util.StringUtil;
 
@@ -164,7 +163,7 @@ public class EmulatorSkin {
                
                int scale = SkinUtil.getValidScale( config );
                
-//             short rotationId = config.getPropertyShort( PropertiesConstants.WINDOW_DIRECTION, (short) 0 );
+//             short rotationId = config.getPropertyShort( PropertiesConstants.WINDOW_ROTATION, RotationInfo.PORTRAIT.id() );
                // has to be portrait mode at first booting time
                arrangeSkin( lcdWidth, lcdHeight, scale, RotationInfo.PORTRAIT.id() );
                
@@ -174,12 +173,12 @@ public class EmulatorSkin {
                addMenuItems( menu );
                shell.setMenu( menu );
                
-               // sdl uses this handle id.
-               windowHandleId = getWindowHandleId( lcdCanvas );
-               
                addLCDListener( lcdCanvas );
                addShellListener( shell );
 
+               // sdl uses this handle id.
+               windowHandleId = getWindowHandleId( lcdCanvas );
+
                return windowHandleId;
 
        }
@@ -309,7 +308,7 @@ public class EmulatorSkin {
                                        config.setProperty( PropertiesConstants.WINDOW_X, shell.getLocation().x );
                                        config.setProperty( PropertiesConstants.WINDOW_Y, shell.getLocation().y );
                                        config.setProperty( PropertiesConstants.WINDOW_SCALE, currentScale );
-                                       config.setProperty( PropertiesConstants.WINDOW_DIRECTION, currentRotationId );
+                                       config.setProperty( PropertiesConstants.WINDOW_ROTATION, currentRotationId );
 
                                        config.saveProperties();
 
@@ -619,7 +618,7 @@ public class EmulatorSkin {
                deviceInfoItem.setText( emulatorName );
                deviceInfoItem.setImage( imageRegistry.getIcon( IconName.DEVICE_INFO ) );
                //FIXME
-//             deviceInfoItem.setEnabled( false );
+               deviceInfoItem.setEnabled( false );
                deviceInfoItem.addSelectionListener( new SelectionAdapter() {
                        @Override
                        public void widgetSelected( SelectionEvent e ) {
@@ -706,11 +705,7 @@ public class EmulatorSkin {
                                                procSdb.start(); //open sdb shell
                                        } catch (Exception ee) {
                                                logger.log(Level.SEVERE, ee.getMessage(), ee);
-
-                                               MessageBox messageBox = new MessageBox(shell, SWT.ICON_ERROR);
-                                               messageBox.setText(SkinUtil.makeEmulatorName(config));
-                                               messageBox.setMessage(ee.getMessage());
-                                               messageBox.open();
+                                               SkinUtil.openMessage( shell, null, "Fail to open Shell.", SWT.ICON_ERROR, config );
                                        }
                                }
 
@@ -738,9 +733,10 @@ public class EmulatorSkin {
 
                final List<MenuItem> rotationList = new ArrayList<MenuItem>();
 
-               final short storedDirectionId = config.getPropertyShort( PropertiesConstants.WINDOW_DIRECTION,
-                               (short) RotationInfo.PORTRAIT.id() );
-
+//             final short storedDirectionId = config.getPropertyShort( PropertiesConstants.WINDOW_ROTATION,
+//                             (short) RotationInfo.PORTRAIT.id() );
+               final short storedDirectionId = RotationInfo.PORTRAIT.id();
+               
                Iterator<Entry<Short, RotationType>> iterator = SkinRotation.getRotationIterator();
 
                while ( iterator.hasNext() ) {
@@ -756,6 +752,10 @@ public class EmulatorSkin {
                                menuItem.setSelection( true );
                        }
 
+                       if ( RotationInfo.PORTRAIT.id() == rotationId ) {
+                               menuItem.setSelection( true );
+                       }
+
                        rotationList.add( menuItem );
 
                }
@@ -785,10 +785,8 @@ public class EmulatorSkin {
                                                }
                                        }
                                        ///////////
-
-                                       MessageBox messageBox = new MessageBox( shell );
-                                       messageBox.setMessage( "Rotation is not ready." );
-                                       messageBox.open();
+                                       
+                                       SkinUtil.openMessage( shell, null, "Rotation is not ready.", SWT.ICON_WARNING, config );
 
                                        return;
 
@@ -883,13 +881,24 @@ public class EmulatorSkin {
                screenshotItem.setText( "Screen Shot" );
                screenshotItem.setImage( imageRegistry.getIcon( IconName.SCREENSHOT ) );
                screenshotItem.addSelectionListener( new SelectionAdapter() {
+                       
                        private boolean isOpen;
+                       
                        @Override
                        public void widgetSelected( SelectionEvent e ) {
-                               if( !isOpen ) {
-                                       isOpen = true;
-                                       ScreenShotDialog dialog = new ScreenShotDialog( shell, lcdCanvas, config );
-                                       dialog.open();
+                               
+                               try {
+                                       
+                                       if( !isOpen ) {
+                                               isOpen = true;
+                                               ScreenShotDialog dialog = new ScreenShotDialog( shell, communicator, EmulatorSkin.this, config );
+                                               dialog.open();
+                                       }
+                                       
+                               } catch ( Exception ex ) {
+                                       logger.log( Level.SEVERE, "Fail to create a screen shot.", ex );
+                                       SkinUtil.openMessage( shell, null, "Fail to create a screen shot.", SWT.ERROR, config );
+                               } finally {
                                        isOpen = false;
                                }
                        }
@@ -978,4 +987,8 @@ public class EmulatorSkin {
 
        }
 
+       public short getCurrentRotationId() {
+               return currentRotationId;
+       }
+
 }
index d0aecab..4800016 100644 (file)
@@ -30,6 +30,7 @@
 package org.tizen.emulator.skin.comm;
 
 import org.tizen.emulator.skin.comm.sock.data.ISendData;
+import org.tizen.emulator.skin.dbi.RotationNameType;
 
 /**
  * 
@@ -102,6 +103,44 @@ public interface ICommunicator extends Runnable {
 
        }
 
+       public enum RotationInfo {
+
+               PORTRAIT( RotationNameType.PORTRAIT.value(), (short)0, 0 ),
+               LANDSCAPE( RotationNameType.LANDSCAPE.value(), (short)1, -90 ),
+               REVERSE_PORTRAIT( RotationNameType.REVERSE_PORTRAIT.value(), (short)2, 180 ),
+               REVERSE_LANDSCAPE( RotationNameType.REVERSE_LANDSCAPE.value(), (short)3, 90 );
+               
+               private String value;
+               private short id;
+               private int angle;
+               
+               RotationInfo( String value, short id, int ratio ) {
+                       this.value = value;
+                       this.id = id;
+                       this.angle = ratio;
+               }
+               public String value() {
+                       return this.value;
+               }
+               public int angle() {
+                       return this.angle;
+               }
+               public short id() {
+                       return this.id;
+               }
+               
+               public static RotationInfo getValue( short id ) {
+                       RotationInfo[] values = RotationInfo.values();
+                       for (int i = 0; i < values.length; i++) {
+                               if( values[i].id == id ) {
+                                       return values[i];
+                               }
+                       }
+                       throw new IllegalArgumentException( Integer.toString(id) );
+               }
+
+       }
+
        public enum SendCommand {
                
                SEND_START( (short)1 ),
@@ -112,6 +151,7 @@ public interface ICommunicator extends Runnable {
                CHANGE_LCD_STATE( (short)13 ),
                OPEN_SHELL( (short)14 ),
                USB_KBD( (short)15 ),
+               SCREEN_SHOT( (short)16 ),
                
                RESPONSE_HEART_BEAT( (short)900 ),
                CLOSE( (short)998 ),
@@ -147,6 +187,7 @@ public interface ICommunicator extends Runnable {
        public enum ReceiveCommand {
                
                HEART_BEAT( (short)1 ),
+               SCREEN_SHOT_DATA( (short)2 ),
                SENSOR_DAEMON_START( (short)800 ),
                SHUTDOWN( (short)999 );
                
index f1c41fb..3737f75 100644 (file)
@@ -29,6 +29,7 @@
 
 package org.tizen.emulator.skin.comm.sock;
 
+import java.io.BufferedInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
@@ -62,8 +63,36 @@ import org.tizen.emulator.skin.util.SkinUtil;
  */
 public class SocketCommunicator implements ICommunicator {
 
+       public class DataTranfer {
+
+               private boolean isTransferState;
+               private byte[] receivedData;
+
+               private DataTranfer() {
+               }
+
+               private void reset() {
+                       receivedData = null;
+                       isTransferState = true;
+               }
+
+               private void setData( byte[] data ) {
+                       this.receivedData = data;
+                       isTransferState = false;
+               }
+
+               public synchronized boolean isTransferState() {
+                       return isTransferState;
+               }
+
+               public synchronized byte[] getReceivedData() {
+                       return receivedData;
+               }
+
+       }
+
        private Logger logger = SkinLogger.getSkinLogger( SocketCommunicator.class ).getLogger();
-       
+
        private EmulatorConfig config;
        private int uId;
        private int windowHandleId;
@@ -73,33 +102,37 @@ public class SocketCommunicator implements ICommunicator {
        private DataInputStream dis;
        private DataOutputStream dos;
 
+       private DataTranfer dataTransfer;
+
        private AtomicInteger heartbeatCount;
 
        private boolean isTerminated;
        private ScheduledExecutorService heartbeatExecutor;
-       
+
        private boolean isSensorDaemonStarted;
 
-       public SocketCommunicator(EmulatorConfig config, int uId, int windowHandleId, EmulatorSkin skin) {
+       public SocketCommunicator( EmulatorConfig config, int uId, int windowHandleId, EmulatorSkin skin ) {
 
                this.config = config;
                this.uId = uId;
                this.windowHandleId = windowHandleId;
                this.skin = skin;
 
-               this.heartbeatCount = new AtomicInteger(0);
+               this.dataTransfer = new DataTranfer();
+
+               this.heartbeatCount = new AtomicInteger( 0 );
                this.heartbeatExecutor = Executors.newSingleThreadScheduledExecutor();
 
                try {
 
-                       String portString = config.getArg(ArgsConstants.SERVER_PORT);
-                       int port = Integer.parseInt(portString);
-                       socket = new Socket("127.0.0.1", port);
-                       logger.info("socket.isConnected():" + socket.isConnected());
+                       String portString = config.getArg( ArgsConstants.SERVER_PORT );
+                       int port = Integer.parseInt( portString );
+                       socket = new Socket( "127.0.0.1", port );
+                       logger.info( "socket.isConnected():" + socket.isConnected() );
 
-               } catch (UnknownHostException e) {
+               } catch ( UnknownHostException e ) {
                        logger.log( Level.SEVERE, e.getMessage(), e );
-               } catch (IOException e) {
+               } catch ( IOException e ) {
                        logger.log( Level.SEVERE, e.getMessage(), e );
                }
 
@@ -110,47 +143,46 @@ public class SocketCommunicator implements ICommunicator {
 
                try {
 
-                       dis = new DataInputStream(socket.getInputStream());
-                       dos = new DataOutputStream(socket.getOutputStream());
-                       
+                       dis = new DataInputStream( socket.getInputStream() );
+                       dos = new DataOutputStream( socket.getOutputStream() );
+
+                       int width = Integer.parseInt( config.getArg( ArgsConstants.RESOLUTION_WIDTH ) );
+                       int height = Integer.parseInt( config.getArg( ArgsConstants.RESOLUTION_HEIGHT ) );
                        int scale = SkinUtil.getValidScale( config );
-                       
-                       short rotation = config.getPropertyShort( PropertiesConstants.WINDOW_DIRECTION, (short) 0 );
-                       
-                       sendToQEMU(SendCommand.SEND_START,
-                                       new StartData(windowHandleId,
-                                                       Integer.parseInt( config.getArg(ArgsConstants.RESOLUTION_WIDTH) ),
-                                                       Integer.parseInt( config.getArg(ArgsConstants.RESOLUTION_HEIGHT) ),
-                                                       scale, rotation));
-
-               } catch (IOException e) {
+                       short rotation = config.getPropertyShort( PropertiesConstants.WINDOW_ROTATION, RotationInfo.PORTRAIT.id() );
+
+                       StartData startData = new StartData( windowHandleId, width, height, scale, rotation );
+
+                       sendToQEMU( SendCommand.SEND_START, startData );
+
+               } catch ( IOException e ) {
                        logger.log( Level.SEVERE, e.getMessage(), e );
                        terminate();
                        return;
                }
-               
+
                String ignoreHeartbeatString = config.getArg( ArgsConstants.TEST_HEART_BEAT_IGNORE, Boolean.FALSE.toString() );
                Boolean ignoreHeartbeat = Boolean.parseBoolean( ignoreHeartbeatString );
-               
-               if( ignoreHeartbeat ) {
+
+               if ( ignoreHeartbeat ) {
                        logger.info( "Ignore Skin heartbeat." );
-               }else {
-                       
-                       heartbeatExecutor.scheduleAtFixedRate(new Runnable() {
-                               
+               } else {
+
+                       heartbeatExecutor.scheduleAtFixedRate( new Runnable() {
+
                                @Override
                                public void run() {
-                                       
+
                                        increaseHeartbeatCount();
-                                       
-                                       if (isHeartbeatExpired()) {
+
+                                       if ( isHeartbeatExpired() ) {
                                                terminate();
                                        }
-                                       
+
                                }
-                               
-                       }, 0, EmulatorConstants.HEART_BEAT_INTERVAL, TimeUnit.SECONDS);
-                       
+
+                       }, 0, EmulatorConstants.HEART_BEAT_INTERVAL, TimeUnit.SECONDS );
+
                }
 
                while ( true ) {
@@ -163,13 +195,14 @@ public class SocketCommunicator implements ICommunicator {
 
                                int reqId = dis.readInt();
                                short cmd = dis.readShort();
+                               int length = dis.readInt();
 
-                               if( logger.isLoggable( Level.FINE ) ) {
-                                       logger.fine( "[Socket] read - reqId:" + reqId + ", command:" + cmd + ", " );
+                               if ( logger.isLoggable( Level.FINE ) ) {
+                                       logger.fine( "[Socket] read - reqId:" + reqId + ", command:" + cmd + ", dataLength:" + length );
                                }
 
                                ReceiveCommand command = null;
-                               
+
                                try {
                                        command = ReceiveCommand.getValue( cmd );
                                } catch ( IllegalArgumentException e ) {
@@ -180,12 +213,25 @@ public class SocketCommunicator implements ICommunicator {
                                switch ( command ) {
                                case HEART_BEAT: {
                                        resetHeartbeatCount();
-                                       if( logger.isLoggable( Level.FINE ) ) {
+                                       if ( logger.isLoggable( Level.FINE ) ) {
                                                logger.fine( "received HEAR_BEAT from QEMU." );
                                        }
                                        sendToQEMU( SendCommand.RESPONSE_HEART_BEAT, null );
                                        break;
                                }
+                               case SCREEN_SHOT_DATA: {
+                                       logger.info( "received SCREEN_SHOT_DATA from QEMU." );
+
+                                       synchronized ( dataTransfer ) {
+                                               byte[] imageData = readData( dis, length );
+                                               dataTransfer.setData( imageData );
+                                               dataTransfer.notifyAll();
+                                       }
+
+                                       logger.info( "finish receiving data from QEMU." );
+
+                                       break;
+                               }
                                case SENSOR_DAEMON_START: {
                                        logger.info( "received SENSOR_DAEMON_START from QEMU." );
                                        synchronized ( this ) {
@@ -212,47 +258,91 @@ public class SocketCommunicator implements ICommunicator {
                        }
 
                }
-               
+
+       }
+
+       private byte[] readData( DataInputStream is, int length ) throws IOException {
+
+               if ( 0 >= length ) {
+                       return null;
+               }
+
+               BufferedInputStream bfis = new BufferedInputStream( is, length );
+               byte[] data = new byte[length];
+
+               int read = 0;
+               int total = 0;
+
+               while ( true ) {
+
+                       if ( total == length ) {
+                               break;
+                       }
+
+                       read = bfis.read( data, total, length - total );
+
+                       if ( 0 > read ) {
+                               if ( total < length ) {
+                                       continue;
+                               }
+                       } else {
+                               total += read;
+                       }
+
+               }
+
+               logger.info( "finished reading stream. read:" + total );
+
+               return data;
+
+       }
+
+       public void sendToQEMU( SendCommand command, ISendData data, boolean useDataTransfer ) {
+               if ( useDataTransfer ) {
+                       this.dataTransfer.reset();
+               }
+               sendToQEMU( command, data );
        }
 
        @Override
-       public void sendToQEMU(SendCommand command, ISendData data) {
+       public void sendToQEMU( SendCommand command, ISendData data ) {
 
                try {
 
-                       //anyway down casting
-                       int reqId = (int) UUID.randomUUID().getMostSignificantBits();
-                       
+                       // anyway down casting
+                       long longReqId = UUID.randomUUID().getMostSignificantBits();
+                       int reqId = (int) ( longReqId >> 32 );
+
                        ByteArrayOutputStream bao = new ByteArrayOutputStream();
-                       DataOutputStream dataOutputStream = new DataOutputStream(bao);
-                       
-                       dataOutputStream.writeInt(uId);
-                       dataOutputStream.writeInt(reqId);
-                       dataOutputStream.writeShort(command.value());
-                       
+                       DataOutputStream dataOutputStream = new DataOutputStream( bao );
+
+                       dataOutputStream.writeInt( uId );
+                       dataOutputStream.writeInt( reqId );
+                       dataOutputStream.writeShort( command.value() );
+
                        short length = 0;
-                       if( null == data ) {
+                       if ( null == data ) {
                                length = 0;
-                               dataOutputStream.writeShort(length);
-                       }else {
+                               dataOutputStream.writeShort( length );
+                       } else {
                                byte[] byteData = data.serialize();
                                length = (short) byteData.length;
-                               dataOutputStream.writeShort(length);
-                               dataOutputStream.write(byteData);
+                               dataOutputStream.writeShort( length );
+                               dataOutputStream.write( byteData );
                        }
 
                        dataOutputStream.flush();
-                       
-                       dos.write(bao.toByteArray());
+
+                       dos.write( bao.toByteArray() );
                        dos.flush();
 
-                       if( logger.isLoggable( Level.FINE ) ) {
-                               logger.fine( "[Socket] write - uid:" + uId + ", reqId:" + reqId + ", command:" + command.value() + " - "
-                                               + command.toString() + ", length:" + length );
+                       if ( logger.isLoggable( Level.FINE ) ) {
+                               logger.fine( "[Socket] write - uid:" + uId + ", reqId:" + reqId + ", command:" + command.value()
+                                               + " - " + command.toString() + ", length:" + length );
                        }
 
                        if ( 0 < length ) {
-                               if( logger.isLoggable( Level.FINE ) ) {
+                               if ( logger.isLoggable( Level.FINE ) ) {
                                        logger.fine( "== data ==" );
                                        logger.fine( data.toString() );
                                }
@@ -274,8 +364,8 @@ public class SocketCommunicator implements ICommunicator {
 
        private void increaseHeartbeatCount() {
                int count = heartbeatCount.incrementAndGet();
-               if( logger.isLoggable( Level.FINE ) ) {
-                       logger.fine("HB count : " + count);
+               if ( logger.isLoggable( Level.FINE ) ) {
+                       logger.fine( "HB count : " + count );
                }
        }
 
@@ -284,15 +374,19 @@ public class SocketCommunicator implements ICommunicator {
        }
 
        private void resetHeartbeatCount() {
-               heartbeatCount.set(0);
+               heartbeatCount.set( 0 );
+       }
+
+       public DataTranfer getDataTranfer() {
+               return dataTransfer;
        }
 
        @Override
        public void terminate() {
-               if (null != heartbeatExecutor) {
+               if ( null != heartbeatExecutor ) {
                        heartbeatExecutor.shutdownNow();
                }
-               IOUtil.closeSocket(socket);
+               IOUtil.closeSocket( socket );
                skin.shutdown();
        }
 
index da7a1f1..d810498 100644 (file)
@@ -65,7 +65,7 @@ public class EmulatorConfig {
        public interface PropertiesConstants {
                public static final String WINDOW_X = "window.x";
                public static final String WINDOW_Y = "window.y";
-               public static final String WINDOW_DIRECTION = "window.rotate";
+               public static final String WINDOW_ROTATION = "window.rotate";
                public static final String WINDOW_SCALE = "window.scale";
        }
        
diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/exception/ScreenShotException.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/exception/ScreenShotException.java
new file mode 100644 (file)
index 0000000..ae9b09d
--- /dev/null
@@ -0,0 +1,56 @@
+/**
+ * 
+ *
+ * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * Hyunjun Son <hj79.son@samsung.com>
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+package org.tizen.emulator.skin.exception;
+
+/**
+ * 
+ *
+ */
+public class ScreenShotException extends EmulatorException {
+
+       private static final long serialVersionUID = 7527776121326217994L;
+
+       public ScreenShotException() {
+               super();
+       }
+
+       public ScreenShotException( Throwable cause ) {
+               super( cause );
+       }
+
+    public ScreenShotException( String message ) {
+        super( message );
+    }
+
+    public ScreenShotException( String message, Throwable cause ) {
+        super( message, cause );
+    }
+
+}
index 0fe11af..647f050 100644 (file)
@@ -29,8 +29,9 @@
 
 package org.tizen.emulator.skin.screenshot;
 
+import java.io.File;
+import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
-import java.io.IOException;
 import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.logging.Level;
@@ -42,206 +43,364 @@ import org.eclipse.swt.events.PaintEvent;
 import org.eclipse.swt.events.PaintListener;
 import org.eclipse.swt.events.SelectionAdapter;
 import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.graphics.GC;
 import org.eclipse.swt.graphics.Image;
 import org.eclipse.swt.graphics.ImageData;
 import org.eclipse.swt.graphics.ImageLoader;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.graphics.Rectangle;
-import org.eclipse.swt.layout.FormAttachment;
-import org.eclipse.swt.layout.FormData;
-import org.eclipse.swt.layout.FormLayout;
+import org.eclipse.swt.graphics.PaletteData;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.Canvas;
 import org.eclipse.swt.widgets.Dialog;
 import org.eclipse.swt.widgets.Event;
 import org.eclipse.swt.widgets.FileDialog;
 import org.eclipse.swt.widgets.Listener;
-import org.eclipse.swt.widgets.Menu;
-import org.eclipse.swt.widgets.MenuItem;
-import org.eclipse.swt.widgets.MessageBox;
 import org.eclipse.swt.widgets.Shell;
 import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.ToolItem;
+import org.tizen.emulator.skin.EmulatorSkin;
+import org.tizen.emulator.skin.comm.ICommunicator.SendCommand;
+import org.tizen.emulator.skin.comm.sock.SocketCommunicator;
+import org.tizen.emulator.skin.comm.sock.SocketCommunicator.DataTranfer;
 import org.tizen.emulator.skin.config.EmulatorConfig;
+import org.tizen.emulator.skin.config.EmulatorConfig.ArgsConstants;
+import org.tizen.emulator.skin.exception.ScreenShotException;
 import org.tizen.emulator.skin.log.SkinLogger;
 import org.tizen.emulator.skin.util.IOUtil;
 import org.tizen.emulator.skin.util.SkinUtil;
+import org.tizen.emulator.skin.util.StringUtil;
 
 public class ScreenShotDialog extends Dialog {
 
+       public final static String DEFAULT_FILE_EXTENSION = "png";
+       
+       public final static int SCREENSHOT_WAIT_INTERVAL = 3; // milli-seconds
+       public final static int SCREENSHOT_WAIT_LIMIT = 3000; // milli-seconds
+       
+       public final static int RED_MASK = 0x0000FF00;
+       public final static int GREEN_MASK = 0x00FF0000;
+       public final static int BLUE_MASK = 0xFF000000;
+       public final static int COLOR_DEPTH = 32;
+
+       public final static int LEFT_MARGIN = 30;
+       public final static int TOP_MARGIN = 30;
+
        private Logger logger = SkinLogger.getSkinLogger( ScreenShotDialog.class ).getLogger();
 
+       private PaletteData paletteData;
        private Image image;
+       private Canvas imageCanvas;
        private Shell shell;
        private Shell parent;
-       private EmulatorConfig config;
        
-       private Canvas canvas;
+       private SocketCommunicator communicator;
+       private EmulatorSkin emulatorSkin;
+       private EmulatorConfig config;
 
-       public ScreenShotDialog( Shell parent, Canvas lcdCanvas, EmulatorConfig config ) {
-               super( parent );
+       public ScreenShotDialog( Shell parent, SocketCommunicator commuicator, EmulatorSkin emulatorSkin, EmulatorConfig config )
+                       throws ScreenShotException {
+               
+               super( parent, SWT.DIALOG_TRIM | SWT.RESIZE );
 
                this.parent = parent;
+               this.communicator = commuicator;
+               this.emulatorSkin = emulatorSkin;
                this.config = config;
-               
-               // image copy
-               capture( lcdCanvas );
 
-               shell = new Shell( parent, SWT.DIALOG_TRIM );
-               shell.setLayout( new FormLayout() );
-               shell.setText( "Screen Shot" );
-               shell.setLocation( parent.getLocation().x + parent.getSize().x + 50, parent.getLocation().y );
+               shell = new Shell( parent, SWT.DIALOG_TRIM | SWT.RESIZE );
+               shell.setText( "Screen Shot - " + SkinUtil.getVmName( config ) );
+               shell.setLocation( parent.getLocation().x + parent.getSize().x + 30, parent.getLocation().y );
                shell.addListener( SWT.Close, new Listener() {
                        @Override
                        public void handleEvent( Event event ) {
-                               image.dispose();
+                               if( null != image ) {
+                                       image.dispose();
+                               }
                        }
                } );
                
-               Menu menu = new Menu( shell, SWT.BAR );
-               makeToolBarMenu( menu );
-               shell.setMenuBar( menu );
-
-               // canvas
-               ScrolledComposite composite = new ScrolledComposite( shell, SWT.V_SCROLL | SWT.H_SCROLL );
+               GridLayout gridLayout = new GridLayout();
+               gridLayout.marginWidth = 0;
+               gridLayout.marginHeight = 0;
+               gridLayout.horizontalSpacing = 0;
+               gridLayout.verticalSpacing = 0;
+               shell.setLayout( gridLayout );
                
-               canvas = new Canvas( composite, SWT.NONE );
-               composite.setContent( canvas );
+               makeMenuBar( shell );
                
-               ImageData imageData = image.getImageData();
-               Rectangle rect = new Rectangle( 0, 0, imageData.width, imageData.height );
-               canvas.setBounds( rect );
+               final ScrolledComposite scrollComposite = new ScrolledComposite( shell, SWT.V_SCROLL | SWT.H_SCROLL );
+               GridData gridData = new GridData( SWT.FILL, SWT.FILL, true, true );
+               scrollComposite.setLayoutData( gridData );
+               
+               scrollComposite.setExpandHorizontal( true );
+               scrollComposite.setExpandVertical( true );
                
-               canvas.addPaintListener( new PaintListener() {
+               final int width = Integer.parseInt( config.getArg( ArgsConstants.RESOLUTION_WIDTH ) );
+               final int height = Integer.parseInt( config.getArg( ArgsConstants.RESOLUTION_HEIGHT ) );
+
+               imageCanvas = new Canvas( scrollComposite, SWT.NONE );
+               imageCanvas.setBackground( shell.getDisplay().getSystemColor( SWT.COLOR_DARK_GRAY ) );
+               imageCanvas.addPaintListener( new PaintListener() {
                        @Override
                        public void paintControl( PaintEvent e ) {
-                               e.gc.drawImage( image, 0, 0 );
+                               
+                               logger.info( "capture screen." );
+
+                               //TODO rotation
+//                             if( null != image && !image.isDisposed() ) {
+//                                     
+//                                     short currentRotationId = ScreenShotDialog.this.emulatorSkin.getCurrentRotationId();
+//                                     RotationInfo rotationInfo = RotationInfo.getValue( currentRotationId );
+//                                     float angle = (float) rotationInfo.angle();
+//                                     
+//                                     if( 0 != angle ) {
+//                                             
+//                                             Transform transform = new Transform( shell.getDisplay() );
+//                                             transform.rotate( angle );
+//                                             transform.translate( -width, 0 );
+//                                             
+//                                             e.gc.setTransform( transform );
+//                                             e.gc.drawImage( image, LEFT_MARGIN, TOP_MARGIN );
+//                                             transform.dispose();
+//                                             
+//                                     }else {
+//                                             e.gc.drawImage( image, LEFT_MARGIN, TOP_MARGIN );
+//                                     }
+//                                     
+//                             }
+                               
+                               e.gc.drawImage( image, LEFT_MARGIN, TOP_MARGIN );
+
                        }
                } );
 
-               int width = 0;
-               int height = 0;
-
-               Point shellLocation = shell.getLocation();
-               Rectangle monitorSize = shell.getDisplay().getClientArea();
+               paletteData = new PaletteData( RED_MASK, GREEN_MASK, BLUE_MASK );
 
-               if( shellLocation.y + imageData.height > monitorSize.height ) {
-                       shell.setSize( imageData.width, imageData.height );
-               }else {
-                       shell.pack();
+               try {
+                       capture();
+               } catch ( ScreenShotException e ) {
+                       if( !shell.isDisposed() ) {
+                               shell.close();
+                       }
+                       throw e;
                }
                
+               scrollComposite.setContent( imageCanvas );
+               ImageData imageData = image.getImageData();
+               scrollComposite.setMinSize( imageData.width + ( 2 * LEFT_MARGIN ), imageData.height + ( 2 * TOP_MARGIN ) );
+               
+               shell.pack();
+               
        }
 
-       private void capture( Canvas canvas ) {
+       private void capture() throws ScreenShotException {
+
+               communicator.sendToQEMU( SendCommand.SCREEN_SHOT, null, true );
+               DataTranfer dataTranfer = communicator.getDataTranfer();
+
+               int count = 0;
+               boolean isFail = false;
+               byte[] receivedData = null;
+               int limitCount = SCREENSHOT_WAIT_LIMIT / SCREENSHOT_WAIT_INTERVAL;
                
-               if( null != this.image ) {
-                       this.image.dispose();
+               synchronized ( dataTranfer ) {
+                       
+                       while( dataTranfer.isTransferState() ) {
+                               
+                               if( limitCount < count ) {
+                                       isFail = true;
+                                       break;
+                               }
+                               
+                               try {
+                                       dataTranfer.wait( SCREENSHOT_WAIT_INTERVAL );
+                               } catch ( InterruptedException e ) {
+                                       logger.log( Level.SEVERE, e.getMessage(), e );
+                               }
+                               
+                               count++;
+                               logger.info( "wait image data... count:" + count );
+                               
+                       }
+                       
+                       receivedData = dataTranfer.getReceivedData();
+                       
                }
                
-               this.image = new Image( parent.getDisplay(), canvas.getBounds() );
-               
-               GC gc = null;
-               try {
-                       gc = new GC( canvas );
-                       gc.copyArea( image, 0, 0 );
-               } finally {
-                       if ( null != gc ) {
-                               gc.dispose();
+               if( !isFail ) {
+
+                       if( null != receivedData ) {
+                               
+                               if( null != this.image ) {
+                                       this.image.dispose();
+                               }
+
+                               int width = Integer.parseInt( config.getArg( ArgsConstants.RESOLUTION_WIDTH ) );
+                               int height = Integer.parseInt( config.getArg( ArgsConstants.RESOLUTION_HEIGHT ) );
+                               ImageData imageData = new ImageData(width, height, COLOR_DEPTH, paletteData, 1, receivedData );
+                               
+                               this.image = new Image( parent.getDisplay(), imageData );
+                               
+                               imageCanvas.redraw();
+                               
+                       }else {
+                               throw new ScreenShotException( "Received image data is null." );
                        }
+                       
+               }else {
+                       throw new ScreenShotException( "Fail to received image data." );
                }
                
-               canvas.update();
-               
        }
        
-       private void makeToolBarMenu( Menu menu ) {
+       private void makeMenuBar( final Shell shell ) {
                
-               MenuItem saveItem = new MenuItem( menu, SWT.FLAT );
+               ToolBar toolBar = new ToolBar( shell, SWT.HORIZONTAL );
+               GridData gridData = new GridData( GridData.FILL_HORIZONTAL );
+               toolBar.setLayoutData( gridData );
+               
+               ToolItem saveItem = new ToolItem( toolBar, SWT.PUSH );
+               //FIXME icon
+//             saveItem.setImage( shell.getDisplay().getSystemImage( SWT.ICON_QUESTION ) );
                saveItem.setText( "Save" );
+               saveItem.setToolTipText( "Save" );
+               saveItem.setSelection( false );
                
                saveItem.addSelectionListener( new SelectionAdapter() {
-                       
                        @Override
                        public void widgetSelected( SelectionEvent e ) {
                                
-                               FileDialog fd = new FileDialog( shell, SWT.SAVE );
-                               fd.setText( "Save Image... " );
+                               FileDialog fileDialog = new FileDialog( shell, SWT.SAVE );
+                               fileDialog.setText( "Save Image" );
+                               
                                String[] filter = { "*.png;*.PNG;*.jpg;*.JPG;*.jpeg;*.JPEG;*.bmp;*.BMP" };
-                               String[] filterName = { "Image Files" };
-                               fd.setFilterExtensions( filter );
-                               fd.setFilterNames( filterName );
+                               fileDialog.setFilterExtensions( filter );
+
+                               String[] filterName = { "Image files (*.png *.jpg *.jpeg *.bmp)" };
+                               fileDialog.setFilterNames( filterName );
 
-                               SimpleDateFormat formatter = new SimpleDateFormat( "yyyy-mm-dd-hhmmss" );
-                               
                                String vmName = SkinUtil.getVmName( config );
+                               SimpleDateFormat formatter = new SimpleDateFormat( "yyyy-MM-dd-hhmmss" );
+                               String dateString = formatter.format( new Date( System.currentTimeMillis() ) );
                                
-                               fd.setFileName( vmName + "-" + formatter.format( new Date( System.currentTimeMillis() ) ) + ".png" );
+                               fileDialog.setFileName( vmName + "-" + dateString + "." + DEFAULT_FILE_EXTENSION );
 
-                               String path = fd.open();
-                               if ( null == path ) {
-                                       return;
+                               String userHome = System.getProperty( "user.home" );
+                               if( !StringUtil.isEmpty( userHome ) ) {
+                                       fileDialog.setFilterPath( userHome );
+                               }else {
+                                       logger.warning( "Cannot find user home path int java System properties." );
                                }
-
-                               int i = path.lastIndexOf( '.' );
-                               String filePath = path;
-                               String format = "";
                                
-                               if ( -1 != i ) {
-                                       filePath = path.substring( 0, i - 1 );
-                                       format = path.substring( i + 1, path.length() );
-                                       format = format.toLowerCase();
-                               }
-
-                               FileOutputStream fos = null;
+                               String filePath = fileDialog.open();
+                               saveFile( filePath, fileDialog );
                                
-                               try {
-                                       
-                                       fos = new FileOutputStream( filePath + "." + format, true );
-                                       
-                                       ImageLoader loader = new ImageLoader();
-                                       loader.data = new ImageData[] { image.getImageData() };
-                                       
-                                       if ( null == format || format.equals( "png" ) ) {
-                                               loader.save( fos, SWT.IMAGE_PNG );
-                                       } else if ( format.equals( "jpg" ) || format.equals( "jpeg" ) ) {
-                                               loader.save( fos, SWT.IMAGE_JPEG );
-                                       } else if ( format.equals( "bmp" ) ) {
-                                               loader.save( fos, SWT.IMAGE_BMP );
-                                       } else {
-                                               
-                                               MessageBox msg = new MessageBox( shell, SWT.ICON_WARNING );
-                                               msg.setText( "Warning" );
-                                               msg.setMessage( "You have to use specific image formats. (PNG/JPG/BMP)" );
-                                               msg.open();
-                                               
-                                       }
-                                       
-                               } catch ( IOException ex ) {
-                                       logger.log( Level.SEVERE, ex.getMessage(), ex );
-                               } finally {
-                                       IOUtil.close( fos );
-                               }
                        }
 
                } );
-
                
-               MenuItem refreshItem = new MenuItem( menu, SWT.FLAT );
+               ToolItem refreshItem = new ToolItem( toolBar, SWT.PUSH );
+               //FIXME icon
+//             refreshItem.setImage( shell.getDisplay().getSystemImage( SWT.ICON_INFORMATION ) );
                refreshItem.setText( "Refresh" );
+               refreshItem.setToolTipText( "Refresh" );
+               refreshItem.setSelection( false );
                
-               saveItem.addSelectionListener( new SelectionAdapter() {
-                       
+               refreshItem.addSelectionListener( new SelectionAdapter() {
                        @Override
                        public void widgetSelected( SelectionEvent e ) {
-                               capture( canvas );
+                               try {
+                                       capture();
+                               } catch ( ScreenShotException ex ) {
+                                       logger.log( Level.SEVERE, "Fail to create a screen shot.", ex );
+                                       SkinUtil.openMessage( shell, null, "Fail to create a screen shot.", SWT.ERROR, config );
+                               }
                        }
 
                } );
                
        }
 
+       private void saveFile( String fileFullPath, FileDialog fileDialog ) {
+               
+               if ( null == fileFullPath ) {
+                       return;
+               }
+
+               String format = "";
+               String[] split = fileFullPath.split( "\\." );
+               
+               if( 1 < split.length ) {
+                       
+                       format = split[split.length - 1];
+
+                       if ( new File( split[split.length - 2] ).isDirectory() ) {
+                               // There is no file name.
+                               SkinUtil.openMessage( shell, null, "Use correct file name.", SWT.ICON_WARNING, config );
+                               String path = fileDialog.open();
+                               saveFile( path, fileDialog );
+
+                       }
+                       
+               }
+               
+               FileOutputStream fos = null;
+               
+               try {
+                       
+                       if( StringUtil.isEmpty( format ) ) {
+                               if( fileFullPath.endsWith( "." ) ) {
+                                       fileFullPath += DEFAULT_FILE_EXTENSION;
+                               }else {
+                                       fileFullPath += "." + DEFAULT_FILE_EXTENSION;
+                               }
+                       }
+                       
+                       fos = new FileOutputStream( fileFullPath, false );
+                       
+                       ImageLoader loader = new ImageLoader();
+                       loader.data = new ImageData[] { image.getImageData() };
+                       
+                       if ( StringUtil.isEmpty( format ) || format.equalsIgnoreCase( "png" ) ) {
+                               loader.save( fos, SWT.IMAGE_PNG );
+                       } else if ( format.equalsIgnoreCase( "jpg" ) || format.equalsIgnoreCase( "jpeg" ) ) {
+                               loader.save( fos, SWT.IMAGE_JPEG );
+                       } else if ( format.equalsIgnoreCase( "bmp" ) ) {
+                               loader.save( fos, SWT.IMAGE_BMP );
+                       } else {
+                               
+                               SkinUtil.openMessage( shell, null, "Use the specified image formats. ( PNG / JPG / JPEG / BMP )",
+                                               SWT.ICON_WARNING, config );
+                               String path = fileDialog.open();
+                               saveFile( path, fileDialog );
+                               
+                       }
+                       
+               } catch ( FileNotFoundException ex ) {
+                       
+                       logger.log( Level.WARNING, "Use correct file name.", ex );
+                       SkinUtil.openMessage( shell, null, "Use correct file name.", SWT.ICON_WARNING, config );
+                       String path = fileDialog.open();
+                       saveFile( path, fileDialog );
+
+               } catch ( Exception ex ) {
+                       
+                       logger.log( Level.SEVERE, "Fail to save this image file.", ex );
+                       SkinUtil.openMessage( shell, null, "Fail to save this image file.", SWT.ERROR, config );
+                       String path = fileDialog.open();
+                       saveFile( path, fileDialog );
+
+               } finally {
+                       IOUtil.close( fos );
+               }
+
+       }
+       
        public void open() {
 
+               if( shell.isDisposed() ) {
+                       return;
+               }
+               
                shell.open();
 
                while ( !shell.isDisposed() ) {
@@ -251,4 +410,5 @@ public class ScreenShotDialog extends Dialog {
                }
 
        }
+               
 }
\ No newline at end of file
index 444ec7a..676ad56 100644 (file)
@@ -35,7 +35,7 @@ import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Map.Entry;
 
-import org.tizen.emulator.skin.dbi.RotationNameType;
+import org.tizen.emulator.skin.comm.ICommunicator.RotationInfo;
 import org.tizen.emulator.skin.dbi.RotationType;
 
 
@@ -44,33 +44,6 @@ import org.tizen.emulator.skin.dbi.RotationType;
  *
  */
 public class SkinRotation {
-
-       public enum RotationInfo {
-
-               PORTRAIT( RotationNameType.PORTRAIT.value(), (short)0, 0 ),
-               LANDSCAPE( RotationNameType.LANDSCAPE.value(), (short)1, -90 ),
-               REVERSE_PORTRAIT( RotationNameType.REVERSE_PORTRAIT.value(), (short)2, 180 ),
-               REVERSE_LANDSCAPE( RotationNameType.REVERSE_LANDSCAPE.value(), (short)3, 90 );
-               
-               private String value;
-               private short id;
-               private int angle;
-               
-               RotationInfo( String value, short id, int ratio ) {
-                       this.value = value;
-                       this.id = id;
-                       this.angle = ratio;
-               }
-               public String value() {
-                       return this.value;
-               }
-               public int angle() {
-                       return this.angle;
-               }
-               public short id() {
-                       return this.id;
-               }
-       }
        
        private static Map<Short, RotationType> rotationMap;
        private static Map<Short, RotationInfo> angleMap;
index 63b266b..847f394 100644 (file)
@@ -38,8 +38,10 @@ import org.eclipse.swt.graphics.ImageData;
 import org.eclipse.swt.graphics.Rectangle;
 import org.eclipse.swt.graphics.Region;
 import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.MessageBox;
 import org.eclipse.swt.widgets.Shell;
 import org.tizen.emulator.skin.EmulatorConstants;
+import org.tizen.emulator.skin.comm.ICommunicator.RotationInfo;
 import org.tizen.emulator.skin.config.EmulatorConfig;
 import org.tizen.emulator.skin.config.EmulatorConfig.ArgsConstants;
 import org.tizen.emulator.skin.config.EmulatorConfig.PropertiesConstants;
@@ -50,7 +52,6 @@ import org.tizen.emulator.skin.dbi.RegionType;
 import org.tizen.emulator.skin.dbi.RotationType;
 import org.tizen.emulator.skin.image.ImageRegistry;
 import org.tizen.emulator.skin.image.ImageRegistry.ImageType;
-import org.tizen.emulator.skin.util.SkinRotation.RotationInfo;
 
 
 /**
@@ -316,5 +317,20 @@ public class SkinUtil {
                        return false;
                }
        }
+       
+       public static <T> void openMessage( Shell shell, String title, String message, int style, EmulatorConfig config ) {
+               
+               MessageBox messageBox = new MessageBox( shell, style );
+               
+               if( !StringUtil.isEmpty( title ) ) {
+                       messageBox.setText( title );
+               }else {
+                       messageBox.setText( makeEmulatorName( config ) );
+               }
+               
+               messageBox.setMessage( StringUtil.nvl( message ) );
+               messageBox.open();
+               
+       }
 
 }
index 93d0158..0b2e42b 100644 (file)
 #include "maruskin_operation.h"
 #include "maru_sdl.h"
 #include "debug_ch.h"
-
 #include "sdb.h"
 #include "nbd.h"
-#include "../mloop_event.h"
+#include "mloop_event.h"
 #include "emul_state.h"
 #include "maruskin_keymap.h"
 #include "emul_state.h"
+#include "hw/maru_pm.h"
+#include "qemu-common.h"
 
 MULTI_DEBUG_CHANNEL(qemu, skin_operation);
 
@@ -114,11 +115,11 @@ void do_hardkey_event( int event_type, int keycode )
 {
     TRACE( "do_hardkey_event event_type:%d, keycode:%d\n", event_type, keycode );
 
-    if ( KEY_PRESSED == event_type ) {
-        if ( kbd_mouse_is_absolute() ) {
-            // home key or power key is used for resume.
-            if ( ( HARD_KEY_HOME == keycode ) || ( HARD_KEY_POWER == keycode ) ) {
-                if ( is_suspended_state() ) {
+    if ( is_suspended_state() ) {
+        if ( KEY_PRESSED == event_type ) {
+            if ( kbd_mouse_is_absolute() ) {
+                // home key or power key is used for resume.
+                if ( ( HARD_KEY_HOME == keycode ) || ( HARD_KEY_POWER == keycode ) ) {
                     INFO( "user requests system resume.\n" );
                     resume();
 #ifdef _WIN32
@@ -198,7 +199,7 @@ void do_rotation_event( int rotation_type)
     socket_send( s, &buf_size, 4 );
     socket_send( s, send_buf, buf_size );
 
-    INFO( "send to sendord(size: %d) 127.0.0.1:%d/tcp \n", buf_size, tizen_base_port + SDB_TCP_EMULD_INDEX);
+    INFO( "send to sensord(size: %d) 127.0.0.1:%d/tcp \n", buf_size, tizen_base_port + SDB_TCP_EMULD_INDEX);
 
     set_emul_rotation(rotation_type);
 
@@ -210,6 +211,53 @@ void do_rotation_event( int rotation_type)
 
 }
 
+QemuSurfaceInfo* get_screenshot_info( void ) {
+
+    DisplaySurface* qemu_display_surface = get_qemu_display_surface();
+
+    if ( !qemu_display_surface ) {
+        ERR( "qemu surface is NULL.\n" );
+        return NULL;
+    }
+
+    QemuSurfaceInfo* info = (QemuSurfaceInfo*) g_malloc0( sizeof(QemuSurfaceInfo) );
+    if ( !info ) {
+        ERR( "Fail to malloc for QemuSurfaceInfo.\n");
+        return NULL;
+    }
+
+    int length = qemu_display_surface->linesize * qemu_display_surface->height;
+    INFO( "screenshot data length:%d\n", length );
+
+    if ( 0 >= length ) {
+        g_free( info );
+        ERR( "screenshot data ( 0 >=length ). length:%d\n", length );
+        return NULL;
+    }
+
+    info->pixel_data = (unsigned char*) g_malloc0( length );
+    if ( !info->pixel_data ) {
+        g_free( info );
+        ERR( "Fail to malloc for pixel data.\n");
+        return NULL;
+    }
+
+    memcpy( info->pixel_data, qemu_display_surface->data, length );
+    info->pixel_data_length = length;
+
+    return info;
+
+}
+
+void free_screenshot_info( QemuSurfaceInfo* info ) {
+    if( info ) {
+        if( info->pixel_data ) {
+            g_free( info->pixel_data );
+        }
+        g_free( info );
+    }
+}
+
 void open_shell(void)
 {
     //TODO
index 7b5f592..dc01472 100644 (file)
 #ifndef MARUSKIN_OPERATION_H_
 #define MARUSKIN_OPERATION_H_
 
+struct QemuSurfaceInfo {
+    unsigned char* pixel_data;
+    int pixel_data_length;
+};
+typedef struct QemuSurfaceInfo QemuSurfaceInfo;
+
 void start_display( int handle_id, int lcd_size_width, int lcd_size_height, double scale_factor, short rotation_type );
 
 void do_mouse_event( int event_type, int x, int y, int z );
@@ -42,6 +48,10 @@ void do_scale_event( double scale_factor);
 
 void do_rotation_event( int rotation_type );
 
+QemuSurfaceInfo* get_screenshot_info( void );
+
+void free_screenshot_info( QemuSurfaceInfo* );
+
 void open_shell(void);
 
 void onoff_usb_kbd( int on );
index b3c433a..cdc44dd 100644 (file)
@@ -54,7 +54,10 @@ MULTI_DEBUG_CHANNEL( qemu, maruskin_server );
 
 #define RECV_BUF_SIZE 32
 #define RECV_HEADER_SIZE 12
-#define SEND_HEADER_SIZE 6
+
+#define SEND_HEADER_SIZE 10
+#define SEND_BIG_BUF_SIZE 1024 * 1024 * 2
+#define SEND_BUF_SIZE 512
 
 #define HEART_BEAT_INTERVAL 1
 #define HEART_BEAT_FAIL_COUNT 5
@@ -72,6 +75,7 @@ enum {
     RECV_CHANGE_LCD_STATE = 13,
     RECV_OPEN_SHELL = 14,
     RECV_USB_KBD = 15,
+    RECV_SCREEN_SHOT = 16,
     RECV_RESPONSE_HEART_BEAT = 900,
     RECV_CLOSE = 998,
     RECV_RESPONSE_SHUTDOWN = 999,
@@ -79,7 +83,7 @@ enum {
 
 enum {
     SEND_HEART_BEAT = 1,
-    SEND_HEART_BEAT_RESPONSE = 2,
+    SEND_SCREEN_SHOT = 2,
     SEND_SENSOR_DAEMON_START = 800,
     SEND_SHUTDOWN = 999,
 };
@@ -101,7 +105,10 @@ static pthread_mutex_t mutex_recv_heartbeat_count = PTHREAD_MUTEX_INITIALIZER;
 
 static void* run_skin_server( void* args );
 static int recv_n( int client_sock, char* read_buf, int recv_len );
-static int send_skin( int client_sock, short send_cmd );
+static int send_skin_header_only( int client_sock, short send_cmd );
+static int send_skin_data( int client_sock, short send_cmd, unsigned char* data, int length, int big_data );
+static int send_n( int client_sock, unsigned char* data, int length, int big_data );
+
 static void* do_heart_beat( void* args );
 static int start_heart_beat( int client_sock );
 static void stop_heart_beat( void );
@@ -149,7 +156,7 @@ int start_skin_server( int argc, char** argv ) {
 void shutdown_skin_server( void ) {
     if ( client_sock ) {
         INFO( "send shutdown to skin.\n" );
-        if ( 0 > send_skin( client_sock, SEND_SHUTDOWN ) ) {
+        if ( 0 > send_skin_header_only( client_sock, SEND_SHUTDOWN ) ) {
             ERR( "fail to send SEND_SHUTDOWN to skin.\n" );
             stop_server = 1;
             // force close
@@ -174,7 +181,7 @@ void notify_sensor_daemon_start( void ) {
     INFO( "notify_sensor_daemon_start\n" );
     is_sensord_initialized = 1;
     if ( client_sock ) {
-        if ( 0 > send_skin( client_sock, SEND_SENSOR_DAEMON_START ) ) {
+        if ( 0 > send_skin_header_only( client_sock, SEND_SENSOR_DAEMON_START ) ) {
             ERR( "fail to send SEND_SENSOR_DAEMON_START to skin.\n" );
         }
     }
@@ -509,6 +516,21 @@ static void* run_skin_server( void* args ) {
                     maruskin_sdl_resize(); //send sdl event
                     break;
                 }
+                case RECV_SCREEN_SHOT: {
+                    log_cnt += sprintf( log_buf + log_cnt, "RECV_SCREEN_SHOT ==\n" );
+                    TRACE( log_buf );
+
+                    QemuSurfaceInfo* info = get_screenshot_info();
+
+                    if ( info ) {
+                        send_skin_data( client_sock, SEND_SCREEN_SHOT, info->pixel_data, info->pixel_data_length, 1 );
+                        free_screenshot_info( info );
+                    } else {
+                        ERR( "Fail to get screenshot data.\n" );
+                    }
+
+                    break;
+                }
                 case RECV_RESPONSE_HEART_BEAT: {
                     log_cnt += sprintf( log_buf + log_cnt, "RECV_RESPONSE_HEART_BEAT ==\n" );
                     TRACE( log_buf );
@@ -592,7 +614,7 @@ static int recv_n( int client_sock, char* read_buf, int recv_len ) {
 
     while ( 1 ) {
 
-        recv_cnt = recv( client_sock, (void*) read_buf, ( recv_len - recv_cnt ), 0 );
+        recv_cnt = recv( client_sock, (void*) ( read_buf + recv_cnt ), ( recv_len - recv_cnt ), 0 );
 
         if ( 0 > recv_cnt ) {
 
@@ -624,29 +646,105 @@ static int recv_n( int client_sock, char* read_buf, int recv_len ) {
 
 }
 
-static int send_skin( int client_sock, short send_cmd ) {
+static void make_header( int client_sock, short send_cmd, int data_length, char* sendbuf ) {
 
-    char sendbuf[SEND_HEADER_SIZE];
-    memset( &sendbuf, 0, SEND_HEADER_SIZE );
+    memset( sendbuf, 0, SEND_HEADER_SIZE );
 
     int request_id = rand();
     TRACE( "== SEND skin request_id:%d, send_cmd:%d ==\n", request_id, send_cmd );
     request_id = htonl( request_id );
 
-    short data = send_cmd;
-    data = htons( data );
+    short cmd = send_cmd;
+    cmd = htons( cmd );
+
+    int length = data_length;
+    length = htonl( length );
 
     char* p = sendbuf;
     memcpy( p, &request_id, sizeof( request_id ) );
     p += sizeof( request_id );
-    memcpy( p, &data, sizeof( data ) );
+    memcpy( p, &cmd, sizeof( cmd ) );
+    p += sizeof( cmd );
+    memcpy( p, &length, sizeof( length ) );
+
+}
 
-    ssize_t send_count = send( client_sock, sendbuf, SEND_HEADER_SIZE, 0 );
+static int send_n( int client_sock, unsigned char* data, int length, int big_data ) {
+
+    int send_cnt = 0;
+    int total_cnt = 0;
+
+    int buf_size = big_data ? SEND_BIG_BUF_SIZE : SEND_BUF_SIZE;
+    char databuf[buf_size];
+
+    INFO( "send_n start. length:%d\n", length );
+
+    while ( 1 ) {
+
+        if ( total_cnt == length ) {
+            break;
+        }
+
+        if ( buf_size < ( length - total_cnt ) ) {
+            send_cnt = buf_size;
+        } else {
+            send_cnt = ( length - total_cnt );
+        }
 
+        memset( &databuf, 0, send_cnt );
+        memcpy( &databuf, (char*) ( data + total_cnt ), send_cnt );
+
+        send_cnt = send( client_sock, databuf, send_cnt, 0 );
+
+        if ( 0 > send_cnt ) {
+            ERR( "send_n error. error code:%d\n", send_cnt );
+            return send_cnt;
+        } else {
+            total_cnt += send_cnt;
+        }
+
+    }
+
+    INFO( "send_n finished.\n" );
+
+    return total_cnt;
+
+}
+
+static int send_skin_header_only( int client_sock, short send_cmd ) {
+
+    char headerbuf[SEND_HEADER_SIZE];
+    make_header( client_sock, send_cmd, 0, headerbuf );
+
+    int send_count = send( client_sock, headerbuf, SEND_HEADER_SIZE, 0 );
     return send_count;
 
 }
 
+static int send_skin_data( int client_sock, short send_cmd, unsigned char* data, int length, int big_data ) {
+
+    char headerbuf[SEND_HEADER_SIZE];
+    make_header( client_sock, send_cmd, length, headerbuf );
+
+    int header_cnt = send( client_sock, headerbuf, SEND_HEADER_SIZE, 0 );
+
+    if ( 0 > header_cnt ) {
+        ERR( "send header for data is NULL.\n" );
+        return header_cnt;
+    }
+
+    if ( !data ) {
+        ERR( "send data is NULL.\n" );
+        return -1;
+    }
+
+    int send_cnt = send_n( client_sock, data, length, big_data );
+    INFO( "send_n result:%d\n", send_cnt );
+
+    return send_cnt;
+
+}
+
 static void* do_heart_beat( void* args ) {
 
     int client_sock = *(int*) args;
@@ -673,7 +771,7 @@ static void* do_heart_beat( void* args ) {
         }
 
         TRACE( "[HB] send heartbeat to skin.\n" );
-        if ( 0 > send_skin( client_sock, SEND_HEART_BEAT ) ) {
+        if ( 0 > send_skin_header_only( client_sock, SEND_HEART_BEAT ) ) {
             fail_count++;
         } else {
             fail_count = 0;