From b0e96416c6dfd795f017359ed39adb23f76e8929 Mon Sep 17 00:00:00 2001 From: Sooyoung Ha Date: Wed, 3 Apr 2013 11:24:32 +0900 Subject: [PATCH] update source for tizen_2.1 --- Makefile.target | 26 +- exec.c | 4 +- hw/virtio-pci.c | 46 + hw/virtio.h | 1 + package/changelog | 201 +- package/emulator-qemu-common.remove.ubuntu-32 | 10 +- package/emulator-qemu-common.remove.ubuntu-64 | 10 +- ...32 => emulator-qemu-x86.install.ubuntu-32} | 10 +- ...64 => emulator-qemu-x86.install.ubuntu-64} | 10 +- package/pkginfo.manifest | 2 +- tizen/distrib/initscript/tizen_kvm | 24 + tizen/src/Makefile | 22 +- tizen/src/Makefile.tizen | 15 +- tizen/src/SDL_gfx/AUTHORS | 1 + tizen/src/SDL_gfx/COPYING | 1 + tizen/src/SDL_gfx/LICENSE | 26 + tizen/src/SDL_gfx/README | 500 ++ tizen/src/SDL_gfx/SDL_rotozoom.c | 1717 +++++ tizen/src/SDL_gfx/SDL_rotozoom.h | 123 + tizen/src/VERSION | 2 +- tizen/src/check_gl.c | 7 + tizen/src/debug_ch.c | 28 +- tizen/src/debug_ch.h | 5 - tizen/src/emul_state.c | 42 +- tizen/src/emul_state.h | 13 +- tizen/src/{option.h => emul_state_darwin.m} | 35 +- tizen/src/emulator.c | 570 +- tizen/src/emulator.h | 19 +- tizen/src/hw/gl_func_perso.h | 4 + tizen/src/hw/gloffscreen.h | 6 +- tizen/src/hw/gloffscreen_agl.c | 363 ++ tizen/src/hw/gloffscreen_test.c | 2 +- tizen/src/hw/gloffscreen_test.h | 34 + tizen/src/hw/gloffscreen_wgl.c | 5 +- tizen/src/hw/gloffscreen_xcomposite.c | 2 +- tizen/src/hw/maru_brightness.c | 48 +- tizen/src/hw/maru_brightness.h | 7 +- tizen/src/hw/maru_camera_common.h | 229 +- tizen/src/hw/maru_camera_common_pci.c | 577 +- tizen/src/hw/maru_camera_darwin.h | 90 +- tizen/src/hw/maru_camera_darwin_converter.c | 14 +- tizen/src/hw/maru_camera_darwin_pci.m | 11 +- tizen/src/hw/maru_camera_linux_pci.c | 2442 +++---- tizen/src/hw/maru_camera_win32_interface.h | 1866 +++--- tizen/src/hw/maru_camera_win32_pci.c | 5591 ++++++++--------- tizen/src/hw/maru_device_ids.h | 6 +- tizen/src/hw/maru_overlay.c | 48 +- tizen/src/hw/maru_overlay.h | 16 +- tizen/src/hw/maru_vga.c | 39 +- tizen/src/hw/maru_virtio_hwkey.c | 263 + tizen/src/hw/maru_virtio_hwkey.h | 60 + tizen/src/hw/maru_virtio_keyboard.c | 53 +- tizen/src/hw/maru_virtio_keyboard.h | 2 + tizen/src/hw/maru_virtio_touchscreen.c | 28 +- tizen/src/hw/maru_virtio_touchscreen.h | 5 +- tizen/src/hw/opengl_exec.c | 147 +- tizen/src/hw/opengl_func.h | 4 +- tizen/src/maru_common.h | 20 +- tizen/src/maru_display.h | 6 +- tizen/src/maru_sdl.c | 45 +- tizen/src/mloop_event.c | 5 +- tizen/src/mloop_event.h | 1 + tizen/src/ns_event.h | 18 - tizen/src/ns_event.m | 18 - tizen/src/option.c | 641 -- tizen/src/osutil-darwin.c | 337 + tizen/src/osutil-linux.c | 354 ++ tizen/src/osutil-win32.c | 358 ++ tizen/src/osutil.c | 91 + tizen/src/osutil.h | 62 + tizen/src/sdb.c | 148 +- tizen/src/sdb.h | 99 +- tizen/src/skin/client/build.xml | 11 +- tizen/src/skin/client/native_src/share.c | 51 +- .../images/key-window/scroll_back.png | Bin 0 -> 2791 bytes .../key-window/scroll_button_down_hover.png | Bin 0 -> 3186 bytes .../key-window/scroll_button_down_nml.png | Bin 0 -> 3181 bytes .../key-window/scroll_button_down_pushed.png | Bin 0 -> 3161 bytes .../key-window/scroll_button_up_hover.png | Bin 0 -> 3184 bytes .../key-window/scroll_button_up_nml.png | Bin 0 -> 3186 bytes .../key-window/scroll_button_up_pushed.png | Bin 0 -> 3165 bytes .../images/key-window/scroll_thumb.png | Bin 0 -> 2957 bytes .../client/skins/emul-320x480/default.dbi | 48 +- .../client/skins/emul-480x800/default.dbi | 48 +- .../client/skins/emul-600x1024/default.dbi | 48 +- .../client/skins/emul-720x1280/default.dbi | 48 +- .../client/skins/emul-general/default.dbi | 4 +- .../tizen/emulator/skin/EmulatorFingers.java | 529 +- .../tizen/emulator/skin/EmulatorSdlSkin.java | 12 + .../tizen/emulator/skin/EmulatorShmSkin.java | 94 +- .../org/tizen/emulator/skin/EmulatorSkin.java | 165 +- .../tizen/emulator/skin/EmulatorSkinMain.java | 39 +- .../emulator/skin/comm/ICommunicator.java | 1 + .../skin/comm/sock/SocketCommunicator.java | 140 +- .../skin/comm/sock/data/DisplayStateData.java | 65 + .../emulator/skin/config/EmulatorConfig.java | 9 +- .../tizen/emulator/skin/custom/ColorTag.java | 66 + .../emulator/skin/custom/CustomButton.java | 246 + .../skin/custom/CustomProgressBar.java | 121 + .../emulator/skin/custom/CustomScrollBar.java | 226 + .../skin/custom/CustomScrolledComposite.java | 178 + .../custom/CustomScrolledCompositeLayout.java | 101 + .../tizen/emulator/skin/custom/KeyWindow.java | 474 ++ .../emulator/skin/custom/SkinWindow.java | 130 + .../emulator/skin/dialog/AboutDialog.java | 17 +- .../emulator/skin/image/ImageRegistry.java | 121 +- .../layout/GeneralPurposeSkinComposer.java | 59 +- .../skin/layout/PhoneShapeSkinComposer.java | 2 +- .../tizen/emulator/skin/util/SkinUtil.java | 4 + tizen/src/skin/maruskin_client.c | 23 +- tizen/src/skin/maruskin_client.h | 1 - tizen/src/skin/maruskin_keymap.h | 4 + tizen/src/skin/maruskin_operation.c | 103 +- tizen/src/skin/maruskin_server.c | 55 +- tizen/src/skin/maruskin_server.h | 4 + vl.c | 166 +- 116 files changed, 13466 insertions(+), 7582 deletions(-) mode change 100644 => 100755 hw/virtio.h rename package/{emulator-qemu-common.install.ubuntu-32 => emulator-qemu-x86.install.ubuntu-32} (81%) rename package/{emulator-qemu-common.install.ubuntu-64 => emulator-qemu-x86.install.ubuntu-64} (81%) create mode 100755 tizen/distrib/initscript/tizen_kvm create mode 100644 tizen/src/SDL_gfx/AUTHORS create mode 100644 tizen/src/SDL_gfx/COPYING create mode 100644 tizen/src/SDL_gfx/LICENSE create mode 100644 tizen/src/SDL_gfx/README create mode 100644 tizen/src/SDL_gfx/SDL_rotozoom.c create mode 100644 tizen/src/SDL_gfx/SDL_rotozoom.h create mode 100644 tizen/src/check_gl.c rename tizen/src/{option.h => emul_state_darwin.m} (64%) create mode 100644 tizen/src/hw/gloffscreen_agl.c create mode 100644 tizen/src/hw/gloffscreen_test.h create mode 100644 tizen/src/hw/maru_virtio_hwkey.c create mode 100644 tizen/src/hw/maru_virtio_hwkey.h delete mode 100644 tizen/src/option.c create mode 100644 tizen/src/osutil-darwin.c create mode 100644 tizen/src/osutil-linux.c create mode 100644 tizen/src/osutil-win32.c create mode 100644 tizen/src/osutil.c create mode 100644 tizen/src/osutil.h create mode 100644 tizen/src/skin/client/resource/images/key-window/scroll_back.png create mode 100644 tizen/src/skin/client/resource/images/key-window/scroll_button_down_hover.png create mode 100644 tizen/src/skin/client/resource/images/key-window/scroll_button_down_nml.png create mode 100644 tizen/src/skin/client/resource/images/key-window/scroll_button_down_pushed.png create mode 100644 tizen/src/skin/client/resource/images/key-window/scroll_button_up_hover.png create mode 100644 tizen/src/skin/client/resource/images/key-window/scroll_button_up_nml.png create mode 100644 tizen/src/skin/client/resource/images/key-window/scroll_button_up_pushed.png create mode 100644 tizen/src/skin/client/resource/images/key-window/scroll_thumb.png create mode 100644 tizen/src/skin/client/src/org/tizen/emulator/skin/comm/sock/data/DisplayStateData.java create mode 100644 tizen/src/skin/client/src/org/tizen/emulator/skin/custom/ColorTag.java create mode 100644 tizen/src/skin/client/src/org/tizen/emulator/skin/custom/CustomButton.java create mode 100644 tizen/src/skin/client/src/org/tizen/emulator/skin/custom/CustomProgressBar.java create mode 100644 tizen/src/skin/client/src/org/tizen/emulator/skin/custom/CustomScrollBar.java create mode 100644 tizen/src/skin/client/src/org/tizen/emulator/skin/custom/CustomScrolledComposite.java create mode 100644 tizen/src/skin/client/src/org/tizen/emulator/skin/custom/CustomScrolledCompositeLayout.java create mode 100644 tizen/src/skin/client/src/org/tizen/emulator/skin/custom/KeyWindow.java create mode 100644 tizen/src/skin/client/src/org/tizen/emulator/skin/custom/SkinWindow.java mode change 100644 => 100755 vl.c diff --git a/Makefile.target b/Makefile.target index 60d860e693..437199188c 100755 --- a/Makefile.target +++ b/Makefile.target @@ -62,7 +62,7 @@ else stap: endif -all: $(PROGS) stap +all: $(PROGS) stap check-gl # Dummy command so that make thinks it has done something @true @@ -322,6 +322,30 @@ $(QEMU_PROG): $(all-obj-y) $(call LINK,$^) endif +CHECK_GL_OBJS = check_gl.o gloffscreen_test.o gloffscreen_common.o +CHECK_GL_LDFLAGS = +CHECK_GL_TARGET = +ifdef CONFIG_LINUX +CHECK_GL_OBJS += gloffscreen_xcomposite.o +CHECK_GL_LDFLAGS += -lGL -lXcomposite -lXext -lglib-2.0 +CHECK_GL_TARGET = check-gl +endif +ifdef CONFIG_WIN32 +CHECK_GL_OBJS += gloffscreen_wgl.o +CHECK_GL_LDFLAGS += -fstack-protector `pkg-config --libs glib-2.0` -lopengl32 -lglu32 -lgdi32 +CHECK_GL_TARGET = check-gl.exe +endif +ifdef CONFIG_DARWIN +CHECK_GL_OBJS += gloffscreen_agl.o +CHECK_GL_LDFLAGS += -mmacosx-version-min=10.4 `pkg-config --cflags --libs glib-2.0` -framework GLUT -framework OpenGL -framework AGL +CHECK_GL_TARGET = check-gl +endif + +check-gl: check_gl.o + gcc -o $(CHECK_GL_TARGET) $(CHECK_GL_OBJS) $(CHECK_GL_LDFLAGS) +check_gl.o: check_gl.c + gcc -c ../tizen/src/check_gl.c + gdbstub-xml.c: $(TARGET_XML_FILES) $(SRC_PATH)/scripts/feature_to_c.sh $(call quiet-command,rm -f $@ && $(SHELL) $(SRC_PATH)/scripts/feature_to_c.sh $@ $(TARGET_XML_FILES)," GEN $(TARGET_DIR)$@") diff --git a/exec.c b/exec.c index a64e70bda0..8e6bf12671 100644 --- a/exec.c +++ b/exec.c @@ -1386,10 +1386,10 @@ void tb_link_page(TranslationBlock *tb, /* check whether the given addr is in TCG generated code buffer or not */ bool is_tcg_gen_code(uintptr_t tc_ptr) { - /* This can be called during code generation, code_gen_buffer_max_size + /* This can be called during code generation, code_gen_buffer_size is used instead of code_gen_ptr for upper boundary checking */ return (tc_ptr >= (uintptr_t)code_gen_buffer && - tc_ptr < (uintptr_t)(code_gen_buffer + code_gen_buffer_max_size)); + tc_ptr < (uintptr_t)(code_gen_buffer + code_gen_buffer_size)); } #endif diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index 8ff80d9319..eb6e23603a 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -970,6 +970,29 @@ static void virtio_esm_exit_pci(PCIDevice *pci_dev) virtio_esm_exit(proxy->vdev); virtio_exit_pci(pci_dev); } + +static int virtio_hwkey_init_pci(PCIDevice *pci_dev) +{ + VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev); + VirtIODevice *vdev; + + vdev = maru_virtio_hwkey_init(&pci_dev->qdev); + if (!vdev) { + return -1; + } + virtio_init_pci(proxy, vdev); + return 0; +} + +static void virtio_hwkey_exit_pci(PCIDevice *pci_dev) +{ + VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev); + + virtio_pci_stop_ioeventfd(proxy); + maru_virtio_hwkey_exit(proxy->vdev); + virtio_exit_pci(pci_dev); +} + #endif static Property virtio_blk_properties[] = { @@ -1245,6 +1268,28 @@ static TypeInfo virtio_esm_info = { .instance_size = sizeof(VirtIOPCIProxy), .class_init = virtio_esm_class_init, }; + +static void virtio_hwkey_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + + k->init = virtio_hwkey_init_pci; + k->exit = virtio_hwkey_exit_pci; + k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; + k->device_id = PCI_DEVICE_ID_VIRTIO_HWKEY; + k->revision = VIRTIO_PCI_ABI_VERSION; + k->class_id = PCI_CLASS_OTHERS; + dc->reset = virtio_pci_reset; +} + +static TypeInfo virtio_hwkey_info = { + .name = "virtio-hwkey-pci", + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(VirtIOPCIProxy), + .class_init = virtio_hwkey_class_init, +}; + #endif /* CONFIG_MARU */ static void virtio_pci_register_types(void) @@ -1261,6 +1306,7 @@ static void virtio_pci_register_types(void) type_register_static(&maru_virtio_touchscreen_info); type_register_static(&virtio_keyboard_info); type_register_static(&virtio_esm_info); + type_register_static(&virtio_hwkey_info); #endif } diff --git a/hw/virtio.h b/hw/virtio.h old mode 100644 new mode 100755 index 1a33b4cde5..0b035618cf --- a/hw/virtio.h +++ b/hw/virtio.h @@ -221,6 +221,7 @@ void virtio_scsi_exit(VirtIODevice *vdev); #include "tizen/src/hw/maru_virtio_touchscreen.h" #include "tizen/src/hw/maru_virtio_keyboard.h" #include "tizen/src/hw/maru_virtio_esm.h" +#include "tizen/src/hw/maru_virtio_hwkey.h" #endif diff --git a/package/changelog b/package/changelog index abcff52fc1..d80973198f 100644 --- a/package/changelog +++ b/package/changelog @@ -1,3 +1,198 @@ -* 2.0.0 -- Tizen 2.0 final release -== SungMin Ha 2013-02-13 +* 1.5.22 +- no need to get the shmkey from another shm +== GiWoong Kim 2013-04-02 +* 1.5.21 +- Fixed a bug that a camera frame is not sent to FW. +== Jinhyung Jo 2013-03-29 +* 1.5.20 +- modified skin's dbi file for key code of phone shape +== Sungmin Ha 2013-03-29 +* 1.5.19 +- modified elem index and mutex lock in virtio-kbd +== Sungmin Ha 2013-03-29 +* 1.5.18 +- Skip the display updates until the LCD is turned off +== GiWoong Kim 2013-03-28 +* 1.5.17 +- modified Makefile to library load on mac from check-gl +== Sungmin Ha 2013-03-26 +* 1.5.16 +- Fix dibs install error by mis-typing. +== Sangjin Kim 2013-03-25 +* 1.5.15 +- Fix dibs build error. +== Sangjin Kim 2013-03-21 +* 1.5.14 +- Generate check-gl binary to use at an emulator-manager. +== Sangjin Kim 2013-03-21 +* 1.5.13 +- Enable pbuffer surface. +== Sangjin Kim 2013-03-20 +* 1.5.6 +- modified virtio hwkey device and improved hwkey mapping +== Sungmin Ha 2013-03-20 +* 1.5.5 +- moved kvm script files from qemu-common to qemu-x86 package. +== Kitae Kim 2013-03-15 +* 1.5.4 +- added routine in case that there is no gksudo. +== Kitae Kim 2013-03-08 +* 1.5.03 +- modified path separator +== GiWoong Kim 2013-02-25 +* 1.5.02 +- Sync-up with tizen 2.0 latest gl source code. +== Sangjin Kim 2013-02-21 +* 1.5.01 +- added virtio hwkey device +== GiWoong Kim 2013-02-21 +* 1.4.90 +- version up +== SungMin Ha 2013-02-15 +* 1.4.89 +- added bottom half instead of mloop +== GiWoong Kim 2013-02-15 +* 1.4.80 +- version up for making new package +== Munkyu Im 2013-02-04 +* 1.4.79 +- added pthread_mutex_destroy +== GiWoong Kim 2013-01-29 +* 1.4.76 +- prepare 10 colors for Pair Tag +== GiWoong Kim 2013-01-25 +* 1.4.67 +- Changed host keyboard status routine on OS X. +== Kitae Kim 2013-01-24 +* 1.4.66 +- modified screenshot operation when vga is not ready +== Sungmin Ha 2013-01-23 +* 1.4.65 +- version up for making new package +== Munkyu Im 2013-01-22 +* 1.4.64 +- Fix emulator crash problem when using EffectsApp. +== Sangjin Kim 2013-01-17 +* 1.4.62 +- removed ifndef for screenshot +== Sungmin Ha 2013-01-17 +* 1.4.61 +- Fixed a problem about displayed useless line on screenshot +== Sungmin Ha 2013-01-16 +* 1.4.60 +- removed setFocus on mac +== GiWoong Kim 2013-01-16 +* 1.4.58 +- modify init process +== Munkyu Im 2013-01-16 +* 1.4.57 +- modified include path +== GiWoong Kim 2013-01-15 +* 1.4.55 +- move SDL_gfx files +== GiWoong Kim 2013-01-15 +* 1.4.51 +- control the focus in general skin +== GiWoong Kim 2013-01-14 +* 1.4.49 +- switch the z-order between main window and key window +== GiWoong Kim 2013-01-11 +* 1.4.43 +- change temp file path +== Munkyu Im 2013-01-09 +* 1.4.42 +- fix dynamic loading library path +== Munkyu Im 2013-01-04 +* 1.4.41 +- fix multi touch on Mac +== Munkyu Im 2013-01-03 +* 1.4.40 +- version up +== Munkyu Im 2013-01-03 +* 1.4.39 +- version up +== Sooyoung Ha 2013-01-03 +* 1.4.38 +- Fixed a memory leak while decoding video. +== Kitae Kim 2012-12-28 +* 1.4.35 +- fix gl capability check fail on windows intel graphics machine. +== Sangjin Kim 2012-12-28 +* 1.4.34 +- fix getting proxy +== Munkyu Im 2012-12-27 +* 1.4.33 +- Fixed codec module and added function declarations for virtio-keyboard. +== Kitae Kim 2012-12-18 +* 1.4.32 +- Copy sdbscript file to bin folder on mac. +== GiWoong Kim 2012-12-18 +* 1.4.25 +- Fixed a capture failure on Linux system. +== Jinhyung Jo 2012-12-17 +* 1.4.24 +- Reverted dibs build script. +- The previous build script was wrong. +== Kitae Kim 2012-12-17 +* 1.4.23 +- Fixed an unexpected termination on Windows while previewing camera. +== Jinhyung Jo 2012-12-17 +* 1.4.22 +- Added multi-touch control scenario +== GiWoong Kim 2012-12-10 +* 1.4.17 +- Added double quotation mark for path. +== GiWoong Kim 2012-12-06 +* 1.4.15 +- rearrange finger image when rotate +== Munkyu In 2012-11-29 +* 1.4.14 +- added try-catch to AboutDialog +== GiWoong Kim 2012-11-29 +* 1.4.13 +- Text dimming issue fixed at windows with nvidia card. +== Sangjin Kim 2012-11-28 +* 1.4.12 +- Convert a HW key container in general skin +== GiWoong Kim 2012-11-26 +* 1.4.9 +- Fix EGL_BAD_ALLOC error when using pixmap surface repeatedly. +== Sangjin Kim 2012-11-22 +* 1.4.8 +- Added force close menu +- Advanced>Force Close +== GiWoong Kim 2012-11-12 +* 1.4.7 +- Fixed a bug of brightness level +== Jinhyung Jo 2012-11-15 +* 1.4.6 +- refactoring of skin code +- Fixed N_SE-12805 issue +== GiWoong Kim 2012-11-14 +* 1.4.5 +- refactoring of skin code +- Added EmulatorSkinState file & define ISkinComposer interface +== GiWoong Kim 2012-11-12 +* 1.4.4 +- Apply qemu_ld/st optimization according to QEMU 1.2 +== Yeongkyoon Lee 2012-11-09 +* 1.4.2 +- Added libattr1-dev, libcap library +- Added libattr1-dev, libcap library +== GiWoong Kim 2012-11-08 +* 1.4.1 +- Disable folding button in general skin +- Disable folding button in general skin +== GiWoong Kim 2012-11-06 +* 1.4.0 +- vga: Support HVGA, WXGA, HD1080, WQXGA resolution. +- Support HVGA, WXGA, HD1080, WQXGA resolution. +== Signed-off-by: Sangjin Kim 2012-11-02 +* 1.3.68 +- Don't lose the release event of HW key +- Event if user releases the mouse cursor at outside of HW key area, it does not lose the event. +== GiWoong Kim 2012-10-29 +* 1.3.66 +- Change SDK version. +- Change version from 2.0a3 to 2.0a4-RC1 +== Kitae Kim 2012-10-23 diff --git a/package/emulator-qemu-common.remove.ubuntu-32 b/package/emulator-qemu-common.remove.ubuntu-32 index f1f106e19c..26af7354de 100755 --- a/package/emulator-qemu-common.remove.ubuntu-32 +++ b/package/emulator-qemu-common.remove.ubuntu-32 @@ -13,6 +13,14 @@ echo "rm -f /etc/init.d/tizen-kvm" >> $TMP_FILE echo "rm -f /lib/udev/rules.d/45-tizen-kvm.rules" >> $TMP_FILE chmod +x $TMP_FILE -gksudo ./$TMP_FILE + +GKSUDO=`which gksudo` +if [ "$GKSUDO" = "" ] +then + echo "there is no gksudo." + sudo ./$TMP_FILE +else + gksudo ./$TMP_FILE +fi rm $TMP_FILE diff --git a/package/emulator-qemu-common.remove.ubuntu-64 b/package/emulator-qemu-common.remove.ubuntu-64 index f1f106e19c..26af7354de 100755 --- a/package/emulator-qemu-common.remove.ubuntu-64 +++ b/package/emulator-qemu-common.remove.ubuntu-64 @@ -13,6 +13,14 @@ echo "rm -f /etc/init.d/tizen-kvm" >> $TMP_FILE echo "rm -f /lib/udev/rules.d/45-tizen-kvm.rules" >> $TMP_FILE chmod +x $TMP_FILE -gksudo ./$TMP_FILE + +GKSUDO=`which gksudo` +if [ "$GKSUDO" = "" ] +then + echo "there is no gksudo." + sudo ./$TMP_FILE +else + gksudo ./$TMP_FILE +fi rm $TMP_FILE diff --git a/package/emulator-qemu-common.install.ubuntu-32 b/package/emulator-qemu-x86.install.ubuntu-32 similarity index 81% rename from package/emulator-qemu-common.install.ubuntu-32 rename to package/emulator-qemu-x86.install.ubuntu-32 index ba1c51fbf4..e2b45922b0 100755 --- a/package/emulator-qemu-common.install.ubuntu-32 +++ b/package/emulator-qemu-x86.install.ubuntu-32 @@ -14,6 +14,14 @@ echo "/etc/init.d/tizen-kvm start" >> $TMP_FILE echo "update-rc.d tizen-kvm defaults" >> $TMP_FILE chmod +x $TMP_FILE -gksudo ./$TMP_FILE + +GKSUDO=`which gksudo` +if [ "$GKSUDO" = "" ] +then + echo "there is no gksudo." + sudo ./$TMP_FILE +else + gksudo ./$TMP_FILE +fi rm $TMP_FILE diff --git a/package/emulator-qemu-common.install.ubuntu-64 b/package/emulator-qemu-x86.install.ubuntu-64 similarity index 81% rename from package/emulator-qemu-common.install.ubuntu-64 rename to package/emulator-qemu-x86.install.ubuntu-64 index ba1c51fbf4..e2b45922b0 100755 --- a/package/emulator-qemu-common.install.ubuntu-64 +++ b/package/emulator-qemu-x86.install.ubuntu-64 @@ -14,6 +14,14 @@ echo "/etc/init.d/tizen-kvm start" >> $TMP_FILE echo "update-rc.d tizen-kvm defaults" >> $TMP_FILE chmod +x $TMP_FILE -gksudo ./$TMP_FILE + +GKSUDO=`which gksudo` +if [ "$GKSUDO" = "" ] +then + echo "there is no gksudo." + sudo ./$TMP_FILE +else + gksudo ./$TMP_FILE +fi rm $TMP_FILE diff --git a/package/pkginfo.manifest b/package/pkginfo.manifest index ec022f60f0..b0d85f692b 100644 --- a/package/pkginfo.manifest +++ b/package/pkginfo.manifest @@ -1,4 +1,4 @@ -Version: 2.0.0 +Version: 1.5.22 Maintainer: Yeong-Kyoon Lee Source: emulator diff --git a/tizen/distrib/initscript/tizen_kvm b/tizen/distrib/initscript/tizen_kvm new file mode 100755 index 0000000000..263a687d2a --- /dev/null +++ b/tizen/distrib/initscript/tizen_kvm @@ -0,0 +1,24 @@ +#!/bin/sh +do_start () { + if grep -qs "^flags.* vmx" /proc/cpuinfo; then + modprobe -b kvm_intel "$KVM_NESTED" + elif grep -qs "^flags.* svm" /proc/cpuinfo; then + modprobe -b kvm_amd + fi +} + +case "$1" in + start) + do_start + ;; + restart|reload|force-reload) + # No-op + ;; + stop) + # No-op + ;; + *) + echo "Usage: $0 start|stop" >&2 + exit 3 + ;; +esac diff --git a/tizen/src/Makefile b/tizen/src/Makefile index 734c1ef69e..7eda9e8ff4 100755 --- a/tizen/src/Makefile +++ b/tizen/src/Makefile @@ -37,6 +37,7 @@ endif ifdef CONFIG_DARWIN $(CC) -mmacosx-version-min=10.4 -o check-hax check_hax.c endif + skin_client: ant -buildfile skin/client/build.xml make-jar @@ -118,13 +119,16 @@ endif cp skin/client/emulator-skin.jar $(EMUL_DIR)/bin ifdef CONFIG_WIN32 + cp ../../i386-softmmu/check-gl.exe $(EMUL_DIR)/bin cp check-hax.exe $(EMUL_DIR)/bin endif ifdef CONFIG_DARWIN + cp ../../i386-softmmu/check-gl $(EMUL_DIR)/bin cp check-hax $(EMUL_DIR)/bin cp sdbscript $(EMUL_DIR)/bin endif ifdef CONFIG_LINUX + cp ../../i386-softmmu/check-gl $(EMUL_DIR)/bin cp -pPr ../distrib/initscript/tizen-kvm $(EMUL_DIR)/etc cp -pPr ../distrib/initscript/45-tizen-kvm.rules $(EMUL_DIR)/etc endif @@ -143,12 +147,15 @@ else endif ifdef CONFIG_DARWIN - install_name_tool -change /opt/local/lib/libgthread-2.0.*.dylib @loader_path/libgthread-2.0.0.dylib $(EMUL_DIR)/bin/qemu-img + install_name_tool -change /opt/local/lib/libgthread-2.0.*.dylib @loader_path/libgthread-2.0.0.dylib $(EMUL_DIR)/bin/qemu-img install_name_tool -change /opt/local/lib/libglib-2.0.*.dylib @loader_path/libglib-2.0.0.dylib $(EMUL_DIR)/bin/qemu-img install_name_tool -change /opt/local/lib/libintl.8.dylib @loader_path/libintl.8.dylib $(EMUL_DIR)/bin/qemu-img install_name_tool -change /opt/local/lib/gcc47/libgcc_s.1.dylib @loader_path/libgcc_s.1.dylib $(EMUL_DIR)/bin/qemu-img install_name_tool -change /opt/local/lib/libz.1.dylib @loader_path/libz.1.dylib $(EMUL_DIR)/bin/qemu-img install_name_tool -change /opt/local/lib/libcurl.4.dylib @loader_path/libcurl.4.dylib $(EMUL_DIR)/bin/qemu-img + install_name_tool -change /opt/local/lib/libglib-2.0.*.dylib @loader_path/libglib-2.0.0.dylib $(EMUL_DIR)/bin/check-gl + install_name_tool -change /opt/local/lib/libintl.8.dylib @loader_path/libintl.8.dylib $(EMUL_DIR)/bin/check-gl + install_name_tool -change /opt/local/lib/gcc47/libgcc_s.1.dylib @loader_path/libgcc_s.1.dylib $(EMUL_DIR)/bin/check-gl @for target in $(TARGET_DIRS); do \ case "$$target" in \ @@ -178,6 +185,7 @@ install_dibs: all_dibs mkdir -p $(DIBS_COMMON_DIR)/etc mkdir -p $(DIBS_X86_DIR)/bin mkdir -p $(DIBS_X86_DIR)/data + mkdir -p $(DIBS_X86_DIR)/etc mkdir -p $(DIBS_ARM_DIR)/bin ifndef CONFIG_DARWIN @for target in $(TARGET_DIRS); do \ @@ -227,17 +235,20 @@ endif cp skin/client/emulator-skin.jar $(DIBS_COMMON_DIR)/bin ifdef CONFIG_WIN32 + cp ../../i386-softmmu/check-gl.exe $(DIBS_COMMON_DIR)/bin cp check-hax.exe $(DIBS_COMMON_DIR)/bin endif ifdef CONFIG_DARWIN + cp ../../i386-softmmu/check-gl $(DIBS_COMMON_DIR)/bin cp check-hax $(DIBS_COMMON_DIR)/bin cp sdbscript $(DIBS_COMMON_DIR)/bin endif ifdef CONFIG_LINUX - echo "Copying tizen-kvm to $(DIBS_COMMON_DIR)/etc" - cp -pPr ../distrib/initscript/tizen-kvm $(DIBS_COMMON_DIR)/etc - cp -pPr ../distrib/initscript/45-tizen-kvm.rules $(DIBS_COMMON_DIR)/etc + cp ../../i386-softmmu/check-gl $(DIBS_COMMON_DIR)/bin + echo "Copying tizen-kvm to $(DIBS_X86_DIR)/etc" + cp -pPr ../distrib/initscript/tizen-kvm $(DIBS_X86_DIR)/etc + cp -pPr ../distrib/initscript/45-tizen-kvm.rules $(DIBS_X86_DIR)/etc endif ifndef CONFIG_DARWIN @@ -258,6 +269,9 @@ ifdef CONFIG_DARWIN install_name_tool -change /opt/local/lib/gcc47/libgcc_s.1.dylib @loader_path/libgcc_s.1.dylib $(DIBS_COMMON_DIR)/bin/qemu-img install_name_tool -change /opt/local/lib/libz.1.dylib @loader_path/libz.1.dylib $(DIBS_COMMON_DIR)/bin/qemu-img install_name_tool -change /opt/local/lib/libcurl.4.dylib @loader_path/libcurl.4.dylib $(DIBS_COMMON_DIR)/bin/qemu-img + install_name_tool -change /opt/local/lib/libglib-2.0.*.dylib @loader_path/libglib-2.0.0.dylib $(DIBS_COMMON_DIR)/bin/check-gl + install_name_tool -change /opt/local/lib/libintl.8.dylib @loader_path/libintl.8.dylib $(DIBS_COMMON_DIR)/bin/check-gl + install_name_tool -change /opt/local/lib/gcc47/libgcc_s.1.dylib @loader_path/libgcc_s.1.dylib $(DIBS_COMMON_DIR)/bin/check-gl @for target in $(TARGET_DIRS); do \ case "$$target" in \ diff --git a/tizen/src/Makefile.tizen b/tizen/src/Makefile.tizen index 8f3ed26d86..e374992410 100755 --- a/tizen/src/Makefile.tizen +++ b/tizen/src/Makefile.tizen @@ -87,7 +87,19 @@ endif #CONFIG_OPENGLES #endif #!CONFIG_DARWIN # maru loader -obj-y += emulator.o emul_state.o option.o maru_err_table.o +obj-y += emulator.o emul_state.o maru_err_table.o + +# osutil +obj-y += osutil.o +ifdef CONFIG_LINUX +obj-y += osutil-linux.o +endif +ifdef CONFIG_WIN32 +obj-y += osutil-win32.o +endif +ifdef CONFIG_DARWIN +obj-y += osutil-darwin.o +endif # maru display obj-y += maru_display.o maru_shm.o @@ -117,6 +129,7 @@ obj-y += maru_usb_touchscreen.o maru_virtio_touchscreen.o obj-y += maru_virtio_keyboard.o obj-y += maru_codec.o obj-y += maru_virtio_esm.o +obj-y += maru_virtio_hwkey.o obj-$(CONFIG_PCI) += maru_camera_common_pci.o obj-$(CONFIG_LINUX) += maru_camera_linux_pci.o diff --git a/tizen/src/SDL_gfx/AUTHORS b/tizen/src/SDL_gfx/AUTHORS new file mode 100644 index 0000000000..9ea070b34f --- /dev/null +++ b/tizen/src/SDL_gfx/AUTHORS @@ -0,0 +1 @@ +Andreas Schiffler diff --git a/tizen/src/SDL_gfx/COPYING b/tizen/src/SDL_gfx/COPYING new file mode 100644 index 0000000000..04bd5d6ac4 --- /dev/null +++ b/tizen/src/SDL_gfx/COPYING @@ -0,0 +1 @@ +(C) A. Schiffler, ZLIB - see file LICENSE diff --git a/tizen/src/SDL_gfx/LICENSE b/tizen/src/SDL_gfx/LICENSE new file mode 100644 index 0000000000..f1eb9d86e4 --- /dev/null +++ b/tizen/src/SDL_gfx/LICENSE @@ -0,0 +1,26 @@ +/* + +Copyright (C) 2001-2011 Andreas Schiffler + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +Andreas Schiffler -- aschiffler at ferzkopp dot net + +*/ \ No newline at end of file diff --git a/tizen/src/SDL_gfx/README b/tizen/src/SDL_gfx/README new file mode 100644 index 0000000000..cc8409d9a4 --- /dev/null +++ b/tizen/src/SDL_gfx/README @@ -0,0 +1,500 @@ +/*! + + +\mainpage SDL_gfx - SDL-1.2 graphics drawing primitives, rotozoom and other supporting functions + + +\section contact_sec Contact and License + +Email aschiffler at ferzkopp dot net to contact the author or better check +author's homepage at http://www.ferzkopp.net for the most up-to-date +contact information. + +This library is licenced under the zlib License, see the file LICENSE for details. + + +\section intro_sec Introduction + +The SDL_gfx library evolved out of the SDL_gfxPrimitives code which +provided basic drawing routines such as lines, circles or polygons for +SDL Surfaces and adding a couple other useful functions for zooming +images for example and doing basic image processing on byte arrays. + +Note that SDL_gfx is compatible with SDL version 1.2 (not SDL2). + +The current components of the SDL_gfx library are: +- Graphic Primitives (SDL_gfxPrimitives.h, SDL_gfxPrimitives.c) +- Rotozoomer (SDL_rotozoom.h, SDL_rotozoom.c) +- Framerate control (SDL_framerate.h, SDL_framerate.c) +- MMX image filters (SDL_imageFilter.h, SDL_imageFilter.c) +- Custom Blit functions (SDL_gfxBlitFunc.h, SDL_gfxBlitFunc.c) +- Build-in 8x8 Font (SDL_gfxPrimitives_font.h) + + + +\subsection notes_gfx Notes on Graphics Primitives + +Care has been taken so that all routines are fully alpha-aware and can +blend any primitive onto the target surface if ALPHA<255. Surface depths +supported are 1,2,3 and 4 bytes per pixel. Surface locking is implemented +in each routine and the library should work well with hardware +accelerated surfaces. + +\htmlonly +
+\endhtmlonly + +Currently, The following Anti-Aliased drawing primitives are available: +- AA-line +- AA-polygon +- AA-circle +- AA-ellipse + +Note: All ___Color routines expect the color to be in the format 0xRRGGBBAA. + +\subsection notes_roto Notes on Rotozoomer + +The rotozoom code is not ASM-speed quality, but it should be fast enough +even for some realtime effects if the CPU is good or bitmaps small. +With interpolation the routines are typically used for pre-rendering stuff +in higher quality (i.e. smoothing) - that's also the reason why the API differs +from SDL_BlitRect() - as they create a new target surface each time rotozoom +is called. The final rendering speed is dependent on the target surface +size as it is beeing xy-scanned when rendering the new surface. + +\htmlonly +
+\endhtmlonly + +Note also that the smoothing toggle is dependent on the input surface bit +depth. 8bit surfaces will \b never be smoothed - only 32bit surfaces will. + +Note that surfaces of other bit depth then 8 and 32 will be converted +on the fly to a 32bit surface using a blit into a temporary surface. This +impacts performance somewhat. + +Smoothing (interpolation) flags work only on 32bit surfaces: +\verbatim + #define SMOOTHING_OFF 0 + #define SMOOTHING_ON 1 +\endverbatim + +\subsection notes_rate Notes on Framerate Manager + +The framerate functions are used to insert delays into the graphics loop +to maintain a constant framerate. + +The implementation is more sophisticated that the usual +\verbatim + SDL_Delay(1000/FPS); +\endverbatim +call since these functions keep track of the desired game time per frame +for a linearly interpolated sequence of future timing points of each frame. +This is done to avoid rounding errors from the inherent instability in the +delay generation and application. + +\htmlonly +
+\endhtmlonly + +i.e. the 100th frame of a game running at 50Hz will be accurately +2.00sec after the 1st frame (if the machine can keep up with the drawing). + +The functions return 0 or 'value' for sucess and -1 for error. All functions +use a pointer to a framerate-manager variable to operate. + + +\subsection notes_filter Notes on ImageFilters + +The imagefilter functions are a collection of MMX optimized routines that +operate on continuous buffers of bytes - typically greyscale images from +framegrabbers and such - performing functions such as image addition and +binarization. All functions (almost ... not the the convolution routines) +have a C implementation that is automatically used on systems without MMX +capabilities. + +The compiler flag -DUSE_MMX toggles the conditional compile of MMX assembly. +An assembler must be installed (i.e. "nasm"). + + +\subsection notes_blitters Notes on Custom Blitters + +The custom blitter functions provide (limited) support for surface +compositing - that is surfaces can be blitted together, and then +still blitted to the screen with transparency intact. + +\subsection platforms Supported Platforms + +\subsubsection platformlinux Unix/Linux + +The library compiles and is tested for a Linux target (gcc compiler) via the +the usual configure;make;make install sequence. + +\subsubsection platformwindows Windows + +A Win32 target is available (VisualC6/7/8/9, mingw32, xmingw32 cross-compiler). +The SDL_gfx.sln will open VS2010 (the old VS2008 .sln is also still included) +including express versions. + +See "Other Builds" for additional makefiles (may be out of date). + +When using the cross-compiler (available on the author's homepage, very +out of date), the build process generates .DLLs. You can use the command +line 'LIB.EXE' tool to generate VC6 compatible .LIB files for linking +purposes. + +\subsubsection platformosx Mac OSX + +The usual autotools build chain should be used. MacPorts or fink may +be required (that's what the author uses). + +Xcode is supported via templates. See "Other Builds" folder Xcode3+.zip - +this template only supports SDL_gfx and not the tests. For this template, the +Deployment Target (the lowest version to run on) is set to 10.5 and expects +the SDL.framework preinstalled in some default location +(either /Library/Frameworks, or ~/Library/Frameworks). + +Older targets are also reported to work (10.3+ native and Project Builder). + +\subsubsection platformqnx QNX + +QNX was reported to build (see .diff in "Other Builds"). + +\subsubsection platformzune Zune + +ZuneHD (WinCE 6 ARM) is reported to build (see OpenZDK in "Other Builds"). +Note that between rendering on the Zune's ARM CPU and constantly uploading +textures to the GPU, SDL_gfx is going to be slow. Also, the libc math +functions all use software FP emulation even when VFP floating point +support is turned on in the compiler, so there's extra overhead due to that +as well. + +\subsubsection platformothers Others + +Other platforms might work but have not been tested by the author. +Please check the file "INSTALL" as well as the folder "Other Builds". + +See also section "Installation" below for more build instructions. + +\section install_sec Installation + +\subsection unix Unix/Linux + +To compile the library your need the SDL 1.2 installed from source or +installed with the 'devel' RPM package. For example on Mandriva, run: +\verbatim + urpmi libSDL1.2-devel +\endverbatim + +Then run +\verbatim + ./autogen.sh # (optional, recommended) + ./configure + make + make install + ldconfig +\endverbatim + +to compile and install the library. The default location for the +installation is /usr/local/lib and /usr/local/include. The libary +path might need to be added to the file: + /etc/ld.so.conf + +Run the shell script 'nodebug.sh' before make, to patch the makefile +for optimized compilation: +\verbatim + ./autogen.sh # (optional, recommended) + ./configure + ./nodebug.sh + make + make install + ldconfig +\endverbatim + +Check the folder "Other Builds" for alternative makefiles. + +\subsection prep Build Prep + +Run autogen.sh or manually: +\verbatim + aclocal --force + libtoolize --force --copy + autoreconf -fvi +\endverbatim + +\subsection nommx No-MMX + +To build without MMX code enabled (i.e. PPC or for AMD64 architecture +which is missing pusha/popa): +\verbatim + ./configure --disable-mmx + make + make install +\endverbatim +i.e. to build on MacOSX 10.3+ use: +\verbatim + ./configure --disable-mmx && make +\endverbatim + +\subsection vs9 Windows (VC9, VS2010) + +Open SDL_gfx.sln solution file and review README. + +\subsection vs8 Windows (VC8, VS2008) + +Open SDL_gfx_VS2008.sln solution file and review README. + + +\subsection vc6 Windows (VC6/7) + +See folder Other Builds. + +To create a Windows DLL using VisualC6: +\verbatim + unzip -a VisualC6.zip + vcvars32.bat + copy VisualC/makefile + nmake +\endverbatim +or +\verbatim + unzip -a VisualC7.zip +\endverbatim +and open the project file. + + +\subsection wince WindowsCE + +See folder Other Builds. + +May need workaround for missing lrint. + + +\subsection cross Cross-Compilation + +To build using mingw32 on Win32, check the makefile contained in mingw.zip + +To create a Windows DLL using the xmingw32 cross-compiler: +\verbatim + cross-configure + cross-make + cross-make install +\endverbatim + +Make sure the -DBUILD_DLL is used (and only then) when creating the DLLs. +Make sure -DWIN32 is used when compiling the sources (creating or using +the DLLs. + +Specify the path to your cross-compiled 'sdl-config', and invoke +'./configure' with the '--host' and '--build' arguments. For example, +to cross-compile a .DLL from GNU/Linux: +\verbatim + SDL_CONFIG=/usr/local/cross-tools/i386-mingw32msvc/bin/sdl-config \ + ./configure --host=i586-mingw32msvc --build=i686-pc-linux-gnu + make + make install +\endverbatim + +\subsection qnx QNX + +To build on QNX6, patch first using: +\verbatim + patch -p0 +#endif + +#include +#include + +#include "SDL_rotozoom.h" + +/* ---- Internally used structures */ + +/*! +\brief A 32 bit RGBA pixel. +*/ +typedef struct tColorRGBA { + Uint8 r; + Uint8 g; + Uint8 b; + Uint8 a; +} tColorRGBA; + +/*! +\brief A 8bit Y/palette pixel. +*/ +typedef struct tColorY { + Uint8 y; +} tColorY; + +/*! +\brief Returns maximum of two numbers a and b. +*/ +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) + +/*! +\brief Number of guard rows added to destination surfaces. + +This is a simple but effective workaround for observed issues. +These rows allocate extra memory and are then hidden from the surface. +Rows are added to the end of destination surfaces when they are allocated. +This catches any potential overflows which seem to happen with +just the right src image dimensions and scale/rotation and can lead +to a situation where the program can segfault. +*/ +#define GUARD_ROWS (2) + +/*! +\brief Lower limit of absolute zoom factor or rotation degrees. +*/ +#define VALUE_LIMIT 0.001 + +/*! +\brief Returns colorkey info for a surface +*/ +static Uint32 _colorkey(SDL_Surface *src) +{ + Uint32 key = 0; +#if (SDL_MINOR_VERSION == 3) + SDL_GetColorKey(src, &key); +#else + if (src) + { + key = src->format->colorkey; + } +#endif + return key; +} + + +/*! +\brief Internal 32 bit integer-factor averaging Shrinker. + +Shrinks 32 bit RGBA/ABGR 'src' surface to 'dst' surface. +Averages color and alpha values values of src pixels to calculate dst pixels. +Assumes src and dst surfaces are of 32 bit depth. +Assumes dst surface was allocated with the correct dimensions. + +\param src The surface to shrink (input). +\param dst The shrunken surface (output). +\param factorx The horizontal shrinking ratio. +\param factory The vertical shrinking ratio. + +\return 0 for success or -1 for error. +*/ +static int _shrinkSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int factorx, int factory) +{ + int x, y, dx, dy, sgap, dgap, ra, ga, ba, aa; + int n_average; + tColorRGBA *sp, *osp, *oosp; + tColorRGBA *dp; + + /* + * Averaging integer shrink + */ + + /* Precalculate division factor */ + n_average = factorx*factory; + + /* + * Scan destination + */ + sp = (tColorRGBA *) src->pixels; + sgap = src->pitch - src->w * 4; + + dp = (tColorRGBA *) dst->pixels; + dgap = dst->pitch - dst->w * 4; + + for (y = 0; y < dst->h; y++) { + + osp=sp; + for (x = 0; x < dst->w; x++) { + + /* Trace out source box and accumulate */ + oosp=sp; + ra=ga=ba=aa=0; + for (dy=0; dy < factory; dy++) { + for (dx=0; dx < factorx; dx++) { + ra += sp->r; + ga += sp->g; + ba += sp->b; + aa += sp->a; + + sp++; + } + /* src dx loop */ + sp = (tColorRGBA *)((Uint8*)sp + (src->pitch - 4*factorx)); // next y + } + /* src dy loop */ + + /* next box-x */ + sp = (tColorRGBA *)((Uint8*)oosp + 4*factorx); + + /* Store result in destination */ + dp->r = ra/n_average; + dp->g = ga/n_average; + dp->b = ba/n_average; + dp->a = aa/n_average; + + /* + * Advance destination pointer + */ + dp++; + } + /* dst x loop */ + + /* next box-y */ + sp = (tColorRGBA *)((Uint8*)osp + src->pitch*factory); + + /* + * Advance destination pointers + */ + dp = (tColorRGBA *) ((Uint8 *) dp + dgap); + } + /* dst y loop */ + + return (0); +} + +/*! +\brief Internal 8 bit integer-factor averaging shrinker. + +Shrinks 8bit Y 'src' surface to 'dst' surface. +Averages color (brightness) values values of src pixels to calculate dst pixels. +Assumes src and dst surfaces are of 8 bit depth. +Assumes dst surface was allocated with the correct dimensions. + +\param src The surface to shrink (input). +\param dst The shrunken surface (output). +\param factorx The horizontal shrinking ratio. +\param factory The vertical shrinking ratio. + +\return 0 for success or -1 for error. +*/ +static int _shrinkSurfaceY(SDL_Surface * src, SDL_Surface * dst, int factorx, int factory) +{ + int x, y, dx, dy, sgap, dgap, a; + int n_average; + Uint8 *sp, *osp, *oosp; + Uint8 *dp; + + /* + * Averaging integer shrink + */ + + /* Precalculate division factor */ + n_average = factorx*factory; + + /* + * Scan destination + */ + sp = (Uint8 *) src->pixels; + sgap = src->pitch - src->w; + + dp = (Uint8 *) dst->pixels; + dgap = dst->pitch - dst->w; + + for (y = 0; y < dst->h; y++) { + + osp=sp; + for (x = 0; x < dst->w; x++) { + + /* Trace out source box and accumulate */ + oosp=sp; + a=0; + for (dy=0; dy < factory; dy++) { + for (dx=0; dx < factorx; dx++) { + a += (*sp); + /* next x */ + sp++; + } + /* end src dx loop */ + /* next y */ + sp = (Uint8 *)((Uint8*)sp + (src->pitch - factorx)); + } + /* end src dy loop */ + + /* next box-x */ + sp = (Uint8 *)((Uint8*)oosp + factorx); + + /* Store result in destination */ + *dp = a/n_average; + + /* + * Advance destination pointer + */ + dp++; + } + /* end dst x loop */ + + /* next box-y */ + sp = (Uint8 *)((Uint8*)osp + src->pitch*factory); + + /* + * Advance destination pointers + */ + dp = (Uint8 *)((Uint8 *)dp + dgap); + } + /* end dst y loop */ + + return (0); +} + +/*! +\brief Internal 32 bit Zoomer with optional anti-aliasing by bilinear interpolation. + +Zooms 32 bit RGBA/ABGR 'src' surface to 'dst' surface. +Assumes src and dst surfaces are of 32 bit depth. +Assumes dst surface was allocated with the correct dimensions. + +\param src The surface to zoom (input). +\param dst The zoomed surface (output). +\param flipx Flag indicating if the image should be horizontally flipped. +\param flipy Flag indicating if the image should be vertically flipped. +\param smooth Antialiasing flag; set to SMOOTHING_ON to enable. + +\return 0 for success or -1 for error. +*/ +static int _zoomSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy, int smooth) +{ + int x, y, sx, sy, ssx, ssy, *sax, *say, *csax, *csay, *salast, csx, csy, ex, ey, cx, cy, sstep, sstepx, sstepy; + tColorRGBA *c00, *c01, *c10, *c11; + tColorRGBA *sp, *csp, *dp; + int spixelgap, spixelw, spixelh, dgap, t1, t2; + + /* + * Allocate memory for row/column increments + */ + if ((sax = (int *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) { + return (-1); + } + if ((say = (int *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) { + free(sax); + return (-1); + } + + /* + * Precalculate row increments + */ + spixelw = (src->w - 1); + spixelh = (src->h - 1); + if (smooth) { + sx = (int) (65536.0 * (float) spixelw / (float) (dst->w - 1)); + sy = (int) (65536.0 * (float) spixelh / (float) (dst->h - 1)); + } else { + sx = (int) (65536.0 * (float) (src->w) / (float) (dst->w)); + sy = (int) (65536.0 * (float) (src->h) / (float) (dst->h)); + } + + /* Maximum scaled source size */ + ssx = (src->w << 16) - 1; + ssy = (src->h << 16) - 1; + + /* Precalculate horizontal row increments */ + csx = 0; + csax = sax; + for (x = 0; x <= dst->w; x++) { + *csax = csx; + csax++; + csx += sx; + + /* Guard from overflows */ + if (csx > ssx) { + csx = ssx; + } + } + + /* Precalculate vertical row increments */ + csy = 0; + csay = say; + for (y = 0; y <= dst->h; y++) { + *csay = csy; + csay++; + csy += sy; + + /* Guard from overflows */ + if (csy > ssy) { + csy = ssy; + } + } + + sp = (tColorRGBA *) src->pixels; + dp = (tColorRGBA *) dst->pixels; + dgap = dst->pitch - dst->w * 4; + spixelgap = src->pitch/4; + + if (flipx) sp += spixelw; + if (flipy) sp += (spixelgap * spixelh); + + /* + * Switch between interpolating and non-interpolating code + */ + if (smooth) { + + /* + * Interpolating Zoom + */ + csay = say; + for (y = 0; y < dst->h; y++) { + csp = sp; + csax = sax; + for (x = 0; x < dst->w; x++) { + /* + * Setup color source pointers + */ + ex = (*csax & 0xffff); + ey = (*csay & 0xffff); + cx = (*csax >> 16); + cy = (*csay >> 16); + sstepx = cx < spixelw; + sstepy = cy < spixelh; + c00 = sp; + c01 = sp; + c10 = sp; + if (sstepy) { + if (flipy) { + c10 -= spixelgap; + } else { + c10 += spixelgap; + } + } + c11 = c10; + if (sstepx) { + if (flipx) { + c01--; + c11--; + } else { + c01++; + c11++; + } + } + + /* + * Draw and interpolate colors + */ + t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff; + t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff; + dp->r = (((t2 - t1) * ey) >> 16) + t1; + t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff; + t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff; + dp->g = (((t2 - t1) * ey) >> 16) + t1; + t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff; + t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff; + dp->b = (((t2 - t1) * ey) >> 16) + t1; + t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff; + t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff; + dp->a = (((t2 - t1) * ey) >> 16) + t1; + /* + * Advance source pointer x + */ + salast = csax; + csax++; + sstep = (*csax >> 16) - (*salast >> 16); + if (flipx) { + sp -= sstep; + } else { + sp += sstep; + } + + /* + * Advance destination pointer x + */ + dp++; + } + /* + * Advance source pointer y + */ + salast = csay; + csay++; + sstep = (*csay >> 16) - (*salast >> 16); + sstep *= spixelgap; + if (flipy) { + sp = csp - sstep; + } else { + sp = csp + sstep; + } + + /* + * Advance destination pointer y + */ + dp = (tColorRGBA *) ((Uint8 *) dp + dgap); + } + } else { + /* + * Non-Interpolating Zoom + */ + csay = say; + for (y = 0; y < dst->h; y++) { + csp = sp; + csax = sax; + for (x = 0; x < dst->w; x++) { + /* + * Draw + */ + *dp = *sp; + + /* + * Advance source pointer x + */ + salast = csax; + csax++; + sstep = (*csax >> 16) - (*salast >> 16); + if (flipx) sstep = -sstep; + sp += sstep; + + /* + * Advance destination pointer x + */ + dp++; + } + /* + * Advance source pointer y + */ + salast = csay; + csay++; + sstep = (*csay >> 16) - (*salast >> 16); + sstep *= spixelgap; + if (flipy) sstep = -sstep; + sp = csp + sstep; + + /* + * Advance destination pointer y + */ + dp = (tColorRGBA *) ((Uint8 *) dp + dgap); + } + } + + /* + * Remove temp arrays + */ + free(sax); + free(say); + + return (0); +} + +/*! + +\brief Internal 8 bit Zoomer without smoothing. + +Zooms 8bit palette/Y 'src' surface to 'dst' surface. +Assumes src and dst surfaces are of 8 bit depth. +Assumes dst surface was allocated with the correct dimensions. + +\param src The surface to zoom (input). +\param dst The zoomed surface (output). +\param flipx Flag indicating if the image should be horizontally flipped. +\param flipy Flag indicating if the image should be vertically flipped. + +\return 0 for success or -1 for error. +*/ +static int _zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy) +{ + int x, y; + Uint32 *sax, *say, *csax, *csay; + int csx, csy; + Uint8 *sp, *dp, *csp; + int dgap; + + /* + * Allocate memory for row increments + */ + if ((sax = (Uint32 *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) { + return (-1); + } + if ((say = (Uint32 *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) { + free(sax); + return (-1); + } + + /* + * Pointer setup + */ + sp = csp = (Uint8 *) src->pixels; + dp = (Uint8 *) dst->pixels; + dgap = dst->pitch - dst->w; + + if (flipx) csp += (src->w-1); + if (flipy) csp = ( (Uint8*)csp + src->pitch*(src->h-1) ); + + /* + * Precalculate row increments + */ + csx = 0; + csax = sax; + for (x = 0; x < dst->w; x++) { + csx += src->w; + *csax = 0; + while (csx >= dst->w) { + csx -= dst->w; + (*csax)++; + } + (*csax) = (*csax) * (flipx ? -1 : 1); + csax++; + } + csy = 0; + csay = say; + for (y = 0; y < dst->h; y++) { + csy += src->h; + *csay = 0; + while (csy >= dst->h) { + csy -= dst->h; + (*csay)++; + } + (*csay) = (*csay) * (flipy ? -1 : 1); + csay++; + } + + /* + * Draw + */ + csay = say; + for (y = 0; y < dst->h; y++) { + csax = sax; + sp = csp; + for (x = 0; x < dst->w; x++) { + /* + * Draw + */ + *dp = *sp; + /* + * Advance source pointers + */ + sp += (*csax); + csax++; + /* + * Advance destination pointer + */ + dp++; + } + /* + * Advance source pointer (for row) + */ + csp += ((*csay) * src->pitch); + csay++; + + /* + * Advance destination pointers + */ + dp += dgap; + } + + /* + * Remove temp arrays + */ + free(sax); + free(say); + + return (0); +} + +/*! +\brief Internal 32 bit rotozoomer with optional anti-aliasing. + +Rotates and zooms 32 bit RGBA/ABGR 'src' surface to 'dst' surface based on the control +parameters by scanning the destination surface and applying optionally anti-aliasing +by bilinear interpolation. +Assumes src and dst surfaces are of 32 bit depth. +Assumes dst surface was allocated with the correct dimensions. + +\param src Source surface. +\param dst Destination surface. +\param cx Horizontal center coordinate. +\param cy Vertical center coordinate. +\param isin Integer version of sine of angle. +\param icos Integer version of cosine of angle. +\param flipx Flag indicating horizontal mirroring should be applied. +\param flipy Flag indicating vertical mirroring should be applied. +\param smooth Flag indicating anti-aliasing should be used. +*/ +static void _transformSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int flipx, int flipy, int smooth) +{ + int x, y, t1, t2, dx, dy, xd, yd, sdx, sdy, ax, ay, ex, ey, sw, sh; + tColorRGBA c00, c01, c10, c11, cswap; + tColorRGBA *pc, *sp; + int gap; + + /* + * Variable setup + */ + xd = ((src->w - dst->w) << 15); + yd = ((src->h - dst->h) << 15); + ax = (cx << 16) - (icos * cx); + ay = (cy << 16) - (isin * cx); + sw = src->w - 1; + sh = src->h - 1; + pc = (tColorRGBA*) dst->pixels; + gap = dst->pitch - dst->w * 4; + + /* + * Switch between interpolating and non-interpolating code + */ + if (smooth) { + for (y = 0; y < dst->h; y++) { + dy = cy - y; + sdx = (ax + (isin * dy)) + xd; + sdy = (ay - (icos * dy)) + yd; + for (x = 0; x < dst->w; x++) { + dx = (sdx >> 16); + dy = (sdy >> 16); + if (flipx) dx = sw - dx; + if (flipy) dy = sh - dy; + if ((dx > -1) && (dy > -1) && (dx < (src->w-1)) && (dy < (src->h-1))) { + sp = (tColorRGBA *)src->pixels;; + sp += ((src->pitch/4) * dy); + sp += dx; + c00 = *sp; + sp += 1; + c01 = *sp; + sp += (src->pitch/4); + c11 = *sp; + sp -= 1; + c10 = *sp; + if (flipx) { + cswap = c00; c00=c01; c01=cswap; + cswap = c10; c10=c11; c11=cswap; + } + if (flipy) { + cswap = c00; c00=c10; c10=cswap; + cswap = c01; c01=c11; c11=cswap; + } + /* + * Interpolate colors + */ + ex = (sdx & 0xffff); + ey = (sdy & 0xffff); + t1 = ((((c01.r - c00.r) * ex) >> 16) + c00.r) & 0xff; + t2 = ((((c11.r - c10.r) * ex) >> 16) + c10.r) & 0xff; + pc->r = (((t2 - t1) * ey) >> 16) + t1; + t1 = ((((c01.g - c00.g) * ex) >> 16) + c00.g) & 0xff; + t2 = ((((c11.g - c10.g) * ex) >> 16) + c10.g) & 0xff; + pc->g = (((t2 - t1) * ey) >> 16) + t1; + t1 = ((((c01.b - c00.b) * ex) >> 16) + c00.b) & 0xff; + t2 = ((((c11.b - c10.b) * ex) >> 16) + c10.b) & 0xff; + pc->b = (((t2 - t1) * ey) >> 16) + t1; + t1 = ((((c01.a - c00.a) * ex) >> 16) + c00.a) & 0xff; + t2 = ((((c11.a - c10.a) * ex) >> 16) + c10.a) & 0xff; + pc->a = (((t2 - t1) * ey) >> 16) + t1; + } + sdx += icos; + sdy += isin; + pc++; + } + pc = (tColorRGBA *) ((Uint8 *) pc + gap); + } + } else { + for (y = 0; y < dst->h; y++) { + dy = cy - y; + sdx = (ax + (isin * dy)) + xd; + sdy = (ay - (icos * dy)) + yd; + for (x = 0; x < dst->w; x++) { + dx = (short) (sdx >> 16); + dy = (short) (sdy >> 16); + if (flipx) dx = (src->w-1)-dx; + if (flipy) dy = (src->h-1)-dy; + if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) { + sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy); + sp += dx; + *pc = *sp; + } + sdx += icos; + sdy += isin; + pc++; + } + pc = (tColorRGBA *) ((Uint8 *) pc + gap); + } + } +} + +/*! + +\brief Rotates and zooms 8 bit palette/Y 'src' surface to 'dst' surface without smoothing. + +Rotates and zooms 8 bit RGBA/ABGR 'src' surface to 'dst' surface based on the control +parameters by scanning the destination surface. +Assumes src and dst surfaces are of 8 bit depth. +Assumes dst surface was allocated with the correct dimensions. + +\param src Source surface. +\param dst Destination surface. +\param cx Horizontal center coordinate. +\param cy Vertical center coordinate. +\param isin Integer version of sine of angle. +\param icos Integer version of cosine of angle. +\param flipx Flag indicating horizontal mirroring should be applied. +\param flipy Flag indicating vertical mirroring should be applied. +*/ +static void transformSurfaceY(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int flipx, int flipy) +{ + int x, y, dx, dy, xd, yd, sdx, sdy, ax, ay, sw, sh; + tColorY *pc, *sp; + int gap; + + /* + * Variable setup + */ + xd = ((src->w - dst->w) << 15); + yd = ((src->h - dst->h) << 15); + ax = (cx << 16) - (icos * cx); + ay = (cy << 16) - (isin * cx); + sw = src->w - 1; + sh = src->h - 1; + pc = (tColorY*) dst->pixels; + gap = dst->pitch - dst->w; + /* + * Clear surface to colorkey + */ + memset(pc, (int)(_colorkey(src) & 0xff), dst->pitch * dst->h); + /* + * Iterate through destination surface + */ + for (y = 0; y < dst->h; y++) { + dy = cy - y; + sdx = (ax + (isin * dy)) + xd; + sdy = (ay - (icos * dy)) + yd; + for (x = 0; x < dst->w; x++) { + dx = (short) (sdx >> 16); + dy = (short) (sdy >> 16); + if (flipx) dx = (src->w-1)-dx; + if (flipy) dy = (src->h-1)-dy; + if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) { + sp = (tColorY *) (src->pixels); + sp += (src->pitch * dy + dx); + *pc = *sp; + } + sdx += icos; + sdy += isin; + pc++; + } + pc += gap; + } +} + +/*! +\brief Rotates a 32 bit surface in increments of 90 degrees. + +Specialized 90 degree rotator which rotates a 'src' surface in 90 degree +increments clockwise returning a new surface. Faster than rotozoomer since +not scanning or interpolation takes place. Input surface must be 32 bit. +(code contributed by J. Schiller, improved by C. Allport and A. Schiffler) + +\param src Source surface to rotate. +\param numClockwiseTurns Number of clockwise 90 degree turns to apply to the source. + +\returns The new, rotated surface; or NULL for surfaces with incorrect input format. +*/ +SDL_Surface* rotateSurface90Degrees(SDL_Surface* src, int numClockwiseTurns) +{ + int row, col, newWidth, newHeight; + int bpp, src_ipr, dst_ipr; + SDL_Surface* dst; + Uint32* srcBuf; + Uint32* dstBuf; + + /* Has to be a valid surface pointer and only 32-bit surfaces (for now) */ + if (!src || src->format->BitsPerPixel != 32) { return NULL; } + + /* normalize numClockwiseTurns */ + while(numClockwiseTurns < 0) { numClockwiseTurns += 4; } + numClockwiseTurns = (numClockwiseTurns % 4); + + /* if it's even, our new width will be the same as the source surface */ + newWidth = (numClockwiseTurns % 2) ? (src->h) : (src->w); + newHeight = (numClockwiseTurns % 2) ? (src->w) : (src->h); + dst = SDL_CreateRGBSurface( src->flags, newWidth, newHeight, src->format->BitsPerPixel, + src->format->Rmask, + src->format->Gmask, + src->format->Bmask, + src->format->Amask); + if(!dst) { + return NULL; + } + + if (SDL_MUSTLOCK(dst)) { + SDL_LockSurface(dst); + } + if (SDL_MUSTLOCK(dst)) { + SDL_LockSurface(dst); + } + + /* Calculate int-per-row */ + bpp = src->format->BitsPerPixel / 8; + src_ipr = src->pitch / bpp; + dst_ipr = dst->pitch / bpp; + + switch(numClockwiseTurns) { + case 0: /* Make a copy of the surface */ + { + /* Unfortunately SDL_BlitSurface cannot be used to make a copy of the surface + since it does not preserve alpha. */ + + if (src->pitch == dst->pitch) { + /* If the pitch is the same for both surfaces, the memory can be copied all at once. */ + memcpy(dst->pixels, src->pixels, (src->h * src->pitch)); + } + else + { + /* If the pitch differs, copy each row separately */ + srcBuf = (Uint32*)(src->pixels); + dstBuf = (Uint32*)(dst->pixels); + for (row = 0; row < src->h; row++) { + memcpy(dstBuf, srcBuf, dst->w * bpp); + srcBuf += src_ipr; + dstBuf += dst_ipr; + } /* end for(col) */ + } /* end for(row) */ + } + break; + + /* rotate clockwise */ + case 1: /* rotated 90 degrees clockwise */ + { + for (row = 0; row < src->h; ++row) { + srcBuf = (Uint32*)(src->pixels) + (row * src_ipr); + dstBuf = (Uint32*)(dst->pixels) + (dst->w - row - 1); + for (col = 0; col < src->w; ++col) { + *dstBuf = *srcBuf; + ++srcBuf; + dstBuf += dst_ipr; + } + /* end for(col) */ + } + /* end for(row) */ + } + break; + + case 2: /* rotated 180 degrees clockwise */ + { + for (row = 0; row < src->h; ++row) { + srcBuf = (Uint32*)(src->pixels) + (row * src_ipr); + dstBuf = (Uint32*)(dst->pixels) + ((dst->h - row - 1) * dst_ipr) + (dst->w - 1); + for (col = 0; col < src->w; ++col) { + *dstBuf = *srcBuf; + ++srcBuf; + --dstBuf; + } + } + } + break; + + case 3: + { + for (row = 0; row < src->h; ++row) { + srcBuf = (Uint32*)(src->pixels) + (row * src_ipr); + dstBuf = (Uint32*)(dst->pixels) + row + ((dst->h - 1) * dst_ipr); + for (col = 0; col < src->w; ++col) { + *dstBuf = *srcBuf; + ++srcBuf; + dstBuf -= dst_ipr; + } + } + } + break; + } + /* end switch */ + + if (SDL_MUSTLOCK(src)) { + SDL_UnlockSurface(src); + } + if (SDL_MUSTLOCK(dst)) { + SDL_UnlockSurface(dst); + } + + return dst; +} + + +/*! +\brief Internal target surface sizing function for rotozooms with trig result return. + +\param width The source surface width. +\param height The source surface height. +\param angle The angle to rotate in degrees. +\param zoomx The horizontal scaling factor. +\param zoomy The vertical scaling factor. +\param dstwidth The calculated width of the destination surface. +\param dstheight The calculated height of the destination surface. +\param canglezoom The sine of the angle adjusted by the zoom factor. +\param sanglezoom The cosine of the angle adjusted by the zoom factor. + +*/ +static void _rotozoomSurfaceSizeTrig(int width, int height, double angle, double zoomx, double zoomy, + int *dstwidth, int *dstheight, + double *canglezoom, double *sanglezoom) +{ + double x, y, cx, cy, sx, sy; + double radangle; + int dstwidthhalf, dstheighthalf; + + /* + * Determine destination width and height by rotating a centered source box + */ + radangle = angle * (M_PI / 180.0); + *sanglezoom = sin(radangle); + *canglezoom = cos(radangle); + *sanglezoom *= zoomx; + *canglezoom *= zoomx; + x = (double)(width / 2); + y = (double)(height / 2); + cx = *canglezoom * x; + cy = *canglezoom * y; + sx = *sanglezoom * x; + sy = *sanglezoom * y; + + dstwidthhalf = MAX((int) + ceil(MAX(MAX(MAX(fabs(cx + sy), fabs(cx - sy)), fabs(-cx + sy)), fabs(-cx - sy))), 1); + dstheighthalf = MAX((int) + ceil(MAX(MAX(MAX(fabs(sx + cy), fabs(sx - cy)), fabs(-sx + cy)), fabs(-sx - cy))), 1); + *dstwidth = 2 * dstwidthhalf; + *dstheight = 2 * dstheighthalf; +} + +/*! +\brief Returns the size of the resulting target surface for a rotozoomSurfaceXY() call. + +\param width The source surface width. +\param height The source surface height. +\param angle The angle to rotate in degrees. +\param zoomx The horizontal scaling factor. +\param zoomy The vertical scaling factor. +\param dstwidth The calculated width of the rotozoomed destination surface. +\param dstheight The calculated height of the rotozoomed destination surface. +*/ +void rotozoomSurfaceSizeXY(int width, int height, double angle, double zoomx, double zoomy, int *dstwidth, int *dstheight) +{ + double dummy_sanglezoom, dummy_canglezoom; + + _rotozoomSurfaceSizeTrig(width, height, angle, zoomx, zoomy, dstwidth, dstheight, &dummy_sanglezoom, &dummy_canglezoom); +} + +/*! +\brief Returns the size of the resulting target surface for a rotozoomSurface() call. + +\param width The source surface width. +\param height The source surface height. +\param angle The angle to rotate in degrees. +\param zoom The scaling factor. +\param dstwidth The calculated width of the rotozoomed destination surface. +\param dstheight The calculated height of the rotozoomed destination surface. +*/ +void rotozoomSurfaceSize(int width, int height, double angle, double zoom, int *dstwidth, int *dstheight) +{ + double dummy_sanglezoom, dummy_canglezoom; + + _rotozoomSurfaceSizeTrig(width, height, angle, zoom, zoom, dstwidth, dstheight, &dummy_sanglezoom, &dummy_canglezoom); +} + +/*! +\brief Rotates and zooms a surface and optional anti-aliasing. + +Rotates and zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface. +'angle' is the rotation in degrees and 'zoom' a scaling factor. If 'smooth' is set +then the destination 32bit surface is anti-aliased. If the surface is not 8bit +or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly. + +\param src The surface to rotozoom. +\param angle The angle to rotate in degrees. +\param zoom The scaling factor. +\param smooth Antialiasing flag; set to SMOOTHING_ON to enable. + +\return The new rotozoomed surface. +*/ +SDL_Surface *rotozoomSurface(SDL_Surface * src, double angle, double zoom, int smooth) +{ + return rotozoomSurfaceXY(src, angle, zoom, zoom, smooth); +} + +/*! +\brief Rotates and zooms a surface with different horizontal and vertival scaling factors and optional anti-aliasing. + +Rotates and zooms a 32bit or 8bit 'src' surface to newly created 'dst' surface. +'angle' is the rotation in degrees, 'zoomx and 'zoomy' scaling factors. If 'smooth' is set +then the destination 32bit surface is anti-aliased. If the surface is not 8bit +or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly. + +\param src The surface to rotozoom. +\param angle The angle to rotate in degrees. +\param zoomx The horizontal scaling factor. +\param zoomy The vertical scaling factor. +\param smooth Antialiasing flag; set to SMOOTHING_ON to enable. + +\return The new rotozoomed surface. +*/ +SDL_Surface *rotozoomSurfaceXY(SDL_Surface * src, double angle, double zoomx, double zoomy, int smooth) +{ + SDL_Surface *rz_src; + SDL_Surface *rz_dst; + double zoominv; + double sanglezoom, canglezoom, sanglezoominv, canglezoominv; + int dstwidthhalf, dstwidth, dstheighthalf, dstheight; + int is32bit; + int i, src_converted; + int flipx,flipy; + Uint8 r,g,b; + Uint32 colorkey = 0; + int colorKeyAvailable = 0; + + /* + * Sanity check + */ + if (src == NULL) + return (NULL); + + if (src->flags & SDL_SRCCOLORKEY) + { + colorkey = _colorkey(src); + SDL_GetRGB(colorkey, src->format, &r, &g, &b); + colorKeyAvailable = 1; + } + /* + * Determine if source surface is 32bit or 8bit + */ + is32bit = (src->format->BitsPerPixel == 32); + if ((is32bit) || (src->format->BitsPerPixel == 8)) { + /* + * Use source surface 'as is' + */ + rz_src = src; + src_converted = 0; + } else { + /* + * New source surface is 32bit with a defined RGBA ordering + */ + rz_src = + SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 +#else + 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff +#endif + ); + if(colorKeyAvailable) + SDL_SetColorKey(src, 0, 0); + + SDL_BlitSurface(src, NULL, rz_src, NULL); + + if(colorKeyAvailable) + SDL_SetColorKey(src, SDL_SRCCOLORKEY, colorkey); + src_converted = 1; + is32bit = 1; + } + + /* + * Sanity check zoom factor + */ + flipx = (zoomx<0.0); + if (flipx) zoomx=-zoomx; + flipy = (zoomy<0.0); + if (flipy) zoomy=-zoomy; + if (zoomx < VALUE_LIMIT) zoomx = VALUE_LIMIT; + if (zoomy < VALUE_LIMIT) zoomy = VALUE_LIMIT; + zoominv = 65536.0 / (zoomx * zoomx); + + /* + * Check if we have a rotozoom or just a zoom + */ + if (fabs(angle) > VALUE_LIMIT) { + + /* + * Angle!=0: full rotozoom + */ + /* + * ----------------------- + */ + + /* Determine target size */ + _rotozoomSurfaceSizeTrig(rz_src->w, rz_src->h, angle, zoomx, zoomy, &dstwidth, &dstheight, &canglezoom, &sanglezoom); + + /* + * Calculate target factors from sin/cos and zoom + */ + sanglezoominv = sanglezoom; + canglezoominv = canglezoom; + sanglezoominv *= zoominv; + canglezoominv *= zoominv; + + /* Calculate half size */ + dstwidthhalf = dstwidth / 2; + dstheighthalf = dstheight / 2; + + /* + * Alloc space to completely contain the rotated surface + */ + rz_dst = NULL; + if (is32bit) { + /* + * Target surface is 32bit with source RGBA/ABGR ordering + */ + rz_dst = + SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32, + rz_src->format->Rmask, rz_src->format->Gmask, + rz_src->format->Bmask, rz_src->format->Amask); + } else { + /* + * Target surface is 8bit + */ + rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0); + } + + /* Check target */ + if (rz_dst == NULL) + return NULL; + + /* Adjust for guard rows */ + rz_dst->h = dstheight; + + if (colorKeyAvailable == 1){ + colorkey = SDL_MapRGB(rz_dst->format, r, g, b); + + SDL_FillRect(rz_dst, NULL, colorkey ); + } + + /* + * Lock source surface + */ + if (SDL_MUSTLOCK(rz_src)) { + SDL_LockSurface(rz_src); + } + + /* + * Check which kind of surface we have + */ + if (is32bit) { + /* + * Call the 32bit transformation routine to do the rotation (using alpha) + */ + _transformSurfaceRGBA(rz_src, rz_dst, dstwidthhalf, dstheighthalf, + (int) (sanglezoominv), (int) (canglezoominv), + flipx, flipy, + smooth); + /* + * Turn on source-alpha support + */ + SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255); + SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src)); + } else { + /* + * Copy palette and colorkey info + */ + for (i = 0; i < rz_src->format->palette->ncolors; i++) { + rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i]; + } + rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors; + /* + * Call the 8bit transformation routine to do the rotation + */ + transformSurfaceY(rz_src, rz_dst, dstwidthhalf, dstheighthalf, + (int) (sanglezoominv), (int) (canglezoominv), + flipx, flipy); + SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src)); + } + /* + * Unlock source surface + */ + if (SDL_MUSTLOCK(rz_src)) { + SDL_UnlockSurface(rz_src); + } + + } else { + + /* + * Angle=0: Just a zoom + */ + /* + * -------------------- + */ + + /* + * Calculate target size + */ + zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight); + + /* + * Alloc space to completely contain the zoomed surface + */ + rz_dst = NULL; + if (is32bit) { + /* + * Target surface is 32bit with source RGBA/ABGR ordering + */ + rz_dst = + SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32, + rz_src->format->Rmask, rz_src->format->Gmask, + rz_src->format->Bmask, rz_src->format->Amask); + } else { + /* + * Target surface is 8bit + */ + rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0); + } + + /* Check target */ + if (rz_dst == NULL) + return NULL; + + /* Adjust for guard rows */ + rz_dst->h = dstheight; + + if (colorKeyAvailable == 1){ + colorkey = SDL_MapRGB(rz_dst->format, r, g, b); + + SDL_FillRect(rz_dst, NULL, colorkey ); + } + + /* + * Lock source surface + */ + if (SDL_MUSTLOCK(rz_src)) { + SDL_LockSurface(rz_src); + } + + /* + * Check which kind of surface we have + */ + if (is32bit) { + /* + * Call the 32bit transformation routine to do the zooming (using alpha) + */ + _zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy, smooth); + + /* + * Turn on source-alpha support + */ + SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255); + SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src)); + } else { + /* + * Copy palette and colorkey info + */ + for (i = 0; i < rz_src->format->palette->ncolors; i++) { + rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i]; + } + rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors; + + /* + * Call the 8bit transformation routine to do the zooming + */ + _zoomSurfaceY(rz_src, rz_dst, flipx, flipy); + SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src)); + } + + /* + * Unlock source surface + */ + if (SDL_MUSTLOCK(rz_src)) { + SDL_UnlockSurface(rz_src); + } + } + + /* + * Cleanup temp surface + */ + if (src_converted) { + SDL_FreeSurface(rz_src); + } + + /* + * Return destination surface + */ + return (rz_dst); +} + +/*! +\brief Calculates the size of the target surface for a zoomSurface() call. + +The minimum size of the target surface is 1. The input factors can be positive or negative. + +\param width The width of the source surface to zoom. +\param height The height of the source surface to zoom. +\param zoomx The horizontal zoom factor. +\param zoomy The vertical zoom factor. +\param dstwidth Pointer to an integer to store the calculated width of the zoomed target surface. +\param dstheight Pointer to an integer to store the calculated height of the zoomed target surface. +*/ +void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, int *dstwidth, int *dstheight) +{ + /* + * Make zoom factors positive + */ + int flipx, flipy; + flipx = (zoomx<0.0); + if (flipx) zoomx = -zoomx; + flipy = (zoomy<0.0); + if (flipy) zoomy = -zoomy; + + /* + * Sanity check zoom factors + */ + if (zoomx < VALUE_LIMIT) { + zoomx = VALUE_LIMIT; + } + if (zoomy < VALUE_LIMIT) { + zoomy = VALUE_LIMIT; + } + + /* + * Calculate target size + */ + *dstwidth = (int) floor(((double) width * zoomx) + 0.5); + *dstheight = (int) floor(((double) height * zoomy) + 0.5); + if (*dstwidth < 1) { + *dstwidth = 1; + } + if (*dstheight < 1) { + *dstheight = 1; + } +} + +/*! +\brief Zoom a surface by independent horizontal and vertical factors with optional smoothing. + +Zooms a 32bit or 8bit 'src' surface to newly created 'dst' surface. +'zoomx' and 'zoomy' are scaling factors for width and height. If 'smooth' is on +then the destination 32bit surface is anti-aliased. If the surface is not 8bit +or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly. +If zoom factors are negative, the image is flipped on the axes. + +\param src The surface to zoom. +\param zoomx The horizontal zoom factor. +\param zoomy The vertical zoom factor. +\param smooth Antialiasing flag; set to SMOOTHING_ON to enable. + +\return The new, zoomed surface. +*/ +SDL_Surface *zoomSurface(SDL_Surface * src, double zoomx, double zoomy, int smooth) +{ + SDL_Surface *rz_src; + SDL_Surface *rz_dst; + int dstwidth, dstheight; + int is32bit; + int i, src_converted; + int flipx, flipy; + + /* + * Sanity check + */ + if (src == NULL) + return (NULL); + + /* + * Determine if source surface is 32bit or 8bit + */ + is32bit = (src->format->BitsPerPixel == 32); + if ((is32bit) || (src->format->BitsPerPixel == 8)) { + /* + * Use source surface 'as is' + */ + rz_src = src; + src_converted = 0; + } else { + /* + * New source surface is 32bit with a defined RGBA ordering + */ + rz_src = + SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 +#else + 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff +#endif + ); + if (rz_src == NULL) { + return NULL; + } + SDL_BlitSurface(src, NULL, rz_src, NULL); + src_converted = 1; + is32bit = 1; + } + + flipx = (zoomx<0.0); + if (flipx) zoomx = -zoomx; + flipy = (zoomy<0.0); + if (flipy) zoomy = -zoomy; + + /* Get size if target */ + zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight); + + /* + * Alloc space to completely contain the zoomed surface + */ + rz_dst = NULL; + if (is32bit) { + /* + * Target surface is 32bit with source RGBA/ABGR ordering + */ + rz_dst = + SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32, + rz_src->format->Rmask, rz_src->format->Gmask, + rz_src->format->Bmask, rz_src->format->Amask); + } else { + /* + * Target surface is 8bit + */ + rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0); + } + + /* Check target */ + if (rz_dst == NULL) { + /* + * Cleanup temp surface + */ + if (src_converted) { + SDL_FreeSurface(rz_src); + } + return NULL; + } + + /* Adjust for guard rows */ + rz_dst->h = dstheight; + + /* + * Lock source surface + */ + if (SDL_MUSTLOCK(rz_src)) { + SDL_LockSurface(rz_src); + } + + /* + * Check which kind of surface we have + */ + if (is32bit) { + /* + * Call the 32bit transformation routine to do the zooming (using alpha) + */ + _zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy, smooth); + /* + * Turn on source-alpha support + */ + SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255); + } else { + /* + * Copy palette and colorkey info + */ + for (i = 0; i < rz_src->format->palette->ncolors; i++) { + rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i]; + } + rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors; + /* + * Call the 8bit transformation routine to do the zooming + */ + _zoomSurfaceY(rz_src, rz_dst, flipx, flipy); + SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src)); + } + /* + * Unlock source surface + */ + if (SDL_MUSTLOCK(rz_src)) { + SDL_UnlockSurface(rz_src); + } + + /* + * Cleanup temp surface + */ + if (src_converted) { + SDL_FreeSurface(rz_src); + } + + /* + * Return destination surface + */ + return (rz_dst); +} + +/*! +\brief Shrink a surface by an integer ratio using averaging. + +Shrinks a 32bit or 8bit 'src' surface to a newly created 'dst' surface. +'factorx' and 'factory' are the shrinking ratios (i.e. 2=1/2 the size, +3=1/3 the size, etc.) The destination surface is antialiased by averaging +the source box RGBA or Y information. If the surface is not 8bit +or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly. +The input surface is not modified. The output surface is newly allocated. + +\param src The surface to shrink. +\param factorx The horizontal shrinking ratio. +\param factory The vertical shrinking ratio. + +\return The new, shrunken surface. +*/ +/*@null@*/ +SDL_Surface *shrinkSurface(SDL_Surface *src, int factorx, int factory) +{ + int result; + SDL_Surface *rz_src; + SDL_Surface *rz_dst = NULL; + int dstwidth, dstheight; + int is32bit; + int i, src_converted; + int haveError = 0; + + /* + * Sanity check + */ + if (src == NULL) { + return (NULL); + } + + /* + * Determine if source surface is 32bit or 8bit + */ + is32bit = (src->format->BitsPerPixel == 32); + if ((is32bit) || (src->format->BitsPerPixel == 8)) { + /* + * Use source surface 'as is' + */ + rz_src = src; + src_converted = 0; + } else { + /* + * New source surface is 32bit with a defined RGBA ordering + */ + rz_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 +#else + 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff +#endif + ); + if (rz_src==NULL) { + haveError = 1; + goto exitShrinkSurface; + } + + SDL_BlitSurface(src, NULL, rz_src, NULL); + src_converted = 1; + is32bit = 1; + } + + /* + * Lock the surface + */ + if (SDL_MUSTLOCK(rz_src)) { + if (SDL_LockSurface(rz_src) < 0) { + haveError = 1; + goto exitShrinkSurface; + } + } + + /* Get size for target */ + dstwidth=rz_src->w/factorx; + while (dstwidth*factorx>rz_src->w) { dstwidth--; } + dstheight=rz_src->h/factory; + while (dstheight*factory>rz_src->h) { dstheight--; } + + /* + * Alloc space to completely contain the shrunken surface + * (with added guard rows) + */ + if (is32bit==1) { + /* + * Target surface is 32bit with source RGBA/ABGR ordering + */ + rz_dst = + SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32, + rz_src->format->Rmask, rz_src->format->Gmask, + rz_src->format->Bmask, rz_src->format->Amask); + } else { + /* + * Target surface is 8bit + */ + rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0); + } + + /* Check target */ + if (rz_dst == NULL) { + haveError = 1; + goto exitShrinkSurface; + } + + /* Adjust for guard rows */ + rz_dst->h = dstheight; + + /* + * Check which kind of surface we have + */ + if (is32bit==1) { + /* + * Call the 32bit transformation routine to do the shrinking (using alpha) + */ + result = _shrinkSurfaceRGBA(rz_src, rz_dst, factorx, factory); + if ((result!=0) || (rz_dst==NULL)) { + haveError = 1; + goto exitShrinkSurface; + } + + /* + * Turn on source-alpha support + */ + result = SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255); + if (result!=0) { + haveError = 1; + goto exitShrinkSurface; + } + } else { + /* + * Copy palette and colorkey info + */ + for (i = 0; i < rz_src->format->palette->ncolors; i++) { + rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i]; + } + rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors; + /* + * Call the 8bit transformation routine to do the shrinking + */ + result = _shrinkSurfaceY(rz_src, rz_dst, factorx, factory); + if (result!=0) { + haveError = 1; + goto exitShrinkSurface; + } + + /* + * Set colorkey on target + */ + result = SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src)); + if (result!=0) { + haveError = 1; + goto exitShrinkSurface; + } + } + +exitShrinkSurface: + if (rz_src!=NULL) { + /* + * Unlock source surface + */ + if (SDL_MUSTLOCK(rz_src)) { + SDL_UnlockSurface(rz_src); + } + + /* + * Cleanup temp surface + */ + if (src_converted==1) { + SDL_FreeSurface(rz_src); + } + } + + /* Check error state; maybe need to cleanup destination */ + if (haveError==1) { + if (rz_dst!=NULL) { + SDL_FreeSurface(rz_dst); + } + rz_dst=NULL; + } + + /* + * Return destination surface + */ + return (rz_dst); +} diff --git a/tizen/src/SDL_gfx/SDL_rotozoom.h b/tizen/src/SDL_gfx/SDL_rotozoom.h new file mode 100644 index 0000000000..80b31f1bce --- /dev/null +++ b/tizen/src/SDL_gfx/SDL_rotozoom.h @@ -0,0 +1,123 @@ +/* + +SDL_rotozoom.c: rotozoomer, zoomer and shrinker for 32bit or 8bit surfaces + +Copyright (C) 2001-2012 Andreas Schiffler + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not +claim that you wrote the original software. If you use this software +in a product, an acknowledgment in the product documentation would be +appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and must not be +misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. + +Andreas Schiffler -- aschiffler at ferzkopp dot net + +*/ + +#ifndef _SDL_rotozoom_h +#define _SDL_rotozoom_h + +#include + +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef M_PI +#define M_PI 3.141592654 +#endif + +#include "SDL.h" + + /* ---- Defines */ + + /*! + \brief Disable anti-aliasing (no smoothing). + */ +#define SMOOTHING_OFF 0 + + /*! + \brief Enable anti-aliasing (smoothing). + */ +#define SMOOTHING_ON 1 + + /* ---- Function Prototypes */ + +#ifdef _MSC_VER +# if defined(DLL_EXPORT) && !defined(LIBSDL_GFX_DLL_IMPORT) +# define SDL_ROTOZOOM_SCOPE __declspec(dllexport) +# else +# ifdef LIBSDL_GFX_DLL_IMPORT +# define SDL_ROTOZOOM_SCOPE __declspec(dllimport) +# endif +# endif +#endif +#ifndef SDL_ROTOZOOM_SCOPE +# define SDL_ROTOZOOM_SCOPE extern +#endif + + /* + + Rotozoom functions + + */ + + SDL_ROTOZOOM_SCOPE SDL_Surface *rotozoomSurface(SDL_Surface * src, double angle, double zoom, int smooth); + + SDL_ROTOZOOM_SCOPE SDL_Surface *rotozoomSurfaceXY + (SDL_Surface * src, double angle, double zoomx, double zoomy, int smooth); + + + SDL_ROTOZOOM_SCOPE void rotozoomSurfaceSize(int width, int height, double angle, double zoom, int *dstwidth, + int *dstheight); + + SDL_ROTOZOOM_SCOPE void rotozoomSurfaceSizeXY + (int width, int height, double angle, double zoomx, double zoomy, + int *dstwidth, int *dstheight); + + /* + + Zooming functions + + */ + + SDL_ROTOZOOM_SCOPE SDL_Surface *zoomSurface(SDL_Surface * src, double zoomx, double zoomy, int smooth); + + SDL_ROTOZOOM_SCOPE void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, int *dstwidth, int *dstheight); + + /* + + Shrinking functions + + */ + + SDL_ROTOZOOM_SCOPE SDL_Surface *shrinkSurface(SDL_Surface * src, int factorx, int factory); + + /* + + Specialized rotation functions + + */ + + SDL_ROTOZOOM_SCOPE SDL_Surface* rotateSurface90Degrees(SDL_Surface* src, int numClockwiseTurns); + + /* Ends C function definitions when using C++ */ +#ifdef __cplusplus +} +#endif + +#endif /* _SDL_rotozoom_h */ diff --git a/tizen/src/VERSION b/tizen/src/VERSION index 227cea2156..47f7d32da5 100644 --- a/tizen/src/VERSION +++ b/tizen/src/VERSION @@ -1 +1 @@ -2.0.0 +Maru diff --git a/tizen/src/check_gl.c b/tizen/src/check_gl.c new file mode 100644 index 0000000000..1d83edb235 --- /dev/null +++ b/tizen/src/check_gl.c @@ -0,0 +1,7 @@ +#include "hw/gloffscreen_test.h" +#include "debug_ch.h" + +int main (int argc, char** argv) +{ + return gl_acceleration_capability_check(); +} diff --git a/tizen/src/debug_ch.c b/tizen/src/debug_ch.c index 955af7f0e4..f11664f7c4 100644 --- a/tizen/src/debug_ch.c +++ b/tizen/src/debug_ch.c @@ -43,25 +43,11 @@ #include "emulator.h" #include "debug_ch.h" -// DEBUGCH file is located in binary directory. -char bin_dir[1024] = {0,}; - -static char logpath[512] = {0,}; static char debugchfile[512] = {0, }; #ifdef _WIN32 static HANDLE handle; #endif -void set_log_path(char *path) -{ - strcpy(logpath, path); -} - -char *get_log_path(void) -{ - return logpath; -} - static inline int interlocked_xchg_add( int *dest, int incr ) { int ret_val; @@ -289,10 +275,10 @@ static void debug_init(void) strcat(debugchfile, "/DEBUGCH"); #endif - if (0 == strlen(bin_dir)) { + if (0 == strlen(bin_path)) { strcpy(debugchfile, "DEBUGCH"); } else { - strcat(debugchfile, bin_dir); + strcat(debugchfile, bin_path); strcat(debugchfile, "DEBUGCH"); } @@ -326,9 +312,9 @@ static void debug_init(void) } open_flags = O_BINARY | O_RDWR | O_CREAT | O_TRUNC; - fd = qemu_open(logpath, open_flags, 0666); + fd = qemu_open(log_path, open_flags, 0666); if(fd < 0) { - fprintf(stderr, "Can't open logfile: %s\n", logpath); + fprintf(stderr, "Can't open logfile: %s\n", log_path); exit(1); } close(fd); @@ -375,7 +361,7 @@ static int dbg_vprintf( const char *format, va_list args ) sprintf(txt, "%s", tmp); // unlock - if ((fp = fopen(logpath, "a+")) == NULL) { + if ((fp = fopen(log_path, "a+")) == NULL) { fprintf(stdout, "Emulator can't open.\n" "Please check if " "this binary file is running on the right path.\n"); @@ -455,9 +441,9 @@ int dbg_log( enum _debug_class cls, struct _debug_channel *channel, va_end(valist); open_flags = O_RDWR | O_APPEND | O_BINARY ; - fd = qemu_open(logpath, open_flags, 0666); + fd = qemu_open(log_path, open_flags, 0666); if(fd < 0) { - fprintf(stderr, "Can't open logfile: %s\n", logpath); + fprintf(stderr, "Can't open logfile: %s\n", log_path); exit(1); } ret_write = qemu_write_full(fd, buf, ret); diff --git a/tizen/src/debug_ch.h b/tizen/src/debug_ch.h index 1788592b6c..e1c193b57c 100644 --- a/tizen/src/debug_ch.h +++ b/tizen/src/debug_ch.h @@ -57,9 +57,6 @@ struct _debug_channel char multiname[15]; }; -void set_log_path(char *path); -char *get_log_path(void); - #ifndef NO_DEBUG #define MSGSIZE_MAX 2048 #define __GET_DEBUGGING_FIXME(dbch) ((dbch)->flags & (1 << __DBCL_FIXME)) @@ -97,8 +94,6 @@ char *get_log_path(void); (void)0 : (void)dbg_printf */ -extern char bin_dir[1024]; - extern unsigned char _dbg_get_channel_flags( struct _debug_channel *channel ); extern int _dbg_set_channel_flags( struct _debug_channel *channel, unsigned char set, unsigned char clear ); diff --git a/tizen/src/emul_state.c b/tizen/src/emul_state.c index b6d78ede81..ea7144454b 100644 --- a/tizen/src/emul_state.c +++ b/tizen/src/emul_state.c @@ -57,17 +57,6 @@ int get_emul_skin_enable(void) return _emul_info.skin_enable; } -/* current emulator condition */ -int get_emulator_condition(void) -{ - return _emul_state.emulator_condition; -} - -void set_emulator_condition(int state) -{ - _emul_state.emulator_condition = state; -} - /* lcd screen size */ void set_emul_lcd_size(int width, int height) { @@ -120,6 +109,28 @@ int get_emul_max_touch_point(void) return _emul_info.max_touch_point; } +/* base port for emualtor vm */ +void set_emul_vm_base_port(int port) +{ + _emul_info.vm_base_port = port; +} + +int get_emul_vm_base_port(void) +{ + return _emul_info.vm_base_port; +} + +/* current emulator condition */ +int get_emulator_condition(void) +{ + return _emul_state.emulator_condition; +} + +void set_emulator_condition(int state) +{ + _emul_state.emulator_condition = state; +} + /* emulator window scale */ void set_emul_win_scale(double scale_factor) { @@ -191,7 +202,7 @@ int get_host_lock_key_state(int key) return -1; } -/* manage CapsLock key state for usb keyboard input */ +/* manage CapsLock key state for host keyboard input */ void set_emul_caps_lock_state(int state) { _emul_state.qemu_caps_lock = state; @@ -199,10 +210,10 @@ void set_emul_caps_lock_state(int state) int get_emul_caps_lock_state(void) { - return _emul_state.qemu_caps_lock; + return _emul_state.qemu_caps_lock; } -/* manage NumLock key state for usb keyboard input */ +/* manage NumLock key state for host keyboard input */ void set_emul_num_lock_state(int state) { _emul_state.qemu_num_lock = state; @@ -210,5 +221,6 @@ void set_emul_num_lock_state(int state) int get_emul_num_lock_state(void) { - return _emul_state.qemu_num_lock; + return _emul_state.qemu_num_lock; } + diff --git a/tizen/src/emul_state.h b/tizen/src/emul_state.h index 66655ccf75..efb123230e 100644 --- a/tizen/src/emul_state.h +++ b/tizen/src/emul_state.h @@ -39,8 +39,8 @@ /* keep it consistent with emulator-skin definition */ enum { - HARD_KEY_HOME = 101, - HARD_KEY_POWER = 103, + HARD_KEY_HOME = 139, + HARD_KEY_POWER = 116, HARD_KEY_VOL_UP = 115, HARD_KEY_VOL_DOWN = 114, }; @@ -80,7 +80,8 @@ typedef struct EmulatorConfigInfo { int lcd_size_h; int sdl_bpp; int max_touch_point; - //TODO: + int vm_base_port; + /* add here */ } EmulatorConfigInfo; typedef struct EmulatorConfigState { @@ -90,7 +91,7 @@ typedef struct EmulatorConfigState { MultiTouchState qemu_mts; int qemu_caps_lock; int qemu_num_lock; - //TODO: + /* add here */ } EmulatorConfigState; @@ -100,6 +101,8 @@ void set_emul_lcd_size(int width, int height); void set_emul_win_scale(double scale); void set_emul_sdl_bpp(int bpp); void set_emul_max_touch_point(int cnt); +void set_emul_vm_base_port(int port); + void set_emulator_condition(int state); void set_emul_rotation(short rotation_type); void set_emul_caps_lock_state(int state); @@ -112,6 +115,8 @@ int get_emul_lcd_height(void); double get_emul_win_scale(void); int get_emul_sdl_bpp(void); int get_emul_max_touch_point(void); +int get_emul_vm_base_port(void); + int get_emulator_condition(void); short get_emul_rotation(void); MultiTouchState *get_emul_multi_touch_state(void); diff --git a/tizen/src/option.h b/tizen/src/emul_state_darwin.m similarity index 64% rename from tizen/src/option.h rename to tizen/src/emul_state_darwin.m index 44b26a7f1a..b4fab4786e 100644 --- a/tizen/src/option.h +++ b/tizen/src/emul_state_darwin.m @@ -1,14 +1,14 @@ -/* +/* * Emulator * - * Copyright (C) 2011, 2012 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (C) 2013 Samsung Electronics Co., Ltd. All rights reserved. * - * Contact: + * Contact: + * Kitae Kim * SeokYeon Hwang * MunKyu Im * GiWoong Kim * YeongKyoon Lee - * HyunJun Son * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -29,19 +29,20 @@ * */ -#ifndef __OPTION_H__ -#define __OPTION_H__ +#import +#import -#include +#include "emul_state.h" -#include -#include -#include -#include -#include -#include - -int gethostDNS(char *dns1, char *dns2); -int gethostproxy(char *http_proxy, char *https_proxy, char *ftp_proxy, char *socks_proxy); -#endif +/* retrieves the status of the host lock key */ +int get_host_lock_key_state_darwin(int key) +{ + /* support only capslock */ + if (key == HOST_CAPSLOCK_KEY) { + return ((NSAlphaShiftKeyMask & [NSEvent modifierFlags]) ? 1 : 0); + } else if (key == HOST_NUMLOCK_KEY) { + return 0; + } + return -1; +} diff --git a/tizen/src/emulator.c b/tizen/src/emulator.c index c7f119edf7..c7abf6d65a 100644 --- a/tizen/src/emulator.c +++ b/tizen/src/emulator.c @@ -32,46 +32,33 @@ #include "maru_common.h" -#include -#ifdef CONFIG_SDL -#include -#endif #include "emulator.h" +#include "osutil.h" #include "guest_debug.h" #include "sdb.h" #include "string.h" #include "skin/maruskin_server.h" #include "skin/maruskin_client.h" #include "guest_server.h" -#include "debug_ch.h" -#include "option.h" #include "emul_state.h" #include "qemu_socket.h" #include "build_info.h" #include "maru_err_table.h" -#include -#include - -#if defined(CONFIG_WIN32) -#include -#elif defined(CONFIG_LINUX) -#include -#include -#include -#include -#include -#endif +#include "maru_display.h" +#include "qemu-config.h" +#include "mloop_event.h" +#include "hw/maru_camera_common.h" +#include "hw/gloffscreen_test.h" +#include "debug_ch.h" -#if defined(CONFIG_DARWIN) -#include -#include -#include -#include -#include -#include "tizen/src/ns_event.h" +#include +#ifdef CONFIG_SDL +#include #endif -#include "mloop_event.h" +#ifdef CONFIG_DARWIN +#include "ns_event.h" +#endif MULTI_DEBUG_CHANNEL(qemu, main); @@ -85,12 +72,23 @@ MULTI_DEBUG_CHANNEL(qemu, main); #define LOGFILE "emulator.log" #define LCD_WIDTH_PREFIX "width=" #define LCD_HEIGHT_PREFIX "height=" + #define MIDBUF 128 +gchar bin_path[PATH_MAX] = { 0, }; +gchar log_path[PATH_MAX] = { 0, }; + int tizen_base_port; -char tizen_target_path[MAXLEN]; -char tizen_target_img_path[MAXLEN]; -char logpath[MAXLEN]; +char tizen_target_path[PATH_MAX]; +char tizen_target_img_path[PATH_MAX]; + +int enable_gl = 0; +int enable_yagl = 0; + +int is_webcam_enabled; + +#define LEN_MARU_KERNEL_CMDLINE 512 +gchar maru_kernel_cmdline[LEN_MARU_KERNEL_CMDLINE]; static int _skin_argc; static char **_skin_argv; @@ -101,11 +99,9 @@ static char **_qemu_argv; int thread_running = 1; /* Check if we need exit main */ #endif -void maru_display_fini(void); - -char *get_logpath(void) +const gchar *get_log_path(void) { - return logpath; + return log_path; } void exit_emulator(void) @@ -117,157 +113,6 @@ void exit_emulator(void) maru_display_fini(); } -void check_shdmem(void) -{ -#if defined(CONFIG_LINUX) - int shm_id; - void *shm_addr; - u_int port; - int val; - struct shmid_ds shm_info; - - for (port = 26100; port < 26200; port += 10) { - shm_id = shmget((key_t)port, 0, 0); - if (shm_id != -1) { - shm_addr = shmat(shm_id, (void *)0, 0); - if ((void *)-1 == shm_addr) { - ERR("error occured at shmat()\n"); - break; - } - - val = shmctl(shm_id, IPC_STAT, &shm_info); - if (val != -1) { - INFO("count of process that use shared memory : %d\n", - shm_info.shm_nattch); - if ((shm_info.shm_nattch > 0) && - strcmp(tizen_target_img_path, (char *)shm_addr) == 0) { - if (check_port_bind_listen(port + 1) > 0) { - shmdt(shm_addr); - continue; - } - shmdt(shm_addr); - maru_register_exit_msg(MARU_EXIT_UNKNOWN, - "Can not execute this VM.\n" - "The same name is running now."); - exit(0); - } else { - shmdt(shm_addr); - } - } - } - } - -#elif defined(CONFIG_WIN32) - u_int port; - char *base_port = NULL; - char *pBuf; - HANDLE hMapFile; - for (port = 26100; port < 26200; port += 10) { - base_port = g_strdup_printf("%d", port); - hMapFile = OpenFileMapping(FILE_MAP_READ, TRUE, base_port); - if (hMapFile == NULL) { - INFO("port %s is not used.\n", base_port); - continue; - } else { - pBuf = (char *)MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 50); - if (pBuf == NULL) { - ERR("Could not map view of file (%d).\n", GetLastError()); - CloseHandle(hMapFile); - } - - if (strcmp(pBuf, tizen_target_img_path) == 0) { - maru_register_exit_msg(MARU_EXIT_UNKNOWN, - "Can not execute this VM.\n" - "The same name is running now."); - UnmapViewOfFile(pBuf); - CloseHandle(hMapFile); - free(base_port); - exit(0); - } else { - UnmapViewOfFile(pBuf); - } - } - - CloseHandle(hMapFile); - free(base_port); - } -#elif defined(CONFIG_DARWIN) - /* TODO: */ -#endif -} - -void make_shdmem(void) -{ -#if defined(CONFIG_LINUX) - int shmid; - char *shared_memory; - - shmid = shmget((key_t)tizen_base_port, MAXLEN, 0666|IPC_CREAT); - if (shmid == -1) { - ERR("shmget failed\n"); - return; - } - - shared_memory = shmat(shmid, (char *)0x00, 0); - if (shared_memory == (void *)-1) { - ERR("shmat failed\n"); - return; - } - sprintf(shared_memory, "%s", tizen_target_img_path); - INFO("shared memory key: %d value: %s\n", - tizen_base_port, (char *)shared_memory); -#elif defined(CONFIG_WIN32) - HANDLE hMapFile; - char *pBuf; - char *port_in_use; - char *shared_memory; - - shared_memory = g_strdup_printf("%s", tizen_target_img_path); - port_in_use = g_strdup_printf("%d", tizen_base_port); - hMapFile = CreateFileMapping( - INVALID_HANDLE_VALUE, /* use paging file */ - NULL, /* default security */ - PAGE_READWRITE, /* read/write access */ - 0, /* maximum object size (high-order DWORD) */ - 50, /* maximum object size (low-order DWORD) */ - port_in_use); /* name of mapping object */ - if (hMapFile == NULL) { - ERR("Could not create file mapping object (%d).\n", GetLastError()); - return; - } - pBuf = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 50); - - if (pBuf == NULL) { - ERR("Could not map view of file (%d).\n", GetLastError()); - CloseHandle(hMapFile); - return; - } - - CopyMemory((PVOID)pBuf, shared_memory, strlen(shared_memory)); - free(port_in_use); - free(shared_memory); -#elif defined(CONFIG_DARWIN) - /* TODO: */ - int shmid; - char *shared_memory; - - shmid = shmget((key_t)SHMKEY, MAXLEN, 0666|IPC_CREAT); - if (shmid == -1) { - ERR("shmget failed\n"); - return; - } - shared_memory = shmat(shmid, (char *)0x00, 0); - if (shared_memory == (void *)-1) { - ERR("shmat failed\n"); - return; - } - sprintf(shared_memory, "%d", get_sdb_base_port() + 2); - INFO("shared memory key: %d, value: %s\n", SHMKEY, (char *)shared_memory); - shmdt(shared_memory); -#endif - return; -} - static void construct_main_window(int skin_argc, char *skin_argv[], int qemu_argc, char *qemu_argv[]) { @@ -319,77 +164,39 @@ static void parse_options(int argc, char *argv[], int *skin_argc, } } -static char *set_bin_dir(char *exec_argv) +static void get_host_proxy(char *http_proxy, char *https_proxy, char *ftp_proxy, char *socks_proxy) { -#ifndef CONFIG_DARWIN - char link_path[1024] = { 0, }; -#endif - char *file_name = NULL; - -#if defined(CONFIG_WIN32) - if (!GetModuleFileName(NULL, link_path, 1024)) { - return NULL; - } - - file_name = strrchr(link_path, '\\'); - strncpy(bin_dir, link_path, strlen(link_path) - strlen(file_name)); - - strcat(bin_dir, "\\"); - -#elif defined(CONFIG_LINUX) - ssize_t len = readlink("/proc/self/exe", link_path, sizeof(link_path) - 1); - - if (len < 0 || len > sizeof(link_path)) { - perror("get_bin_dir error : "); - return NULL; - } - - link_path[len] = '\0'; - - file_name = strrchr(link_path, '/'); - strncpy(bin_dir, link_path, strlen(link_path) - strlen(file_name)); - - strcat(bin_dir, "/"); - -#else - if (!exec_argv) { - return NULL; - } - - char *data = strdup(exec_argv); - if (!data) { - fprintf(stderr, "Fail to strdup for paring a binary directory.\n"); - return NULL; - } - - file_name = strrchr(data, '/'); - if (!file_name) { - free(data); - return NULL; - } + get_host_proxy_os(http_proxy, https_proxy, ftp_proxy, socks_proxy); +} - strncpy(bin_dir, data, strlen(data) - strlen(file_name)); +static void set_bin_path(gchar * exec_argv) +{ + set_bin_path_os(exec_argv); +} - strcat(bin_dir, "/"); - free(data); -#endif +gchar * get_bin_path(void) +{ + return bin_path; +} - return bin_dir; +static void check_vm_lock(void) +{ + check_vm_lock_os(); } -char *get_bin_path(void) +static void make_vm_lock(void) { - return bin_dir; + make_vm_lock_os(); } -void set_image_and_log_path(char *qemu_argv) +static void set_image_and_log_path(char *qemu_argv) { int i, j = 0; int name_len = 0; int prefix_len = 0; int suffix_len = 0; int max = 0; - char *path = malloc(MAXLEN); + char *path = malloc(PATH_MAX); name_len = strlen(qemu_argv); prefix_len = strlen(IMAGE_PATH_PREFIX); suffix_len = strlen(IMAGE_PATH_SUFFIX); @@ -403,33 +210,34 @@ void set_image_and_log_path(char *qemu_argv) } else { strcpy(tizen_target_path, g_path_get_dirname(path)); } + strcpy(tizen_target_img_path, path); free(path); - strcpy(logpath, tizen_target_path); - strcat(logpath, LOGS_SUFFIX); + + strcpy(log_path, tizen_target_path); + strcat(log_path, LOGS_SUFFIX); #ifdef CONFIG_WIN32 - if (access(g_win32_locale_filename_from_utf8(logpath), R_OK) != 0) { - g_mkdir(g_win32_locale_filename_from_utf8(logpath), 0755); + if (access(g_win32_locale_filename_from_utf8(log_path), R_OK) != 0) { + g_mkdir(g_win32_locale_filename_from_utf8(log_path), 0755); } #else - if (access(logpath, R_OK) != 0) { - g_mkdir(logpath, 0755); + if (access(log_path, R_OK) != 0) { + g_mkdir(log_path, 0755); } #endif - strcat(logpath, LOGFILE); - set_log_path(logpath); + strcat(log_path, LOGFILE); } -void redir_output(void) +static void redir_output(void) { FILE *fp; - fp = freopen(logpath, "a+", stdout); + fp = freopen(log_path, "a+", stdout); if (fp == NULL) { fprintf(stderr, "log file open error\n"); } - fp = freopen(logpath, "a+", stderr); + fp = freopen(log_path, "a+", stderr); if (fp == NULL) { fprintf(stderr, "log file open error\n"); } @@ -437,7 +245,7 @@ void redir_output(void) setvbuf(stderr, NULL, _IOLBF, BUFSIZ); } -void extract_qemu_info(int qemu_argc, char **qemu_argv) +static void extract_qemu_info(int qemu_argc, char **qemu_argv) { int i = 0; @@ -450,7 +258,7 @@ void extract_qemu_info(int qemu_argc, char **qemu_argv) } -void extract_skin_info(int skin_argc, char **skin_argv) +static void extract_skin_info(int skin_argc, char **skin_argv) { int i = 0; int w = 0, h = 0; @@ -476,7 +284,7 @@ void extract_skin_info(int skin_argc, char **skin_argv) } -static void system_info(void) +static void print_system_info(void) { #define DIV 1024 @@ -484,7 +292,7 @@ static void system_info(void) struct tm *tm_time; struct timeval tval; - INFO("* SDK Version : %s\n", build_version); + INFO("* Board name : %s\n", build_version); INFO("* Package %s\n", pkginfo_version); INFO("* Package %s\n", pkginfo_maintainer); INFO("* Git Head : %s\n", pkginfo_githead); @@ -505,132 +313,168 @@ static void system_info(void) SDL_Linked_Version()->minor, SDL_Linked_Version()->patch); #endif + print_system_info_os(); +} -#if defined(CONFIG_WIN32) - INFO("* Windows\n"); - - /* Retrieves information about the current os */ - OSVERSIONINFO osvi; - ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); +typedef struct { + const char *device_name; + int found; +} device_opt_finding_t; - if (GetVersionEx(&osvi)) { - INFO("* MajorVersion : %d, MinorVersion : %d, BuildNumber : %d, \ - PlatformId : %d, CSDVersion : %s\n", osvi.dwMajorVersion, - osvi.dwMinorVersion, osvi.dwBuildNumber, - osvi.dwPlatformId, osvi.szCSDVersion); +static int find_device_opt (QemuOpts *opts, void *opaque) +{ + device_opt_finding_t *devp = (device_opt_finding_t *) opaque; + if (devp->found == 1) { + return 0; } - /* Retrieves information about the current system */ - SYSTEM_INFO sysi; - ZeroMemory(&sysi, sizeof(SYSTEM_INFO)); - - GetSystemInfo(&sysi); - INFO("* Processor type : %d, Number of processors : %d\n", - sysi.dwProcessorType, sysi.dwNumberOfProcessors); - - MEMORYSTATUSEX memInfo; - memInfo.dwLength = sizeof(MEMORYSTATUSEX); - GlobalMemoryStatusEx(&memInfo); - INFO("* Total Ram : %llu kB, Free: %lld kB\n", - memInfo.ullTotalPhys / DIV, memInfo.ullAvailPhys / DIV); - -#elif defined(CONFIG_LINUX) - INFO("* Linux\n"); - - /* depends on building */ - INFO("* QEMU build machine linux kernel version : (%d, %d, %d)\n", - LINUX_VERSION_CODE >> 16, - (LINUX_VERSION_CODE >> 8) & 0xff, - LINUX_VERSION_CODE & 0xff); - - /* depends on launching */ - struct utsname host_uname_buf; - if (uname(&host_uname_buf) == 0) { - INFO("* Host machine uname : %s %s %s %s %s\n", - host_uname_buf.sysname, host_uname_buf.nodename, - host_uname_buf.release, host_uname_buf.version, - host_uname_buf.machine); + const char *str = qemu_opt_get (opts, "driver"); + if (strcmp (str, devp->device_name) == 0) { + devp->found = 1; } + return 0; +} - struct sysinfo sys_info; - if (sysinfo(&sys_info) == 0) { - INFO("* Total Ram : %llu kB, Free: %llu kB\n", - sys_info.totalram * (unsigned long long)sys_info.mem_unit / DIV, - sys_info.freeram * (unsigned long long)sys_info.mem_unit / DIV); - } +#define DEFAULT_QEMU_DNS_IP "10.0.2.3" +static void prepare_basic_features(void) +{ + char http_proxy[MIDBUF] ={0}, https_proxy[MIDBUF] = {0,}, + ftp_proxy[MIDBUF] = {0,}, socks_proxy[MIDBUF] = {0,}, + dns[MIDBUF] = {0}; - /* get linux distribution */ - INFO("* Linux distribution infomation :\n"); - char lsb_release_cmd[MAXLEN] = "lsb_release -d -r -c >> "; - strcat(lsb_release_cmd, logpath); - if(system(lsb_release_cmd) < 0) { - INFO("system function command '%s' \ - returns error !", lsb_release_cmd); - } + tizen_base_port = get_sdb_base_port(); - /* pci device description */ - INFO("* PCI devices :\n"); - char lspci_cmd[MAXLEN] = "lspci >> "; - strcat(lspci_cmd, logpath); - if(system(lspci_cmd) < 0) { - INFO("system function command '%s' \ - returns error !", lspci_cmd); - } + get_host_proxy(http_proxy, https_proxy, ftp_proxy, socks_proxy); + /* using "DNS" provided by default QEMU */ + g_strlcpy(dns, DEFAULT_QEMU_DNS_IP, strlen(DEFAULT_QEMU_DNS_IP) + 1); + + check_vm_lock(); + socket_init(); + make_vm_lock(); + + sdb_setup(); /* determine the base port for emulator */ + set_emul_vm_base_port(tizen_base_port); -#elif defined(CONFIG_DARWIN) - INFO("* Mac\n"); + gchar * const tmp_str = g_strdup_printf(" sdb_port=%d," + " http_proxy=%s https_proxy=%s ftp_proxy=%s socks_proxy=%s" + " dns1=%s", get_emul_vm_base_port(), + http_proxy, https_proxy, ftp_proxy, socks_proxy, dns); - /* uname */ - INFO("* Host machine uname :\n"); - char uname_cmd[MAXLEN] = "uname -a >> "; - strcat(uname_cmd, logpath); - if(system(uname_cmd) < 0) { - INFO("system function command '%s' \ - returns error !", uname_cmd); + g_strlcat(maru_kernel_cmdline, tmp_str, LEN_MARU_KERNEL_CMDLINE); + + g_free(tmp_str); +} + +#define VIRTIOGL_DEV_NAME "virtio-gl-pci" +#ifdef CONFIG_GL_BACKEND +static void prepare_opengl_acceleration(void) +{ + int capability_check_gl = 0; + + if (enable_gl && enable_yagl) { + ERR("Error: only one openGL passthrough device can be used at one time!\n"); + exit(1); } - /* hw information */ - int mib[2]; - size_t len; - char *sys_info; - int sys_num = 0; - - mib[0] = CTL_HW; - mib[1] = HW_MODEL; - sysctl(mib, 2, NULL, &len, NULL, 0); - sys_info = malloc(len * sizeof(char)); - if (sysctl(mib, 2, sys_info, &len, NULL, 0) >= 0) { - INFO("* Machine model : %s\n", sys_info); + + if (enable_gl || enable_yagl) { + capability_check_gl = gl_acceleration_capability_check(); + + if (capability_check_gl != 0) { + enable_gl = enable_yagl = 0; + WARN("Warn: GL acceleration was disabled due to the fail of GL check!\n"); + } } - free(sys_info); - - mib[0] = CTL_HW; - mib[1] = HW_MACHINE; - sysctl(mib, 2, NULL, &len, NULL, 0); - sys_info = malloc(len * sizeof(char)); - if (sysctl(mib, 2, sys_info, &len, NULL, 0) >= 0) { - INFO("* Machine class : %s\n", sys_info); + if (enable_gl) { + device_opt_finding_t devp = {VIRTIOGL_DEV_NAME, 0}; + qemu_opts_foreach(qemu_find_opts("device"), find_device_opt, &devp, 0); + if (devp.found == 0) { + if (!qemu_opts_parse(qemu_find_opts("device"), VIRTIOGL_DEV_NAME, 1)) { + exit(1); + } + } } - free(sys_info); - mib[0] = CTL_HW; - mib[1] = HW_NCPU; - len = sizeof(sys_num); - if (sysctl(mib, 2, &sys_num, &len, NULL, 0) >= 0) { - INFO("* Number of processors : %d\n", sys_num); - } + gchar * const tmp_str = g_strdup_printf(" gles=%d yagl=%d", enable_gl, enable_yagl); + + g_strlcat(maru_kernel_cmdline, tmp_str, LEN_MARU_KERNEL_CMDLINE); + + g_free(tmp_str); +} +#endif - mib[0] = CTL_HW; - mib[1] = HW_PHYSMEM; - len = sizeof(sys_num); - if (sysctl(mib, 2, &sys_num, &len, NULL, 0) >= 0) { - INFO("* Total memory : %llu bytes\n", sys_num); +#define MARUCAM_DEV_NAME "maru_camera_pci" +#define WEBCAM_INFO_IGNORE 0x00 +#define WEBCAM_INFO_WRITE 0x04 +static void prepare_host_webcam(void) +{ + is_webcam_enabled = marucam_device_check(WEBCAM_INFO_WRITE); + + if (!is_webcam_enabled) { + INFO("[Webcam] Webcam support was disabled " + "due to the fail of webcam capability check!\n"); + } + else { + device_opt_finding_t devp = {MARUCAM_DEV_NAME, 0}; + qemu_opts_foreach(qemu_find_opts("device"), find_device_opt, &devp, 0); + if (devp.found == 0) { + if (!qemu_opts_parse(qemu_find_opts("device"), MARUCAM_DEV_NAME, 1)) { + INFO("Failed to initialize the marucam device.\n"); + exit(1); + } + } + INFO("[Webcam] Webcam support was enabled.\n"); } + gchar * const tmp_str = g_strdup_printf(" enable_cam=%d", is_webcam_enabled); + + g_strlcat(maru_kernel_cmdline, tmp_str, LEN_MARU_KERNEL_CMDLINE); + + g_free(tmp_str); +} + +const gchar * prepare_maru_devices(const gchar *kernel_cmdline) +{ + INFO("Prepare maru specified kernel command line\n"); + + g_strlcpy(maru_kernel_cmdline, kernel_cmdline, LEN_MARU_KERNEL_CMDLINE); + + // Prepare basic features + prepare_basic_features(); + + // Prepare GL acceleration +#ifdef CONFIG_GL_BACKEND + prepare_opengl_acceleration(); #endif - INFO("\n"); + // Prepare host webcam + prepare_host_webcam(); + + INFO("kernel command : %s\n", maru_kernel_cmdline); + + return maru_kernel_cmdline; +} + +int maru_device_check(QemuOpts *opts) +{ +#if defined(CONFIG_GL_BACKEND) + // virtio-gl pci device + if (!enable_gl) { + // ignore virtio-gl-pci device, even if users set it in option. + const char *driver = qemu_opt_get(opts, "driver"); + if (driver && (strcmp (driver, VIRTIOGL_DEV_NAME) == 0)) { + return -1; + } + } +#endif + if (!is_webcam_enabled) { + const char *driver = qemu_opt_get(opts, "driver"); + if (driver && (strcmp (driver, MARUCAM_DEV_NAME) == 0)) { + return -1; + } + } + + return 0; } void prepare_maru(void) @@ -653,7 +497,7 @@ static int emulator_main(int argc, char *argv[]) { parse_options(argc, argv, &_skin_argc, &_skin_argv, &_qemu_argc, &_qemu_argv); - set_bin_dir(_qemu_argv[0]); + set_bin_path(_qemu_argv[0]); extract_qemu_info(_qemu_argc, _qemu_argv); INFO("Emulator start !!!\n"); @@ -661,7 +505,7 @@ static int emulator_main(int argc, char *argv[]) extract_skin_info(_skin_argc, _skin_argv); - system_info(); + print_system_info(); INFO("Prepare running...\n"); /* Redirect stdout and stderr after debug_ch is initialized. */ diff --git a/tizen/src/emulator.h b/tizen/src/emulator.h index f5e93d854b..d487892bf0 100644 --- a/tizen/src/emulator.h +++ b/tizen/src/emulator.h @@ -31,23 +31,28 @@ /** * @file emulator.h - * @brief - header of file these are config struecture and defines in emulator + * @brief - header file for emulator.c */ #ifndef __EMULATOR_H__ #define __EMULATOR_H__ +#include "maru_common.h" +#include "qlist.h" +#include "qemu-option.h" + #define MAXLEN 512 #define MAXPACKETLEN 60 #define SHMKEY 26099 +extern gchar bin_path[]; +extern gchar log_path[]; + void exit_emulator(void); char *get_bin_path(void); -void set_image_and_log_path(char *qemu_argv); -void redir_output(void); -void extract_qemu_info(int qemu_argc, char **qemu_argv); -void extract_skin_info(int skin_argc, char **skin_argv); void prepare_maru(void); -void check_shdmem(void); -void make_shdmem(void); + +const gchar * get_log_path(void); +const gchar * prepare_maru_devices(const gchar * kernel_cmdline); +int maru_device_check(QemuOpts *opts); #endif /* __EMULATOR_H__ */ diff --git a/tizen/src/hw/gl_func_perso.h b/tizen/src/hw/gl_func_perso.h index 1488343e9c..4d7ad9eff3 100644 --- a/tizen/src/hw/gl_func_perso.h +++ b/tizen/src/hw/gl_func_perso.h @@ -60,6 +60,10 @@ MAGIC_MACRO(glXGetDriverConfig), MAGIC_MACRO(glXSwapIntervalSGI), MAGIC_MACRO(glXCreatePixmap), MAGIC_MACRO(glXDestroyPixmap), +MAGIC_MACRO(glXBindTexImageARB_fake), +MAGIC_MACRO(glXReleaseTexImageARB_fake), +MAGIC_MACRO(glXCreatePbuffer), +MAGIC_MACRO(glXDestroyPbuffer), MAGIC_MACRO(glGetString), diff --git a/tizen/src/hw/gloffscreen.h b/tizen/src/hw/gloffscreen.h index 806db14b68..11547c71be 100644 --- a/tizen/src/hw/gloffscreen.h +++ b/tizen/src/hw/gloffscreen.h @@ -83,8 +83,10 @@ extern void glo_context_destroy(GloContext *context); /* Update the context in surface and free previous light-weight context */ extern void glo_surface_update_context(GloSurface *surface, GloContext *context, int free_flags); -/* Link the pixmap associated with surface as texture */ -extern void glo_surface_as_texture(GloSurface *surface); +/* Link the pixmap/pbuffer associated with surface as texture. + * ctxt is the target context for the texture operation + */ +extern void glo_surface_as_texture(GloContext *ctxt, GloSurface *surface); /* Create a surface with given width and height, */ extern GloSurface *glo_surface_create(int width, int height, GloContext *context); diff --git a/tizen/src/hw/gloffscreen_agl.c b/tizen/src/hw/gloffscreen_agl.c new file mode 100644 index 0000000000..0d61423e69 --- /dev/null +++ b/tizen/src/hw/gloffscreen_agl.c @@ -0,0 +1,363 @@ +/*Offscreen OpenGL abstraction layer - AGL specific +* +* Copyright (c) 2010 Intel Corporation +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ +#ifdef __APPLE__ + +#include +#include +#include +#include +#include +/*hack due to conflicting typedefs in qemu's softfloat.h*/ +#define __SECURITYHI__ 1 + +#include +#include +#include "gloffscreen.h" + +#ifdef GL_DEBUG +#define TRACE(fmt, ...) printf("%s@%d: " fmt "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) +#else +#define TRACE(...) +#endif + +struct _GloContext +{ + GLuint formatFlags; + AGLPixelFormat pixelFormat; + AGLContext context; + }; + +struct _GloSurface +{ + GLuint width; + GLuint height; + GloContext *context; + AGLPbuffer pbuffer; + }; + +extern void glo_surface_getcontents_readpixels(int formatFlags, int stride, + int bpp, int width, int height, + void *data); + + + +/* Initialise gloffscreen */ +int glo_init(void) +{ + int major, minor; + aglGetVersion(&major, &minor); + fprintf(stdout, "%s----AGL version %d.%d\n",__FUNCTION__, major, minor); + return 0; + } + +/* Uninitialise gloffscreen */ +void glo_kill(void) +{ + +} + +const char *glo_glXQueryExtensionsString(void) +{ + return ""; + } + +/* Like wglGetProcAddress/glxGetProcAddress */ + void *glo_getprocaddress(const char *procName) + { + void *ret = NULL; + + if (procName) + { + if (!strncmp(procName, "glX", 3)) + ret = (void *)1; + else + ret = dlsym(RTLD_NEXT, procName); + } + +#if 0//standard code for mac to look up procaddress, but seems slow that above. + NSSymbol symbol; + char *symbolname; + symbolname = malloc(strlen(procName) +2); + strcpy(symbolname +1, procName); + symbolname[0] = '_'; + symbol = NULL; + if(NSIsSymbolNameDefined(symbolname)) + symbol = NSLookupAndBindSymbol(symbolname); + free(symbolname); + ret = symbol ? NSAddressOfSymbol (symbol) : NULL; +#endif + TRACE("'%s' --> %p", procName, ret); + return ret; +} + +/* Create an OpenGL context for a certain pixel format. +* formatflags are from the GLO_ constants +*/ + +GloContext *__glo_context_create(int formatFlags) +{ + int rgba[4]; + glo_flags_get_rgba_bits(formatFlags, rgba); + const int attribs[] = { + AGL_RGBA, + AGL_MINIMUM_POLICY, + AGL_PIXEL_SIZE, glo_flags_get_bytes_per_pixel(formatFlags) * 8, + AGL_RED_SIZE, rgba[0], + AGL_GREEN_SIZE, rgba[1], + AGL_BLUE_SIZE, rgba[2], + AGL_ALPHA_SIZE, rgba[3], + AGL_DEPTH_SIZE, glo_flags_get_depth_bits(formatFlags), + AGL_STENCIL_SIZE, glo_flags_get_stencil_bits(formatFlags), + AGL_ACCELERATED, + AGL_NO_RECOVERY, + AGL_NONE + }; + + TRACE("req %dbpp %d-%d-%d-%d depth %d stencil %d", + glo_flags_get_bytes_per_pixel(formatFlags) * 8, + rgba[0], rgba[1], rgba[2], rgba[3], + glo_flags_get_depth_bits(formatFlags), + glo_flags_get_stencil_bits(formatFlags)); + + AGLPixelFormat pf = aglChoosePixelFormat(NULL, 0, attribs); + if (pf == NULL) + fprintf(stderr, "No matching pixelformat found."); + else + { + GLint bpp = 0, a = 0, d = 0, s = 0; + aglDescribePixelFormat(pf, AGL_PIXEL_SIZE, &bpp); + aglDescribePixelFormat(pf, AGL_ALPHA_SIZE, &a); + aglDescribePixelFormat(pf, AGL_DEPTH_SIZE, &d); + aglDescribePixelFormat(pf, AGL_STENCIL_SIZE, &s); + + formatFlags &= ~(GLO_FF_ALPHA_MASK | GLO_FF_BITS_MASK | GLO_FF_DEPTH_MASK | GLO_FF_STENCIL_MASK); + switch (bpp) { + case 16: formatFlags |= GLO_FF_BITS_16; break; + case 24: formatFlags |= GLO_FF_BITS_24; break; + case 32: formatFlags |= GLO_FF_BITS_32; break; + default: fprintf(stderr, "got unsupported bpp %d", bpp); break; + } + + if (a > 0) + { + formatFlags |= GLO_FF_ALPHA; + } + + switch (d) { + case 0: break; + case 16: formatFlags |= GLO_FF_DEPTH_16; break; + case 24: formatFlags |= GLO_FF_DEPTH_24; break; + case 32: formatFlags |= GLO_FF_DEPTH_32; break; + default: fprintf(stderr, "got unsupported depth %d", d); break; + } + + switch (s) { + case 0: break; + case 8: formatFlags |= GLO_FF_STENCIL_8; break; + default: fprintf(stderr, "got unsupported stencil %d", s); break; + } + } + GloContext *context = (GloContext *)g_malloc(sizeof(*context)); + memset(context, 0, sizeof(*context)); + context->formatFlags = formatFlags; + context->pixelFormat = pf; + + return context; + +} + +GloContext *glo_context_create(int formatFlags, GloContext *shareLists) +{ + GloContext *context = __glo_context_create(formatFlags); + if(!context) + return NULL; + + context->context = aglCreateContext(context->pixelFormat, shareLists ? shareLists->context : NULL); + if (context->context == NULL) + { + fprintf(stderr, "aglCreateContext failed: %s", aglErrorString(aglGetError())); + } + + else + { + if(context->pixelFormat != NULL) + { + aglDestroyPixelFormat(context->pixelFormat); + context->pixelFormat = NULL; + } + } + + TRACE("context=%p", context); + return context; +} + +/* Destroy a previously created OpenGL context */ +void glo_context_destroy(GloContext *context) +{ + TRACE("context=%p", context); + if (context) + { + aglDestroyContext(context->context); + if(context->pixelFormat != NULL) + { + aglDestroyPixelFormat(context->pixelFormat); + context->pixelFormat = NULL; + } + context->context = NULL; + g_free(context); + } +} + +void glo_surface_update_context(GloSurface *surface, GloContext *context, int free_flags) +{ + if ( surface->context ) + { + if ( free_flags) /* light-weight context */ + g_free(surface->context); + } + surface->context = context; +} + + + +/* Create a surface with given width and height, formatflags are from the + * GLO_ constants */ +GloSurface *glo_surface_create(int width, int height, GloContext *context) +{ + GloSurface *surface = NULL; + if (context) + { + surface = (GloSurface *)g_malloc(sizeof(*surface)); + memset(surface, 0, sizeof(*surface)); + surface->width = width; + surface->height = height; + surface->context = context; + + TRACE("%dx%d", surface->width, surface->height); + if (aglCreatePBuffer(width, height, GL_TEXTURE_2D, GL_RGBA, 0, &surface->pbuffer) == GL_FALSE) + fprintf(stderr, "aglCreatePbuffer failed: %s", aglErrorString(aglGetError())); + + } + TRACE("surface=%p", surface); + return surface; +} + +/* Destroy the given surface */ +void glo_surface_destroy(GloSurface *surface) +{ + TRACE("surface=%p", surface); + if (surface) + { + aglDestroyPBuffer(surface->pbuffer); + surface->pbuffer = NULL; + g_free(surface); + } +} + +/* Make the given surface current */ +int glo_surface_makecurrent(GloSurface *surface) +{ + int ret = GL_FALSE; + TRACE("surface=%p", surface); + if (surface) + { + if (aglSetPBuffer(surface->context->context, surface->pbuffer, 0, 0, 0) == GL_FALSE) + fprintf(stderr, "aglSetPbuffer failed: %s", aglErrorString(aglGetError())); + ret = aglSetCurrentContext(surface->context->context); + } else + { + ret = aglSetCurrentContext(NULL); + } + + if (ret == GL_FALSE) + fprintf(stderr, "aglSetCurrentContext failed: %s", aglErrorString(aglGetError())); + + TRACE("Return ret=%d\n", ret); + return ret; + } + +void glo_surface_updatecontents(GloSurface *surface) +{ + const GLint swap_interval = 1; + + if(!surface) + return; + aglSwapBuffers(surface->context->context); + aglSetInteger(surface->context->context, AGL_SWAP_INTERVAL, &swap_interval); +} + + +/* Get the contents of the given surface */ +void glo_surface_getcontents(GloSurface *surface, int stride, int bpp, + void *data) +{ + const GLint swap_interval = 1; + if (surface) + { + aglSwapBuffers(surface->context->context); + aglSetInteger(surface->context->context, AGL_SWAP_INTERVAL, &swap_interval); + glo_surface_getcontents_readpixels(surface->context->formatFlags, stride, bpp, surface->width, surface->height, data); + } +} + +/* Return the width and height of the given surface */ +void glo_surface_get_size(GloSurface *surface, int *width, int *height) +{ + if (width) + { + *width = surface->width; + } + + if (height) + { + *height = surface->height; + } +} + +/* Bind the surface as texture */ +void glo_surface_as_texture(GloContext *ctxt, GloSurface *surface) +{ +#if 0 + //Not QUit sure about this function; + int glFormat, glType; + glo_surface_updatecontents(surface); + /*XXX: changet the fixed target: GL_TEXTURE_2D*/ + glo_flags_get_readpixel_type(surface->context->formatFlags, &glFormat, &glType); + fprintf(stderr, "surface_as_texture:teximage:width=%d,height=%d, glFormat=0x%x, glType=0x%x.\n", surface->width, surface->height, glFormat, glType); + /* glTexImage2D use different RGB order than the contexts in the pixmap surface */ +/* glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surface->width, surface->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->image->data);*/ + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surface->width, surface->height, 0, glFormat, glType, surface->pbuffer); +#else + if (aglTexImagePBuffer(ctxt->context, surface->pbuffer, GL_BACK) == GL_FALSE) + fprintf(stderr, "aglTexImagePBuffer failed: %s", aglErrorString(aglGetError())); + +#endif +} + +void glo_surface_release_texture(GloSurface *surface) +{ + +} + +#endif + diff --git a/tizen/src/hw/gloffscreen_test.c b/tizen/src/hw/gloffscreen_test.c index d5b65b9422..2799421938 100644 --- a/tizen/src/hw/gloffscreen_test.c +++ b/tizen/src/hw/gloffscreen_test.c @@ -24,7 +24,7 @@ * THE SOFTWARE. */ -#include "gloffscreen.h" +#include "gloffscreen_test.h" #include #include diff --git a/tizen/src/hw/gloffscreen_test.h b/tizen/src/hw/gloffscreen_test.h new file mode 100644 index 0000000000..452704340c --- /dev/null +++ b/tizen/src/hw/gloffscreen_test.h @@ -0,0 +1,34 @@ +/* + * Offscreen OpenGL abstraction layer + * + * Copyright (c) 2010 Intel Corporation + * Written by: + * Gordon Williams + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef __GLOFFSCREEN_TEST_H__ +#define __GLOFFSCREEN_TEST_H__ + +#include "gloffscreen.h" + +int gl_acceleration_capability_check(void); + +#endif /* __GLOFFSCREEN_TEST_H__ */ diff --git a/tizen/src/hw/gloffscreen_wgl.c b/tizen/src/hw/gloffscreen_wgl.c index a72e9beef9..15f22fe2da 100644 --- a/tizen/src/hw/gloffscreen_wgl.c +++ b/tizen/src/hw/gloffscreen_wgl.c @@ -659,6 +659,9 @@ static const char *STANDARD_GL_FUNCTIONS ={ "glXGetVisualFromFBConfig\0" "glXIsDirect\0" "glXCreatePixmap\0" +"glXDestroyPixmap\0" +"glXCreatePbuffer\n" +"glXDestroyPbuffer\n" "\0" }; @@ -964,7 +967,7 @@ void glo_surface_get_size(GloSurface *surface, int *width, int *height) { } /* Bind the surface as texture */ -void glo_surface_as_texture(GloSurface *surface) +void glo_surface_as_texture(GloContext *ctxt, GloSurface *surface) { #if 0 int glFormat, glType; diff --git a/tizen/src/hw/gloffscreen_xcomposite.c b/tizen/src/hw/gloffscreen_xcomposite.c index 85550ed1a7..6162d721c8 100644 --- a/tizen/src/hw/gloffscreen_xcomposite.c +++ b/tizen/src/hw/gloffscreen_xcomposite.c @@ -479,7 +479,7 @@ void glo_surface_get_size(GloSurface *surface, int *width, int *height) { } /* Bind the surface as texture */ -void glo_surface_as_texture(GloSurface *surface) +void glo_surface_as_texture(GloContext *ctxt, GloSurface *surface) { #if 0 void (*ptr_func_glXBindTexImageEXT) (Display *dpy, GLXDrawable draw, int buffer, int *attrib_list); diff --git a/tizen/src/hw/maru_brightness.c b/tizen/src/hw/maru_brightness.c index 4b0f233a97..a170dbac44 100644 --- a/tizen/src/hw/maru_brightness.c +++ b/tizen/src/hw/maru_brightness.c @@ -1,17 +1,10 @@ /* * Maru brightness device for VGA * - * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: - * SeokYeon Hwang - * SangJin Kim - * MunKyu Im - * KiTae Kim * JinHyung Jo - * SungMin Ha - * JiHye Kim - * GiWoong Kim * YeongKyoon Lee * DongKyun Yun * DoHyung Hong @@ -29,7 +22,8 @@ * * 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. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. * * Contributors: * - S-Core Co., Ltd @@ -44,6 +38,7 @@ #include "pci.h" #include "maru_device_ids.h" #include "maru_brightness.h" +#include "skin/maruskin_server.h" #include "debug_ch.h" MULTI_DEBUG_CHANNEL(qemu, maru_brightness); @@ -81,6 +76,8 @@ uint8_t brightness_tbl[] = {100, /* level 0 : for dimming */ /* level 81 ~ 90 */ 226, 228, 229, 231, 232, 234, 235, 237, 238, 240, /* level 91 ~ 99 */ 241, 243, 244, 246, 247, 249, 250, 252, 253}; +QEMUBH *bh; + static uint64_t brightness_reg_read(void *opaque, target_phys_addr_t addr, unsigned size) @@ -123,10 +120,19 @@ static void brightness_reg_write(void *opaque, return; case BRIGHTNESS_OFF: INFO("brightness_off : %lld\n", val); + if (brightness_off == val) { + return; + } + brightness_off = val; + #ifdef TARGET_ARM vga_hw_invalidate(); #endif + + /* notify to skin process */ + qemu_bh_schedule(bh); + return; default: ERR("wrong brightness register write - addr : %d\n", (int)addr); @@ -140,6 +146,22 @@ static const MemoryRegionOps brightness_mmio_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; +static void brightness_exitfn(PCIDevice *dev) +{ + if (bh) { + qemu_bh_delete(bh); + } +} + +static void maru_brightness_bh(void *opaque) +{ + if (brightness_off == 0) { + notify_brightness(TRUE); + } else { + notify_brightness(FALSE); + } +} + static int brightness_initfn(PCIDevice *dev) { BrightnessState *s = DO_UPCAST(BrightnessState, dev, dev); @@ -153,15 +175,12 @@ static int brightness_initfn(PCIDevice *dev) "maru_brightness_mmio", BRIGHTNESS_REG_SIZE); pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio_addr); + bh = qemu_bh_new(maru_brightness_bh, s); + return 0; } /* external interface */ -int pci_get_brightness(void) -{ - return brightness_level; -} - DeviceState *pci_maru_brightness_init(PCIBus *bus) { return &pci_create_simple(bus, -1, QEMU_DEV_NAME)->qdev; @@ -173,6 +192,7 @@ static void brightness_classinit(ObjectClass *klass, void *data) k->no_hotplug = 1; k->init = brightness_initfn; + k->exit = brightness_exitfn; } static TypeInfo brightness_info = { diff --git a/tizen/src/hw/maru_brightness.h b/tizen/src/hw/maru_brightness.h index eebaa5d6e7..98787c3ffe 100644 --- a/tizen/src/hw/maru_brightness.h +++ b/tizen/src/hw/maru_brightness.h @@ -1,9 +1,10 @@ /* * Maru brightness device for VGA * - * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: + * Jinhyung Jo * GiWoong Kim * YeongKyoon Lee * Hyunjun Son @@ -20,7 +21,8 @@ * * 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. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. * * Contributors: * - S-Core Co., Ltd @@ -39,7 +41,6 @@ extern uint32_t brightness_level; extern uint32_t brightness_off; extern uint8_t brightness_tbl[]; -int pci_get_brightness(void); DeviceState *pci_maru_brightness_init(PCIBus *bus); #endif /* MARU_BRIGHTNESS_H_ */ diff --git a/tizen/src/hw/maru_camera_common.h b/tizen/src/hw/maru_camera_common.h index 802030891b..9d914adfa5 100644 --- a/tizen/src/hw/maru_camera_common.h +++ b/tizen/src/hw/maru_camera_common.h @@ -1,114 +1,115 @@ -/* - * Common header of MARU Virtual Camera device. - * - * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: - * JinHyung Jo - * YeongKyoon Lee - * - * 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 - * - */ - -#ifndef _MARU_CAMERA_COMMON_H_ -#define _MARU_CAMERA_COMMON_H_ - -#include "pci.h" -#include "qemu-thread.h" - -#define MARUCAM_MAX_PARAM 20 -#define MARUCAM_SKIPFRAMES 2 - -/* must sync with GUEST camera_driver */ -#define MARUCAM_CMD_INIT 0x00 -#define MARUCAM_CMD_OPEN 0x04 -#define MARUCAM_CMD_CLOSE 0x08 -#define MARUCAM_CMD_ISR 0x0C -#define MARUCAM_CMD_START_PREVIEW 0x10 -#define MARUCAM_CMD_STOP_PREVIEW 0x14 -#define MARUCAM_CMD_S_PARAM 0x18 -#define MARUCAM_CMD_G_PARAM 0x1C -#define MARUCAM_CMD_ENUM_FMT 0x20 -#define MARUCAM_CMD_TRY_FMT 0x24 -#define MARUCAM_CMD_S_FMT 0x28 -#define MARUCAM_CMD_G_FMT 0x2C -#define MARUCAM_CMD_QCTRL 0x30 -#define MARUCAM_CMD_S_CTRL 0x34 -#define MARUCAM_CMD_G_CTRL 0x38 -#define MARUCAM_CMD_ENUM_FSIZES 0x3C -#define MARUCAM_CMD_ENUM_FINTV 0x40 -#define MARUCAM_CMD_S_DATA 0x44 -#define MARUCAM_CMD_G_DATA 0x48 -#define MARUCAM_CMD_DATACLR 0x50 -#define MARUCAM_CMD_REQFRAME 0x54 - -typedef struct MaruCamState MaruCamState; -typedef struct MaruCamParam MaruCamParam; - -struct MaruCamParam { - uint32_t top; - uint32_t retVal; - uint32_t errCode; - uint32_t stack[MARUCAM_MAX_PARAM]; -}; - -struct MaruCamState { - PCIDevice dev; - MaruCamParam *param; - QemuThread thread_id; - QemuMutex thread_mutex;; - QemuCond thread_cond; - QEMUBH *tx_bh; - - bool destroying; - void *vaddr; /* vram ptr */ - uint32_t isr; - uint32_t streamon; - uint32_t buf_size; - uint32_t req_frame; - - MemoryRegion vram; - MemoryRegion mmio; -}; - -/* ------------------------------------------------------------------------- */ -/* Fucntion prototype */ -/* ------------------------------------------------------------------------- */ -int marucam_device_check(int log_flag); -void marucam_device_init(MaruCamState *state); -void marucam_device_exit(MaruCamState *state); -void marucam_device_open(MaruCamState *state); -void marucam_device_close(MaruCamState *state); -void marucam_device_start_preview(MaruCamState *state); -void marucam_device_stop_preview(MaruCamState *state); -void marucam_device_s_param(MaruCamState *state); -void marucam_device_g_param(MaruCamState *state); -void marucam_device_s_fmt(MaruCamState *state); -void marucam_device_g_fmt(MaruCamState *state); -void marucam_device_try_fmt(MaruCamState *state); -void marucam_device_enum_fmt(MaruCamState *state); -void marucam_device_qctrl(MaruCamState *state); -void marucam_device_s_ctrl(MaruCamState *state); -void marucam_device_g_ctrl(MaruCamState *state); -void marucam_device_enum_fsizes(MaruCamState *state); -void marucam_device_enum_fintv(MaruCamState *state); - -int maru_camera_pci_init(PCIBus *bus); - -#endif /* _MARU_CAMERA_COMMON_H_ */ +/* + * Common header of MARU Virtual Camera device. + * + * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * JinHyung Jo + * YeongKyoon Lee + * + * 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 + * + */ + +#ifndef _MARU_CAMERA_COMMON_H_ +#define _MARU_CAMERA_COMMON_H_ + +#include "pci.h" +#include "qemu-thread.h" + +#define MARUCAM_MAX_PARAM 20 +#define MARUCAM_SKIPFRAMES 2 + +/* must sync with GUEST camera_driver */ +#define MARUCAM_CMD_INIT 0x00 +#define MARUCAM_CMD_OPEN 0x04 +#define MARUCAM_CMD_CLOSE 0x08 +#define MARUCAM_CMD_ISR 0x0C +#define MARUCAM_CMD_START_PREVIEW 0x10 +#define MARUCAM_CMD_STOP_PREVIEW 0x14 +#define MARUCAM_CMD_S_PARAM 0x18 +#define MARUCAM_CMD_G_PARAM 0x1C +#define MARUCAM_CMD_ENUM_FMT 0x20 +#define MARUCAM_CMD_TRY_FMT 0x24 +#define MARUCAM_CMD_S_FMT 0x28 +#define MARUCAM_CMD_G_FMT 0x2C +#define MARUCAM_CMD_QCTRL 0x30 +#define MARUCAM_CMD_S_CTRL 0x34 +#define MARUCAM_CMD_G_CTRL 0x38 +#define MARUCAM_CMD_ENUM_FSIZES 0x3C +#define MARUCAM_CMD_ENUM_FINTV 0x40 +#define MARUCAM_CMD_S_DATA 0x44 +#define MARUCAM_CMD_G_DATA 0x48 +#define MARUCAM_CMD_DATACLR 0x50 +#define MARUCAM_CMD_REQFRAME 0x54 + +typedef struct MaruCamState MaruCamState; +typedef struct MaruCamParam MaruCamParam; + +struct MaruCamParam { + uint32_t top; + uint32_t retVal; + uint32_t errCode; + uint32_t stack[MARUCAM_MAX_PARAM]; +}; + +struct MaruCamState { + PCIDevice dev; + MaruCamParam *param; + QemuThread thread_id; + QemuMutex thread_mutex;; + QemuCond thread_cond; + QEMUBH *tx_bh; + + bool destroying; + void *vaddr; /* vram ptr */ + uint32_t isr; + uint32_t streamon; + uint32_t buf_size; + uint32_t req_frame; + + MemoryRegion vram; + MemoryRegion mmio; +}; + +/* ------------------------------------------------------------------------- */ +/* Fucntion prototype */ +/* ------------------------------------------------------------------------- */ +int marucam_device_check(int log_flag); +void marucam_device_init(MaruCamState *state); +void marucam_device_exit(MaruCamState *state); +void marucam_device_open(MaruCamState *state); +void marucam_device_close(MaruCamState *state); +void marucam_device_start_preview(MaruCamState *state); +void marucam_device_stop_preview(MaruCamState *state); +void marucam_device_s_param(MaruCamState *state); +void marucam_device_g_param(MaruCamState *state); +void marucam_device_s_fmt(MaruCamState *state); +void marucam_device_g_fmt(MaruCamState *state); +void marucam_device_try_fmt(MaruCamState *state); +void marucam_device_enum_fmt(MaruCamState *state); +void marucam_device_qctrl(MaruCamState *state); +void marucam_device_s_ctrl(MaruCamState *state); +void marucam_device_g_ctrl(MaruCamState *state); +void marucam_device_enum_fsizes(MaruCamState *state); +void marucam_device_enum_fintv(MaruCamState *state); + +int maru_camera_pci_init(PCIBus *bus); + +#endif /* _MARU_CAMERA_COMMON_H_ */ diff --git a/tizen/src/hw/maru_camera_common_pci.c b/tizen/src/hw/maru_camera_common_pci.c index 42d853a6e9..1dd20cc9c1 100644 --- a/tizen/src/hw/maru_camera_common_pci.c +++ b/tizen/src/hw/maru_camera_common_pci.c @@ -1,286 +1,291 @@ -/* - * Common implementation of MARU Virtual Camera device by PCI bus. - * - * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: - * JinHyung Jo - * YeongKyoon Lee - * - * 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 - * - */ - - -#include -#include -#include -#include -#include -#include - -#include "qemu-common.h" -#include "cpu-common.h" - -#include "pci.h" -#include "pci_ids.h" -#include "maru_device_ids.h" - -#include "maru_camera_common.h" -#include "tizen/src/debug_ch.h" - -MULTI_DEBUG_CHANNEL(tizen, camera_pci); - -#define MARU_PCI_CAMERA_DEVICE_NAME "maru_camera_pci" - -#define MARUCAM_MEM_SIZE (4 * 1024 * 1024) /* 4MB */ -#define MARUCAM_REG_SIZE (256) /* 64 * 4Byte */ - -/* - * I/O functions - */ -static inline uint32_t -marucam_mmio_read(void *opaque, target_phys_addr_t offset) -{ - uint32_t ret = 0; - MaruCamState *state = (MaruCamState*)opaque; - - switch (offset & 0xFF) { - case MARUCAM_CMD_ISR: - qemu_mutex_lock(&state->thread_mutex); - ret = state->isr; - if (ret != 0) { - qemu_irq_lower(state->dev.irq[2]); - state->isr = 0; - } - qemu_mutex_unlock(&state->thread_mutex); - break; - case MARUCAM_CMD_G_DATA: - ret = state->param->stack[state->param->top++]; - break; - case MARUCAM_CMD_OPEN: - case MARUCAM_CMD_CLOSE: - case MARUCAM_CMD_START_PREVIEW: - case MARUCAM_CMD_STOP_PREVIEW: - case MARUCAM_CMD_S_PARAM: - case MARUCAM_CMD_G_PARAM: - case MARUCAM_CMD_ENUM_FMT: - case MARUCAM_CMD_TRY_FMT: - case MARUCAM_CMD_S_FMT: - case MARUCAM_CMD_G_FMT: - case MARUCAM_CMD_QCTRL: - case MARUCAM_CMD_S_CTRL: - case MARUCAM_CMD_G_CTRL: - case MARUCAM_CMD_ENUM_FSIZES: - case MARUCAM_CMD_ENUM_FINTV: - ret = state->param->errCode; - state->param->errCode = 0; - break; - default: - ERR("Not supported command: 0x%x\n", offset); - ret = EINVAL; - break; - } - return ret; -} - -static inline void -marucam_mmio_write(void *opaque, target_phys_addr_t offset, uint32_t value) -{ - MaruCamState *state = (MaruCamState*)opaque; - - switch(offset & 0xFF) { - case MARUCAM_CMD_OPEN: - marucam_device_open(state); - break; - case MARUCAM_CMD_CLOSE: - marucam_device_close(state); - break; - case MARUCAM_CMD_START_PREVIEW: - marucam_device_start_preview(state); - break; - case MARUCAM_CMD_STOP_PREVIEW: - marucam_device_stop_preview(state); - memset(state->vaddr, 0, MARUCAM_MEM_SIZE); - break; - case MARUCAM_CMD_S_PARAM: - marucam_device_s_param(state); - break; - case MARUCAM_CMD_G_PARAM: - marucam_device_g_param(state); - break; - case MARUCAM_CMD_ENUM_FMT: - marucam_device_enum_fmt(state); - break; - case MARUCAM_CMD_TRY_FMT: - marucam_device_try_fmt(state); - break; - case MARUCAM_CMD_S_FMT: - marucam_device_s_fmt(state); - break; - case MARUCAM_CMD_G_FMT: - marucam_device_g_fmt(state); - break; - case MARUCAM_CMD_QCTRL: - marucam_device_qctrl(state); - break; - case MARUCAM_CMD_S_CTRL: - marucam_device_s_ctrl(state); - break; - case MARUCAM_CMD_G_CTRL: - marucam_device_g_ctrl(state); - break; - case MARUCAM_CMD_ENUM_FSIZES: - marucam_device_enum_fsizes(state); - break; - case MARUCAM_CMD_ENUM_FINTV: - marucam_device_enum_fintv(state); - break; - case MARUCAM_CMD_S_DATA: - state->param->stack[state->param->top++] = value; - break; - case MARUCAM_CMD_DATACLR: - memset(state->param, 0, sizeof(MaruCamParam)); - break; - case MARUCAM_CMD_REQFRAME: - qemu_mutex_lock(&state->thread_mutex); - state->req_frame = value + 1; - qemu_mutex_unlock(&state->thread_mutex); - break; - default: - ERR("Not supported command: 0x%x\n", offset); - break; - } -} - -static const MemoryRegionOps maru_camera_mmio_ops = { - .old_mmio = { - .read = { - marucam_mmio_read, - marucam_mmio_read, - marucam_mmio_read, - }, - .write = { - marucam_mmio_write, - marucam_mmio_write, - marucam_mmio_write, - }, - }, - .endianness = DEVICE_LITTLE_ENDIAN, -}; - -/* - * QEMU bottom half funtion - */ -static void marucam_tx_bh(void *opaque) -{ - MaruCamState *state = (MaruCamState *)opaque; - - qemu_mutex_lock(&state->thread_mutex); - if (state->isr) { - qemu_irq_raise(state->dev.irq[2]); - } - qemu_mutex_unlock(&state->thread_mutex); -} - -/* - * Initialization function - */ -static int marucam_initfn(PCIDevice *dev) -{ - MaruCamState *s = DO_UPCAST(MaruCamState, dev, dev); - uint8_t *pci_conf = s->dev.config; - - pci_config_set_interrupt_pin(pci_conf, 0x03); - - memory_region_init_ram(&s->vram, "marucamera.ram", MARUCAM_MEM_SIZE); - s->vaddr = memory_region_get_ram_ptr(&s->vram); - memset(s->vaddr, 0, MARUCAM_MEM_SIZE); - - memory_region_init_io (&s->mmio, &maru_camera_mmio_ops, s, - "maru-camera-mmio", MARUCAM_REG_SIZE); - pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram); - pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio); - - /* for worker thread */ - s->param = (MaruCamParam*)g_malloc0(sizeof(MaruCamParam)); - qemu_cond_init(&s->thread_cond); - qemu_mutex_init(&s->thread_mutex); - - marucam_device_init(s); - - s->tx_bh = qemu_bh_new(marucam_tx_bh, s); - INFO("[%s] camera device was initialized.\n", __func__); - - return 0; -} - -/* - * Termination function - */ -static void marucam_exitfn(PCIDevice *pci_dev) -{ - MaruCamState *s = - OBJECT_CHECK(MaruCamState, pci_dev, MARU_PCI_CAMERA_DEVICE_NAME); - - marucam_device_exit(s); - g_free(s->param); - qemu_cond_destroy(&s->thread_cond); - qemu_mutex_destroy(&s->thread_mutex); - - memory_region_destroy(&s->vram); - memory_region_destroy(&s->mmio); - - - INFO("[%s] camera device was released.\n", __func__); -} - -int maru_camera_pci_init(PCIBus *bus) -{ - INFO("[%s] camera device was initialized.\n", __func__); - pci_create_simple(bus, -1, MARU_PCI_CAMERA_DEVICE_NAME); - return 0; -} - -static void maru_camera_pci_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->no_hotplug = 1; - k->init = marucam_initfn; - k->exit = marucam_exitfn; - k->vendor_id = PCI_VENDOR_ID_TIZEN; - k->device_id = PCI_DEVICE_ID_VIRTUAL_CAMERA; - k->class_id = PCI_CLASS_OTHERS; - dc->desc = "MARU Virtual Camera device for Tizen emulator"; -} - -static TypeInfo maru_camera_info = { - .name = MARU_PCI_CAMERA_DEVICE_NAME, - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(MaruCamState), - .class_init = maru_camera_pci_class_init, -}; - -static void maru_camera_pci_register_types(void) -{ - type_register_static(&maru_camera_info); -} - -type_init(maru_camera_pci_register_types) +/* + * Common implementation of MARU Virtual Camera device by PCI bus. + * + * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * JinHyung Jo + * YeongKyoon Lee + * + * 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 + * + */ + + +#include +#include +#include +#include +#include +#include + +#include "qemu-common.h" +#include "cpu-common.h" + +#include "pci.h" +#include "pci_ids.h" +#include "maru_device_ids.h" + +#include "maru_camera_common.h" +#include "tizen/src/debug_ch.h" + +MULTI_DEBUG_CHANNEL(tizen, camera_pci); + +#define MARU_PCI_CAMERA_DEVICE_NAME "maru_camera_pci" + +#define MARUCAM_MEM_SIZE (4 * 1024 * 1024) /* 4MB */ +#define MARUCAM_REG_SIZE (256) /* 64 * 4Byte */ + +/* + * I/O functions + */ +static inline uint32_t +marucam_mmio_read(void *opaque, target_phys_addr_t offset) +{ + uint32_t ret = 0; + MaruCamState *state = (MaruCamState *)opaque; + + switch (offset & 0xFF) { + case MARUCAM_CMD_ISR: + qemu_mutex_lock(&state->thread_mutex); + ret = state->isr; + if (ret != 0) { + qemu_irq_lower(state->dev.irq[2]); + state->isr = 0; + } + qemu_mutex_unlock(&state->thread_mutex); + break; + case MARUCAM_CMD_G_DATA: + ret = state->param->stack[state->param->top++]; + break; + case MARUCAM_CMD_OPEN: + case MARUCAM_CMD_CLOSE: + case MARUCAM_CMD_START_PREVIEW: + case MARUCAM_CMD_STOP_PREVIEW: + case MARUCAM_CMD_S_PARAM: + case MARUCAM_CMD_G_PARAM: + case MARUCAM_CMD_ENUM_FMT: + case MARUCAM_CMD_TRY_FMT: + case MARUCAM_CMD_S_FMT: + case MARUCAM_CMD_G_FMT: + case MARUCAM_CMD_QCTRL: + case MARUCAM_CMD_S_CTRL: + case MARUCAM_CMD_G_CTRL: + case MARUCAM_CMD_ENUM_FSIZES: + case MARUCAM_CMD_ENUM_FINTV: + ret = state->param->errCode; + state->param->errCode = 0; + break; + default: + ERR("Not supported command: 0x%x\n", offset); + ret = EINVAL; + break; + } + return ret; +} + +static inline void +marucam_mmio_write(void *opaque, target_phys_addr_t offset, uint32_t value) +{ + MaruCamState *state = (MaruCamState *)opaque; + + switch (offset & 0xFF) { + case MARUCAM_CMD_OPEN: + marucam_device_open(state); + break; + case MARUCAM_CMD_CLOSE: + marucam_device_close(state); + break; + case MARUCAM_CMD_START_PREVIEW: + marucam_device_start_preview(state); + break; + case MARUCAM_CMD_STOP_PREVIEW: + marucam_device_stop_preview(state); + memset(state->vaddr, 0, MARUCAM_MEM_SIZE); + break; + case MARUCAM_CMD_S_PARAM: + marucam_device_s_param(state); + break; + case MARUCAM_CMD_G_PARAM: + marucam_device_g_param(state); + break; + case MARUCAM_CMD_ENUM_FMT: + marucam_device_enum_fmt(state); + break; + case MARUCAM_CMD_TRY_FMT: + marucam_device_try_fmt(state); + break; + case MARUCAM_CMD_S_FMT: + marucam_device_s_fmt(state); + break; + case MARUCAM_CMD_G_FMT: + marucam_device_g_fmt(state); + break; + case MARUCAM_CMD_QCTRL: + marucam_device_qctrl(state); + break; + case MARUCAM_CMD_S_CTRL: + marucam_device_s_ctrl(state); + break; + case MARUCAM_CMD_G_CTRL: + marucam_device_g_ctrl(state); + break; + case MARUCAM_CMD_ENUM_FSIZES: + marucam_device_enum_fsizes(state); + break; + case MARUCAM_CMD_ENUM_FINTV: + marucam_device_enum_fintv(state); + break; + case MARUCAM_CMD_S_DATA: + state->param->stack[state->param->top++] = value; + break; + case MARUCAM_CMD_DATACLR: + memset(state->param, 0, sizeof(MaruCamParam)); + break; + case MARUCAM_CMD_REQFRAME: + qemu_mutex_lock(&state->thread_mutex); + state->req_frame = value + 1; + qemu_mutex_unlock(&state->thread_mutex); + break; + default: + ERR("Not supported command: 0x%x\n", offset); + break; + } +} + +static const MemoryRegionOps maru_camera_mmio_ops = { + .old_mmio = { + .read = { + marucam_mmio_read, + marucam_mmio_read, + marucam_mmio_read, + }, + .write = { + marucam_mmio_write, + marucam_mmio_write, + marucam_mmio_write, + }, + }, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +/* + * QEMU bottom half funtion + */ +static void marucam_tx_bh(void *opaque) +{ + MaruCamState *state = (MaruCamState *)opaque; + + qemu_mutex_lock(&state->thread_mutex); + if (state->isr) { + qemu_irq_raise(state->dev.irq[2]); + } + qemu_mutex_unlock(&state->thread_mutex); +} + +/* + * Initialization function + */ +static int marucam_initfn(PCIDevice *dev) +{ + MaruCamState *s = DO_UPCAST(MaruCamState, dev, dev); + uint8_t *pci_conf = s->dev.config; + + pci_config_set_interrupt_pin(pci_conf, 0x03); + + memory_region_init_ram(&s->vram, "marucamera.ram", MARUCAM_MEM_SIZE); + s->vaddr = memory_region_get_ram_ptr(&s->vram); + memset(s->vaddr, 0, MARUCAM_MEM_SIZE); + + memory_region_init_io(&s->mmio, + &maru_camera_mmio_ops, + s, + "maru-camera-mmio", + MARUCAM_REG_SIZE); + + pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram); + pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio); + + /* for worker thread */ + s->param = (MaruCamParam *)g_malloc0(sizeof(MaruCamParam)); + qemu_cond_init(&s->thread_cond); + qemu_mutex_init(&s->thread_mutex); + + marucam_device_init(s); + + s->tx_bh = qemu_bh_new(marucam_tx_bh, s); + INFO("[%s] camera device was initialized.\n", __func__); + + return 0; +} + +/* + * Termination function + */ +static void marucam_exitfn(PCIDevice *pci_dev) +{ + MaruCamState *s = + OBJECT_CHECK(MaruCamState, pci_dev, MARU_PCI_CAMERA_DEVICE_NAME); + + marucam_device_exit(s); + g_free(s->param); + qemu_cond_destroy(&s->thread_cond); + qemu_mutex_destroy(&s->thread_mutex); + + memory_region_destroy(&s->vram); + memory_region_destroy(&s->mmio); + + + INFO("[%s] camera device was released.\n", __func__); +} + +int maru_camera_pci_init(PCIBus *bus) +{ + INFO("[%s] camera device was initialized.\n", __func__); + pci_create_simple(bus, -1, MARU_PCI_CAMERA_DEVICE_NAME); + return 0; +} + +static void maru_camera_pci_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + + k->no_hotplug = 1; + k->init = marucam_initfn; + k->exit = marucam_exitfn; + k->vendor_id = PCI_VENDOR_ID_TIZEN; + k->device_id = PCI_DEVICE_ID_VIRTUAL_CAMERA; + k->class_id = PCI_CLASS_OTHERS; + dc->desc = "MARU Virtual Camera device for Tizen emulator"; +} + +static TypeInfo maru_camera_info = { + .name = MARU_PCI_CAMERA_DEVICE_NAME, + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(MaruCamState), + .class_init = maru_camera_pci_class_init, +}; + +static void maru_camera_pci_register_types(void) +{ + type_register_static(&maru_camera_info); +} + +type_init(maru_camera_pci_register_types) diff --git a/tizen/src/hw/maru_camera_darwin.h b/tizen/src/hw/maru_camera_darwin.h index 25e480796e..2ac39f9172 100644 --- a/tizen/src/hw/maru_camera_darwin.h +++ b/tizen/src/hw/maru_camera_darwin.h @@ -1,4 +1,13 @@ /* + * Header of MARU Virtual Camera device for MacOS. + * + * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * Jun Tian + * JinHyung Jo + * YeongKyoon Lee + * * 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 @@ -12,41 +21,68 @@ * 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. + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd * */ #ifndef _MARU_CAMERA_DARWIN_H_ #define _MARU_CAMERA_DARWIN_H_ -#define MAKEFOURCC(a,b,c,d)\ - (((uint32_t)(a)<<0)|((uint32_t)(b)<<8)|((uint32_t)(c)<<16)|((uint32_t)(d)<<24)) +#define MAKEFOURCC(a, b, c, d) \ + (((uint32_t)(a) << 0) | \ + ((uint32_t)(b) << 8) | \ + ((uint32_t)(c) << 16) | \ + ((uint32_t)(d) << 24)) -/* Pixel format FOURCC depth Description */ -#define V4L2_PIX_FMT_RGB555 MAKEFOURCC('R','G','B','O') /* 16 RGB-5-5-5 */ -#define V4L2_PIX_FMT_RGB565 MAKEFOURCC('R','G','B','P') /* 16 RGB-5-6-5 */ -#define V4L2_PIX_FMT_RGB555X MAKEFOURCC('R','G','B','Q') /* 16 RGB-5-5-5 BE */ -#define V4L2_PIX_FMT_RGB565X MAKEFOURCC('R','G','B','R') /* 16 RGB-5-6-5 BE */ -#define V4L2_PIX_FMT_BGR24 MAKEFOURCC('B','G','R','3') /* 24 BGR-8-8-8 */ -#define V4L2_PIX_FMT_RGB24 MAKEFOURCC('R','G','B','3') /* 24 RGB-8-8-8 */ -#define V4L2_PIX_FMT_BGR32 MAKEFOURCC('B','G','R','4') /* 32 BGR-8-8-8-8 */ -#define V4L2_PIX_FMT_RGB32 MAKEFOURCC('R','G','B','4') /* 32 RGB-8-8-8-8 */ -#define V4L2_PIX_FMT_YVU410 MAKEFOURCC('Y','V','U','9') /* 9 YVU 4:1:0 */ -#define V4L2_PIX_FMT_YVU420 MAKEFOURCC('Y','V','1','2') /* 12 YVU 4:2:0 */ -#define V4L2_PIX_FMT_YUYV MAKEFOURCC('Y','U','Y','V') /* 16 YUV 4:2:2 */ -#define V4L2_PIX_FMT_UYVY MAKEFOURCC('U','Y','V','Y') /* 16 YUV 4:2:2 */ -#define V4L2_PIX_FMT_YUV422P MAKEFOURCC('4','2','2','P') /* 16 YVU422 planar */ -#define V4L2_PIX_FMT_YUV411P MAKEFOURCC('4','1','1','P') /* 16 YVU411 planar */ -#define V4L2_PIX_FMT_Y41P MAKEFOURCC('Y','4','1','P') /* 12 YUV 4:1:1 */ -#define V4L2_PIX_FMT_YUV444 MAKEFOURCC('Y','4','4','4') /* 16 xxxxyyyy uuuuvvvv */ -#define V4L2_PIX_FMT_YUV555 MAKEFOURCC('Y','U','V','O') /* 16 YUV-5-5-5 */ -#define V4L2_PIX_FMT_YUV565 MAKEFOURCC('Y','U','V','P') /* 16 YUV-5-6-5 */ -#define V4L2_PIX_FMT_YUV32 MAKEFOURCC('Y','U','V','4') /* 32 YUV-8-8-8-8 */ -#define V4L2_PIX_FMT_YUV410 MAKEFOURCC('Y','U','V','9') /* 9 YUV 4:1:0 */ -#define V4L2_PIX_FMT_YUV420 MAKEFOURCC('Y','U','1','2') /* 12 YUV 4:2:0 */ -#define V4L2_PIX_FMT_YYUV MAKEFOURCC('Y','Y','U','V') /* 16 YUV 4:2:2 */ +/* 16 RGB-5-5-5 */ +#define V4L2_PIX_FMT_RGB555 MAKEFOURCC('R', 'G', 'B', 'O') +/* 16 RGB-5-6-5 */ +#define V4L2_PIX_FMT_RGB565 MAKEFOURCC('R', 'G', 'B', 'P') +/* 16 RGB-5-5-5 BE */ +#define V4L2_PIX_FMT_RGB555X MAKEFOURCC('R', 'G', 'B', 'Q') +/* 16 RGB-5-6-5 BE */ +#define V4L2_PIX_FMT_RGB565X MAKEFOURCC('R', 'G', 'B', 'R') +/* 24 BGR-8-8-8 */ +#define V4L2_PIX_FMT_BGR24 MAKEFOURCC('B', 'G', 'R', '3') +/* 24 RGB-8-8-8 */ +#define V4L2_PIX_FMT_RGB24 MAKEFOURCC('R', 'G', 'B', '3') +/* 32 BGR-8-8-8-8 */ +#define V4L2_PIX_FMT_BGR32 MAKEFOURCC('B', 'G', 'R', '4') +/* 32 RGB-8-8-8-8 */ +#define V4L2_PIX_FMT_RGB32 MAKEFOURCC('R', 'G', 'B', '4') +/* 9 YVU 4:1:0 */ +#define V4L2_PIX_FMT_YVU410 MAKEFOURCC('Y', 'V', 'U', '9') +/* 12 YVU 4:2:0 */ +#define V4L2_PIX_FMT_YVU420 MAKEFOURCC('Y', 'V', '1', '2') +/* 16 YUV 4:2:2 */ +#define V4L2_PIX_FMT_YUYV MAKEFOURCC('Y', 'U', 'Y', 'V') +/* 16 YUV 4:2:2 */ +#define V4L2_PIX_FMT_UYVY MAKEFOURCC('U', 'Y', 'V', 'Y') +/* 16 YVU422 planar */ +#define V4L2_PIX_FMT_YUV422P MAKEFOURCC('4', '2', '2', 'P') +/* 16 YVU411 planar */ +#define V4L2_PIX_FMT_YUV411P MAKEFOURCC('4', '1', '1', 'P') +/* 12 YUV 4:1:1 */ +#define V4L2_PIX_FMT_Y41P MAKEFOURCC('Y', '4', '1', 'P') +/* 16 xxxxyyyy uuuuvvvv */ +#define V4L2_PIX_FMT_YUV444 MAKEFOURCC('Y', '4', '4', '4') +/* 16 YUV-5-5-5 */ +#define V4L2_PIX_FMT_YUV555 MAKEFOURCC('Y', 'U', 'V', 'O') +/* 16 YUV-5-6-5 */ +#define V4L2_PIX_FMT_YUV565 MAKEFOURCC('Y', 'U', 'V', 'P') +/* 32 YUV-8-8-8-8 */ +#define V4L2_PIX_FMT_YUV32 MAKEFOURCC('Y', 'U', 'V', '4') +/* 9 YUV 4:1:0 */ +#define V4L2_PIX_FMT_YUV410 MAKEFOURCC('Y', 'U', 'V', '9') +/* 12 YUV 4:2:0 */ +#define V4L2_PIX_FMT_YUV420 MAKEFOURCC('Y', 'U', '1', '2') +/* 16 YUV 4:2:2 */ +#define V4L2_PIX_FMT_YYUV MAKEFOURCC('Y', 'Y', 'U', 'V') void convert_frame(uint32_t pixel_format, int frame_width, int frame_height, - size_t frame_size, void* frame_pixels, void* video_buf); + size_t frame_size, void *frame_pixels, void *video_buf); #endif /* _MARU_CAMERA_DARWIN_H_ */ diff --git a/tizen/src/hw/maru_camera_darwin_converter.c b/tizen/src/hw/maru_camera_darwin_converter.c index 817e705be3..7105e663d4 100644 --- a/tizen/src/hw/maru_camera_darwin_converter.c +++ b/tizen/src/hw/maru_camera_darwin_converter.c @@ -1,4 +1,13 @@ /* + * Implementation of color conversion for MARU Virtual Camera device on MacOS. + * + * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * Jun Tian + * JinHyung Jo + * YeongKyoon Lee + * * 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 @@ -12,7 +21,10 @@ * 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. + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd * */ diff --git a/tizen/src/hw/maru_camera_darwin_pci.m b/tizen/src/hw/maru_camera_darwin_pci.m index 336ef3b6d0..d8d3a2f5da 100644 --- a/tizen/src/hw/maru_camera_darwin_pci.m +++ b/tizen/src/hw/maru_camera_darwin_pci.m @@ -1,12 +1,12 @@ /* - * Implementation of MARU Virtual Camera device by PCI bus on Linux. + * Implementation of MARU Virtual Camera device by PCI bus on MacOS. * - * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved * * Contact: + * Jun Tian * JinHyung Jo * YeongKyoon Lee - * Jun Tian * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -20,7 +20,8 @@ * * 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. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. * * Contributors: * - S-Core Co., Ltd @@ -635,7 +636,7 @@ void marucam_device_stop_preview(MaruCamState *state) usleep(10000); } } - + if (mcd->driver != nil) { [mcd->driver stopCapture]; } diff --git a/tizen/src/hw/maru_camera_linux_pci.c b/tizen/src/hw/maru_camera_linux_pci.c index 7cd039412c..be5dc6c6ca 100644 --- a/tizen/src/hw/maru_camera_linux_pci.c +++ b/tizen/src/hw/maru_camera_linux_pci.c @@ -1,1194 +1,1248 @@ -/* - * Implementation of MARU Virtual Camera device by PCI bus on Linux. - * - * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: - * JinHyung Jo - * YeongKyoon Lee - * - * 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 - * - */ - -#include "qemu-common.h" -#include "maru_camera_common.h" -#include "pci.h" -#include "kvm.h" -#include "tizen/src/debug_ch.h" - -#include - -#include -#include -#include - -#include -#include - -MULTI_DEBUG_CHANNEL(tizen, camera_linux); - -#define CLEAR(x) memset(&(x), 0, sizeof(x)) - -#define MARUCAM_DEFAULT_BUFFER_COUNT 4 - -#define MARUCAM_CTRL_VALUE_MAX 20 -#define MARUCAM_CTRL_VALUE_MIN 1 -#define MARUCAM_CTRL_VALUE_MID 10 -#define MARUCAM_CTRL_VALUE_STEP 1 - -enum { - _MC_THREAD_PAUSED, - _MC_THREAD_STREAMON, - _MC_THREAD_STREAMOFF, -}; - -typedef struct marucam_framebuffer { - void *data; - size_t size; -} marucam_framebuffer; - -static int n_framebuffer; -static struct marucam_framebuffer *framebuffer; - -static const char *dev_name = "/dev/video0"; -static int v4l2_fd; -static int convert_trial; -static int ready_count; - -static struct v4l2_format dst_fmt; - -static int yioctl(int fd, int req, void *arg) -{ - int r; - - do { - r = ioctl(fd, req, arg); - } while (r < 0 && errno == EINTR); - - return r; -} - -static int xioctl(int fd, int req, void *arg) -{ - int r; - - do { - r = v4l2_ioctl(fd, req, arg); - } while (r < 0 && errno == EINTR); - - return r; -} - -typedef struct tagMaruCamConvertPixfmt { - uint32_t fmt; /* fourcc */ -} MaruCamConvertPixfmt; - -static MaruCamConvertPixfmt supported_dst_pixfmts[] = { - { V4L2_PIX_FMT_YUYV }, - { V4L2_PIX_FMT_YUV420 }, - { V4L2_PIX_FMT_YVU420 }, -}; - -typedef struct tagMaruCamConvertFrameInfo { - uint32_t width; - uint32_t height; -} MaruCamConvertFrameInfo; - -static MaruCamConvertFrameInfo supported_dst_frames[] = { - { 640, 480 }, - { 352, 288 }, - { 320, 240 }, - { 176, 144 }, - { 160, 120 }, -}; - -struct marucam_qctrl { - uint32_t id; - uint32_t hit; - int32_t min; - int32_t max; - int32_t step; - int32_t init_val; -}; - -static struct marucam_qctrl qctrl_tbl[] = { - { V4L2_CID_BRIGHTNESS, 0, }, - { V4L2_CID_CONTRAST, 0, }, - { V4L2_CID_SATURATION, 0, }, - { V4L2_CID_SHARPNESS, 0, }, -}; - -static void marucam_reset_controls(void) -{ - uint32_t i; - for (i = 0; i < ARRAY_SIZE(qctrl_tbl); i++) { - if (qctrl_tbl[i].hit) { - struct v4l2_control ctrl = {0,}; - qctrl_tbl[i].hit = 0; - ctrl.id = qctrl_tbl[i].id; - ctrl.value = qctrl_tbl[i].init_val; - if (xioctl(v4l2_fd, VIDIOC_S_CTRL, &ctrl) < 0) { - ERR("Failed to reset control value: id(0x%x), errstr(%s)\n", - ctrl.id, strerror(errno)); - } - } - } -} - -static int32_t value_convert_from_guest(int32_t min, int32_t max, int32_t value) -{ - double rate = 0.0; - int32_t dist = 0, ret = 0; - - dist = max - min; - - if (dist < MARUCAM_CTRL_VALUE_MAX) { - rate = (double)MARUCAM_CTRL_VALUE_MAX / (double)dist; - ret = min + (int32_t)(value / rate); - } else { - rate = (double)dist / (double)MARUCAM_CTRL_VALUE_MAX; - ret = min + (int32_t)(rate * value); - } - return ret; -} - -static int32_t value_convert_to_guest(int32_t min, int32_t max, int32_t value) -{ - double rate = 0.0; - int32_t dist = 0, ret = 0; - - dist = max - min; - - if (dist < MARUCAM_CTRL_VALUE_MAX) { - rate = (double)MARUCAM_CTRL_VALUE_MAX / (double)dist; - ret = (int32_t)((double)(value - min) * rate); - } else { - rate = (double)dist / (double)MARUCAM_CTRL_VALUE_MAX; - ret = (int32_t)((double)(value - min) / rate); - } - - return ret; -} - -static void set_maxframeinterval(MaruCamState *state, uint32_t pixel_format, - uint32_t width, uint32_t height) -{ - struct v4l2_frmivalenum fival; - struct v4l2_streamparm sp; - uint32_t min_num = 0, min_denom = 0; - - CLEAR(fival); - fival.pixel_format = pixel_format; - fival.width = width; - fival.height = height; - - if (xioctl(v4l2_fd, VIDIOC_ENUM_FRAMEINTERVALS, &fival) < 0) { - ERR("Unable to enumerate intervals for pixelformat(0x%x), (%d:%d)\n", - pixel_format, width, height); - return; - } - - if (fival.type == V4L2_FRMIVAL_TYPE_DISCRETE) { - float max_ival = -1.0; - do { - float cur_ival = (float)fival.discrete.numerator - / (float)fival.discrete.denominator; - if (cur_ival > max_ival) { - max_ival = cur_ival; - min_num = fival.discrete.numerator; - min_denom = fival.discrete.denominator; - } - TRACE("Discrete frame interval %u/%u supported\n", - fival.discrete.numerator, fival.discrete.denominator); - fival.index++; - } while (xioctl(v4l2_fd, VIDIOC_ENUM_FRAMEINTERVALS, &fival) >= 0); - } else if ((fival.type == V4L2_FRMIVAL_TYPE_STEPWISE) || - (fival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS)) { - TRACE("Frame intervals from %u/%u to %u/%u supported", - fival.stepwise.min.numerator, fival.stepwise.min.denominator, - fival.stepwise.max.numerator, fival.stepwise.max.denominator); - if (fival.type == V4L2_FRMIVAL_TYPE_STEPWISE) { - TRACE("with %u/%u step", fival.stepwise.step.numerator, - fival.stepwise.step.denominator); - } - if (((float)fival.stepwise.max.denominator / - (float)fival.stepwise.max.numerator) > - ((float)fival.stepwise.min.denominator / - (float)fival.stepwise.min.numerator)) { - min_num = fival.stepwise.max.numerator; - min_denom = fival.stepwise.max.denominator; - } else { - min_num = fival.stepwise.min.numerator; - min_denom = fival.stepwise.min.denominator; - } - } - TRACE("The actual min values: %u/%u\n", min_num, min_denom); - - CLEAR(sp); - sp.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - sp.parm.capture.timeperframe.numerator = min_num; - sp.parm.capture.timeperframe.denominator = min_denom; - - if (xioctl(v4l2_fd, VIDIOC_S_PARM, &sp) < 0) { - ERR("Failed to set to minimum FPS(%u/%u)\n", min_num, min_denom); - } -} - -static uint32_t stop_capturing(void) -{ - enum v4l2_buf_type type; - - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (xioctl(v4l2_fd, VIDIOC_STREAMOFF, &type) < 0) { - ERR("Failed to ioctl() with VIDIOC_STREAMOFF: %s\n", strerror(errno)); - return errno; - } - return 0; -} - -static uint32_t start_capturing(void) -{ - enum v4l2_buf_type type; - - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (xioctl(v4l2_fd, VIDIOC_STREAMON, &type) < 0) { - ERR("Failed to ioctl() with VIDIOC_STREAMON: %s\n", strerror(errno)); - return errno; - } - return 0; -} - -static void free_framebuffers(marucam_framebuffer *fb, int buf_num) -{ - int i; - - if (fb == NULL) { - ERR("The framebuffer is NULL. Failed to release the framebuffer\n"); - return; - } else if (buf_num == 0) { - ERR("The buffer count is 0. Failed to release the framebuffer\n"); - return; - } else { - TRACE("[%s]:fb(0x%p), buf_num(%d)\n", __func__, fb, buf_num); - } - - /* Unmap framebuffers. */ - for (i = 0; i < buf_num; i++) { - if (fb[i].data != NULL) { - v4l2_munmap(fb[i].data, fb[i].size); - fb[i].data = NULL; - fb[i].size = 0; - } else { - ERR("framebuffer[%d].data is NULL.\n", i); - } - } -} - -static uint32_t -mmap_framebuffers(marucam_framebuffer **fb, int *buf_num) -{ - struct v4l2_requestbuffers req; - - CLEAR(req); - req.count = MARUCAM_DEFAULT_BUFFER_COUNT; - req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - req.memory = V4L2_MEMORY_MMAP; - if (xioctl(v4l2_fd, VIDIOC_REQBUFS, &req) < 0) { - if (errno == EINVAL) { - ERR("%s does not support memory mapping: %s\n", - dev_name, strerror(errno)); - } else { - ERR("Failed to request bufs: %s\n", strerror(errno)); - } - return errno; - } - if (req.count == 0) { - ERR("Insufficient buffer memory on %s\n", dev_name); - return EINVAL; - } - - *fb = g_new0(marucam_framebuffer, req.count); - if (*fb == NULL) { - ERR("Not enough memory to allocate framebuffers\n"); - return ENOMEM; - } - - for (*buf_num = 0; *buf_num < req.count; ++*buf_num) { - struct v4l2_buffer buf; - CLEAR(buf); - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; - buf.index = *buf_num; - if (xioctl(v4l2_fd, VIDIOC_QUERYBUF, &buf) < 0) { - ERR("Failed to ioctl() with VIDIOC_QUERYBUF: %s\n", - strerror(errno)); - return errno; - } - - (*fb)[*buf_num].size = buf.length; - (*fb)[*buf_num].data = v4l2_mmap(NULL, - buf.length, - PROT_READ | PROT_WRITE, - MAP_SHARED, - v4l2_fd, buf.m.offset); - if (MAP_FAILED == (*fb)[*buf_num].data) { - ERR("Failed to mmap: %s\n", strerror(errno)); - return errno; - } - - /* Queue the mapped buffer. */ - CLEAR(buf); - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; - buf.index = *buf_num; - if (xioctl(v4l2_fd, VIDIOC_QBUF, &buf) < 0) { - ERR("Failed to ioctl() with VIDIOC_QBUF: %s\n", strerror(errno)); - return errno; - } - } - return 0; -} - -static int is_streamon(MaruCamState *state) -{ - int st; - qemu_mutex_lock(&state->thread_mutex); - st = state->streamon; - qemu_mutex_unlock(&state->thread_mutex); - return (st == _MC_THREAD_STREAMON); -} - -static int is_stream_paused(MaruCamState *state) -{ - int st; - qemu_mutex_lock(&state->thread_mutex); - st = state->streamon; - qemu_mutex_unlock(&state->thread_mutex); - return (st == _MC_THREAD_PAUSED); -} - -static void __raise_err_intr(MaruCamState *state) -{ - qemu_mutex_lock(&state->thread_mutex); - if (state->streamon == _MC_THREAD_STREAMON) { - state->req_frame = 0; /* clear request */ - state->isr = 0x08; /* set a error flag of rasing a interrupt */ - qemu_bh_schedule(state->tx_bh); - } - qemu_mutex_unlock(&state->thread_mutex); -} - -static void -notify_buffer_ready(MaruCamState *state, void *ptr, size_t size) -{ - void *buf = NULL; - - qemu_mutex_lock(&state->thread_mutex); - if (state->streamon == _MC_THREAD_STREAMON) { - if (ready_count < MARUCAM_SKIPFRAMES) { - /* skip a frame cause first some frame are distorted */ - ++ready_count; - TRACE("Skip %d frame\n", ready_count); - qemu_mutex_unlock(&state->thread_mutex); - return; - } - if (state->req_frame == 0) { - TRACE("There is no request\n"); - qemu_mutex_unlock(&state->thread_mutex); - return; - } - buf = state->vaddr + state->buf_size * (state->req_frame - 1); - memcpy(buf, ptr, state->buf_size); - state->req_frame = 0; /* clear request */ - state->isr |= 0x01; /* set a flag of rasing a interrupt */ - qemu_bh_schedule(state->tx_bh); - } - qemu_mutex_unlock(&state->thread_mutex); -} - -static int read_frame(MaruCamState *state) -{ - struct v4l2_buffer buf; - - CLEAR(buf); - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; - if (xioctl(v4l2_fd, VIDIOC_DQBUF, &buf) < 0) { - switch (errno) { - case EAGAIN: - case EINTR: - ERR("DQBUF error, try again: %s\n", strerror(errno)); - return 0; - case EIO: - ERR("The v4l2_read() met the EIO\n"); - if (convert_trial-- == -1) { - ERR("Try count for v4l2_read is exceeded: %s\n", - strerror(errno)); - return -1; - } - return 0; - default: - ERR("DQBUF error: %s\n", strerror(errno)); - return -1; - } - } - - notify_buffer_ready(state, framebuffer[buf.index].data, buf.bytesused); - - if (xioctl(v4l2_fd, VIDIOC_QBUF, &buf) < 0) { - ERR("QBUF error: %s\n", strerror(errno)); - return -1; - } - return 0; -} - -static int __v4l2_streaming(MaruCamState *state) -{ - fd_set fds; - struct timeval tv; - int ret; - static uint32_t timeout_n = 0; - - FD_ZERO(&fds); - FD_SET(v4l2_fd, &fds); - - tv.tv_sec = 1; - tv.tv_usec = 0; - - ret = select(v4l2_fd + 1, &fds, NULL, NULL, &tv); - if (ret < 0) { - if (errno == EAGAIN || errno == EINTR) { - ERR("Select again: %s\n", strerror(errno)); - return 0; - } - ERR("Failed to select: %s\n", strerror(errno)); - __raise_err_intr(state); - return -1; - } else if (!ret) { - timeout_n++; - ERR("Select timed out: count(%u)\n", timeout_n); - if (timeout_n >= 5) { - __raise_err_intr(state); - return -1; - } - return 0; - } - - if (!v4l2_fd || (v4l2_fd == -1)) { - ERR("The file descriptor is closed or not opened\n"); - __raise_err_intr(state); - return -1; - } - - ret = read_frame(state); - if (ret < 0) { - ERR("Failed to operate the read_frame()\n"); - __raise_err_intr(state); - return -1; - } - - /* clear the skip count for select time-out */ - if (timeout_n > 0) { - timeout_n = 0; - } - - return 0; -} - -/* Worker thread */ -static void *marucam_worker_thread(void *thread_param) -{ - MaruCamState *state = (MaruCamState *)thread_param; - - while (1) { - qemu_mutex_lock(&state->thread_mutex); - state->streamon = _MC_THREAD_PAUSED; - qemu_cond_wait(&state->thread_cond, &state->thread_mutex); - qemu_mutex_unlock(&state->thread_mutex); - - if (state->destroying) { - break; - } - - convert_trial = 10; - ready_count = 0; - qemu_mutex_lock(&state->thread_mutex); - state->streamon = _MC_THREAD_STREAMON; - qemu_mutex_unlock(&state->thread_mutex); - INFO("Streaming on ......\n"); - - while (1) { - if (is_streamon(state)) { - if (__v4l2_streaming(state) < 0) { - INFO("...... Streaming off\n"); - break; - } - } else { - INFO("...... Streaming off\n"); - break; - } - } - } - - return NULL; -} - -int marucam_device_check(int log_flag) -{ - int tmp_fd; - struct timeval t1, t2; - struct stat st; - struct v4l2_fmtdesc format; - struct v4l2_frmsizeenum size; - struct v4l2_capability cap; - int ret = 0; - - gettimeofday(&t1, NULL); - if (stat(dev_name, &st) < 0) { - fprintf(stdout, "[Webcam] Cannot identify '%s': %s\n", - dev_name, strerror(errno)); - } else { - if (!S_ISCHR(st.st_mode)) { - fprintf(stdout, "[Webcam] %s is no character device\n", - dev_name); - } - } - - tmp_fd = open(dev_name, O_RDWR | O_NONBLOCK, 0); - if (tmp_fd < 0) { - fprintf(stdout, "[Webcam] Camera device open failed: %s\n", dev_name); - gettimeofday(&t2, NULL); - fprintf(stdout, "[Webcam] Elapsed time: %lu:%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } - if (ioctl(tmp_fd, VIDIOC_QUERYCAP, &cap) < 0) { - fprintf(stdout, "[Webcam] Could not qeury video capabilities\n"); - close(tmp_fd); - gettimeofday(&t2, NULL); - fprintf(stdout, "[Webcam] Elapsed time: %lu:%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } - if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) || - !(cap.capabilities & V4L2_CAP_STREAMING)) { - fprintf(stdout, "[Webcam] Not supported video driver\n"); - close(tmp_fd); - gettimeofday(&t2, NULL); - fprintf(stdout, "[Webcam] Elapsed time: %lu:%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } - ret = 1; - - if (log_flag) { - fprintf(stdout, "[Webcam] Driver: %s\n", cap.driver); - fprintf(stdout, "[Webcam] Card: %s\n", cap.card); - fprintf(stdout, "[Webcam] Bus info: %s\n", cap.bus_info); - - CLEAR(format); - format.index = 0; - format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - if (yioctl(tmp_fd, VIDIOC_ENUM_FMT, &format) < 0) { - close(tmp_fd); - gettimeofday(&t2, NULL); - fprintf(stdout, "[Webcam] Elapsed time: %lu:%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } - - do { - CLEAR(size); - size.index = 0; - size.pixel_format = format.pixelformat; - - fprintf(stdout, "[Webcam] PixelFormat: %c%c%c%c\n", - (char)(format.pixelformat), - (char)(format.pixelformat >> 8), - (char)(format.pixelformat >> 16), - (char)(format.pixelformat >> 24)); - - if (yioctl(tmp_fd, VIDIOC_ENUM_FRAMESIZES, &size) < 0) { - close(tmp_fd); - gettimeofday(&t2, NULL); - fprintf(stdout, "[Webcam] Elapsed time: %lu:%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } - - if (size.type == V4L2_FRMSIZE_TYPE_DISCRETE) { - do { - fprintf(stdout, "[Webcam] got discrete frame size %dx%d\n", - size.discrete.width, size.discrete.height); - size.index++; - } while (yioctl(tmp_fd, VIDIOC_ENUM_FRAMESIZES, &size) >= 0); - } else if (size.type == V4L2_FRMSIZE_TYPE_STEPWISE) { - fprintf(stdout, "[Webcam] we have stepwise frame sizes:\n"); - fprintf(stdout, "[Webcam] min width: %d, min height: %d\n", - size.stepwise.min_width, size.stepwise.min_height); - fprintf(stdout, "[Webcam] max width: %d, max height: %d\n", - size.stepwise.max_width, size.stepwise.max_height); - fprintf(stdout, "[Webcam] step width: %d, step height: %d\n", - size.stepwise.step_width, size.stepwise.step_height); - } else if (size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) { - fprintf(stdout, "[Webcam] we have continuous frame sizes:\n"); - fprintf(stdout, "[Webcam] min width: %d, min height: %d\n", - size.stepwise.min_width, size.stepwise.min_height); - fprintf(stdout, "[Webcam] max width: %d, max height: %d\n", - size.stepwise.max_width, size.stepwise.max_height); - - } - format.index++; - } while (yioctl(tmp_fd, VIDIOC_ENUM_FMT, &format) >= 0); - } - - close(tmp_fd); - gettimeofday(&t2, NULL); - fprintf(stdout, "[Webcam] Elapsed time: %lu:%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; -} - -void marucam_device_init(MaruCamState *state) -{ - state->destroying = false; - qemu_thread_create(&state->thread_id, marucam_worker_thread, (void *)state, - QEMU_THREAD_JOINABLE); -} - -void marucam_device_exit(MaruCamState *state) -{ - state->destroying = true; - qemu_mutex_lock(&state->thread_mutex); - qemu_cond_signal(&state->thread_cond); - qemu_mutex_unlock(&state->thread_mutex); - qemu_thread_join(&state->thread_id); -} - -void marucam_device_open(MaruCamState *state) -{ - MaruCamParam *param = state->param; - - param->top = 0; - v4l2_fd = v4l2_open(dev_name, O_RDWR | O_NONBLOCK, 0); - if (v4l2_fd < 0) { - ERR("The v4l2 device open failed: %s\n", dev_name); - param->errCode = EINVAL; - return; - } - INFO("Opened\n"); - - /* FIXME : Do not use fixed values */ - CLEAR(dst_fmt); - dst_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - dst_fmt.fmt.pix.width = 640; - dst_fmt.fmt.pix.height = 480; - dst_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; - dst_fmt.fmt.pix.field = V4L2_FIELD_ANY; - - if (xioctl(v4l2_fd, VIDIOC_S_FMT, &dst_fmt) < 0) { - ERR("Failed to set video format: format(0x%x), width:height(%d:%d), " - "errstr(%s)\n", dst_fmt.fmt.pix.pixelformat, dst_fmt.fmt.pix.width, - dst_fmt.fmt.pix.height, strerror(errno)); - param->errCode = errno; - return; - } - TRACE("Set the default format: w:h(%dx%d), fmt(0x%x), size(%d), " - "color(%d), field(%d)\n", - dst_fmt.fmt.pix.width, dst_fmt.fmt.pix.height, - dst_fmt.fmt.pix.pixelformat, dst_fmt.fmt.pix.sizeimage, - dst_fmt.fmt.pix.colorspace, dst_fmt.fmt.pix.field); -} - -void marucam_device_start_preview(MaruCamState *state) -{ - struct timespec req; - MaruCamParam *param = state->param; - param->top = 0; - req.tv_sec = 0; - req.tv_nsec = 10000000; - - INFO("Pixfmt(%c%c%c%C), W:H(%d:%d), buf size(%u)\n", - (char)(dst_fmt.fmt.pix.pixelformat), - (char)(dst_fmt.fmt.pix.pixelformat >> 8), - (char)(dst_fmt.fmt.pix.pixelformat >> 16), - (char)(dst_fmt.fmt.pix.pixelformat >> 24), - dst_fmt.fmt.pix.width, - dst_fmt.fmt.pix.height, - dst_fmt.fmt.pix.sizeimage); - - param->errCode = mmap_framebuffers(&framebuffer, &n_framebuffer); - if (param->errCode) { - ERR("Failed to mmap framebuffers\n"); - if (framebuffer != NULL) { - free_framebuffers(framebuffer, n_framebuffer); - g_free(framebuffer); - framebuffer = NULL; - n_framebuffer = 0; - } - return; - } - - param->errCode = start_capturing(); - if (param->errCode) { - if (framebuffer != NULL) { - free_framebuffers(framebuffer, n_framebuffer); - g_free(framebuffer); - framebuffer = NULL; - n_framebuffer = 0; - } - return; - } - - INFO("Starting preview\n"); - state->buf_size = dst_fmt.fmt.pix.sizeimage; - qemu_mutex_lock(&state->thread_mutex); - qemu_cond_signal(&state->thread_cond); - qemu_mutex_unlock(&state->thread_mutex); - - /* nanosleep until thread is streamon */ - while (!is_streamon(state)) { - nanosleep(&req, NULL); - } -} - -void marucam_device_stop_preview(MaruCamState *state) -{ - struct timespec req; - struct v4l2_requestbuffers reqbuf; - MaruCamParam *param = state->param; - param->top = 0; - req.tv_sec = 0; - req.tv_nsec = 50000000; - - if (is_streamon(state)) { - qemu_mutex_lock(&state->thread_mutex); - state->streamon = _MC_THREAD_STREAMOFF; - qemu_mutex_unlock(&state->thread_mutex); - - /* nanosleep until thread is paused */ - while (!is_stream_paused(state)) { - nanosleep(&req, NULL); - } - } - - param->errCode = stop_capturing(); - if (framebuffer != NULL) { - free_framebuffers(framebuffer, n_framebuffer); - g_free(framebuffer); - framebuffer = NULL; - n_framebuffer = 0; - } - state->buf_size = 0; - - reqbuf.count = 0; - reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - reqbuf.memory = V4L2_MEMORY_MMAP; - if (xioctl(v4l2_fd, VIDIOC_REQBUFS, &reqbuf) < 0) { - ERR("Failed to ioctl() with VIDIOC_REQBUF in stop_preview: %s\n", - strerror(errno)); - } - INFO("Stopping preview\n"); -} - -void marucam_device_s_param(MaruCamState *state) -{ - MaruCamParam *param = state->param; - - param->top = 0; - - /* If KVM enabled, We use default FPS of the webcam. - * If KVM disabled, we use mininum FPS of the webcam */ - if (!kvm_enabled()) { - set_maxframeinterval(state, dst_fmt.fmt.pix.pixelformat, - dst_fmt.fmt.pix.width, - dst_fmt.fmt.pix.height); - } -} - -void marucam_device_g_param(MaruCamState *state) -{ - MaruCamParam *param = state->param; - - /* We use default FPS of the webcam - * return a fixed value on guest ini file (1/30). - */ - param->top = 0; - param->stack[0] = 0x1000; /* V4L2_CAP_TIMEPERFRAME */ - param->stack[1] = 1; /* numerator */ - param->stack[2] = 30; /* denominator */ -} - -void marucam_device_s_fmt(MaruCamState *state) -{ - struct v4l2_format format; - MaruCamParam *param = state->param; - - param->top = 0; - CLEAR(format); - format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - format.fmt.pix.width = param->stack[0]; - format.fmt.pix.height = param->stack[1]; - format.fmt.pix.pixelformat = param->stack[2]; - format.fmt.pix.field = V4L2_FIELD_ANY; - - if (xioctl(v4l2_fd, VIDIOC_S_FMT, &format) < 0) { - ERR("Failed to set video format: format(0x%x), width:height(%d:%d), " - "errstr(%s)\n", format.fmt.pix.pixelformat, format.fmt.pix.width, - format.fmt.pix.height, strerror(errno)); - param->errCode = errno; - return; - } - - memcpy(&dst_fmt, &format, sizeof(format)); - param->stack[0] = dst_fmt.fmt.pix.width; - param->stack[1] = dst_fmt.fmt.pix.height; - param->stack[2] = dst_fmt.fmt.pix.field; - param->stack[3] = dst_fmt.fmt.pix.pixelformat; - param->stack[4] = dst_fmt.fmt.pix.bytesperline; - param->stack[5] = dst_fmt.fmt.pix.sizeimage; - param->stack[6] = dst_fmt.fmt.pix.colorspace; - param->stack[7] = dst_fmt.fmt.pix.priv; - TRACE("Set the format: w:h(%dx%d), fmt(0x%x), size(%d), " - "color(%d), field(%d)\n", - dst_fmt.fmt.pix.width, dst_fmt.fmt.pix.height, - dst_fmt.fmt.pix.pixelformat, dst_fmt.fmt.pix.sizeimage, - dst_fmt.fmt.pix.colorspace, dst_fmt.fmt.pix.field); -} - -void marucam_device_g_fmt(MaruCamState *state) -{ - struct v4l2_format format; - MaruCamParam *param = state->param; - - param->top = 0; - CLEAR(format); - format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - if (xioctl(v4l2_fd, VIDIOC_G_FMT, &format) < 0) { - ERR("Failed to get video format: %s\n", strerror(errno)); - param->errCode = errno; - } else { - param->stack[0] = format.fmt.pix.width; - param->stack[1] = format.fmt.pix.height; - param->stack[2] = format.fmt.pix.field; - param->stack[3] = format.fmt.pix.pixelformat; - param->stack[4] = format.fmt.pix.bytesperline; - param->stack[5] = format.fmt.pix.sizeimage; - param->stack[6] = format.fmt.pix.colorspace; - param->stack[7] = format.fmt.pix.priv; - TRACE("Get the format: w:h(%dx%d), fmt(0x%x), size(%d), " - "color(%d), field(%d)\n", - format.fmt.pix.width, format.fmt.pix.height, - format.fmt.pix.pixelformat, format.fmt.pix.sizeimage, - format.fmt.pix.colorspace, format.fmt.pix.field); - } -} - -void marucam_device_try_fmt(MaruCamState *state) -{ - struct v4l2_format format; - MaruCamParam *param = state->param; - - param->top = 0; - CLEAR(format); - format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - format.fmt.pix.width = param->stack[0]; - format.fmt.pix.height = param->stack[1]; - format.fmt.pix.pixelformat = param->stack[2]; - format.fmt.pix.field = V4L2_FIELD_ANY; - - if (xioctl(v4l2_fd, VIDIOC_TRY_FMT, &format) < 0) { - ERR("Failed to check video format: format(0x%x), width:height(%d:%d)," - " errstr(%s)\n", format.fmt.pix.pixelformat, format.fmt.pix.width, - format.fmt.pix.height, strerror(errno)); - param->errCode = errno; - return; - } - param->stack[0] = format.fmt.pix.width; - param->stack[1] = format.fmt.pix.height; - param->stack[2] = format.fmt.pix.field; - param->stack[3] = format.fmt.pix.pixelformat; - param->stack[4] = format.fmt.pix.bytesperline; - param->stack[5] = format.fmt.pix.sizeimage; - param->stack[6] = format.fmt.pix.colorspace; - param->stack[7] = format.fmt.pix.priv; - TRACE("Check the format: w:h(%dx%d), fmt(0x%x), size(%d), " - "color(%d), field(%d)\n", - format.fmt.pix.width, format.fmt.pix.height, - format.fmt.pix.pixelformat, format.fmt.pix.sizeimage, - format.fmt.pix.colorspace, format.fmt.pix.field); -} - -void marucam_device_enum_fmt(MaruCamState *state) -{ - uint32_t index; - MaruCamParam *param = state->param; - - param->top = 0; - index = param->stack[0]; - - if (index >= ARRAY_SIZE(supported_dst_pixfmts)) { - param->errCode = EINVAL; - return; - } - param->stack[1] = 0; /* flags = NONE */ - param->stack[2] = supported_dst_pixfmts[index].fmt; /* pixelformat */ - /* set description */ - switch (supported_dst_pixfmts[index].fmt) { - case V4L2_PIX_FMT_YUYV: - memcpy(¶m->stack[3], "YUYV", 32); - break; - case V4L2_PIX_FMT_YUV420: - memcpy(¶m->stack[3], "YU12", 32); - break; - case V4L2_PIX_FMT_YVU420: - memcpy(¶m->stack[3], "YV12", 32); - break; - default: - ERR("Invalid fixel format\n"); - param->errCode = EINVAL; - break; - } -} - -void marucam_device_qctrl(MaruCamState *state) -{ - uint32_t i; - char name[32] = {0,}; - struct v4l2_queryctrl ctrl; - MaruCamParam *param = state->param; - - param->top = 0; - CLEAR(ctrl); - ctrl.id = param->stack[0]; - - switch (ctrl.id) { - case V4L2_CID_BRIGHTNESS: - TRACE("Query : BRIGHTNESS\n"); - memcpy((void *)name, (void *)"brightness", 32); - i = 0; - break; - case V4L2_CID_CONTRAST: - TRACE("Query : CONTRAST\n"); - memcpy((void *)name, (void *)"contrast", 32); - i = 1; - break; - case V4L2_CID_SATURATION: - TRACE("Query : SATURATION\n"); - memcpy((void *)name, (void *)"saturation", 32); - i = 2; - break; - case V4L2_CID_SHARPNESS: - TRACE("Query : SHARPNESS\n"); - memcpy((void *)name, (void *)"sharpness", 32); - i = 3; - break; - default: - ERR("Invalid control ID\n"); - param->errCode = EINVAL; - return; - } - - if (xioctl(v4l2_fd, VIDIOC_QUERYCTRL, &ctrl) < 0) { - if (errno != EINVAL) { - ERR("Failed to query video controls: %s\n", strerror(errno)); - } - param->errCode = errno; - return; - } else { - struct v4l2_control sctrl; - CLEAR(sctrl); - sctrl.id = ctrl.id; - if ((ctrl.maximum + ctrl.minimum) == 0) { - sctrl.value = 0; - } else { - sctrl.value = (ctrl.maximum + ctrl.minimum) / 2; - } - if (xioctl(v4l2_fd, VIDIOC_S_CTRL, &sctrl) < 0) { - ERR("Failed to set control value: id(0x%x), value(%d), " - "errstr(%s)\n", sctrl.id, sctrl.value, strerror(errno)); - param->errCode = errno; - return; - } - qctrl_tbl[i].hit = 1; - qctrl_tbl[i].min = ctrl.minimum; - qctrl_tbl[i].max = ctrl.maximum; - qctrl_tbl[i].step = ctrl.step; - qctrl_tbl[i].init_val = ctrl.default_value; - } - - /* set fixed values by FW configuration file */ - param->stack[0] = ctrl.id; - param->stack[1] = MARUCAM_CTRL_VALUE_MIN; /* minimum */ - param->stack[2] = MARUCAM_CTRL_VALUE_MAX; /* maximum */ - param->stack[3] = MARUCAM_CTRL_VALUE_STEP; /* step */ - param->stack[4] = MARUCAM_CTRL_VALUE_MID; /* default_value */ - param->stack[5] = ctrl.flags; - /* name field setting */ - memcpy(¶m->stack[6], (void *)name, sizeof(ctrl.name)); -} - -void marucam_device_s_ctrl(MaruCamState *state) -{ - uint32_t i; - struct v4l2_control ctrl; - MaruCamParam *param = state->param; - - param->top = 0; - CLEAR(ctrl); - ctrl.id = param->stack[0]; - - switch (ctrl.id) { - case V4L2_CID_BRIGHTNESS: - i = 0; - TRACE("%d is set to the value of the BRIGHTNESS\n", param->stack[1]); - break; - case V4L2_CID_CONTRAST: - i = 1; - TRACE("%d is set to the value of the CONTRAST\n", param->stack[1]); - break; - case V4L2_CID_SATURATION: - i = 2; - TRACE("%d is set to the value of the SATURATION\n", param->stack[1]); - break; - case V4L2_CID_SHARPNESS: - i = 3; - TRACE("%d is set to the value of the SHARPNESS\n", param->stack[1]); - break; - default: - ERR("Our emulator does not support this control: 0x%x\n", ctrl.id); - param->errCode = EINVAL; - return; - } - - ctrl.value = value_convert_from_guest(qctrl_tbl[i].min, - qctrl_tbl[i].max, param->stack[1]); - if (xioctl(v4l2_fd, VIDIOC_S_CTRL, &ctrl) < 0) { - ERR("Failed to set control value: id(0x%x), value(r:%d, c:%d), " - "errstr(%s)\n", ctrl.id, param->stack[1], ctrl.value, - strerror(errno)); - param->errCode = errno; - return; - } -} - -void marucam_device_g_ctrl(MaruCamState *state) -{ - uint32_t i; - struct v4l2_control ctrl; - MaruCamParam *param = state->param; - - param->top = 0; - CLEAR(ctrl); - ctrl.id = param->stack[0]; - - switch (ctrl.id) { - case V4L2_CID_BRIGHTNESS: - TRACE("Gets the value of the BRIGHTNESS\n"); - i = 0; - break; - case V4L2_CID_CONTRAST: - TRACE("Gets the value of the CONTRAST\n"); - i = 1; - break; - case V4L2_CID_SATURATION: - TRACE("Gets the value of the SATURATION\n"); - i = 2; - break; - case V4L2_CID_SHARPNESS: - TRACE("Gets the value of the SHARPNESS\n"); - i = 3; - break; - default: - ERR("Our emulator does not support this control: 0x%x\n", ctrl.id); - param->errCode = EINVAL; - return; - } - - if (xioctl(v4l2_fd, VIDIOC_G_CTRL, &ctrl) < 0) { - ERR("Failed to get video control value: %s\n", strerror(errno)); - param->errCode = errno; - return; - } - param->stack[0] = value_convert_to_guest(qctrl_tbl[i].min, - qctrl_tbl[i].max, ctrl.value); - TRACE("Value: %d\n", param->stack[0]); -} - -void marucam_device_enum_fsizes(MaruCamState *state) -{ - uint32_t index, pixfmt, i; - MaruCamParam *param = state->param; - - param->top = 0; - index = param->stack[0]; - pixfmt = param->stack[1]; - - if (index >= ARRAY_SIZE(supported_dst_frames)) { - param->errCode = EINVAL; - return; - } - for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) { - if (supported_dst_pixfmts[i].fmt == pixfmt) { - break; - } - } - - if (i == ARRAY_SIZE(supported_dst_pixfmts)) { - param->errCode = EINVAL; - return; - } - - param->stack[0] = supported_dst_frames[index].width; - param->stack[1] = supported_dst_frames[index].height; -} - -void marucam_device_enum_fintv(MaruCamState *state) -{ - MaruCamParam *param = state->param; - - param->top = 0; - - /* switch by index(param->stack[0]) */ - switch (param->stack[0]) { - case 0: - /* we only use 1/30 frame interval */ - param->stack[1] = 30; /* denominator */ - break; - default: - param->errCode = EINVAL; - return; - } - param->stack[0] = 1; /* numerator */ -} - -void marucam_device_close(MaruCamState *state) -{ - if (!is_stream_paused(state)) { - marucam_device_stop_preview(state); - } - - marucam_reset_controls(); - - v4l2_close(v4l2_fd); - v4l2_fd = 0; - INFO("Closed\n"); -} +/* + * Implementation of MARU Virtual Camera device by PCI bus on Linux. + * + * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * JinHyung Jo + * YeongKyoon Lee + * + * 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 + * + */ + +#include "qemu-common.h" +#include "maru_camera_common.h" +#include "pci.h" +#include "kvm.h" +#include "tizen/src/debug_ch.h" + +#include + +#include +#include +#include + +#include +#include + +MULTI_DEBUG_CHANNEL(tizen, camera_linux); + +#define CLEAR(x) memset(&(x), 0, sizeof(x)) + +#define MARUCAM_DEFAULT_BUFFER_COUNT 4 +#define MARUCAM_DUMMYFRAME_COUNT 2 + +#define MARUCAM_CTRL_VALUE_MAX 20 +#define MARUCAM_CTRL_VALUE_MIN 1 +#define MARUCAM_CTRL_VALUE_MID 10 +#define MARUCAM_CTRL_VALUE_STEP 1 + +enum { + _MC_THREAD_PAUSED, + _MC_THREAD_STREAMON, + _MC_THREAD_STREAMOFF, +}; + +typedef struct marucam_framebuffer { + void *data; + size_t size; +} marucam_framebuffer; + +static int n_framebuffer; +static struct marucam_framebuffer *framebuffer; + +static const char *dev_name = "/dev/video0"; +static int v4l2_fd; +static int convert_trial; +static int ready_count; +static int timeout_n; + +static struct v4l2_format dst_fmt; + +static void make_yu12_black(unsigned char *dest, uint32_t width, uint32_t height) +{ + uint32_t x, y; + unsigned char *udest, *vdest; + + /* Y */ + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + *dest++ = 16; + } + } + + /* U + V */ + udest = dest; + vdest = dest + width * height / 4; + + for (y = 0; y < height / 2; y++) { + for (x = 0; x < width / 2; x++) { + *udest++ = *vdest++ = 128; + } + } +} + +static int yioctl(int fd, int req, void *arg) +{ + int r; + + do { + r = ioctl(fd, req, arg); + } while (r < 0 && errno == EINTR); + + return r; +} + +static int xioctl(int fd, int req, void *arg) +{ + int r; + + do { + r = v4l2_ioctl(fd, req, arg); + } while (r < 0 && errno == EINTR); + + return r; +} + +typedef struct tagMaruCamConvertPixfmt { + uint32_t fmt; /* fourcc */ +} MaruCamConvertPixfmt; + +static MaruCamConvertPixfmt supported_dst_pixfmts[] = { + { V4L2_PIX_FMT_YUYV }, + { V4L2_PIX_FMT_YUV420 }, + { V4L2_PIX_FMT_YVU420 }, +}; + +typedef struct tagMaruCamConvertFrameInfo { + uint32_t width; + uint32_t height; +} MaruCamConvertFrameInfo; + +static MaruCamConvertFrameInfo supported_dst_frames[] = { + { 640, 480 }, + { 352, 288 }, + { 320, 240 }, + { 176, 144 }, + { 160, 120 }, +}; + +struct marucam_qctrl { + uint32_t id; + uint32_t hit; + int32_t min; + int32_t max; + int32_t step; + int32_t init_val; +}; + +static struct marucam_qctrl qctrl_tbl[] = { + { V4L2_CID_BRIGHTNESS, 0, }, + { V4L2_CID_CONTRAST, 0, }, + { V4L2_CID_SATURATION, 0, }, + { V4L2_CID_SHARPNESS, 0, }, +}; + +static void marucam_reset_controls(void) +{ + uint32_t i; + for (i = 0; i < ARRAY_SIZE(qctrl_tbl); i++) { + if (qctrl_tbl[i].hit) { + struct v4l2_control ctrl = {0,}; + qctrl_tbl[i].hit = 0; + ctrl.id = qctrl_tbl[i].id; + ctrl.value = qctrl_tbl[i].init_val; + if (xioctl(v4l2_fd, VIDIOC_S_CTRL, &ctrl) < 0) { + ERR("Failed to reset control value: id(0x%x), errstr(%s)\n", + ctrl.id, strerror(errno)); + } + } + } +} + +static int32_t value_convert_from_guest(int32_t min, int32_t max, int32_t value) +{ + double rate = 0.0; + int32_t dist = 0, ret = 0; + + dist = max - min; + + if (dist < MARUCAM_CTRL_VALUE_MAX) { + rate = (double)MARUCAM_CTRL_VALUE_MAX / (double)dist; + ret = min + (int32_t)(value / rate); + } else { + rate = (double)dist / (double)MARUCAM_CTRL_VALUE_MAX; + ret = min + (int32_t)(rate * value); + } + return ret; +} + +static int32_t value_convert_to_guest(int32_t min, int32_t max, int32_t value) +{ + double rate = 0.0; + int32_t dist = 0, ret = 0; + + dist = max - min; + + if (dist < MARUCAM_CTRL_VALUE_MAX) { + rate = (double)MARUCAM_CTRL_VALUE_MAX / (double)dist; + ret = (int32_t)((double)(value - min) * rate); + } else { + rate = (double)dist / (double)MARUCAM_CTRL_VALUE_MAX; + ret = (int32_t)((double)(value - min) / rate); + } + + return ret; +} + +static void set_maxframeinterval(MaruCamState *state, uint32_t pixel_format, + uint32_t width, uint32_t height) +{ + struct v4l2_frmivalenum fival; + struct v4l2_streamparm sp; + uint32_t min_num = 0, min_denom = 0; + + CLEAR(fival); + fival.pixel_format = pixel_format; + fival.width = width; + fival.height = height; + + if (xioctl(v4l2_fd, VIDIOC_ENUM_FRAMEINTERVALS, &fival) < 0) { + ERR("Unable to enumerate intervals for pixelformat(0x%x), (%d:%d)\n", + pixel_format, width, height); + return; + } + + if (fival.type == V4L2_FRMIVAL_TYPE_DISCRETE) { + float max_ival = -1.0; + do { + float cur_ival = (float)fival.discrete.numerator + / (float)fival.discrete.denominator; + if (cur_ival > max_ival) { + max_ival = cur_ival; + min_num = fival.discrete.numerator; + min_denom = fival.discrete.denominator; + } + TRACE("Discrete frame interval %u/%u supported\n", + fival.discrete.numerator, fival.discrete.denominator); + fival.index++; + } while (xioctl(v4l2_fd, VIDIOC_ENUM_FRAMEINTERVALS, &fival) >= 0); + } else if ((fival.type == V4L2_FRMIVAL_TYPE_STEPWISE) || + (fival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS)) { + TRACE("Frame intervals from %u/%u to %u/%u supported", + fival.stepwise.min.numerator, fival.stepwise.min.denominator, + fival.stepwise.max.numerator, fival.stepwise.max.denominator); + if (fival.type == V4L2_FRMIVAL_TYPE_STEPWISE) { + TRACE("with %u/%u step", fival.stepwise.step.numerator, + fival.stepwise.step.denominator); + } + if (((float)fival.stepwise.max.denominator / + (float)fival.stepwise.max.numerator) > + ((float)fival.stepwise.min.denominator / + (float)fival.stepwise.min.numerator)) { + min_num = fival.stepwise.max.numerator; + min_denom = fival.stepwise.max.denominator; + } else { + min_num = fival.stepwise.min.numerator; + min_denom = fival.stepwise.min.denominator; + } + } + TRACE("The actual min values: %u/%u\n", min_num, min_denom); + + CLEAR(sp); + sp.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + sp.parm.capture.timeperframe.numerator = min_num; + sp.parm.capture.timeperframe.denominator = min_denom; + + if (xioctl(v4l2_fd, VIDIOC_S_PARM, &sp) < 0) { + ERR("Failed to set to minimum FPS(%u/%u)\n", min_num, min_denom); + } +} + +static uint32_t stop_capturing(void) +{ + enum v4l2_buf_type type; + + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (xioctl(v4l2_fd, VIDIOC_STREAMOFF, &type) < 0) { + ERR("Failed to ioctl() with VIDIOC_STREAMOFF: %s\n", strerror(errno)); + return errno; + } + return 0; +} + +static uint32_t start_capturing(void) +{ + enum v4l2_buf_type type; + + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (xioctl(v4l2_fd, VIDIOC_STREAMON, &type) < 0) { + ERR("Failed to ioctl() with VIDIOC_STREAMON: %s\n", strerror(errno)); + return errno; + } + return 0; +} + +static void free_framebuffers(marucam_framebuffer *fb, int buf_num) +{ + int i; + + if (fb == NULL) { + ERR("The framebuffer is NULL. Failed to release the framebuffer\n"); + return; + } else if (buf_num == 0) { + ERR("The buffer count is 0. Failed to release the framebuffer\n"); + return; + } else { + TRACE("[%s]:fb(0x%p), buf_num(%d)\n", __func__, fb, buf_num); + } + + /* Unmap framebuffers. */ + for (i = 0; i < buf_num; i++) { + if (fb[i].data != NULL) { + v4l2_munmap(fb[i].data, fb[i].size); + fb[i].data = NULL; + fb[i].size = 0; + } else { + ERR("framebuffer[%d].data is NULL.\n", i); + } + } +} + +static uint32_t +mmap_framebuffers(marucam_framebuffer **fb, int *buf_num) +{ + struct v4l2_requestbuffers req; + + CLEAR(req); + req.count = MARUCAM_DEFAULT_BUFFER_COUNT; + req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + req.memory = V4L2_MEMORY_MMAP; + if (xioctl(v4l2_fd, VIDIOC_REQBUFS, &req) < 0) { + if (errno == EINVAL) { + ERR("%s does not support memory mapping: %s\n", + dev_name, strerror(errno)); + } else { + ERR("Failed to request bufs: %s\n", strerror(errno)); + } + return errno; + } + if (req.count == 0) { + ERR("Insufficient buffer memory on %s\n", dev_name); + return EINVAL; + } + + *fb = g_new0(marucam_framebuffer, req.count); + if (*fb == NULL) { + ERR("Not enough memory to allocate framebuffers\n"); + return ENOMEM; + } + + for (*buf_num = 0; *buf_num < req.count; ++*buf_num) { + struct v4l2_buffer buf; + CLEAR(buf); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = *buf_num; + if (xioctl(v4l2_fd, VIDIOC_QUERYBUF, &buf) < 0) { + ERR("Failed to ioctl() with VIDIOC_QUERYBUF: %s\n", + strerror(errno)); + return errno; + } + + (*fb)[*buf_num].size = buf.length; + (*fb)[*buf_num].data = v4l2_mmap(NULL, + buf.length, + PROT_READ | PROT_WRITE, + MAP_SHARED, + v4l2_fd, buf.m.offset); + if (MAP_FAILED == (*fb)[*buf_num].data) { + ERR("Failed to mmap: %s\n", strerror(errno)); + return errno; + } + + /* Queue the mapped buffer. */ + CLEAR(buf); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = *buf_num; + if (xioctl(v4l2_fd, VIDIOC_QBUF, &buf) < 0) { + ERR("Failed to ioctl() with VIDIOC_QBUF: %s\n", strerror(errno)); + return errno; + } + } + return 0; +} + +static int is_streamon(MaruCamState *state) +{ + int st; + qemu_mutex_lock(&state->thread_mutex); + st = state->streamon; + qemu_mutex_unlock(&state->thread_mutex); + return (st == _MC_THREAD_STREAMON); +} + +static int is_stream_paused(MaruCamState *state) +{ + int st; + qemu_mutex_lock(&state->thread_mutex); + st = state->streamon; + qemu_mutex_unlock(&state->thread_mutex); + return (st == _MC_THREAD_PAUSED); +} + +/* sends a frame, YU12/black color */ +static void __raise_empty_intr(MaruCamState *state) +{ + void *buf = NULL; + qemu_mutex_lock(&state->thread_mutex); + if (state->streamon == _MC_THREAD_STREAMON && state->req_frame) { + buf = state->vaddr + state->buf_size * (state->req_frame - 1); + make_yu12_black(buf, dst_fmt.fmt.pix.width, dst_fmt.fmt.pix.height); + state->req_frame = 0; /* clear request */ + state->isr = 0x01; /* set a flag of raising a interrupt */ + qemu_bh_schedule(state->tx_bh); + } + qemu_mutex_unlock(&state->thread_mutex); +} + +static void __raise_err_intr(MaruCamState *state) +{ + qemu_mutex_lock(&state->thread_mutex); + if (state->streamon == _MC_THREAD_STREAMON) { + state->req_frame = 0; /* clear request */ + state->isr = 0x08; /* set a error flag of raising a interrupt */ + qemu_bh_schedule(state->tx_bh); + } + qemu_mutex_unlock(&state->thread_mutex); +} + +static void +notify_buffer_ready(MaruCamState *state, void *ptr, size_t size) +{ + void *buf = NULL; + + qemu_mutex_lock(&state->thread_mutex); + if (state->streamon == _MC_THREAD_STREAMON) { + if (ready_count < MARUCAM_SKIPFRAMES) { + /* skip a frame cause first some frame are distorted */ + ++ready_count; + TRACE("Skip %d frame\n", ready_count); + qemu_mutex_unlock(&state->thread_mutex); + return; + } + if (state->req_frame == 0) { + TRACE("There is no request\n"); + qemu_mutex_unlock(&state->thread_mutex); + return; + } + buf = state->vaddr + state->buf_size * (state->req_frame - 1); + memcpy(buf, ptr, state->buf_size); + state->req_frame = 0; /* clear request */ + state->isr |= 0x01; /* set a flag of rasing a interrupt */ + qemu_bh_schedule(state->tx_bh); + } + qemu_mutex_unlock(&state->thread_mutex); +} + +static int read_frame(MaruCamState *state) +{ + struct v4l2_buffer buf; + + CLEAR(buf); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + if (xioctl(v4l2_fd, VIDIOC_DQBUF, &buf) < 0) { + switch (errno) { + case EAGAIN: + case EINTR: + ERR("DQBUF error, try again: %s\n", strerror(errno)); + return 0; + case EIO: + ERR("The v4l2_read() met the EIO\n"); + if (convert_trial-- == -1) { + ERR("Try count for v4l2_read is exceeded: %s\n", + strerror(errno)); + return -1; + } + return 0; + default: + ERR("DQBUF error: %s\n", strerror(errno)); + return -1; + } + } + + notify_buffer_ready(state, framebuffer[buf.index].data, buf.bytesused); + + if (xioctl(v4l2_fd, VIDIOC_QBUF, &buf) < 0) { + ERR("QBUF error: %s\n", strerror(errno)); + return -1; + } + return 0; +} + +static int __v4l2_streaming(MaruCamState *state) +{ + fd_set fds; + struct timeval tv; + int ret; + + FD_ZERO(&fds); + FD_SET(v4l2_fd, &fds); + + tv.tv_sec = 1; + tv.tv_usec = 0; + + ret = select(v4l2_fd + 1, &fds, NULL, NULL, &tv); + if (ret < 0) { + if (errno == EAGAIN || errno == EINTR) { + ERR("Select again: %s\n", strerror(errno)); + return 0; + } + ERR("Failed to select: %s\n", strerror(errno)); + __raise_err_intr(state); + return -1; + } else if (!ret) { + timeout_n++; + ERR("Select timed out: count(%u)\n", timeout_n); + if (ready_count == 0) { + if (timeout_n <= MARUCAM_DUMMYFRAME_COUNT) { + ERR("Sends dummy data to initialize the camera\n"); + __raise_empty_intr(state); + return 0; + } else { + ERR("Webcam is busy, failed to a read frame." + " Raises an error\n"); + __raise_err_intr(state); + return -1; + } + } + if (timeout_n >= 5) { + ERR("Webcam is busy, failed to a read frame. Raises an error\n"); + __raise_err_intr(state); + return -1; + } + return 0; + } + + if (!v4l2_fd || (v4l2_fd == -1)) { + ERR("The file descriptor is closed or not opened\n"); + __raise_err_intr(state); + return -1; + } + + ret = read_frame(state); + if (ret < 0) { + ERR("Failed to operate the read_frame()\n"); + __raise_err_intr(state); + return -1; + } + + /* clear the skip count for select time-out */ + if (timeout_n > 0) { + timeout_n = 0; + } + + return 0; +} + +/* Worker thread */ +static void *marucam_worker_thread(void *thread_param) +{ + MaruCamState *state = (MaruCamState *)thread_param; + + while (1) { + qemu_mutex_lock(&state->thread_mutex); + state->streamon = _MC_THREAD_PAUSED; + qemu_cond_wait(&state->thread_cond, &state->thread_mutex); + qemu_mutex_unlock(&state->thread_mutex); + + if (state->destroying) { + break; + } + + convert_trial = 10; + ready_count = 0; + timeout_n = 0; + qemu_mutex_lock(&state->thread_mutex); + state->streamon = _MC_THREAD_STREAMON; + qemu_mutex_unlock(&state->thread_mutex); + INFO("Streaming on ......\n"); + + while (1) { + if (is_streamon(state)) { + if (__v4l2_streaming(state) < 0) { + INFO("...... Streaming off\n"); + break; + } + } else { + INFO("...... Streaming off\n"); + break; + } + } + } + + return NULL; +} + +int marucam_device_check(int log_flag) +{ + int tmp_fd; + struct timeval t1, t2; + struct stat st; + struct v4l2_fmtdesc format; + struct v4l2_frmsizeenum size; + struct v4l2_capability cap; + int ret = 0; + + gettimeofday(&t1, NULL); + if (stat(dev_name, &st) < 0) { + fprintf(stdout, "[Webcam] Cannot identify '%s': %s\n", + dev_name, strerror(errno)); + } else { + if (!S_ISCHR(st.st_mode)) { + fprintf(stdout, "[Webcam] %s is no character device\n", + dev_name); + } + } + + tmp_fd = open(dev_name, O_RDWR | O_NONBLOCK, 0); + if (tmp_fd < 0) { + fprintf(stdout, "[Webcam] Camera device open failed: %s\n", dev_name); + gettimeofday(&t2, NULL); + fprintf(stdout, "[Webcam] Elapsed time: %lu:%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } + if (ioctl(tmp_fd, VIDIOC_QUERYCAP, &cap) < 0) { + fprintf(stdout, "[Webcam] Could not qeury video capabilities\n"); + close(tmp_fd); + gettimeofday(&t2, NULL); + fprintf(stdout, "[Webcam] Elapsed time: %lu:%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } + if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) || + !(cap.capabilities & V4L2_CAP_STREAMING)) { + fprintf(stdout, "[Webcam] Not supported video driver\n"); + close(tmp_fd); + gettimeofday(&t2, NULL); + fprintf(stdout, "[Webcam] Elapsed time: %lu:%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } + ret = 1; + + if (log_flag) { + fprintf(stdout, "[Webcam] Driver: %s\n", cap.driver); + fprintf(stdout, "[Webcam] Card: %s\n", cap.card); + fprintf(stdout, "[Webcam] Bus info: %s\n", cap.bus_info); + + CLEAR(format); + format.index = 0; + format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + if (yioctl(tmp_fd, VIDIOC_ENUM_FMT, &format) < 0) { + close(tmp_fd); + gettimeofday(&t2, NULL); + fprintf(stdout, "[Webcam] Elapsed time: %lu:%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } + + do { + CLEAR(size); + size.index = 0; + size.pixel_format = format.pixelformat; + + fprintf(stdout, "[Webcam] PixelFormat: %c%c%c%c\n", + (char)(format.pixelformat), + (char)(format.pixelformat >> 8), + (char)(format.pixelformat >> 16), + (char)(format.pixelformat >> 24)); + + if (yioctl(tmp_fd, VIDIOC_ENUM_FRAMESIZES, &size) < 0) { + close(tmp_fd); + gettimeofday(&t2, NULL); + fprintf(stdout, "[Webcam] Elapsed time: %lu:%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } + + if (size.type == V4L2_FRMSIZE_TYPE_DISCRETE) { + do { + fprintf(stdout, "[Webcam] got discrete frame size %dx%d\n", + size.discrete.width, size.discrete.height); + size.index++; + } while (yioctl(tmp_fd, VIDIOC_ENUM_FRAMESIZES, &size) >= 0); + } else if (size.type == V4L2_FRMSIZE_TYPE_STEPWISE) { + fprintf(stdout, "[Webcam] we have stepwise frame sizes:\n"); + fprintf(stdout, "[Webcam] min width: %d, min height: %d\n", + size.stepwise.min_width, size.stepwise.min_height); + fprintf(stdout, "[Webcam] max width: %d, max height: %d\n", + size.stepwise.max_width, size.stepwise.max_height); + fprintf(stdout, "[Webcam] step width: %d, step height: %d\n", + size.stepwise.step_width, size.stepwise.step_height); + } else if (size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) { + fprintf(stdout, "[Webcam] we have continuous frame sizes:\n"); + fprintf(stdout, "[Webcam] min width: %d, min height: %d\n", + size.stepwise.min_width, size.stepwise.min_height); + fprintf(stdout, "[Webcam] max width: %d, max height: %d\n", + size.stepwise.max_width, size.stepwise.max_height); + + } + format.index++; + } while (yioctl(tmp_fd, VIDIOC_ENUM_FMT, &format) >= 0); + } + + close(tmp_fd); + gettimeofday(&t2, NULL); + fprintf(stdout, "[Webcam] Elapsed time: %lu:%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; +} + +void marucam_device_init(MaruCamState *state) +{ + state->destroying = false; + qemu_thread_create(&state->thread_id, marucam_worker_thread, (void *)state, + QEMU_THREAD_JOINABLE); +} + +void marucam_device_exit(MaruCamState *state) +{ + state->destroying = true; + qemu_mutex_lock(&state->thread_mutex); + qemu_cond_signal(&state->thread_cond); + qemu_mutex_unlock(&state->thread_mutex); + qemu_thread_join(&state->thread_id); +} + +void marucam_device_open(MaruCamState *state) +{ + MaruCamParam *param = state->param; + + param->top = 0; + v4l2_fd = v4l2_open(dev_name, O_RDWR | O_NONBLOCK, 0); + if (v4l2_fd < 0) { + ERR("The v4l2 device open failed: %s\n", dev_name); + param->errCode = EINVAL; + return; + } + INFO("Opened\n"); + + /* FIXME : Do not use fixed values */ + CLEAR(dst_fmt); + dst_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + dst_fmt.fmt.pix.width = 640; + dst_fmt.fmt.pix.height = 480; + dst_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; + dst_fmt.fmt.pix.field = V4L2_FIELD_ANY; + + if (xioctl(v4l2_fd, VIDIOC_S_FMT, &dst_fmt) < 0) { + ERR("Failed to set video format: format(0x%x), width:height(%d:%d), " + "errstr(%s)\n", dst_fmt.fmt.pix.pixelformat, dst_fmt.fmt.pix.width, + dst_fmt.fmt.pix.height, strerror(errno)); + param->errCode = errno; + return; + } + TRACE("Set the default format: w:h(%dx%d), fmt(0x%x), size(%d), " + "color(%d), field(%d)\n", + dst_fmt.fmt.pix.width, dst_fmt.fmt.pix.height, + dst_fmt.fmt.pix.pixelformat, dst_fmt.fmt.pix.sizeimage, + dst_fmt.fmt.pix.colorspace, dst_fmt.fmt.pix.field); +} + +void marucam_device_start_preview(MaruCamState *state) +{ + struct timespec req; + MaruCamParam *param = state->param; + param->top = 0; + req.tv_sec = 0; + req.tv_nsec = 10000000; + + INFO("Pixfmt(%c%c%c%C), W:H(%d:%d), buf size(%u)\n", + (char)(dst_fmt.fmt.pix.pixelformat), + (char)(dst_fmt.fmt.pix.pixelformat >> 8), + (char)(dst_fmt.fmt.pix.pixelformat >> 16), + (char)(dst_fmt.fmt.pix.pixelformat >> 24), + dst_fmt.fmt.pix.width, + dst_fmt.fmt.pix.height, + dst_fmt.fmt.pix.sizeimage); + + param->errCode = mmap_framebuffers(&framebuffer, &n_framebuffer); + if (param->errCode) { + ERR("Failed to mmap framebuffers\n"); + if (framebuffer != NULL) { + free_framebuffers(framebuffer, n_framebuffer); + g_free(framebuffer); + framebuffer = NULL; + n_framebuffer = 0; + } + return; + } + + param->errCode = start_capturing(); + if (param->errCode) { + if (framebuffer != NULL) { + free_framebuffers(framebuffer, n_framebuffer); + g_free(framebuffer); + framebuffer = NULL; + n_framebuffer = 0; + } + return; + } + + INFO("Starting preview\n"); + state->buf_size = dst_fmt.fmt.pix.sizeimage; + qemu_mutex_lock(&state->thread_mutex); + qemu_cond_signal(&state->thread_cond); + qemu_mutex_unlock(&state->thread_mutex); + + /* nanosleep until thread is streamon */ + while (!is_streamon(state)) { + nanosleep(&req, NULL); + } +} + +void marucam_device_stop_preview(MaruCamState *state) +{ + struct timespec req; + struct v4l2_requestbuffers reqbuf; + MaruCamParam *param = state->param; + param->top = 0; + req.tv_sec = 0; + req.tv_nsec = 50000000; + + if (is_streamon(state)) { + qemu_mutex_lock(&state->thread_mutex); + state->streamon = _MC_THREAD_STREAMOFF; + qemu_mutex_unlock(&state->thread_mutex); + + /* nanosleep until thread is paused */ + while (!is_stream_paused(state)) { + nanosleep(&req, NULL); + } + } + + param->errCode = stop_capturing(); + if (framebuffer != NULL) { + free_framebuffers(framebuffer, n_framebuffer); + g_free(framebuffer); + framebuffer = NULL; + n_framebuffer = 0; + } + state->buf_size = 0; + + reqbuf.count = 0; + reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + reqbuf.memory = V4L2_MEMORY_MMAP; + if (xioctl(v4l2_fd, VIDIOC_REQBUFS, &reqbuf) < 0) { + ERR("Failed to ioctl() with VIDIOC_REQBUF in stop_preview: %s\n", + strerror(errno)); + } + INFO("Stopping preview\n"); +} + +void marucam_device_s_param(MaruCamState *state) +{ + MaruCamParam *param = state->param; + + param->top = 0; + + /* If KVM enabled, We use default FPS of the webcam. + * If KVM disabled, we use mininum FPS of the webcam */ + if (!kvm_enabled()) { + set_maxframeinterval(state, dst_fmt.fmt.pix.pixelformat, + dst_fmt.fmt.pix.width, + dst_fmt.fmt.pix.height); + } +} + +void marucam_device_g_param(MaruCamState *state) +{ + MaruCamParam *param = state->param; + + /* We use default FPS of the webcam + * return a fixed value on guest ini file (1/30). + */ + param->top = 0; + param->stack[0] = 0x1000; /* V4L2_CAP_TIMEPERFRAME */ + param->stack[1] = 1; /* numerator */ + param->stack[2] = 30; /* denominator */ +} + +void marucam_device_s_fmt(MaruCamState *state) +{ + struct v4l2_format format; + MaruCamParam *param = state->param; + + param->top = 0; + CLEAR(format); + format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + format.fmt.pix.width = param->stack[0]; + format.fmt.pix.height = param->stack[1]; + format.fmt.pix.pixelformat = param->stack[2]; + format.fmt.pix.field = V4L2_FIELD_ANY; + + if (xioctl(v4l2_fd, VIDIOC_S_FMT, &format) < 0) { + ERR("Failed to set video format: format(0x%x), width:height(%d:%d), " + "errstr(%s)\n", format.fmt.pix.pixelformat, format.fmt.pix.width, + format.fmt.pix.height, strerror(errno)); + param->errCode = errno; + return; + } + + memcpy(&dst_fmt, &format, sizeof(format)); + param->stack[0] = dst_fmt.fmt.pix.width; + param->stack[1] = dst_fmt.fmt.pix.height; + param->stack[2] = dst_fmt.fmt.pix.field; + param->stack[3] = dst_fmt.fmt.pix.pixelformat; + param->stack[4] = dst_fmt.fmt.pix.bytesperline; + param->stack[5] = dst_fmt.fmt.pix.sizeimage; + param->stack[6] = dst_fmt.fmt.pix.colorspace; + param->stack[7] = dst_fmt.fmt.pix.priv; + TRACE("Set the format: w:h(%dx%d), fmt(0x%x), size(%d), " + "color(%d), field(%d)\n", + dst_fmt.fmt.pix.width, dst_fmt.fmt.pix.height, + dst_fmt.fmt.pix.pixelformat, dst_fmt.fmt.pix.sizeimage, + dst_fmt.fmt.pix.colorspace, dst_fmt.fmt.pix.field); +} + +void marucam_device_g_fmt(MaruCamState *state) +{ + struct v4l2_format format; + MaruCamParam *param = state->param; + + param->top = 0; + CLEAR(format); + format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + if (xioctl(v4l2_fd, VIDIOC_G_FMT, &format) < 0) { + ERR("Failed to get video format: %s\n", strerror(errno)); + param->errCode = errno; + } else { + param->stack[0] = format.fmt.pix.width; + param->stack[1] = format.fmt.pix.height; + param->stack[2] = format.fmt.pix.field; + param->stack[3] = format.fmt.pix.pixelformat; + param->stack[4] = format.fmt.pix.bytesperline; + param->stack[5] = format.fmt.pix.sizeimage; + param->stack[6] = format.fmt.pix.colorspace; + param->stack[7] = format.fmt.pix.priv; + TRACE("Get the format: w:h(%dx%d), fmt(0x%x), size(%d), " + "color(%d), field(%d)\n", + format.fmt.pix.width, format.fmt.pix.height, + format.fmt.pix.pixelformat, format.fmt.pix.sizeimage, + format.fmt.pix.colorspace, format.fmt.pix.field); + } +} + +void marucam_device_try_fmt(MaruCamState *state) +{ + struct v4l2_format format; + MaruCamParam *param = state->param; + + param->top = 0; + CLEAR(format); + format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + format.fmt.pix.width = param->stack[0]; + format.fmt.pix.height = param->stack[1]; + format.fmt.pix.pixelformat = param->stack[2]; + format.fmt.pix.field = V4L2_FIELD_ANY; + + if (xioctl(v4l2_fd, VIDIOC_TRY_FMT, &format) < 0) { + ERR("Failed to check video format: format(0x%x), width:height(%d:%d)," + " errstr(%s)\n", format.fmt.pix.pixelformat, format.fmt.pix.width, + format.fmt.pix.height, strerror(errno)); + param->errCode = errno; + return; + } + param->stack[0] = format.fmt.pix.width; + param->stack[1] = format.fmt.pix.height; + param->stack[2] = format.fmt.pix.field; + param->stack[3] = format.fmt.pix.pixelformat; + param->stack[4] = format.fmt.pix.bytesperline; + param->stack[5] = format.fmt.pix.sizeimage; + param->stack[6] = format.fmt.pix.colorspace; + param->stack[7] = format.fmt.pix.priv; + TRACE("Check the format: w:h(%dx%d), fmt(0x%x), size(%d), " + "color(%d), field(%d)\n", + format.fmt.pix.width, format.fmt.pix.height, + format.fmt.pix.pixelformat, format.fmt.pix.sizeimage, + format.fmt.pix.colorspace, format.fmt.pix.field); +} + +void marucam_device_enum_fmt(MaruCamState *state) +{ + uint32_t index; + MaruCamParam *param = state->param; + + param->top = 0; + index = param->stack[0]; + + if (index >= ARRAY_SIZE(supported_dst_pixfmts)) { + param->errCode = EINVAL; + return; + } + param->stack[1] = 0; /* flags = NONE */ + param->stack[2] = supported_dst_pixfmts[index].fmt; /* pixelformat */ + /* set description */ + switch (supported_dst_pixfmts[index].fmt) { + case V4L2_PIX_FMT_YUYV: + memcpy(¶m->stack[3], "YUYV", 32); + break; + case V4L2_PIX_FMT_YUV420: + memcpy(¶m->stack[3], "YU12", 32); + break; + case V4L2_PIX_FMT_YVU420: + memcpy(¶m->stack[3], "YV12", 32); + break; + default: + ERR("Invalid fixel format\n"); + param->errCode = EINVAL; + break; + } +} + +void marucam_device_qctrl(MaruCamState *state) +{ + uint32_t i; + char name[32] = {0,}; + struct v4l2_queryctrl ctrl; + MaruCamParam *param = state->param; + + param->top = 0; + CLEAR(ctrl); + ctrl.id = param->stack[0]; + + switch (ctrl.id) { + case V4L2_CID_BRIGHTNESS: + TRACE("Query : BRIGHTNESS\n"); + memcpy((void *)name, (void *)"brightness", 32); + i = 0; + break; + case V4L2_CID_CONTRAST: + TRACE("Query : CONTRAST\n"); + memcpy((void *)name, (void *)"contrast", 32); + i = 1; + break; + case V4L2_CID_SATURATION: + TRACE("Query : SATURATION\n"); + memcpy((void *)name, (void *)"saturation", 32); + i = 2; + break; + case V4L2_CID_SHARPNESS: + TRACE("Query : SHARPNESS\n"); + memcpy((void *)name, (void *)"sharpness", 32); + i = 3; + break; + default: + ERR("Invalid control ID\n"); + param->errCode = EINVAL; + return; + } + + if (xioctl(v4l2_fd, VIDIOC_QUERYCTRL, &ctrl) < 0) { + if (errno != EINVAL) { + ERR("Failed to query video controls: %s\n", strerror(errno)); + } + param->errCode = errno; + return; + } else { + struct v4l2_control sctrl; + CLEAR(sctrl); + sctrl.id = ctrl.id; + if ((ctrl.maximum + ctrl.minimum) == 0) { + sctrl.value = 0; + } else { + sctrl.value = (ctrl.maximum + ctrl.minimum) / 2; + } + if (xioctl(v4l2_fd, VIDIOC_S_CTRL, &sctrl) < 0) { + ERR("Failed to set control value: id(0x%x), value(%d), " + "errstr(%s)\n", sctrl.id, sctrl.value, strerror(errno)); + param->errCode = errno; + return; + } + qctrl_tbl[i].hit = 1; + qctrl_tbl[i].min = ctrl.minimum; + qctrl_tbl[i].max = ctrl.maximum; + qctrl_tbl[i].step = ctrl.step; + qctrl_tbl[i].init_val = ctrl.default_value; + } + + /* set fixed values by FW configuration file */ + param->stack[0] = ctrl.id; + param->stack[1] = MARUCAM_CTRL_VALUE_MIN; /* minimum */ + param->stack[2] = MARUCAM_CTRL_VALUE_MAX; /* maximum */ + param->stack[3] = MARUCAM_CTRL_VALUE_STEP; /* step */ + param->stack[4] = MARUCAM_CTRL_VALUE_MID; /* default_value */ + param->stack[5] = ctrl.flags; + /* name field setting */ + memcpy(¶m->stack[6], (void *)name, sizeof(ctrl.name)); +} + +void marucam_device_s_ctrl(MaruCamState *state) +{ + uint32_t i; + struct v4l2_control ctrl; + MaruCamParam *param = state->param; + + param->top = 0; + CLEAR(ctrl); + ctrl.id = param->stack[0]; + + switch (ctrl.id) { + case V4L2_CID_BRIGHTNESS: + i = 0; + TRACE("%d is set to the value of the BRIGHTNESS\n", param->stack[1]); + break; + case V4L2_CID_CONTRAST: + i = 1; + TRACE("%d is set to the value of the CONTRAST\n", param->stack[1]); + break; + case V4L2_CID_SATURATION: + i = 2; + TRACE("%d is set to the value of the SATURATION\n", param->stack[1]); + break; + case V4L2_CID_SHARPNESS: + i = 3; + TRACE("%d is set to the value of the SHARPNESS\n", param->stack[1]); + break; + default: + ERR("Our emulator does not support this control: 0x%x\n", ctrl.id); + param->errCode = EINVAL; + return; + } + + ctrl.value = value_convert_from_guest(qctrl_tbl[i].min, + qctrl_tbl[i].max, param->stack[1]); + if (xioctl(v4l2_fd, VIDIOC_S_CTRL, &ctrl) < 0) { + ERR("Failed to set control value: id(0x%x), value(r:%d, c:%d), " + "errstr(%s)\n", ctrl.id, param->stack[1], ctrl.value, + strerror(errno)); + param->errCode = errno; + return; + } +} + +void marucam_device_g_ctrl(MaruCamState *state) +{ + uint32_t i; + struct v4l2_control ctrl; + MaruCamParam *param = state->param; + + param->top = 0; + CLEAR(ctrl); + ctrl.id = param->stack[0]; + + switch (ctrl.id) { + case V4L2_CID_BRIGHTNESS: + TRACE("Gets the value of the BRIGHTNESS\n"); + i = 0; + break; + case V4L2_CID_CONTRAST: + TRACE("Gets the value of the CONTRAST\n"); + i = 1; + break; + case V4L2_CID_SATURATION: + TRACE("Gets the value of the SATURATION\n"); + i = 2; + break; + case V4L2_CID_SHARPNESS: + TRACE("Gets the value of the SHARPNESS\n"); + i = 3; + break; + default: + ERR("Our emulator does not support this control: 0x%x\n", ctrl.id); + param->errCode = EINVAL; + return; + } + + if (xioctl(v4l2_fd, VIDIOC_G_CTRL, &ctrl) < 0) { + ERR("Failed to get video control value: %s\n", strerror(errno)); + param->errCode = errno; + return; + } + param->stack[0] = value_convert_to_guest(qctrl_tbl[i].min, + qctrl_tbl[i].max, ctrl.value); + TRACE("Value: %d\n", param->stack[0]); +} + +void marucam_device_enum_fsizes(MaruCamState *state) +{ + uint32_t index, pixfmt, i; + MaruCamParam *param = state->param; + + param->top = 0; + index = param->stack[0]; + pixfmt = param->stack[1]; + + if (index >= ARRAY_SIZE(supported_dst_frames)) { + param->errCode = EINVAL; + return; + } + for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) { + if (supported_dst_pixfmts[i].fmt == pixfmt) { + break; + } + } + + if (i == ARRAY_SIZE(supported_dst_pixfmts)) { + param->errCode = EINVAL; + return; + } + + param->stack[0] = supported_dst_frames[index].width; + param->stack[1] = supported_dst_frames[index].height; +} + +void marucam_device_enum_fintv(MaruCamState *state) +{ + MaruCamParam *param = state->param; + + param->top = 0; + + /* switch by index(param->stack[0]) */ + switch (param->stack[0]) { + case 0: + /* we only use 1/30 frame interval */ + param->stack[1] = 30; /* denominator */ + break; + default: + param->errCode = EINVAL; + return; + } + param->stack[0] = 1; /* numerator */ +} + +void marucam_device_close(MaruCamState *state) +{ + if (!is_stream_paused(state)) { + marucam_device_stop_preview(state); + } + + marucam_reset_controls(); + + v4l2_close(v4l2_fd); + v4l2_fd = 0; + INFO("Closed\n"); +} diff --git a/tizen/src/hw/maru_camera_win32_interface.h b/tizen/src/hw/maru_camera_win32_interface.h index 9c0e126735..11e0e24cb5 100644 --- a/tizen/src/hw/maru_camera_win32_interface.h +++ b/tizen/src/hw/maru_camera_win32_interface.h @@ -1,932 +1,934 @@ -/* - * Interface definition header for Windows host. - * - * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: - * JinHyung Jo - * YeongKyoon Lee - * - * 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 - * - */ - -#ifndef _MARU_CAMERA_INTERFACE_H_ -#define _MARU_CAMERA_INTERFACE_H_ - -static const WCHAR HWCPinName[] = L"HWCInputPin\0"; -static const WCHAR HWCFilterName[] = L"HWCFilter\0"; - -/* Forward Declarations */ -FWD_DECL(IBaseFilter); -FWD_DECL(IFilterGraph); - -/* defines */ -#define MAX_PIN_NAME 128 -#define MAX_FILTER_NAME 128 - -#define DECLARE_INTERFACE2(i) \ - _COM_interface i { CONST_VTABLE struct i##Vtbl *lpVtbl; }; \ - typedef CONST_VTABLE struct i##Vtbl i##Vtbl; \ - CONST_VTABLE struct i##Vtbl -#define DECLARE_INTERFACE2_(i,b) DECLARE_INTERFACE2(i) - -typedef LONGLONG REFERENCE_TIME; -typedef long OAFilterState; -typedef DWORD_PTR HSEMAPHORE; -typedef DWORD_PTR HEVENT; - -typedef enum _FilterState { - State_Stopped, - State_Paused, - State_Running -} FILTER_STATE; - -typedef struct _FilterInfo { - WCHAR achName[MAX_FILTER_NAME]; - IFilterGraph *pGraph; -} FILTER_INFO; - -typedef enum _PinDirection -{ PINDIR_INPUT = 0, - PINDIR_OUTPUT = ( PINDIR_INPUT + 1 ) -} PIN_DIRECTION; - -typedef struct _PinInfo { - IBaseFilter *pFilter; - PIN_DIRECTION dir; - WCHAR achName[MAX_PIN_NAME]; -} PIN_INFO; - -typedef struct _AllocatorProperties { - long cBuffers; - long cbBuffer; - long cbAlign; - long cbPrefix; -} ALLOCATOR_PROPERTIES; - -typedef struct _AMMediaType { - GUID majortype; - GUID subtype; - BOOL bFixedSizeSamples; - BOOL bTemporalCompression; - ULONG lSampleSize; - GUID formattype; - IUnknown *pUnk; - ULONG cbFormat; - BYTE *pbFormat; -} AM_MEDIA_TYPE; - -typedef enum tagVideoProcAmpFlags { - VideoProcAmp_Flags_Auto = 0x0001, - VideoProcAmp_Flags_Manual = 0x0002 -} VideoProcAmpFlags; - -typedef enum tagVideoProcAmpProperty { - VideoProcAmp_Brightness, - VideoProcAmp_Contrast, - VideoProcAmp_Hue, - VideoProcAmp_Saturation, - VideoProcAmp_Sharpness, - VideoProcAmp_Gamma, - VideoProcAmp_ColorEnable, - VideoProcAmp_WhiteBalance, - VideoProcAmp_BacklightCompensation, - VideoProcAmp_Gain -} VideoProcAmpProperty; - -typedef struct tagVIDEOINFOHEADER { - RECT rcSource; - RECT rcTarget; - DWORD dwBitRate; - DWORD dwBitErrorRate; - REFERENCE_TIME AvgTimePerFrame; - BITMAPINFOHEADER bmiHeader; -} VIDEOINFOHEADER; - -typedef struct _VIDEO_STREAM_CONFIG_CAPS -{ - GUID guid; - ULONG VideoStandard; - SIZE InputSize; - SIZE MinCroppingSize; - SIZE MaxCroppingSize; - int CropGranularityX; - int CropGranularityY; - int CropAlignX; - int CropAlignY; - SIZE MinOutputSize; - SIZE MaxOutputSize; - int OutputGranularityX; - int OutputGranularityY; - int StretchTapsX; - int StretchTapsY; - int ShrinkTapsX; - int ShrinkTapsY; - LONGLONG MinFrameInterval; - LONGLONG MaxFrameInterval; - LONG MinBitsPerSecond; - LONG MaxBitsPerSecond; -} VIDEO_STREAM_CONFIG_CAPS; - - -/* Interface & Class GUIDs */ -static const IID IID_IGrabCallback = {0x4C337035,0xC89E,0x4B42,{0x9B,0x0C,0x36,0x74,0x44,0xDD,0x70,0xDD}}; - -EXTERN_C const IID IID_IBaseFilter; -EXTERN_C const IID IID_ICreateDevEnum; -EXTERN_C const IID IID_IGraphBuilder; -EXTERN_C const IID IID_IMediaSeeking; -EXTERN_C const IID IID_IMediaEventSink; -EXTERN_C const IID IID_IMemInputPin; -EXTERN_C const IID IID_IEnumPins; -EXTERN_C const IID IID_IMediaFilter; -EXTERN_C const IID IID_IEnumMediaTypes; -EXTERN_C const IID IID_IMemAllocator; -EXTERN_C const IID IID_IPin; -EXTERN_C const IID IID_ICaptureGraphBuilder2; -EXTERN_C const IID IID_IFileSinkFilter; -EXTERN_C const IID IID_IAMCopyCaptureFileProgress; -EXTERN_C const IID IID_IEnumFilters; -EXTERN_C const IID IID_IMediaSample; -EXTERN_C const IID IID_IMediaControl; -EXTERN_C const IID IID_IAMStreamConfig; -EXTERN_C const IID IID_IAMVideoProcAmp; - -EXTERN_C const IID CLSID_CaptureGraphBuilder2; -EXTERN_C const IID CLSID_VideoInputDeviceCategory; -EXTERN_C const IID CLSID_AudioRender; -EXTERN_C const IID CLSID_SystemDeviceEnum; -EXTERN_C const IID CLSID_AudioRendererCategory; -EXTERN_C const IID CLSID_FilterGraph; -EXTERN_C const IID CLSID_InfTee; -EXTERN_C const IID CLSID_VideoMixingRenderer9; -EXTERN_C const IID CLSID_MemoryAllocator; - - -/* other types GUIDs*/ -EXTERN_C const IID MEDIATYPE_Audio; -EXTERN_C const IID MEDIATYPE_Video; -EXTERN_C const IID MEDIATYPE_Stream; -EXTERN_C const IID MEDIASUBTYPE_PCM; -EXTERN_C const IID MEDIASUBTYPE_WAVE; -EXTERN_C const IID MEDIASUBTYPE_Avi; -EXTERN_C const IID MEDIASUBTYPE_RGB32; -EXTERN_C const IID MEDIASUBTYPE_YV12; -EXTERN_C const IID MEDIASUBTYPE_YUY2; -EXTERN_C const IID MEDIASUBTYPE_I420; -EXTERN_C const IID MEDIASUBTYPE_YUYV; -EXTERN_C const IID FORMAT_WaveFormatEx; -EXTERN_C const IID FORMAT_VideoInfo; -EXTERN_C const IID FORMAT_VideoInfo2; -EXTERN_C const IID PIN_CATEGORY_CAPTURE; -EXTERN_C const IID PIN_CATEGORY_PREVIEW; - - -#define MEDIATYPE_NULL GUID_NULL -#define MEDIASUBTYPE_NULL GUID_NULL - -#define INTERFACE IGrabCallback -DECLARE_INTERFACE_(IGrabCallback, IUnknown) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - STDMETHOD(Grab)(THIS_ ULONG,BYTE*) PURE; -}; -#undef INTERFACE - -#ifdef COBJMACROS -#define IGrabCallback_QueryInterface(T,a,b) (T)->lpVtbl->QueryInterface(T,a,b) -#define IGrabCallback_AddRef(T) (T)->lpVtbl->AddRef(T) -#define IGrabCallback_Release(T) (T)->lpVtbl->Release(T) -#define IGrabCallback_Grab(T,a,b) (T)->lpVtbl->Grab(T,a,b) -#endif /* COBJMACROS */ - -#define INTERFACE IAMCopyCaptureFileProgress -DECLARE_INTERFACE_(IAMCopyCaptureFileProgress, IUnknown) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - STDMETHOD(Progress)(THIS_ int) PURE; -}; -#undef INTERFACE -#define INTERFACE IReferenceClock -DECLARE_INTERFACE_(IReferenceClock, IUnknown) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - STDMETHOD(GetTime)(THIS_ REFERENCE_TIME *) PURE; - STDMETHOD(AdviseTime)(THIS_ REFERENCE_TIME, REFERENCE_TIME, HEVENT, DWORD_PTR *) PURE; - STDMETHOD(AdvisePeriodic)(THIS_ REFERENCE_TIME, REFERENCE_TIME, HSEMAPHORE, DWORD_PTR *) PURE; - STDMETHOD(Unadvise)(THIS_ DWORD_PTR) PURE; -}; -#undef INTERFACE -#define INTERFACE IEnumFilters -DECLARE_INTERFACE_(IEnumFilters, IUnknown) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - STDMETHOD(Next)(THIS_ ULONG, IBaseFilter **, ULONG *) PURE; - STDMETHOD(Skip)(THIS_ ULONG) PURE; - STDMETHOD(Reset)(THIS) PURE; - STDMETHOD(Clone)(THIS_ IEnumFilters **) PURE; -}; -#undef INTERFACE -#define INTERFACE IEnumMediaTypes -DECLARE_INTERFACE_(IEnumMediaTypes, IUnknown) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - STDMETHOD(Next)(THIS_ ULONG, AM_MEDIA_TYPE **, ULONG *) PURE; - STDMETHOD(Skip)(THIS_ ULONG) PURE; - STDMETHOD(Reset)(THIS) PURE; - STDMETHOD(Clone)(THIS_ IEnumMediaTypes **) PURE; -}; -#undef INTERFACE -#define INTERFACE IPin -DECLARE_INTERFACE_(IPin, IUnknown) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - STDMETHOD(Connect)(THIS_ IPin *, const AM_MEDIA_TYPE *) PURE; - STDMETHOD(ReceiveConnection)(THIS_ IPin *, const AM_MEDIA_TYPE *) PURE; - STDMETHOD(Disconnect)(THIS) PURE; - STDMETHOD(ConnectedTo)(THIS_ IPin **) PURE; - STDMETHOD(ConnectionMediaType)(THIS_ AM_MEDIA_TYPE *) PURE; - STDMETHOD(QueryPinInfo)(THIS_ PIN_INFO *) PURE; - STDMETHOD(QueryDirection)(THIS_ PIN_DIRECTION *) PURE; - STDMETHOD(QueryId)(THIS_ LPWSTR *) PURE; - STDMETHOD(QueryAccept)(THIS_ const AM_MEDIA_TYPE *) PURE; - STDMETHOD(EnumMediaTypes)(THIS_ IEnumMediaTypes **) PURE; - STDMETHOD(QueryInternalConnections)(THIS_ IPin **, ULONG *) PURE; - STDMETHOD(EndOfStream)(THIS) PURE; - STDMETHOD(BeginFlush)(THIS) PURE; - STDMETHOD(EndFlush)(THIS) PURE; - STDMETHOD(NewSegment)(THIS_ REFERENCE_TIME, REFERENCE_TIME, double) PURE; -}; -#undef INTERFACE -#define INTERFACE IEnumPins -DECLARE_INTERFACE_(IEnumPins, IUnknown) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - STDMETHOD(Next)(THIS_ ULONG, IPin **, ULONG *) PURE; - STDMETHOD(Skip)(THIS_ ULONG) PURE; - STDMETHOD(Reset)(THIS) PURE; - STDMETHOD(Clone)(THIS_ IEnumPins **) PURE; -}; -#undef INTERFACE -#define INTERFACE IMediaFilter -DECLARE_INTERFACE_(IMediaFilter, IPersist) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - STDMETHOD(GetClassID)(THIS_ CLSID*) PURE; - STDMETHOD(Stop)(THIS) PURE; - STDMETHOD(Pause)(THIS) PURE; - STDMETHOD(Run)(THIS_ REFERENCE_TIME) PURE; - STDMETHOD(GetState)(THIS_ DWORD, FILTER_STATE *) PURE; - STDMETHOD(SetSyncSource)(THIS_ IReferenceClock *) PURE; - STDMETHOD(GetSyncSource)(THIS_ IReferenceClock **) PURE; -}; -#undef INTERFACE -#define INTERFACE IBaseFilter -DECLARE_INTERFACE2_(IBaseFilter, IMediaFilter) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - STDMETHOD(GetClassID)(THIS_ CLSID*) PURE; - STDMETHOD(Stop)(THIS) PURE; - STDMETHOD(Pause)(THIS) PURE; - STDMETHOD(Run)(THIS_ REFERENCE_TIME) PURE; - STDMETHOD(GetState)(THIS_ DWORD, FILTER_STATE *) PURE; - STDMETHOD(SetSyncSource)(THIS_ IReferenceClock *) PURE; - STDMETHOD(GetSyncSource)(THIS_ IReferenceClock **) PURE; - STDMETHOD(EnumPins)(THIS_ IEnumPins **) PURE; - STDMETHOD(FindPin)(THIS_ LPCWSTR, IPin **) PURE; - STDMETHOD(QueryFilterInfo)(THIS_ FILTER_INFO *) PURE; - STDMETHOD(JoinFilterGraph)(THIS_ IFilterGraph *, LPCWSTR) PURE; - STDMETHOD(QueryVendorInfo)(THIS_ LPWSTR *) PURE; -}; -#undef INTERFACE -#define INTERFACE IFilterGraph -DECLARE_INTERFACE2_(IFilterGraph, IUnknown) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - STDMETHOD(AddFilter)(THIS_ IBaseFilter *, LPCWSTR) PURE; - STDMETHOD(RemoveFilter)(THIS_ IBaseFilter *) PURE; - STDMETHOD(EnumFilters)(THIS_ IEnumFilters **) PURE; - STDMETHOD(FindFilterByName)(THIS_ LPCWSTR, IBaseFilter **) PURE; - STDMETHOD(ConnectDirect)(THIS_ IPin *, IPin *, const AM_MEDIA_TYPE *) PURE; - STDMETHOD(Reconnect)(THIS_ IPin *) PURE; - STDMETHOD(Disconnect)(THIS_ IPin *) PURE; - STDMETHOD(SetDefaultSyncSource)(THIS) PURE; -}; -#undef INTERFACE -#define INTERFACE IGraphBuilder -DECLARE_INTERFACE_(IGraphBuilder ,IFilterGraph) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - STDMETHOD(AddFilter)(THIS_ IBaseFilter *, LPCWSTR) PURE; - STDMETHOD(RemoveFilter)(THIS_ IBaseFilter *) PURE; - STDMETHOD(EnumFilters)(THIS_ IEnumFilters **) PURE; - STDMETHOD(FindFilterByName)(THIS_ LPCWSTR, IBaseFilter **) PURE; - STDMETHOD(ConnectDirect)(THIS_ IPin *, IPin *, const AM_MEDIA_TYPE *) PURE; - STDMETHOD(Reconnect)(THIS_ IPin *) PURE; - STDMETHOD(Disconnect)(THIS_ IPin *) PURE; - STDMETHOD(SetDefaultSyncSource)(THIS) PURE; - STDMETHOD(Connect)(THIS_ IPin *, IPin *) PURE; - STDMETHOD(Render)(THIS_ IPin *) PURE; - STDMETHOD(RenderFile)(THIS_ LPCWSTR, LPCWSTR) PURE; - STDMETHOD(AddSourceFilter)(THIS_ LPCWSTR, LPCWSTR, IBaseFilter **) PURE; - STDMETHOD(SetLogFile)(THIS_ DWORD_PTR) PURE; - STDMETHOD(Abort)(THIS) PURE; - STDMETHOD(ShouldOperationContinue)(THIS) PURE; -}; -#undef INTERFACE -#define INTERFACE ICreateDevEnum -DECLARE_INTERFACE_(ICreateDevEnum, IUnknown) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - STDMETHOD(CreateClassEnumerator)(THIS_ REFCLSID, IEnumMoniker **, DWORD) PURE; -}; -#undef INTERFACE -#define INTERFACE IMediaSample -DECLARE_INTERFACE_(IMediaSample, IUnknown) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - STDMETHOD(GetPointer)(THIS_ BYTE **) PURE; - STDMETHOD_(long, GetSize)(THIS) PURE; - STDMETHOD(GetTime)(THIS_ REFERENCE_TIME *, REFERENCE_TIME *) PURE; - STDMETHOD(SetTime)(THIS_ REFERENCE_TIME *, REFERENCE_TIME *) PURE; - STDMETHOD(IsSyncPoint)(THIS) PURE; - STDMETHOD(SetSyncPoint)(THIS_ BOOL) PURE; - STDMETHOD(IsPreroll)(THIS) PURE; - STDMETHOD(SetPreroll)(THIS_ BOOL) PURE; - STDMETHOD_(long, GetActualDataLength)(THIS) PURE; - STDMETHOD(SetActualDataLength)(THIS_ long) PURE; - STDMETHOD(GetMediaType)(THIS_ AM_MEDIA_TYPE **) PURE; - STDMETHOD(SetMediaType)(THIS_ AM_MEDIA_TYPE *) PURE; - STDMETHOD(IsDiscontinuity)(THIS) PURE; - STDMETHOD(SetDiscontinuity)(THIS_ BOOL) PURE; - STDMETHOD(GetMediaTime)(THIS_ LONGLONG *, LONGLONG *) PURE; - STDMETHOD(SetMediaTime)(THIS_ LONGLONG *, LONGLONG *) PURE; -}; -#undef INTERFACE -#define INTERFACE IMemAllocator -DECLARE_INTERFACE_(IMemAllocator, IUnknown) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - STDMETHOD(SetProperties)(THIS_ ALLOCATOR_PROPERTIES *, ALLOCATOR_PROPERTIES *) PURE; - STDMETHOD(GetProperties)(THIS_ ALLOCATOR_PROPERTIES *) PURE; - STDMETHOD(Commit)(THIS) PURE; - STDMETHOD(Decommit)(THIS) PURE; - STDMETHOD(GetBuffer)(THIS_ IMediaSample **, REFERENCE_TIME *, REFERENCE_TIME *, DWORD) PURE; - STDMETHOD(ReleaseBuffer)(THIS_ IMediaSample *) PURE; - -}; -#undef INTERFACE -#define INTERFACE IMemInputPin -DECLARE_INTERFACE_(IMemInputPin, IUnknown) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - STDMETHOD(GetAllocator)(THIS_ IMemAllocator **) PURE; - STDMETHOD(NotifyAllocator)(THIS_ IMemAllocator *, BOOL) PURE; - STDMETHOD(GetAllocatorRequirements)(THIS_ ALLOCATOR_PROPERTIES *) PURE; - STDMETHOD(Receive)(THIS_ IMediaSample *) PURE; - STDMETHOD(ReceiveMultiple)(THIS_ IMediaSample **, long, long *) PURE; - STDMETHOD(ReceiveCanBlock)(THIS) PURE; -}; -#undef INTERFACE -#define INTERFACE IFileSinkFilter -DECLARE_INTERFACE_(IFileSinkFilter, IUnknown) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - STDMETHOD(SetFileName)(THIS_ LPCOLESTR,const AM_MEDIA_TYPE *) PURE; - STDMETHOD(GetCurFile)(THIS_ LPOLESTR *,AM_MEDIA_TYPE*) PURE; -}; -#undef INTERFACE -#define INTERFACE ICaptureGraphBuilder2 -DECLARE_INTERFACE_(ICaptureGraphBuilder2, IUnknown) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - STDMETHOD(SetFiltergraph)(THIS_ IGraphBuilder*) PURE; - STDMETHOD(GetFiltergraph)(THIS_ IGraphBuilder**) PURE; - STDMETHOD(SetOutputFileName)(THIS_ const GUID*,LPCOLESTR,IBaseFilter**,IFileSinkFilter**) PURE; - STDMETHOD(FindInterface)(THIS_ const GUID*,const GUID*,IBaseFilter*,REFIID,void**) PURE; - STDMETHOD(RenderStream)(THIS_ const GUID*,const GUID*,IUnknown*,IBaseFilter*,IBaseFilter*) PURE; - STDMETHOD(ControlStream)(THIS_ const GUID*,const GUID*,IBaseFilter*,REFERENCE_TIME*,REFERENCE_TIME*,WORD,WORD) PURE; - STDMETHOD(AllocCapFile)(THIS_ LPCOLESTR,DWORDLONG) PURE; - STDMETHOD(CopyCaptureFile)(THIS_ LPOLESTR,LPOLESTR,int,IAMCopyCaptureFileProgress*) PURE; - STDMETHOD(FindPin)(THIS_ IUnknown*,PIN_DIRECTION,const GUID*,const GUID*,BOOL,int,IPin**) PURE; -}; -#undef INTERFACE -#define INTERFACE IAMStreamConfig -DECLARE_INTERFACE_(IAMStreamConfig, IUnknown) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - STDMETHOD(SetFormat)(THIS_ AM_MEDIA_TYPE*) PURE; - STDMETHOD(GetFormat)(THIS_ AM_MEDIA_TYPE**) PURE; - STDMETHOD(GetNumberOfCapabilities)(THIS_ int*,int*) PURE; - STDMETHOD(GetStreamCaps)(THIS_ int,AM_MEDIA_TYPE**,BYTE*) PURE; -}; -#undef INTERFACE -#define INTERFACE IAMVideoProcAmp -DECLARE_INTERFACE_(IAMVideoProcAmp, IUnknown) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - STDMETHOD(GetRange)(THIS_ long,long*,long*,long*,long*,long*) PURE; - STDMETHOD(Set)(THIS_ long,long,long) PURE; - STDMETHOD(Get)(THIS_ long,long*,long*) PURE; -}; -#undef INTERFACE -#define INTERFACE IMediaControl -DECLARE_INTERFACE_(IMediaControl, IDispatch) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - STDMETHOD(GetTypeInfoCount)(THIS_ UINT*); - STDMETHOD(GetTypeInfo)(THIS_ UINT,LCID,ITypeInfo**); - STDMETHOD(GetIDsOfNames)(THIS_ REFIID,LPOLESTR*,UINT,LCID,DISPID*); - STDMETHOD(Invoke)(THIS_ DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*); - STDMETHOD(Run)(THIS); - STDMETHOD(Pause)(THIS); - STDMETHOD(Stop)(THIS); - STDMETHOD(GetState)(THIS_ LONG, OAFilterState*); - STDMETHOD(RenderFile)(THIS_ BSTR); - STDMETHOD(AddSourceFilter)(THIS_ BSTR,IDispatch**); - STDMETHOD(get_FilterCollection)(THIS_ IDispatch**); - STDMETHOD(get_RegFilterCollection)(THIS_ IDispatch**); - STDMETHOD(StopWhenReady)(THIS); -}; -#undef INTERFACE - -#ifdef COBJMACROS -#define ICreateDevEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define ICreateDevEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) -#define ICreateDevEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) -#define ICreateDevEnum_CreateClassEnumerator(This,clsidDeviceClass,ppEnumMoniker,dwFlags) \ - ( (This)->lpVtbl -> CreateClassEnumerator(This,clsidDeviceClass,ppEnumMoniker,dwFlags) ) -#endif /* COBJMACROS */ - -#ifdef COBJMACROS -#define IPin_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define IPin_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) -#define IPin_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) -#define IPin_Connect(This,pReceivePin,pmt) \ - ( (This)->lpVtbl -> Connect(This,pReceivePin,pmt) ) -#define IPin_ReceiveConnection(This,pConnector,pmt) \ - ( (This)->lpVtbl -> ReceiveConnection(This,pConnector,pmt) ) -#define IPin_Disconnect(This) \ - ( (This)->lpVtbl -> Disconnect(This) ) -#define IPin_ConnectedTo(This,pPin) \ - ( (This)->lpVtbl -> ConnectedTo(This,pPin) ) -#define IPin_ConnectionMediaType(This,pmt) \ - ( (This)->lpVtbl -> ConnectionMediaType(This,pmt) ) -#define IPin_QueryPinInfo(This,pInfo) \ - ( (This)->lpVtbl -> QueryPinInfo(This,pInfo) ) -#define IPin_QueryDirection(This,pPinDir) \ - ( (This)->lpVtbl -> QueryDirection(This,pPinDir) ) -#define IPin_QueryId(This,Id) \ - ( (This)->lpVtbl -> QueryId(This,Id) ) -#define IPin_QueryAccept(This,pmt) \ - ( (This)->lpVtbl -> QueryAccept(This,pmt) ) -#define IPin_EnumMediaTypes(This,ppEnum) \ - ( (This)->lpVtbl -> EnumMediaTypes(This,ppEnum) ) -#define IPin_QueryInternalConnections(This,apPin,nPin) \ - ( (This)->lpVtbl -> QueryInternalConnections(This,apPin,nPin) ) -#define IPin_EndOfStream(This) \ - ( (This)->lpVtbl -> EndOfStream(This) ) -#define IPin_BeginFlush(This) \ - ( (This)->lpVtbl -> BeginFlush(This) ) -#define IPin_EndFlush(This) \ - ( (This)->lpVtbl -> EndFlush(This) ) -#define IPin_NewSegment(This,tStart,tStop,dRate) \ - ( (This)->lpVtbl -> NewSegment(This,tStart,tStop,dRate) ) -#endif /* COBJMACROS */ - -#ifdef COBJMACROS -#define IEnumPins_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define IEnumPins_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) -#define IEnumPins_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) -#define IEnumPins_Next(This,cPins,ppPins,pcFetched) \ - ( (This)->lpVtbl -> Next(This,cPins,ppPins,pcFetched) ) -#define IEnumPins_Skip(This,cPins) \ - ( (This)->lpVtbl -> Skip(This,cPins) ) -#define IEnumPins_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) -#define IEnumPins_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) -#endif /* COBJMACROS */ - -#ifdef COBJMACROS -#define IAMStreamConfig_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define IAMStreamConfig_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) -#define IAMStreamConfig_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) -#define IAMStreamConfig_SetFormat(This,pmt) \ - ( (This)->lpVtbl -> SetFormat(This,pmt) ) -#define IAMStreamConfig_GetFormat(This,ppmt) \ - ( (This)->lpVtbl -> GetFormat(This,ppmt) ) -#define IAMStreamConfig_GetNumberOfCapabilities(This,piCount,piSize) \ - ( (This)->lpVtbl -> GetNumberOfCapabilities(This,piCount,piSize) ) -#define IAMStreamConfig_GetStreamCaps(This,iIndex,ppmt,pSCC) \ - ( (This)->lpVtbl -> GetStreamCaps(This,iIndex,ppmt,pSCC) ) -#endif /* COBJMACROS */ - -#ifdef COBJMACROS -#define IFilterGraph_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define IFilterGraph_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) -#define IFilterGraph_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) -#define IFilterGraph_AddFilter(This,pFilter,pName) \ - ( (This)->lpVtbl -> AddFilter(This,pFilter,pName) ) -#define IFilterGraph_RemoveFilter(This,pFilter) \ - ( (This)->lpVtbl -> RemoveFilter(This,pFilter) ) -#define IFilterGraph_EnumFilters(This,ppEnum) \ - ( (This)->lpVtbl -> EnumFilters(This,ppEnum) ) -#define IFilterGraph_FindFilterByName(This,pName,ppFilter) \ - ( (This)->lpVtbl -> FindFilterByName(This,pName,ppFilter) ) -#define IFilterGraph_ConnectDirect(This,ppinOut,ppinIn,pmt) \ - ( (This)->lpVtbl -> ConnectDirect(This,ppinOut,ppinIn,pmt) ) -#define IFilterGraph_Reconnect(This,ppin) \ - ( (This)->lpVtbl -> Reconnect(This,ppin) ) -#define IFilterGraph_Disconnect(This,ppin) \ - ( (This)->lpVtbl -> Disconnect(This,ppin) ) -#define IFilterGraph_SetDefaultSyncSource(This) \ - ( (This)->lpVtbl -> SetDefaultSyncSource(This) ) -#endif /* COBJMACROS */ - -#ifdef COBJMACROS -#define IMediaFilter_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define IMediaFilter_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) -#define IMediaFilter_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) -#define IMediaFilter_GetClassID(This,pClassID) \ - ( (This)->lpVtbl -> GetClassID(This,pClassID) ) -#define IMediaFilter_Stop(This) \ - ( (This)->lpVtbl -> Stop(This) ) -#define IMediaFilter_Pause(This) \ - ( (This)->lpVtbl -> Pause(This) ) -#define IMediaFilter_Run(This,tStart) \ - ( (This)->lpVtbl -> Run(This,tStart) ) -#define IMediaFilter_GetState(This,dwMilliSecsTimeout,State) \ - ( (This)->lpVtbl -> GetState(This,dwMilliSecsTimeout,State) ) -#define IMediaFilter_SetSyncSource(This,pClock) \ - ( (This)->lpVtbl -> SetSyncSource(This,pClock) ) -#define IMediaFilter_GetSyncSource(This,pClock) \ - ( (This)->lpVtbl -> GetSyncSource(This,pClock) ) -#endif /* COBJMACROS */ - -#ifdef COBJMACROS -#define IBaseFilter_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define IBaseFilter_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) -#define IBaseFilter_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) -#define IBaseFilter_GetClassID(This,pClassID) \ - ( (This)->lpVtbl -> GetClassID(This,pClassID) ) -#define IBaseFilter_Stop(This) \ - ( (This)->lpVtbl -> Stop(This) ) -#define IBaseFilter_Pause(This) \ - ( (This)->lpVtbl -> Pause(This) ) -#define IBaseFilter_Run(This,tStart) \ - ( (This)->lpVtbl -> Run(This,tStart) ) -#define IBaseFilter_GetState(This,dwMilliSecsTimeout,State) \ - ( (This)->lpVtbl -> GetState(This,dwMilliSecsTimeout,State) ) -#define IBaseFilter_SetSyncSource(This,pClock) \ - ( (This)->lpVtbl -> SetSyncSource(This,pClock) ) -#define IBaseFilter_GetSyncSource(This,pClock) \ - ( (This)->lpVtbl -> GetSyncSource(This,pClock) ) -#define IBaseFilter_EnumPins(This,ppEnum) \ - ( (This)->lpVtbl -> EnumPins(This,ppEnum) ) -#define IBaseFilter_FindPin(This,Id,ppPin) \ - ( (This)->lpVtbl -> FindPin(This,Id,ppPin) ) -#define IBaseFilter_QueryFilterInfo(This,pInfo) \ - ( (This)->lpVtbl -> QueryFilterInfo(This,pInfo) ) -#define IBaseFilter_JoinFilterGraph(This,pGraph,pName) \ - ( (This)->lpVtbl -> JoinFilterGraph(This,pGraph,pName) ) -#define IBaseFilter_QueryVendorInfo(This,pVendorInfo) \ - ( (This)->lpVtbl -> QueryVendorInfo(This,pVendorInfo) ) -#endif /* COBJMACROS */ - -#ifdef COBJMACROS -#define IMediaSample_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define IMediaSample_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) -#define IMediaSample_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) -#define IMediaSample_GetPointer(This,ppBuffer) \ - ( (This)->lpVtbl -> GetPointer(This,ppBuffer) ) -#define IMediaSample_GetSize(This) \ - ( (This)->lpVtbl -> GetSize(This) ) -#define IMediaSample_GetTime(This,pTimeStart,pTimeEnd) \ - ( (This)->lpVtbl -> GetTime(This,pTimeStart,pTimeEnd) ) -#define IMediaSample_SetTime(This,pTimeStart,pTimeEnd) \ - ( (This)->lpVtbl -> SetTime(This,pTimeStart,pTimeEnd) ) -#define IMediaSample_IsSyncPoint(This) \ - ( (This)->lpVtbl -> IsSyncPoint(This) ) -#define IMediaSample_SetSyncPoint(This,bIsSyncPoint) \ - ( (This)->lpVtbl -> SetSyncPoint(This,bIsSyncPoint) ) -#define IMediaSample_IsPreroll(This) \ - ( (This)->lpVtbl -> IsPreroll(This) ) -#define IMediaSample_SetPreroll(This,bIsPreroll) \ - ( (This)->lpVtbl -> SetPreroll(This,bIsPreroll) ) -#define IMediaSample_GetActualDataLength(This) \ - ( (This)->lpVtbl -> GetActualDataLength(This) ) -#define IMediaSample_SetActualDataLength(This,length) \ - ( (This)->lpVtbl -> SetActualDataLength(This,length) ) -#define IMediaSample_GetMediaType(This,ppMediaType) \ - ( (This)->lpVtbl -> GetMediaType(This,ppMediaType) ) -#define IMediaSample_SetMediaType(This,pMediaType) \ - ( (This)->lpVtbl -> SetMediaType(This,pMediaType) ) -#define IMediaSample_IsDiscontinuity(This) \ - ( (This)->lpVtbl -> IsDiscontinuity(This) ) -#define IMediaSample_SetDiscontinuity(This,bDiscontinuity) \ - ( (This)->lpVtbl -> SetDiscontinuity(This,bDiscontinuity) ) -#define IMediaSample_GetMediaTime(This,pTimeStart,pTimeEnd) \ - ( (This)->lpVtbl -> GetMediaTime(This,pTimeStart,pTimeEnd) ) -#define IMediaSample_SetMediaTime(This,pTimeStart,pTimeEnd) \ - ( (This)->lpVtbl -> SetMediaTime(This,pTimeStart,pTimeEnd) ) -#endif /* COBJMACROS */ - -#ifdef COBJMACROS -#define IEnumFilters_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define IEnumFilters_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) -#define IEnumFilters_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) -#define IEnumFilters_Next(This,cFilters,ppFilter,pcFetched) \ - ( (This)->lpVtbl -> Next(This,cFilters,ppFilter,pcFetched) ) -#define IEnumFilters_Skip(This,cFilters) \ - ( (This)->lpVtbl -> Skip(This,cFilters) ) -#define IEnumFilters_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) -#define IEnumFilters_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) -#endif /* COBJMACROS */ - -#ifdef COBJMACROS -#define IMemAllocator_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define IMemAllocator_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) -#define IMemAllocator_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) -#define IMemAllocator_SetProperties(This,pRequest,pActual) \ - ( (This)->lpVtbl -> SetProperties(This,pRequest,pActual) ) -#define IMemAllocator_GetProperties(This,pProps) \ - ( (This)->lpVtbl -> GetProperties(This,pProps) ) -#define IMemAllocator_Commit(This) \ - ( (This)->lpVtbl -> Commit(This) ) -#define IMemAllocator_Decommit(This) \ - ( (This)->lpVtbl -> Decommit(This) ) -#define IMemAllocator_GetBuffer(This,ppBuffer,pStartTime,pEndTime,dwFlags) \ - ( (This)->lpVtbl -> GetBuffer(This,ppBuffer,pStartTime,pEndTime,dwFlags) ) -#define IMemAllocator_ReleaseBuffer(This,pBuffer) \ - ( (This)->lpVtbl -> ReleaseBuffer(This,pBuffer) ) -#endif /* COBJMACROS */ - -#ifdef COBJMACROS -#define IMemInputPin_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define IMemInputPin_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) -#define IMemInputPin_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) -#define IMemInputPin_GetAllocator(This,ppAllocator) \ - ( (This)->lpVtbl -> GetAllocator(This,ppAllocator) ) -#define IMemInputPin_NotifyAllocator(This,pAllocator,bReadOnly) \ - ( (This)->lpVtbl -> NotifyAllocator(This,pAllocator,bReadOnly) ) -#define IMemInputPin_GetAllocatorRequirements(This,pProps) \ - ( (This)->lpVtbl -> GetAllocatorRequirements(This,pProps) ) -#define IMemInputPin_Receive(This,pSample) \ - ( (This)->lpVtbl -> Receive(This,pSample) ) -#define IMemInputPin_ReceiveMultiple(This,pSamples,nSamples,nSamplesProcessed) \ - ( (This)->lpVtbl -> ReceiveMultiple(This,pSamples,nSamples,nSamplesProcessed) ) -#define IMemInputPin_ReceiveCanBlock(This) \ - ( (This)->lpVtbl -> ReceiveCanBlock(This) ) -#endif /* COBJMACROS */ - -#ifdef COBJMACROS -#define IGraphBuilder_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define IGraphBuilder_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) -#define IGraphBuilder_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) -#define IGraphBuilder_AddFilter(This,pFilter,pName) \ - ( (This)->lpVtbl -> AddFilter(This,pFilter,pName) ) -#define IGraphBuilder_RemoveFilter(This,pFilter) \ - ( (This)->lpVtbl -> RemoveFilter(This,pFilter) ) -#define IGraphBuilder_EnumFilters(This,ppEnum) \ - ( (This)->lpVtbl -> EnumFilters(This,ppEnum) ) -#define IGraphBuilder_FindFilterByName(This,pName,ppFilter) \ - ( (This)->lpVtbl -> FindFilterByName(This,pName,ppFilter) ) -#define IGraphBuilder_ConnectDirect(This,ppinOut,ppinIn,pmt) \ - ( (This)->lpVtbl -> ConnectDirect(This,ppinOut,ppinIn,pmt) ) -#define IGraphBuilder_Reconnect(This,ppin) \ - ( (This)->lpVtbl -> Reconnect(This,ppin) ) -#define IGraphBuilder_Disconnect(This,ppin) \ - ( (This)->lpVtbl -> Disconnect(This,ppin) ) -#define IGraphBuilder_SetDefaultSyncSource(This) \ - ( (This)->lpVtbl -> SetDefaultSyncSource(This) ) -#define IGraphBuilder_Connect(This,ppinOut,ppinIn) \ - ( (This)->lpVtbl -> Connect(This,ppinOut,ppinIn) ) -#define IGraphBuilder_Render(This,ppinOut) \ - ( (This)->lpVtbl -> Render(This,ppinOut) ) -#define IGraphBuilder_RenderFile(This,lpcwstrFile,lpcwstrPlayList) \ - ( (This)->lpVtbl -> RenderFile(This,lpcwstrFile,lpcwstrPlayList) ) -#define IGraphBuilder_AddSourceFilter(This,lpcwstrFileName,lpcwstrFilterName,ppFilter) \ - ( (This)->lpVtbl -> AddSourceFilter(This,lpcwstrFileName,lpcwstrFilterName,ppFilter) ) -#define IGraphBuilder_SetLogFile(This,hFile) \ - ( (This)->lpVtbl -> SetLogFile(This,hFile) ) -#define IGraphBuilder_Abort(This) \ - ( (This)->lpVtbl -> Abort(This) ) -#define IGraphBuilder_ShouldOperationContinue(This) \ - ( (This)->lpVtbl -> ShouldOperationContinue(This) ) -#endif /* COBJMACROS */ - -#ifdef COBJMACROS -#define IEnumMediaTypes_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define IEnumMediaTypes_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) -#define IEnumMediaTypes_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) -#define IEnumMediaTypes_Next(This,cMediaTypes,ppMediaTypes,pcFetched) \ - ( (This)->lpVtbl -> Next(This,cMediaTypes,ppMediaTypes,pcFetched) ) -#define IEnumMediaTypes_Skip(This,cMediaTypes) \ - ( (This)->lpVtbl -> Skip(This,cMediaTypes) ) -#define IEnumMediaTypes_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) -#define IEnumMediaTypes_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) -#endif /* COBJMACROS */ - -#ifdef COBJMACROS -#define IMediaControl_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define IMediaControl_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) -#define IMediaControl_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) -#define IMediaControl_GetTypeInfoCount(This,pctinfo) \ - ( (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) ) -#define IMediaControl_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - ( (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) ) -#define IMediaControl_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - ( (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) ) -#define IMediaControl_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - ( (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) ) -#define IMediaControl_Run(This) \ - ( (This)->lpVtbl -> Run(This) ) -#define IMediaControl_Pause(This) \ - ( (This)->lpVtbl -> Pause(This) ) -#define IMediaControl_Stop(This) \ - ( (This)->lpVtbl -> Stop(This) ) -#define IMediaControl_GetState(This,msTimeout,pfs) \ - ( (This)->lpVtbl -> GetState(This,msTimeout,pfs) ) -#define IMediaControl_RenderFile(This,strFilename) \ - ( (This)->lpVtbl -> RenderFile(This,strFilename) ) -#define IMediaControl_AddSourceFilter(This,strFilename,ppUnk) \ - ( (This)->lpVtbl -> AddSourceFilter(This,strFilename,ppUnk) ) -#define IMediaControl_get_FilterCollection(This,ppUnk) \ - ( (This)->lpVtbl -> get_FilterCollection(This,ppUnk) ) -#define IMediaControl_get_RegFilterCollection(This,ppUnk) \ - ( (This)->lpVtbl -> get_RegFilterCollection(This,ppUnk) ) -#define IMediaControl_StopWhenReady(This) \ - ( (This)->lpVtbl -> StopWhenReady(This) ) -#endif /* COBJMACROS */ - -#ifdef COBJMACROS -#define IAMVideoProcAmp_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define IAMVideoProcAmp_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) -#define IAMVideoProcAmp_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) -#define IAMVideoProcAmp_GetRange(This,Property,pMin,pMax,pSteppingDelta,pDefault,pCapsFlags) \ - ( (This)->lpVtbl -> GetRange(This,Property,pMin,pMax,pSteppingDelta,pDefault,pCapsFlags) ) -#define IAMVideoProcAmp_Set(This,Property,lValue,Flags) \ - ( (This)->lpVtbl -> Set(This,Property,lValue,Flags) ) -#define IAMVideoProcAmp_Get(This,Property,lValue,Flags) \ - ( (This)->lpVtbl -> Get(This,Property,lValue,Flags) ) -#endif /* COBJMACROS */ - -#ifdef COBJMACROS -#define IFileSinkFilter_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define IFileSinkFilter_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) -#define IFileSinkFilter_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) -#define IFileSinkFilter_SetFileName(This,pszFileName,pmt) \ - ( (This)->lpVtbl -> SetFileName(This,pszFileName,pmt) ) -#define IFileSinkFilter_GetCurFile(This,ppszFileName,pmt) \ - ( (This)->lpVtbl -> GetCurFile(This,ppszFileName,pmt) ) -#endif /* COBJMACROS */ - -#ifdef COBJMACROS -#define IAMCopyCaptureFileProgress_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define IAMCopyCaptureFileProgress_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) -#define IAMCopyCaptureFileProgress_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) -#define IAMCopyCaptureFileProgress_Progress(This,iProgress) \ - ( (This)->lpVtbl -> Progress(This,iProgress) ) -#endif /* COBJMACROS */ - - -#ifdef COBJMACROS -#define ICaptureGraphBuilder2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define ICaptureGraphBuilder2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) -#define ICaptureGraphBuilder2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) -#define ICaptureGraphBuilder2_SetFiltergraph(This,pfg) \ - ( (This)->lpVtbl -> SetFiltergraph(This,pfg) ) -#define ICaptureGraphBuilder2_GetFiltergraph(This,ppfg) \ - ( (This)->lpVtbl -> GetFiltergraph(This,ppfg) ) -#define ICaptureGraphBuilder2_SetOutputFileName(This,pType,lpstrFile,ppf,ppSink) \ - ( (This)->lpVtbl -> SetOutputFileName(This,pType,lpstrFile,ppf,ppSink) ) -#define ICaptureGraphBuilder2_FindInterface(This,pCategory,pType,pf,riid,ppint) \ - ( (This)->lpVtbl -> FindInterface(This,pCategory,pType,pf,riid,ppint) ) -#define ICaptureGraphBuilder2_RenderStream(This,pCategory,pType,pSource,pfCompressor,pfRenderer) \ - ( (This)->lpVtbl -> RenderStream(This,pCategory,pType,pSource,pfCompressor,pfRenderer) ) -#define ICaptureGraphBuilder2_ControlStream(This,pCategory,pType,pFilter,pstart,pstop,wStartCookie,wStopCookie) \ - ( (This)->lpVtbl -> ControlStream(This,pCategory,pType,pFilter,pstart,pstop,wStartCookie,wStopCookie) ) -#define ICaptureGraphBuilder2_AllocCapFile(This,lpstr,dwlSize) \ - ( (This)->lpVtbl -> AllocCapFile(This,lpstr,dwlSize) ) -#define ICaptureGraphBuilder2_CopyCaptureFile(This,lpwstrOld,lpwstrNew,fAllowEscAbort,pCallback) \ - ( (This)->lpVtbl -> CopyCaptureFile(This,lpwstrOld,lpwstrNew,fAllowEscAbort,pCallback) ) -#define ICaptureGraphBuilder2_FindPin(This,pSource,pindir,pCategory,pType,fUnconnected,num,ppPin) \ - ( (This)->lpVtbl -> FindPin(This,pSource,pindir,pCategory,pType,fUnconnected,num,ppPin) ) -#endif /* COBJMACROS */ - -#endif // _MARU_CAMERA_INTERFACE_H_ +/* + * Interface definition header for Windows host. + * + * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * JinHyung Jo + * YeongKyoon Lee + * + * 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 + * + */ + +#ifndef _MARU_CAMERA_INTERFACE_H_ +#define _MARU_CAMERA_INTERFACE_H_ + +extern int hax_enabled(void); + +static const WCHAR HWCPinName[] = L"HWCInputPin\0"; +static const WCHAR HWCFilterName[] = L"HWCFilter\0"; + +/* Forward Declarations */ +FWD_DECL(IBaseFilter); +FWD_DECL(IFilterGraph); + +/* defines */ +#define MAX_PIN_NAME 128 +#define MAX_FILTER_NAME 128 + +#define DECLARE_INTERFACE2(i) \ + _COM_interface i { CONST_VTABLE struct i##Vtbl *lpVtbl; }; \ + typedef CONST_VTABLE struct i##Vtbl i##Vtbl; \ + CONST_VTABLE struct i##Vtbl +#define DECLARE_INTERFACE2_(i, b) DECLARE_INTERFACE2(i) + +typedef LONGLONG REFERENCE_TIME; +typedef long OAFilterState; +typedef DWORD_PTR HSEMAPHORE; +typedef DWORD_PTR HEVENT; + +typedef enum _FilterState { + State_Stopped, + State_Paused, + State_Running +} FILTER_STATE; + +typedef struct _FilterInfo { + WCHAR achName[MAX_FILTER_NAME]; + IFilterGraph *pGraph; +} FILTER_INFO; + +typedef enum _PinDirection { + PINDIR_INPUT = 0, + PINDIR_OUTPUT = (PINDIR_INPUT + 1) +} PIN_DIRECTION; + +typedef struct _PinInfo { + IBaseFilter *pFilter; + PIN_DIRECTION dir; + WCHAR achName[MAX_PIN_NAME]; +} PIN_INFO; + +typedef struct _AllocatorProperties { + long cBuffers; + long cbBuffer; + long cbAlign; + long cbPrefix; +} ALLOCATOR_PROPERTIES; + +typedef struct _AMMediaType { + GUID majortype; + GUID subtype; + BOOL bFixedSizeSamples; + BOOL bTemporalCompression; + ULONG lSampleSize; + GUID formattype; + IUnknown *pUnk; + ULONG cbFormat; + BYTE *pbFormat; +} AM_MEDIA_TYPE; + +typedef enum tagVideoProcAmpFlags { + VideoProcAmp_Flags_Auto = 0x0001, + VideoProcAmp_Flags_Manual = 0x0002 +} VideoProcAmpFlags; + +typedef enum tagVideoProcAmpProperty { + VideoProcAmp_Brightness, + VideoProcAmp_Contrast, + VideoProcAmp_Hue, + VideoProcAmp_Saturation, + VideoProcAmp_Sharpness, + VideoProcAmp_Gamma, + VideoProcAmp_ColorEnable, + VideoProcAmp_WhiteBalance, + VideoProcAmp_BacklightCompensation, + VideoProcAmp_Gain +} VideoProcAmpProperty; + +typedef struct tagVIDEOINFOHEADER { + RECT rcSource; + RECT rcTarget; + DWORD dwBitRate; + DWORD dwBitErrorRate; + REFERENCE_TIME AvgTimePerFrame; + BITMAPINFOHEADER bmiHeader; +} VIDEOINFOHEADER; + +typedef struct _VIDEO_STREAM_CONFIG_CAPS { + GUID guid; + ULONG VideoStandard; + SIZE InputSize; + SIZE MinCroppingSize; + SIZE MaxCroppingSize; + int CropGranularityX; + int CropGranularityY; + int CropAlignX; + int CropAlignY; + SIZE MinOutputSize; + SIZE MaxOutputSize; + int OutputGranularityX; + int OutputGranularityY; + int StretchTapsX; + int StretchTapsY; + int ShrinkTapsX; + int ShrinkTapsY; + LONGLONG MinFrameInterval; + LONGLONG MaxFrameInterval; + LONG MinBitsPerSecond; + LONG MaxBitsPerSecond; +} VIDEO_STREAM_CONFIG_CAPS; + + +/* Interface & Class GUIDs */ +static const IID IID_IGrabCallback = {0x4C337035,0xC89E,0x4B42,{0x9B,0x0C,0x36,0x74,0x44,0xDD,0x70,0xDD}}; + +EXTERN_C const IID IID_IBaseFilter; +EXTERN_C const IID IID_ICreateDevEnum; +EXTERN_C const IID IID_IGraphBuilder; +EXTERN_C const IID IID_IMediaSeeking; +EXTERN_C const IID IID_IMediaEventSink; +EXTERN_C const IID IID_IMemInputPin; +EXTERN_C const IID IID_IEnumPins; +EXTERN_C const IID IID_IMediaFilter; +EXTERN_C const IID IID_IEnumMediaTypes; +EXTERN_C const IID IID_IMemAllocator; +EXTERN_C const IID IID_IPin; +EXTERN_C const IID IID_ICaptureGraphBuilder2; +EXTERN_C const IID IID_IFileSinkFilter; +EXTERN_C const IID IID_IAMCopyCaptureFileProgress; +EXTERN_C const IID IID_IEnumFilters; +EXTERN_C const IID IID_IMediaSample; +EXTERN_C const IID IID_IMediaControl; +EXTERN_C const IID IID_IAMStreamConfig; +EXTERN_C const IID IID_IAMVideoProcAmp; + +EXTERN_C const IID CLSID_CaptureGraphBuilder2; +EXTERN_C const IID CLSID_VideoInputDeviceCategory; +EXTERN_C const IID CLSID_AudioRender; +EXTERN_C const IID CLSID_SystemDeviceEnum; +EXTERN_C const IID CLSID_AudioRendererCategory; +EXTERN_C const IID CLSID_FilterGraph; +EXTERN_C const IID CLSID_InfTee; +EXTERN_C const IID CLSID_VideoMixingRenderer9; +EXTERN_C const IID CLSID_MemoryAllocator; + + +/* other types GUIDs*/ +EXTERN_C const IID MEDIATYPE_Audio; +EXTERN_C const IID MEDIATYPE_Video; +EXTERN_C const IID MEDIATYPE_Stream; +EXTERN_C const IID MEDIASUBTYPE_PCM; +EXTERN_C const IID MEDIASUBTYPE_WAVE; +EXTERN_C const IID MEDIASUBTYPE_Avi; +EXTERN_C const IID MEDIASUBTYPE_RGB32; +EXTERN_C const IID MEDIASUBTYPE_YV12; +EXTERN_C const IID MEDIASUBTYPE_YUY2; +EXTERN_C const IID MEDIASUBTYPE_I420; +EXTERN_C const IID MEDIASUBTYPE_YUYV; +EXTERN_C const IID FORMAT_WaveFormatEx; +EXTERN_C const IID FORMAT_VideoInfo; +EXTERN_C const IID FORMAT_VideoInfo2; +EXTERN_C const IID PIN_CATEGORY_CAPTURE; +EXTERN_C const IID PIN_CATEGORY_PREVIEW; + + +#define MEDIATYPE_NULL GUID_NULL +#define MEDIASUBTYPE_NULL GUID_NULL + +#define INTERFACE IGrabCallback +DECLARE_INTERFACE_(IGrabCallback, IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(Grab)(THIS_ ULONG,BYTE*) PURE; +}; +#undef INTERFACE + +#ifdef COBJMACROS +#define IGrabCallback_QueryInterface(T,a,b) (T)->lpVtbl->QueryInterface(T,a,b) +#define IGrabCallback_AddRef(T) (T)->lpVtbl->AddRef(T) +#define IGrabCallback_Release(T) (T)->lpVtbl->Release(T) +#define IGrabCallback_Grab(T,a,b) (T)->lpVtbl->Grab(T,a,b) +#endif /* COBJMACROS */ + +#define INTERFACE IAMCopyCaptureFileProgress +DECLARE_INTERFACE_(IAMCopyCaptureFileProgress, IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(Progress)(THIS_ int) PURE; +}; +#undef INTERFACE +#define INTERFACE IReferenceClock +DECLARE_INTERFACE_(IReferenceClock, IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(GetTime)(THIS_ REFERENCE_TIME *) PURE; + STDMETHOD(AdviseTime)(THIS_ REFERENCE_TIME, REFERENCE_TIME, HEVENT, DWORD_PTR *) PURE; + STDMETHOD(AdvisePeriodic)(THIS_ REFERENCE_TIME, REFERENCE_TIME, HSEMAPHORE, DWORD_PTR *) PURE; + STDMETHOD(Unadvise)(THIS_ DWORD_PTR) PURE; +}; +#undef INTERFACE +#define INTERFACE IEnumFilters +DECLARE_INTERFACE_(IEnumFilters, IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(Next)(THIS_ ULONG, IBaseFilter **, ULONG *) PURE; + STDMETHOD(Skip)(THIS_ ULONG) PURE; + STDMETHOD(Reset)(THIS) PURE; + STDMETHOD(Clone)(THIS_ IEnumFilters **) PURE; +}; +#undef INTERFACE +#define INTERFACE IEnumMediaTypes +DECLARE_INTERFACE_(IEnumMediaTypes, IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(Next)(THIS_ ULONG, AM_MEDIA_TYPE **, ULONG *) PURE; + STDMETHOD(Skip)(THIS_ ULONG) PURE; + STDMETHOD(Reset)(THIS) PURE; + STDMETHOD(Clone)(THIS_ IEnumMediaTypes **) PURE; +}; +#undef INTERFACE +#define INTERFACE IPin +DECLARE_INTERFACE_(IPin, IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(Connect)(THIS_ IPin *, const AM_MEDIA_TYPE *) PURE; + STDMETHOD(ReceiveConnection)(THIS_ IPin *, const AM_MEDIA_TYPE *) PURE; + STDMETHOD(Disconnect)(THIS) PURE; + STDMETHOD(ConnectedTo)(THIS_ IPin **) PURE; + STDMETHOD(ConnectionMediaType)(THIS_ AM_MEDIA_TYPE *) PURE; + STDMETHOD(QueryPinInfo)(THIS_ PIN_INFO *) PURE; + STDMETHOD(QueryDirection)(THIS_ PIN_DIRECTION *) PURE; + STDMETHOD(QueryId)(THIS_ LPWSTR *) PURE; + STDMETHOD(QueryAccept)(THIS_ const AM_MEDIA_TYPE *) PURE; + STDMETHOD(EnumMediaTypes)(THIS_ IEnumMediaTypes **) PURE; + STDMETHOD(QueryInternalConnections)(THIS_ IPin **, ULONG *) PURE; + STDMETHOD(EndOfStream)(THIS) PURE; + STDMETHOD(BeginFlush)(THIS) PURE; + STDMETHOD(EndFlush)(THIS) PURE; + STDMETHOD(NewSegment)(THIS_ REFERENCE_TIME, REFERENCE_TIME, double) PURE; +}; +#undef INTERFACE +#define INTERFACE IEnumPins +DECLARE_INTERFACE_(IEnumPins, IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(Next)(THIS_ ULONG, IPin **, ULONG *) PURE; + STDMETHOD(Skip)(THIS_ ULONG) PURE; + STDMETHOD(Reset)(THIS) PURE; + STDMETHOD(Clone)(THIS_ IEnumPins **) PURE; +}; +#undef INTERFACE +#define INTERFACE IMediaFilter +DECLARE_INTERFACE_(IMediaFilter, IPersist) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(GetClassID)(THIS_ CLSID*) PURE; + STDMETHOD(Stop)(THIS) PURE; + STDMETHOD(Pause)(THIS) PURE; + STDMETHOD(Run)(THIS_ REFERENCE_TIME) PURE; + STDMETHOD(GetState)(THIS_ DWORD, FILTER_STATE *) PURE; + STDMETHOD(SetSyncSource)(THIS_ IReferenceClock *) PURE; + STDMETHOD(GetSyncSource)(THIS_ IReferenceClock **) PURE; +}; +#undef INTERFACE +#define INTERFACE IBaseFilter +DECLARE_INTERFACE2_(IBaseFilter, IMediaFilter) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(GetClassID)(THIS_ CLSID*) PURE; + STDMETHOD(Stop)(THIS) PURE; + STDMETHOD(Pause)(THIS) PURE; + STDMETHOD(Run)(THIS_ REFERENCE_TIME) PURE; + STDMETHOD(GetState)(THIS_ DWORD, FILTER_STATE *) PURE; + STDMETHOD(SetSyncSource)(THIS_ IReferenceClock *) PURE; + STDMETHOD(GetSyncSource)(THIS_ IReferenceClock **) PURE; + STDMETHOD(EnumPins)(THIS_ IEnumPins **) PURE; + STDMETHOD(FindPin)(THIS_ LPCWSTR, IPin **) PURE; + STDMETHOD(QueryFilterInfo)(THIS_ FILTER_INFO *) PURE; + STDMETHOD(JoinFilterGraph)(THIS_ IFilterGraph *, LPCWSTR) PURE; + STDMETHOD(QueryVendorInfo)(THIS_ LPWSTR *) PURE; +}; +#undef INTERFACE +#define INTERFACE IFilterGraph +DECLARE_INTERFACE2_(IFilterGraph, IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(AddFilter)(THIS_ IBaseFilter *, LPCWSTR) PURE; + STDMETHOD(RemoveFilter)(THIS_ IBaseFilter *) PURE; + STDMETHOD(EnumFilters)(THIS_ IEnumFilters **) PURE; + STDMETHOD(FindFilterByName)(THIS_ LPCWSTR, IBaseFilter **) PURE; + STDMETHOD(ConnectDirect)(THIS_ IPin *, IPin *, const AM_MEDIA_TYPE *) PURE; + STDMETHOD(Reconnect)(THIS_ IPin *) PURE; + STDMETHOD(Disconnect)(THIS_ IPin *) PURE; + STDMETHOD(SetDefaultSyncSource)(THIS) PURE; +}; +#undef INTERFACE +#define INTERFACE IGraphBuilder +DECLARE_INTERFACE_(IGraphBuilder ,IFilterGraph) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(AddFilter)(THIS_ IBaseFilter *, LPCWSTR) PURE; + STDMETHOD(RemoveFilter)(THIS_ IBaseFilter *) PURE; + STDMETHOD(EnumFilters)(THIS_ IEnumFilters **) PURE; + STDMETHOD(FindFilterByName)(THIS_ LPCWSTR, IBaseFilter **) PURE; + STDMETHOD(ConnectDirect)(THIS_ IPin *, IPin *, const AM_MEDIA_TYPE *) PURE; + STDMETHOD(Reconnect)(THIS_ IPin *) PURE; + STDMETHOD(Disconnect)(THIS_ IPin *) PURE; + STDMETHOD(SetDefaultSyncSource)(THIS) PURE; + STDMETHOD(Connect)(THIS_ IPin *, IPin *) PURE; + STDMETHOD(Render)(THIS_ IPin *) PURE; + STDMETHOD(RenderFile)(THIS_ LPCWSTR, LPCWSTR) PURE; + STDMETHOD(AddSourceFilter)(THIS_ LPCWSTR, LPCWSTR, IBaseFilter **) PURE; + STDMETHOD(SetLogFile)(THIS_ DWORD_PTR) PURE; + STDMETHOD(Abort)(THIS) PURE; + STDMETHOD(ShouldOperationContinue)(THIS) PURE; +}; +#undef INTERFACE +#define INTERFACE ICreateDevEnum +DECLARE_INTERFACE_(ICreateDevEnum, IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(CreateClassEnumerator)(THIS_ REFCLSID, IEnumMoniker **, DWORD) PURE; +}; +#undef INTERFACE +#define INTERFACE IMediaSample +DECLARE_INTERFACE_(IMediaSample, IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(GetPointer)(THIS_ BYTE **) PURE; + STDMETHOD_(long, GetSize)(THIS) PURE; + STDMETHOD(GetTime)(THIS_ REFERENCE_TIME *, REFERENCE_TIME *) PURE; + STDMETHOD(SetTime)(THIS_ REFERENCE_TIME *, REFERENCE_TIME *) PURE; + STDMETHOD(IsSyncPoint)(THIS) PURE; + STDMETHOD(SetSyncPoint)(THIS_ BOOL) PURE; + STDMETHOD(IsPreroll)(THIS) PURE; + STDMETHOD(SetPreroll)(THIS_ BOOL) PURE; + STDMETHOD_(long, GetActualDataLength)(THIS) PURE; + STDMETHOD(SetActualDataLength)(THIS_ long) PURE; + STDMETHOD(GetMediaType)(THIS_ AM_MEDIA_TYPE **) PURE; + STDMETHOD(SetMediaType)(THIS_ AM_MEDIA_TYPE *) PURE; + STDMETHOD(IsDiscontinuity)(THIS) PURE; + STDMETHOD(SetDiscontinuity)(THIS_ BOOL) PURE; + STDMETHOD(GetMediaTime)(THIS_ LONGLONG *, LONGLONG *) PURE; + STDMETHOD(SetMediaTime)(THIS_ LONGLONG *, LONGLONG *) PURE; +}; +#undef INTERFACE +#define INTERFACE IMemAllocator +DECLARE_INTERFACE_(IMemAllocator, IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(SetProperties)(THIS_ ALLOCATOR_PROPERTIES *, ALLOCATOR_PROPERTIES *) PURE; + STDMETHOD(GetProperties)(THIS_ ALLOCATOR_PROPERTIES *) PURE; + STDMETHOD(Commit)(THIS) PURE; + STDMETHOD(Decommit)(THIS) PURE; + STDMETHOD(GetBuffer)(THIS_ IMediaSample **, REFERENCE_TIME *, REFERENCE_TIME *, DWORD) PURE; + STDMETHOD(ReleaseBuffer)(THIS_ IMediaSample *) PURE; + +}; +#undef INTERFACE +#define INTERFACE IMemInputPin +DECLARE_INTERFACE_(IMemInputPin, IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(GetAllocator)(THIS_ IMemAllocator **) PURE; + STDMETHOD(NotifyAllocator)(THIS_ IMemAllocator *, BOOL) PURE; + STDMETHOD(GetAllocatorRequirements)(THIS_ ALLOCATOR_PROPERTIES *) PURE; + STDMETHOD(Receive)(THIS_ IMediaSample *) PURE; + STDMETHOD(ReceiveMultiple)(THIS_ IMediaSample **, long, long *) PURE; + STDMETHOD(ReceiveCanBlock)(THIS) PURE; +}; +#undef INTERFACE +#define INTERFACE IFileSinkFilter +DECLARE_INTERFACE_(IFileSinkFilter, IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(SetFileName)(THIS_ LPCOLESTR,const AM_MEDIA_TYPE *) PURE; + STDMETHOD(GetCurFile)(THIS_ LPOLESTR *,AM_MEDIA_TYPE*) PURE; +}; +#undef INTERFACE +#define INTERFACE ICaptureGraphBuilder2 +DECLARE_INTERFACE_(ICaptureGraphBuilder2, IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(SetFiltergraph)(THIS_ IGraphBuilder*) PURE; + STDMETHOD(GetFiltergraph)(THIS_ IGraphBuilder**) PURE; + STDMETHOD(SetOutputFileName)(THIS_ const GUID*,LPCOLESTR,IBaseFilter**,IFileSinkFilter**) PURE; + STDMETHOD(FindInterface)(THIS_ const GUID*,const GUID*,IBaseFilter*,REFIID,void**) PURE; + STDMETHOD(RenderStream)(THIS_ const GUID*,const GUID*,IUnknown*,IBaseFilter*,IBaseFilter*) PURE; + STDMETHOD(ControlStream)(THIS_ const GUID*,const GUID*,IBaseFilter*,REFERENCE_TIME*,REFERENCE_TIME*,WORD,WORD) PURE; + STDMETHOD(AllocCapFile)(THIS_ LPCOLESTR,DWORDLONG) PURE; + STDMETHOD(CopyCaptureFile)(THIS_ LPOLESTR,LPOLESTR,int,IAMCopyCaptureFileProgress*) PURE; + STDMETHOD(FindPin)(THIS_ IUnknown*,PIN_DIRECTION,const GUID*,const GUID*,BOOL,int,IPin**) PURE; +}; +#undef INTERFACE +#define INTERFACE IAMStreamConfig +DECLARE_INTERFACE_(IAMStreamConfig, IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(SetFormat)(THIS_ AM_MEDIA_TYPE*) PURE; + STDMETHOD(GetFormat)(THIS_ AM_MEDIA_TYPE**) PURE; + STDMETHOD(GetNumberOfCapabilities)(THIS_ int*,int*) PURE; + STDMETHOD(GetStreamCaps)(THIS_ int,AM_MEDIA_TYPE**,BYTE*) PURE; +}; +#undef INTERFACE +#define INTERFACE IAMVideoProcAmp +DECLARE_INTERFACE_(IAMVideoProcAmp, IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(GetRange)(THIS_ long,long*,long*,long*,long*,long*) PURE; + STDMETHOD(Set)(THIS_ long,long,long) PURE; + STDMETHOD(Get)(THIS_ long,long*,long*) PURE; +}; +#undef INTERFACE +#define INTERFACE IMediaControl +DECLARE_INTERFACE_(IMediaControl, IDispatch) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(GetTypeInfoCount)(THIS_ UINT*); + STDMETHOD(GetTypeInfo)(THIS_ UINT,LCID,ITypeInfo**); + STDMETHOD(GetIDsOfNames)(THIS_ REFIID,LPOLESTR*,UINT,LCID,DISPID*); + STDMETHOD(Invoke)(THIS_ DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*); + STDMETHOD(Run)(THIS); + STDMETHOD(Pause)(THIS); + STDMETHOD(Stop)(THIS); + STDMETHOD(GetState)(THIS_ LONG, OAFilterState*); + STDMETHOD(RenderFile)(THIS_ BSTR); + STDMETHOD(AddSourceFilter)(THIS_ BSTR,IDispatch**); + STDMETHOD(get_FilterCollection)(THIS_ IDispatch**); + STDMETHOD(get_RegFilterCollection)(THIS_ IDispatch**); + STDMETHOD(StopWhenReady)(THIS); +}; +#undef INTERFACE + +#ifdef COBJMACROS +#define ICreateDevEnum_QueryInterface(This,riid,ppvObject) \ + ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) +#define ICreateDevEnum_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) +#define ICreateDevEnum_Release(This) \ + ((This)->lpVtbl->Release(This)) +#define ICreateDevEnum_CreateClassEnumerator(This,clsidDeviceClass,ppEnumMoniker,dwFlags) \ + ((This)->lpVtbl->CreateClassEnumerator(This,clsidDeviceClass,ppEnumMoniker,dwFlags)) +#endif /* COBJMACROS */ + +#ifdef COBJMACROS +#define IPin_QueryInterface(This,riid,ppvObject) \ + ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) +#define IPin_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) +#define IPin_Release(This) \ + ((This)->lpVtbl->Release(This)) +#define IPin_Connect(This,pReceivePin,pmt) \ + ((This)->lpVtbl->Connect(This,pReceivePin,pmt)) +#define IPin_ReceiveConnection(This,pConnector,pmt) \ + ((This)->lpVtbl->ReceiveConnection(This,pConnector,pmt)) +#define IPin_Disconnect(This) \ + ((This)->lpVtbl->Disconnect(This)) +#define IPin_ConnectedTo(This,pPin) \ + ((This)->lpVtbl->ConnectedTo(This,pPin)) +#define IPin_ConnectionMediaType(This,pmt) \ + ((This)->lpVtbl->ConnectionMediaType(This,pmt)) +#define IPin_QueryPinInfo(This,pInfo) \ + ((This)->lpVtbl->QueryPinInfo(This,pInfo)) +#define IPin_QueryDirection(This,pPinDir) \ + ((This)->lpVtbl->QueryDirection(This,pPinDir)) +#define IPin_QueryId(This,Id) \ + ((This)->lpVtbl->QueryId(This,Id)) +#define IPin_QueryAccept(This,pmt) \ + ((This)->lpVtbl->QueryAccept(This,pmt)) +#define IPin_EnumMediaTypes(This,ppEnum) \ + ((This)->lpVtbl->EnumMediaTypes(This,ppEnum)) +#define IPin_QueryInternalConnections(This,apPin,nPin) \ + ((This)->lpVtbl->QueryInternalConnections(This,apPin,nPin)) +#define IPin_EndOfStream(This) \ + ((This)->lpVtbl->EndOfStream(This)) +#define IPin_BeginFlush(This) \ + ((This)->lpVtbl->BeginFlush(This)) +#define IPin_EndFlush(This) \ + ((This)->lpVtbl->EndFlush(This)) +#define IPin_NewSegment(This,tStart,tStop,dRate) \ + ((This)->lpVtbl->NewSegment(This,tStart,tStop,dRate)) +#endif /* COBJMACROS */ + +#ifdef COBJMACROS +#define IEnumPins_QueryInterface(This,riid,ppvObject) \ + ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) +#define IEnumPins_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) +#define IEnumPins_Release(This) \ + ((This)->lpVtbl->Release(This)) +#define IEnumPins_Next(This,cPins,ppPins,pcFetched) \ + ((This)->lpVtbl->Next(This,cPins,ppPins,pcFetched)) +#define IEnumPins_Skip(This,cPins) \ + ((This)->lpVtbl->Skip(This,cPins)) +#define IEnumPins_Reset(This) \ + ((This)->lpVtbl->Reset(This)) +#define IEnumPins_Clone(This,ppEnum) \ + ((This)->lpVtbl->Clone(This,ppEnum)) +#endif /* COBJMACROS */ + +#ifdef COBJMACROS +#define IAMStreamConfig_QueryInterface(This,riid,ppvObject) \ + ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) +#define IAMStreamConfig_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) +#define IAMStreamConfig_Release(This) \ + ((This)->lpVtbl->Release(This)) +#define IAMStreamConfig_SetFormat(This,pmt) \ + ((This)->lpVtbl->SetFormat(This,pmt)) +#define IAMStreamConfig_GetFormat(This,ppmt) \ + ((This)->lpVtbl->GetFormat(This,ppmt)) +#define IAMStreamConfig_GetNumberOfCapabilities(This,piCount,piSize) \ + ((This)->lpVtbl->GetNumberOfCapabilities(This,piCount,piSize)) +#define IAMStreamConfig_GetStreamCaps(This,iIndex,ppmt,pSCC) \ + ((This)->lpVtbl->GetStreamCaps(This,iIndex,ppmt,pSCC)) +#endif /* COBJMACROS */ + +#ifdef COBJMACROS +#define IFilterGraph_QueryInterface(This,riid,ppvObject) \ + ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) +#define IFilterGraph_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) +#define IFilterGraph_Release(This) \ + ((This)->lpVtbl->Release(This)) +#define IFilterGraph_AddFilter(This,pFilter,pName) \ + ((This)->lpVtbl->AddFilter(This,pFilter,pName)) +#define IFilterGraph_RemoveFilter(This,pFilter) \ + ((This)->lpVtbl->RemoveFilter(This,pFilter)) +#define IFilterGraph_EnumFilters(This,ppEnum) \ + ((This)->lpVtbl->EnumFilters(This,ppEnum)) +#define IFilterGraph_FindFilterByName(This,pName,ppFilter) \ + ((This)->lpVtbl->FindFilterByName(This,pName,ppFilter)) +#define IFilterGraph_ConnectDirect(This,ppinOut,ppinIn,pmt) \ + ((This)->lpVtbl->ConnectDirect(This,ppinOut,ppinIn,pmt)) +#define IFilterGraph_Reconnect(This,ppin) \ + ((This)->lpVtbl->Reconnect(This,ppin)) +#define IFilterGraph_Disconnect(This,ppin) \ + ((This)->lpVtbl->Disconnect(This,ppin)) +#define IFilterGraph_SetDefaultSyncSource(This) \ + ((This)->lpVtbl->SetDefaultSyncSource(This)) +#endif /* COBJMACROS */ + +#ifdef COBJMACROS +#define IMediaFilter_QueryInterface(This,riid,ppvObject) \ + ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) +#define IMediaFilter_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) +#define IMediaFilter_Release(This) \ + ((This)->lpVtbl->Release(This)) +#define IMediaFilter_GetClassID(This,pClassID) \ + ((This)->lpVtbl->GetClassID(This,pClassID)) +#define IMediaFilter_Stop(This) \ + ((This)->lpVtbl->Stop(This)) +#define IMediaFilter_Pause(This) \ + ((This)->lpVtbl->Pause(This)) +#define IMediaFilter_Run(This,tStart) \ + ((This)->lpVtbl->Run(This,tStart)) +#define IMediaFilter_GetState(This,dwMilliSecsTimeout,State) \ + ((This)->lpVtbl->GetState(This,dwMilliSecsTimeout,State)) +#define IMediaFilter_SetSyncSource(This,pClock) \ + ((This)->lpVtbl->SetSyncSource(This,pClock)) +#define IMediaFilter_GetSyncSource(This,pClock) \ + ((This)->lpVtbl->GetSyncSource(This,pClock)) +#endif /* COBJMACROS */ + +#ifdef COBJMACROS +#define IBaseFilter_QueryInterface(This,riid,ppvObject) \ + ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) +#define IBaseFilter_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) +#define IBaseFilter_Release(This) \ + ((This)->lpVtbl->Release(This)) +#define IBaseFilter_GetClassID(This,pClassID) \ + ((This)->lpVtbl->GetClassID(This,pClassID)) +#define IBaseFilter_Stop(This) \ + ((This)->lpVtbl->Stop(This)) +#define IBaseFilter_Pause(This) \ + ((This)->lpVtbl->Pause(This)) +#define IBaseFilter_Run(This,tStart) \ + ((This)->lpVtbl->Run(This,tStart)) +#define IBaseFilter_GetState(This,dwMilliSecsTimeout,State) \ + ((This)->lpVtbl->GetState(This,dwMilliSecsTimeout,State)) +#define IBaseFilter_SetSyncSource(This,pClock) \ + ((This)->lpVtbl->SetSyncSource(This,pClock)) +#define IBaseFilter_GetSyncSource(This,pClock) \ + ((This)->lpVtbl->GetSyncSource(This,pClock)) +#define IBaseFilter_EnumPins(This,ppEnum) \ + ((This)->lpVtbl->EnumPins(This,ppEnum)) +#define IBaseFilter_FindPin(This,Id,ppPin) \ + ((This)->lpVtbl->FindPin(This,Id,ppPin)) +#define IBaseFilter_QueryFilterInfo(This,pInfo) \ + ((This)->lpVtbl->QueryFilterInfo(This,pInfo)) +#define IBaseFilter_JoinFilterGraph(This,pGraph,pName) \ + ((This)->lpVtbl->JoinFilterGraph(This,pGraph,pName)) +#define IBaseFilter_QueryVendorInfo(This,pVendorInfo) \ + ((This)->lpVtbl->QueryVendorInfo(This,pVendorInfo)) +#endif /* COBJMACROS */ + +#ifdef COBJMACROS +#define IMediaSample_QueryInterface(This,riid,ppvObject) \ + ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) +#define IMediaSample_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) +#define IMediaSample_Release(This) \ + ((This)->lpVtbl->Release(This)) +#define IMediaSample_GetPointer(This,ppBuffer) \ + ((This)->lpVtbl->GetPointer(This,ppBuffer)) +#define IMediaSample_GetSize(This) \ + ((This)->lpVtbl->GetSize(This)) +#define IMediaSample_GetTime(This,pTimeStart,pTimeEnd) \ + ((This)->lpVtbl->GetTime(This,pTimeStart,pTimeEnd)) +#define IMediaSample_SetTime(This,pTimeStart,pTimeEnd) \ + ((This)->lpVtbl->SetTime(This,pTimeStart,pTimeEnd)) +#define IMediaSample_IsSyncPoint(This) \ + ((This)->lpVtbl->IsSyncPoint(This)) +#define IMediaSample_SetSyncPoint(This,bIsSyncPoint) \ + ((This)->lpVtbl->SetSyncPoint(This,bIsSyncPoint)) +#define IMediaSample_IsPreroll(This) \ + ((This)->lpVtbl->IsPreroll(This)) +#define IMediaSample_SetPreroll(This,bIsPreroll) \ + ((This)->lpVtbl->SetPreroll(This,bIsPreroll)) +#define IMediaSample_GetActualDataLength(This) \ + ((This)->lpVtbl->GetActualDataLength(This)) +#define IMediaSample_SetActualDataLength(This,length) \ + ((This)->lpVtbl->SetActualDataLength(This,length)) +#define IMediaSample_GetMediaType(This,ppMediaType) \ + ((This)->lpVtbl->GetMediaType(This,ppMediaType)) +#define IMediaSample_SetMediaType(This,pMediaType) \ + ((This)->lpVtbl->SetMediaType(This,pMediaType)) +#define IMediaSample_IsDiscontinuity(This) \ + ((This)->lpVtbl->IsDiscontinuity(This)) +#define IMediaSample_SetDiscontinuity(This,bDiscontinuity) \ + ((This)->lpVtbl->SetDiscontinuity(This,bDiscontinuity)) +#define IMediaSample_GetMediaTime(This,pTimeStart,pTimeEnd) \ + ((This)->lpVtbl->GetMediaTime(This,pTimeStart,pTimeEnd)) +#define IMediaSample_SetMediaTime(This,pTimeStart,pTimeEnd) \ + ((This)->lpVtbl->SetMediaTime(This,pTimeStart,pTimeEnd)) +#endif /* COBJMACROS */ + +#ifdef COBJMACROS +#define IEnumFilters_QueryInterface(This,riid,ppvObject) \ + ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) +#define IEnumFilters_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) +#define IEnumFilters_Release(This) \ + ((This)->lpVtbl->Release(This)) +#define IEnumFilters_Next(This,cFilters,ppFilter,pcFetched) \ + ((This)->lpVtbl->Next(This,cFilters,ppFilter,pcFetched)) +#define IEnumFilters_Skip(This,cFilters) \ + ((This)->lpVtbl->Skip(This,cFilters)) +#define IEnumFilters_Reset(This) \ + ((This)->lpVtbl->Reset(This)) +#define IEnumFilters_Clone(This,ppEnum) \ + ((This)->lpVtbl->Clone(This,ppEnum)) +#endif /* COBJMACROS */ + +#ifdef COBJMACROS +#define IMemAllocator_QueryInterface(This,riid,ppvObject) \ + ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) +#define IMemAllocator_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) +#define IMemAllocator_Release(This) \ + ((This)->lpVtbl->Release(This)) +#define IMemAllocator_SetProperties(This,pRequest,pActual) \ + ((This)->lpVtbl->SetProperties(This,pRequest,pActual)) +#define IMemAllocator_GetProperties(This,pProps) \ + ((This)->lpVtbl->GetProperties(This,pProps)) +#define IMemAllocator_Commit(This) \ + ((This)->lpVtbl->Commit(This)) +#define IMemAllocator_Decommit(This) \ + ((This)->lpVtbl->Decommit(This)) +#define IMemAllocator_GetBuffer(This,ppBuffer,pStartTime,pEndTime,dwFlags) \ + ((This)->lpVtbl->GetBuffer(This,ppBuffer,pStartTime,pEndTime,dwFlags)) +#define IMemAllocator_ReleaseBuffer(This,pBuffer) \ + ((This)->lpVtbl->ReleaseBuffer(This,pBuffer)) +#endif /* COBJMACROS */ + +#ifdef COBJMACROS +#define IMemInputPin_QueryInterface(This,riid,ppvObject) \ + ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) +#define IMemInputPin_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) +#define IMemInputPin_Release(This) \ + ((This)->lpVtbl->Release(This)) +#define IMemInputPin_GetAllocator(This,ppAllocator) \ + ((This)->lpVtbl->GetAllocator(This,ppAllocator)) +#define IMemInputPin_NotifyAllocator(This,pAllocator,bReadOnly) \ + ((This)->lpVtbl->NotifyAllocator(This,pAllocator,bReadOnly)) +#define IMemInputPin_GetAllocatorRequirements(This,pProps) \ + ((This)->lpVtbl->GetAllocatorRequirements(This,pProps)) +#define IMemInputPin_Receive(This,pSample) \ + ((This)->lpVtbl->Receive(This,pSample)) +#define IMemInputPin_ReceiveMultiple(This,pSamples,nSamples,nSamplesProcessed) \ + ((This)->lpVtbl->ReceiveMultiple(This,pSamples,nSamples,nSamplesProcessed)) +#define IMemInputPin_ReceiveCanBlock(This) \ + ((This)->lpVtbl->ReceiveCanBlock(This)) +#endif /* COBJMACROS */ + +#ifdef COBJMACROS +#define IGraphBuilder_QueryInterface(This,riid,ppvObject) \ + ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) +#define IGraphBuilder_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) +#define IGraphBuilder_Release(This) \ + ((This)->lpVtbl->Release(This)) +#define IGraphBuilder_AddFilter(This,pFilter,pName) \ + ((This)->lpVtbl->AddFilter(This,pFilter,pName)) +#define IGraphBuilder_RemoveFilter(This,pFilter) \ + ((This)->lpVtbl->RemoveFilter(This,pFilter)) +#define IGraphBuilder_EnumFilters(This,ppEnum) \ + ((This)->lpVtbl->EnumFilters(This,ppEnum)) +#define IGraphBuilder_FindFilterByName(This,pName,ppFilter) \ + ((This)->lpVtbl->FindFilterByName(This,pName,ppFilter)) +#define IGraphBuilder_ConnectDirect(This,ppinOut,ppinIn,pmt) \ + ((This)->lpVtbl->ConnectDirect(This,ppinOut,ppinIn,pmt)) +#define IGraphBuilder_Reconnect(This,ppin) \ + ((This)->lpVtbl->Reconnect(This,ppin)) +#define IGraphBuilder_Disconnect(This,ppin) \ + ((This)->lpVtbl->Disconnect(This,ppin)) +#define IGraphBuilder_SetDefaultSyncSource(This) \ + ((This)->lpVtbl->SetDefaultSyncSource(This)) +#define IGraphBuilder_Connect(This,ppinOut,ppinIn) \ + ((This)->lpVtbl->Connect(This,ppinOut,ppinIn)) +#define IGraphBuilder_Render(This,ppinOut) \ + ((This)->lpVtbl->Render(This,ppinOut)) +#define IGraphBuilder_RenderFile(This,lpcwstrFile,lpcwstrPlayList) \ + ((This)->lpVtbl->RenderFile(This,lpcwstrFile,lpcwstrPlayList)) +#define IGraphBuilder_AddSourceFilter(This,lpcwstrFileName,lpcwstrFilterName,ppFilter) \ + ((This)->lpVtbl->AddSourceFilter(This,lpcwstrFileName,lpcwstrFilterName,ppFilter)) +#define IGraphBuilder_SetLogFile(This,hFile) \ + ((This)->lpVtbl->SetLogFile(This,hFile)) +#define IGraphBuilder_Abort(This) \ + ((This)->lpVtbl->Abort(This)) +#define IGraphBuilder_ShouldOperationContinue(This) \ + ((This)->lpVtbl->ShouldOperationContinue(This)) +#endif /* COBJMACROS */ + +#ifdef COBJMACROS +#define IEnumMediaTypes_QueryInterface(This,riid,ppvObject) \ + ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) +#define IEnumMediaTypes_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) +#define IEnumMediaTypes_Release(This) \ + ((This)->lpVtbl->Release(This)) +#define IEnumMediaTypes_Next(This,cMediaTypes,ppMediaTypes,pcFetched) \ + ((This)->lpVtbl->Next(This,cMediaTypes,ppMediaTypes,pcFetched)) +#define IEnumMediaTypes_Skip(This,cMediaTypes) \ + ((This)->lpVtbl->Skip(This,cMediaTypes)) +#define IEnumMediaTypes_Reset(This) \ + ((This)->lpVtbl->Reset(This)) +#define IEnumMediaTypes_Clone(This,ppEnum) \ + ((This)->lpVtbl->Clone(This,ppEnum)) +#endif /* COBJMACROS */ + +#ifdef COBJMACROS +#define IMediaControl_QueryInterface(This,riid,ppvObject) \ + ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) +#define IMediaControl_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) +#define IMediaControl_Release(This) \ + ((This)->lpVtbl->Release(This)) +#define IMediaControl_GetTypeInfoCount(This,pctinfo) \ + ((This)->lpVtbl->GetTypeInfoCount(This,pctinfo)) +#define IMediaControl_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + ((This)->lpVtbl->GetTypeInfo(This,iTInfo,lcid,ppTInfo)) +#define IMediaControl_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + ((This)->lpVtbl->GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)) +#define IMediaControl_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + ((This)->lpVtbl->Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)) +#define IMediaControl_Run(This) \ + ((This)->lpVtbl->Run(This)) +#define IMediaControl_Pause(This) \ + ((This)->lpVtbl->Pause(This)) +#define IMediaControl_Stop(This) \ + ((This)->lpVtbl->Stop(This)) +#define IMediaControl_GetState(This,msTimeout,pfs) \ + ((This)->lpVtbl->GetState(This,msTimeout,pfs)) +#define IMediaControl_RenderFile(This,strFilename) \ + ((This)->lpVtbl->RenderFile(This,strFilename)) +#define IMediaControl_AddSourceFilter(This,strFilename,ppUnk) \ + ((This)->lpVtbl->AddSourceFilter(This,strFilename,ppUnk)) +#define IMediaControl_get_FilterCollection(This,ppUnk) \ + ((This)->lpVtbl->get_FilterCollection(This,ppUnk)) +#define IMediaControl_get_RegFilterCollection(This,ppUnk) \ + ((This)->lpVtbl->get_RegFilterCollection(This,ppUnk)) +#define IMediaControl_StopWhenReady(This) \ + ((This)->lpVtbl->StopWhenReady(This)) +#endif /* COBJMACROS */ + +#ifdef COBJMACROS +#define IAMVideoProcAmp_QueryInterface(This,riid,ppvObject) \ + ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) +#define IAMVideoProcAmp_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) +#define IAMVideoProcAmp_Release(This) \ + ((This)->lpVtbl->Release(This)) +#define IAMVideoProcAmp_GetRange(This,Property,pMin,pMax,pSteppingDelta,pDefault,pCapsFlags) \ + ((This)->lpVtbl->GetRange(This,Property,pMin,pMax,pSteppingDelta,pDefault,pCapsFlags)) +#define IAMVideoProcAmp_Set(This,Property,lValue,Flags) \ + ((This)->lpVtbl->Set(This,Property,lValue,Flags)) +#define IAMVideoProcAmp_Get(This,Property,lValue,Flags) \ + ((This)->lpVtbl->Get(This,Property,lValue,Flags)) +#endif /* COBJMACROS */ + +#ifdef COBJMACROS +#define IFileSinkFilter_QueryInterface(This,riid,ppvObject) \ + ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) +#define IFileSinkFilter_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) +#define IFileSinkFilter_Release(This) \ + ((This)->lpVtbl->Release(This)) +#define IFileSinkFilter_SetFileName(This,pszFileName,pmt) \ + ((This)->lpVtbl->SetFileName(This,pszFileName,pmt)) +#define IFileSinkFilter_GetCurFile(This,ppszFileName,pmt) \ + ((This)->lpVtbl->GetCurFile(This,ppszFileName,pmt)) +#endif /* COBJMACROS */ + +#ifdef COBJMACROS +#define IAMCopyCaptureFileProgress_QueryInterface(This,riid,ppvObject) \ + ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) +#define IAMCopyCaptureFileProgress_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) +#define IAMCopyCaptureFileProgress_Release(This) \ + ((This)->lpVtbl->Release(This)) +#define IAMCopyCaptureFileProgress_Progress(This,iProgress) \ + ((This)->lpVtbl->Progress(This,iProgress)) +#endif /* COBJMACROS */ + + +#ifdef COBJMACROS +#define ICaptureGraphBuilder2_QueryInterface(This,riid,ppvObject) \ + ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) +#define ICaptureGraphBuilder2_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) +#define ICaptureGraphBuilder2_Release(This) \ + ((This)->lpVtbl->Release(This)) +#define ICaptureGraphBuilder2_SetFiltergraph(This,pfg) \ + ((This)->lpVtbl->SetFiltergraph(This,pfg)) +#define ICaptureGraphBuilder2_GetFiltergraph(This,ppfg) \ + ((This)->lpVtbl->GetFiltergraph(This,ppfg)) +#define ICaptureGraphBuilder2_SetOutputFileName(This,pType,lpstrFile,ppf,ppSink) \ + ((This)->lpVtbl->SetOutputFileName(This,pType,lpstrFile,ppf,ppSink)) +#define ICaptureGraphBuilder2_FindInterface(This,pCategory,pType,pf,riid,ppint) \ + ((This)->lpVtbl->FindInterface(This,pCategory,pType,pf,riid,ppint)) +#define ICaptureGraphBuilder2_RenderStream(This,pCategory,pType,pSource,pfCompressor,pfRenderer) \ + ((This)->lpVtbl->RenderStream(This,pCategory,pType,pSource,pfCompressor,pfRenderer)) +#define ICaptureGraphBuilder2_ControlStream(This,pCategory,pType,pFilter,pstart,pstop,wStartCookie,wStopCookie) \ + ((This)->lpVtbl->ControlStream(This,pCategory,pType,pFilter,pstart,pstop,wStartCookie,wStopCookie)) +#define ICaptureGraphBuilder2_AllocCapFile(This,lpstr,dwlSize) \ + ((This)->lpVtbl->AllocCapFile(This,lpstr,dwlSize)) +#define ICaptureGraphBuilder2_CopyCaptureFile(This,lpwstrOld,lpwstrNew,fAllowEscAbort,pCallback) \ + ((This)->lpVtbl->CopyCaptureFile(This,lpwstrOld,lpwstrNew,fAllowEscAbort,pCallback)) +#define ICaptureGraphBuilder2_FindPin(This,pSource,pindir,pCategory,pType,fUnconnected,num,ppPin) \ + ((This)->lpVtbl->FindPin(This,pSource,pindir,pCategory,pType,fUnconnected,num,ppPin)) +#endif /* COBJMACROS */ + +#endif /* _MARU_CAMERA_INTERFACE_H_ */ diff --git a/tizen/src/hw/maru_camera_win32_pci.c b/tizen/src/hw/maru_camera_win32_pci.c index 312f86a0f7..f2a044501a 100644 --- a/tizen/src/hw/maru_camera_win32_pci.c +++ b/tizen/src/hw/maru_camera_win32_pci.c @@ -1,2796 +1,2795 @@ -/* - * Implementation of MARU Virtual Camera device by PCI bus on Windows. - * - * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: - * JinHyung Jo - * YeongKyoon Lee - * - * 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 - * - */ - - -#include "qemu-common.h" -#include "maru_camera_common.h" -#include "tizen/src/debug_ch.h" - -#define CINTERFACE -#define COBJMACROS -#include "ocidl.h" -#include "errors.h" /* for VFW_E_XXXX */ -#include "mmsystem.h" /* for MAKEFOURCC macro */ -#include "maru_camera_win32_interface.h" - -MULTI_DEBUG_CHANNEL(tizen, camera_win32); - -extern int hax_enabled(void); - -/* - * COM Interface implementations - * - */ - -#define SAFE_RELEASE(x) \ - do { \ - if (x) { \ - (x)->lpVtbl->Release(x); \ - x = NULL; \ - } \ - } while (0) - -typedef HRESULT (STDAPICALLTYPE *CallbackFn)(ULONG dwSize, BYTE *pBuffer); - -/* - * HWCGrabCallback - */ - -typedef struct HWCGrabCallback { - IGrabCallback IGrabCallback_iface; - long m_cRef; - CallbackFn m_pCallback; - STDMETHODIMP (*SetCallback)(IGrabCallback *iface, CallbackFn pCallbackFn); -} HWCGrabCallback; - -static inline HWCGrabCallback *impl_from_IGrabCallback(IGrabCallback *iface) -{ - return CONTAINING_RECORD(iface, HWCGrabCallback, IGrabCallback_iface); -} - -static STDMETHODIMP HWCGrabCallback_QueryInterface(IGrabCallback *iface, - REFIID riid, void **ppv) -{ - if (IsEqualIID(riid, &IID_IUnknown)) { - *ppv = (IUnknown *)iface; - } else if (IsEqualIID(riid, &IID_IGrabCallback)) { - *ppv = (IGrabCallback *)iface; - } else { - *ppv = NULL; - return E_NOINTERFACE; - } - - IGrabCallback_AddRef(iface); - return S_OK; -} - -static STDMETHODIMP_(ULONG) HWCGrabCallback_AddRef(IGrabCallback *iface) -{ - HWCGrabCallback *This = impl_from_IGrabCallback(iface); - - return InterlockedIncrement(&This->m_cRef); -} - -static STDMETHODIMP_(ULONG) HWCGrabCallback_Release(IGrabCallback *iface) -{ - HWCGrabCallback *This = impl_from_IGrabCallback(iface); - - if (InterlockedDecrement(&This->m_cRef) == 0) { - This->m_pCallback = NULL; - g_free((void *)This); - This = NULL; - return 0; - } - - return This->m_cRef; -} - -static STDMETHODIMP HWCGrabCallback_Grab(IGrabCallback *iface, - ULONG dwSize, BYTE *pBuffer) -{ - HWCGrabCallback *This = impl_from_IGrabCallback(iface); - - if (This->m_pCallback) { - HRESULT hr = This->m_pCallback(dwSize, pBuffer); - if (FAILED(hr)) { - return E_FAIL; - } else { - return S_OK; - } - } - - return E_FAIL; -} - -static STDMETHODIMP HWCGrabCallback_SetCallback(IGrabCallback *iface, - CallbackFn pCallbackFn) -{ - HWCGrabCallback *This = impl_from_IGrabCallback(iface); - - This->m_pCallback = pCallbackFn; - return S_OK; -} - -static IGrabCallbackVtbl HWCGrabCallback_Vtbl = { - HWCGrabCallback_QueryInterface, - HWCGrabCallback_AddRef, - HWCGrabCallback_Release, - HWCGrabCallback_Grab -}; - -static STDMETHODIMP HWCGrabCallback_Construct(IGrabCallback **ppv) -{ - HWCGrabCallback *This = - (HWCGrabCallback *)g_malloc0(sizeof(HWCGrabCallback)); - - if (!This) { - ERR("failed to HWCGrabCallback_Construct, E_OUTOFMEMORY\n"); - return E_OUTOFMEMORY; - } - - This->IGrabCallback_iface.lpVtbl = &HWCGrabCallback_Vtbl; - This->m_cRef = 1; - This->m_pCallback = NULL; - This->SetCallback = HWCGrabCallback_SetCallback; - *ppv = &This->IGrabCallback_iface; - return S_OK; -} - -/* - * HWCPin - */ - -typedef struct HWCInPin { - IPin IPin_iface; - IMemInputPin IMemInputPin_iface; - IBaseFilter *m_pCFilter; - IPin *m_pConnectedPin; - IGrabCallback *m_pCallback; - IMemAllocator *m_pAllocator; - BOOL m_bReadOnly; - long m_cRef; - STDMETHODIMP (*SetGrabCallbackIF)(IPin *iface, IGrabCallback *pCaptureCB); -} HWCInPin; - -static inline HWCInPin *impl_from_IPin(IPin *iface) -{ - return CONTAINING_RECORD(iface, HWCInPin, IPin_iface); -} - -static inline HWCInPin *impl_from_IMemInputPin(IMemInputPin *iface) -{ - return CONTAINING_RECORD(iface, HWCInPin, IMemInputPin_iface); -} - -static STDMETHODIMP HWCPin_QueryInterface(IPin *iface, REFIID riid, void **ppv) -{ - HWCInPin *This = impl_from_IPin(iface); - - if (IsEqualIID(riid, &IID_IUnknown)) { - *ppv = (IUnknown *)(&This->IPin_iface); - IPin_AddRef((IPin *)*ppv); - } else if (IsEqualIID(riid, &IID_IPin)) { - *ppv = (IPin *)(&This->IPin_iface); - IPin_AddRef((IPin *)*ppv); - } else if (IsEqualIID(riid, &IID_IMemInputPin)) { - *ppv = (IMemInputPin *)(&This->IMemInputPin_iface); - IPin_AddRef((IMemInputPin *)*ppv); - } else { - *ppv = NULL; - return E_NOINTERFACE; - } - - return S_OK; -} - -static STDMETHODIMP_(ULONG) HWCPin_AddRef(IPin *iface) -{ - HWCInPin *This = impl_from_IPin(iface); - - return InterlockedIncrement(&This->m_cRef); -} - -static STDMETHODIMP_(ULONG) HWCPin_Release(IPin *iface) -{ - HWCInPin *This = impl_from_IPin(iface); - - if (InterlockedDecrement(&This->m_cRef) == 0) { - if (This->m_pCallback) { - SAFE_RELEASE(This->m_pCallback); - } - if (This->m_pConnectedPin) { - SAFE_RELEASE(This->m_pConnectedPin); - } - if (This->m_pAllocator) { - IMemAllocator_Decommit(This->m_pAllocator); - SAFE_RELEASE(This->m_pAllocator); - } - g_free((void *)This); - This = NULL; - return 0; - } - return This->m_cRef; -} - -static STDMETHODIMP HWCPin_Connect(IPin *iface, - IPin *pReceivePin, - const AM_MEDIA_TYPE *pmt) -{ - HWCInPin *This = impl_from_IPin(iface); - - if (!pReceivePin) { - return E_POINTER; - } - - if (This->m_pConnectedPin) { - return VFW_E_ALREADY_CONNECTED; - } - - if (!pmt) { - return S_OK; - } - return S_FALSE; -} - -static STDMETHODIMP HWCPin_ReceiveConnection(IPin *iface, IPin *pConnector, - const AM_MEDIA_TYPE *pmt) -{ - PIN_DIRECTION pd; - FILTER_STATE fs; - HWCInPin *This = impl_from_IPin(iface); - - if (pConnector == NULL || pmt == NULL) { - return E_POINTER; - } - - if (This->m_pConnectedPin) { - return VFW_E_ALREADY_CONNECTED; - } - IBaseFilter_GetState(This->m_pCFilter, 0, &fs); - if (fs != State_Stopped) { - return VFW_E_NOT_STOPPED; - } - IPin_QueryDirection(pConnector, &pd); - if (pd == PINDIR_INPUT) { - return VFW_E_INVALID_DIRECTION; - } - - This->m_pConnectedPin = pConnector; - IPin_AddRef(This->m_pConnectedPin); - return S_OK; -} - -static STDMETHODIMP HWCPin_Disconnect(IPin *iface) -{ - HWCInPin *This = impl_from_IPin(iface); - - HRESULT hr; - FILTER_STATE fs; - IBaseFilter_GetState(This->m_pCFilter, 0, &fs); - if (fs != State_Stopped) { - return VFW_E_NOT_STOPPED; - } - if (This->m_pConnectedPin == NULL) { - hr = S_FALSE; - } else { - if (This->m_pAllocator) { - hr = IMemAllocator_Decommit(This->m_pAllocator); - if (FAILED(hr)) { - return hr; - } - SAFE_RELEASE(This->m_pAllocator); - } - SAFE_RELEASE(This->m_pConnectedPin); - hr = S_OK; - } - return hr; -} - -static STDMETHODIMP HWCPin_ConnectedTo(IPin *iface, IPin **ppPin) -{ - HWCInPin *This = impl_from_IPin(iface); - - if (ppPin == NULL) { - return E_POINTER; - } - - if (This->m_pConnectedPin == NULL) { - *ppPin = NULL; - return VFW_E_NOT_CONNECTED; - } else { - *ppPin = This->m_pConnectedPin; - IPin_AddRef(This->m_pConnectedPin); - } - return S_OK; -} - -static STDMETHODIMP HWCPin_ConnectionMediaType(IPin *iface, AM_MEDIA_TYPE *pmt) -{ - if (pmt == NULL) { - return E_POINTER; - } - return VFW_E_NOT_CONNECTED; -} - -static STDMETHODIMP HWCPin_QueryPinInfo(IPin *iface, PIN_INFO *pInfo) -{ - HWCInPin *This = impl_from_IPin(iface); - - if (pInfo == NULL) { - return E_POINTER; - } - - pInfo->pFilter = This->m_pCFilter; - if (This->m_pCFilter) { - IBaseFilter_AddRef(This->m_pCFilter); - } - memcpy((void *)pInfo->achName, (void *)HWCPinName, sizeof(HWCPinName)); - pInfo->dir = PINDIR_INPUT; - return S_OK; -} - -static STDMETHODIMP HWCPin_QueryDirection(IPin *iface, PIN_DIRECTION *pPinDir) -{ - if (pPinDir == NULL) { - return E_POINTER; - } - *pPinDir = PINDIR_INPUT; - return S_OK; -} - -static STDMETHODIMP HWCPin_QueryId(IPin *iface, LPWSTR *Id) -{ - PVOID pId; - if (Id == NULL) { - return E_POINTER; - } - pId = CoTaskMemAlloc(sizeof(HWCPinName)); - memcpy((void *)pId, (void *)HWCPinName, sizeof(HWCPinName)); - *Id = (LPWSTR)pId; - return S_OK; -} - -static STDMETHODIMP HWCPin_QueryAccept(IPin *iface, const AM_MEDIA_TYPE *pmt) -{ - if (pmt == NULL) { - return E_POINTER; - } - return S_OK; -} - -static STDMETHODIMP HWCPin_EnumMediaTypes(IPin *iface, - IEnumMediaTypes **ppEnum) -{ - if (ppEnum == NULL) { - return E_POINTER; - } - return E_NOTIMPL; -} - -static STDMETHODIMP HWCPin_QueryInternalConnections(IPin *iface, - IPin **ppPin, - ULONG *nPin) -{ - return E_NOTIMPL; -} - -static STDMETHODIMP HWCPin_EndOfStream(IPin *iface) -{ - return S_OK; -} - -static STDMETHODIMP HWCPin_BeginFlush(IPin *iface) -{ - return S_OK; -} - -static STDMETHODIMP HWCPin_EndFlush(IPin *iface) -{ - return S_OK; -} - -static STDMETHODIMP HWCPin_NewSegment(IPin *iface, REFERENCE_TIME tStart, - REFERENCE_TIME tStop, double dRate) -{ - return S_OK; -} - -static STDMETHODIMP HWCMemInputPin_QueryInterface(IMemInputPin *iface, - REFIID riid, void **ppv) -{ - HWCInPin *This = impl_from_IMemInputPin(iface); - - if (IsEqualIID(riid, &IID_IUnknown)) { - *ppv = (IUnknown *)(&This->IMemInputPin_iface); - IPin_AddRef((IPin *)*ppv); - } else if (IsEqualIID(riid, &IID_IPin)) { - *ppv = (IPin *)(&This->IPin_iface); - IPin_AddRef((IPin *)*ppv); - } else if (IsEqualIID(riid, &IID_IMemInputPin)) { - *ppv = (IMemInputPin *)(&This->IMemInputPin_iface); - IPin_AddRef((IMemInputPin *)*ppv); - } else { - *ppv = NULL; - return E_NOINTERFACE; - } - - return S_OK; -} - -static STDMETHODIMP_(ULONG) HWCMemInputPin_AddRef(IMemInputPin *iface) -{ - HWCInPin *This = impl_from_IMemInputPin(iface); - - return InterlockedIncrement(&This->m_cRef); -} - -static STDMETHODIMP_(ULONG) HWCMemInputPin_Release(IMemInputPin *iface) -{ - HWCInPin *This = impl_from_IMemInputPin(iface); - - if (InterlockedDecrement(&This->m_cRef) == 0) { - if (This->m_pCallback) { - SAFE_RELEASE(This->m_pCallback); - } - if (This->m_pConnectedPin) { - SAFE_RELEASE(This->m_pConnectedPin); - } - if (This->m_pAllocator) { - IMemAllocator_Decommit(This->m_pAllocator); - SAFE_RELEASE(This->m_pAllocator); - } - g_free((void *)This); - This = NULL; - return 0; - } - return This->m_cRef; -} - -static STDMETHODIMP HWCMemInputPin_GetAllocator(IMemInputPin *iface, - IMemAllocator **ppAllocator) -{ - HWCInPin *This = impl_from_IMemInputPin(iface); - - if (ppAllocator == NULL) { - return E_POINTER; - } - - if (This->m_pAllocator == NULL) { - HRESULT hr = CoCreateInstance(&CLSID_MemoryAllocator, NULL, - CLSCTX_INPROC_SERVER, - &IID_IMemAllocator, - (void **)&(This->m_pAllocator)); - if (FAILED(hr)) { - ERR("Failed to CoCreateInstance for retrieving MemoryAllocator\n"); - return hr; - } - } - ASSERT(This->m_pAllocator != NULL); - *ppAllocator = This->m_pAllocator; - IMemAllocator_AddRef(This->m_pAllocator); - - return S_OK; -} - -static STDMETHODIMP HWCMemInputPin_NotifyAllocator(IMemInputPin *iface, - IMemAllocator *pAllocator, - BOOL bReadOnly) -{ - HWCInPin *This = impl_from_IMemInputPin(iface); - - if (pAllocator == NULL) { - return E_POINTER; - } - - IMemAllocator *pOldAllocator = This->m_pAllocator; - IMemAllocator_AddRef(pAllocator); - This->m_pAllocator = pAllocator; - - if (pOldAllocator != NULL) { - SAFE_RELEASE(pOldAllocator); - } - - This->m_bReadOnly = bReadOnly; - - return S_OK; -} - -static STDMETHODIMP HWCMemInputPin_GetAllocatorRequirements( - IMemInputPin *iface, - ALLOCATOR_PROPERTIES *pProps) -{ - return E_NOTIMPL; -} - -static STDMETHODIMP HWCMemInputPin_Receive(IMemInputPin *iface, - IMediaSample *pSample) -{ - HWCInPin *This = impl_from_IMemInputPin(iface); - - if (pSample == NULL) { - ERR("pSample is NULL\n"); - return E_POINTER; - } - if (This->m_pCallback != NULL) { - HRESULT hr; - BYTE *pBuffer = NULL; - DWORD dwSize = 0; - dwSize = IMediaSample_GetSize(pSample); - hr = IMediaSample_GetPointer(pSample, &pBuffer); - if (FAILED(hr)) { - ERR("Receive function : " - "failed to IMediaSample_GetPointer, 0x%ld\n", hr); - return hr; - } - hr = IGrabCallback_Grab(This->m_pCallback, dwSize, pBuffer); - if (FAILED(hr)) { - ERR("Receive function : failed to IGrabCallback_Grab, 0x%ld\n", - hr); - return hr; - } - } - return S_OK; -} - -static STDMETHODIMP HWCMemInputPin_ReceiveMultiple(IMemInputPin *iface, - IMediaSample **pSamples, - long nSamples, - long *nSamplesProcessed) -{ - HRESULT hr = S_OK; - - if (pSamples == NULL) { - return E_POINTER; - } - - *nSamplesProcessed = 0; - - while (nSamples-- > 0) { - hr = IMemInputPin_Receive(iface, pSamples[*nSamplesProcessed]); - if (hr != S_OK) { - break; - } - (*nSamplesProcessed)++; - } - return hr; -} - -static STDMETHODIMP HWCMemInputPin_ReceiveCanBlock(IMemInputPin *iface) -{ - return S_FALSE; -} - -static STDMETHODIMP HWCPin_SetCallback(IPin *iface, IGrabCallback *pCaptureCB) -{ - HWCInPin *This = impl_from_IPin(iface); - - if (pCaptureCB == NULL) { - SAFE_RELEASE(This->m_pCallback); - } else { - This->m_pCallback = pCaptureCB; - IGrabCallback_AddRef(This->m_pCallback); - } - - return S_OK; -} - - -static IPinVtbl HWCPin_Vtbl = { - HWCPin_QueryInterface, - HWCPin_AddRef, - HWCPin_Release, - HWCPin_Connect, - HWCPin_ReceiveConnection, - HWCPin_Disconnect, - HWCPin_ConnectedTo, - HWCPin_ConnectionMediaType, - HWCPin_QueryPinInfo, - HWCPin_QueryDirection, - HWCPin_QueryId, - HWCPin_QueryAccept, - HWCPin_EnumMediaTypes, - HWCPin_QueryInternalConnections, - HWCPin_EndOfStream, - HWCPin_BeginFlush, - HWCPin_EndFlush, - HWCPin_NewSegment -}; - -static IMemInputPinVtbl HWCMemInputPin_Vtbl = { - HWCMemInputPin_QueryInterface, - HWCMemInputPin_AddRef, - HWCMemInputPin_Release, - HWCMemInputPin_GetAllocator, - HWCMemInputPin_NotifyAllocator, - HWCMemInputPin_GetAllocatorRequirements, - HWCMemInputPin_Receive, - HWCMemInputPin_ReceiveMultiple, - HWCMemInputPin_ReceiveCanBlock -}; - -static STDMETHODIMP HWCInPin_Construct(IBaseFilter *pFilter, IPin **ppv) -{ - HWCInPin *This = (HWCInPin *)g_malloc0(sizeof(HWCInPin)); - - if (!This) { - ERR("failed to HWCInPin_Construct, E_OUTOFMEMORY\n"); - return E_OUTOFMEMORY; - } - - This->IPin_iface.lpVtbl = &HWCPin_Vtbl; - This->IMemInputPin_iface.lpVtbl = &HWCMemInputPin_Vtbl; - This->m_bReadOnly = FALSE; - This->m_pCFilter = pFilter; - This->m_pConnectedPin = NULL; - This->m_pCallback = NULL; - This->m_pAllocator = NULL; - This->m_cRef = 1; - This->SetGrabCallbackIF = HWCPin_SetCallback; - *ppv = &This->IPin_iface; - - return S_OK; -} - -/* - * HWCEnumPins - */ - -typedef struct HWCEnumPins { - IEnumPins IEnumPins_iface; - IBaseFilter *m_pFilter; - int m_nPos; - long m_cRef; -} HWCEnumPins; - -static inline HWCEnumPins *impl_from_IEnumPins(IEnumPins *iface) -{ - return CONTAINING_RECORD(iface, HWCEnumPins, IEnumPins_iface); -} - -static STDMETHODIMP HWCEnumPins_QueryInterface(IEnumPins *iface, - REFIID riid, void **ppv) -{ - if (ppv == NULL) { - return E_POINTER; - } - - if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IEnumPins)) { - *ppv = iface; - } else { - *ppv = NULL; - return E_NOINTERFACE; - } - - IEnumPins_AddRef(iface); - return S_OK; -} - -static STDMETHODIMP_(ULONG) HWCEnumPins_AddRef(IEnumPins *iface) -{ - HWCEnumPins *This = impl_from_IEnumPins(iface); - - return InterlockedIncrement(&This->m_cRef); -} - -static STDMETHODIMP_(ULONG) HWCEnumPins_Release(IEnumPins *iface) -{ - HWCEnumPins *This = impl_from_IEnumPins(iface); - - if (InterlockedDecrement(&This->m_cRef) == 0) { - if (This->m_pFilter) { - SAFE_RELEASE(This->m_pFilter); - } - This->m_nPos = 0; - g_free((void *)This); - This = NULL; - return 0; - } - return This->m_cRef; -} - -static STDMETHODIMP HWCEnumPins_Next(IEnumPins *iface, ULONG cPins, - IPin **ppPins, ULONG *pcFetched) -{ - ULONG fetched; - HWCEnumPins *This = impl_from_IEnumPins(iface); - - if (ppPins == NULL) { - return E_POINTER; - } - - if (This->m_nPos < 1 && cPins > 0) { - IPin *pPin; - IBaseFilter_FindPin(This->m_pFilter, HWCPinName, &pPin); - *ppPins = pPin; - fetched = 1; - This->m_nPos++; - } else { - fetched = 0; - } - - if (pcFetched != NULL) { - *pcFetched = fetched; - } - - return (fetched == cPins) ? S_OK : S_FALSE; -} - -static STDMETHODIMP HWCEnumPins_Skip(IEnumPins *iface, ULONG cPins) -{ - HWCEnumPins *This = impl_from_IEnumPins(iface); - This->m_nPos += cPins; - return (This->m_nPos >= 1) ? S_FALSE : S_OK; -} - -static STDMETHODIMP HWCEnumPins_Reset(IEnumPins *iface) -{ - HWCEnumPins *This = impl_from_IEnumPins(iface); - This->m_nPos = 0; - return S_OK; -} - -static STDMETHODIMP HWCEnumPins_Construct(IBaseFilter *pFilter, - int nPos, IEnumPins **ppv); - -static STDMETHODIMP HWCEnumPins_Clone(IEnumPins *iface, IEnumPins **ppEnum) -{ - HWCEnumPins *This = impl_from_IEnumPins(iface); - - if (ppEnum == NULL) { - return E_POINTER; - } - - HWCEnumPins_Construct(This->m_pFilter, This->m_nPos, ppEnum); - if (*ppEnum == NULL) { - ERR("failed to HWCEnumPins_Construct in clone, E_OUTOFMEMORY\n"); - return E_OUTOFMEMORY; - } - - return S_OK; -} - -static IEnumPinsVtbl HWCEnumPins_Vtbl = { - HWCEnumPins_QueryInterface, - HWCEnumPins_AddRef, - HWCEnumPins_Release, - HWCEnumPins_Next, - HWCEnumPins_Skip, - HWCEnumPins_Reset, - HWCEnumPins_Clone -}; - - -static STDMETHODIMP HWCEnumPins_Construct(IBaseFilter *pFilter, - int nPos, IEnumPins **ppv) -{ - HWCEnumPins *This = (HWCEnumPins *)g_malloc0(sizeof(HWCEnumPins)); - - if (!This) { - ERR("failed to HWCEnumPins_Construct, E_OUTOFMEMORY\n"); - return E_OUTOFMEMORY; - } - - This->IEnumPins_iface.lpVtbl = &HWCEnumPins_Vtbl; - This->m_pFilter = pFilter; - if (This->m_pFilter) { - IBaseFilter_AddRef(This->m_pFilter); - } - This->m_cRef = 1; - This->m_nPos = nPos; - *ppv = &This->IEnumPins_iface; - - return S_OK; -} - -/* - * HWCFilter - */ - -typedef struct HWCFilter { - IBaseFilter IBaseFilter_iface; - IPin *m_pPin; - IFilterGraph *m_pFilterGraph; - FILTER_STATE m_state; - long m_cRef; -} HWCFilter; - -static inline HWCFilter *impl_from_IBaseFilter(IBaseFilter *iface) -{ - return CONTAINING_RECORD(iface, HWCFilter, IBaseFilter_iface); -} - -static STDMETHODIMP HWCFilter_QueryInterface(IBaseFilter *iface, - REFIID riid, void **ppv) -{ - if (IsEqualIID(riid, &IID_IUnknown)) { - *ppv = (IUnknown *)iface; - } else if (IsEqualIID(riid, &IID_IPersist)) { - *ppv = (IPersist *)iface; - } else if (IsEqualIID(riid, &IID_IMediaFilter)) { - *ppv = (IMediaFilter *)iface; - } else if (IsEqualIID(riid, &IID_IBaseFilter)) { - *ppv = (IBaseFilter *)iface; - } else { - *ppv = NULL; - return E_NOINTERFACE; - } - - IBaseFilter_AddRef(iface); - return S_OK; -} - -static STDMETHODIMP_(ULONG) HWCFilter_AddRef(IBaseFilter *iface) -{ - HWCFilter *This = impl_from_IBaseFilter(iface); - - return InterlockedIncrement(&This->m_cRef); -} - -static STDMETHODIMP_(ULONG) HWCFilter_Release(IBaseFilter *iface) -{ - HWCFilter *This = impl_from_IBaseFilter(iface); - - if (InterlockedDecrement(&This->m_cRef) == 0) { - if (This->m_pPin) { - SAFE_RELEASE(This->m_pPin); - } - g_free((void *)This); - This = NULL; - return 0; - } - return This->m_cRef; -} - -static STDMETHODIMP HWCFilter_GetClassID(IBaseFilter *iface, CLSID *pClsID) -{ - if (pClsID == NULL) { - return E_POINTER; - } - return E_NOTIMPL; -} - -static STDMETHODIMP HWCFilter_GetState(IBaseFilter *iface, DWORD dwMSecs, - FILTER_STATE *State) -{ - HWCFilter *This = impl_from_IBaseFilter(iface); - *State = This->m_state; - return S_OK; -} - -static STDMETHODIMP HWCFilter_SetSyncSource(IBaseFilter *iface, - IReferenceClock *pClock) -{ - return S_OK; -} - -static STDMETHODIMP HWCFilter_GetSyncSource(IBaseFilter *iface, - IReferenceClock **pClock) -{ - *pClock = NULL; - return S_OK; -} - -static STDMETHODIMP HWCFilter_Stop(IBaseFilter *iface) -{ - HWCFilter *This = impl_from_IBaseFilter(iface); - - IPin_EndFlush(This->m_pPin); - This->m_state = State_Stopped; - return S_OK; -} - -static STDMETHODIMP HWCFilter_Pause(IBaseFilter *iface) -{ - HWCFilter *This = impl_from_IBaseFilter(iface); - This->m_state = State_Paused; - return S_OK; -} - -static STDMETHODIMP HWCFilter_Run(IBaseFilter *iface, REFERENCE_TIME tStart) -{ - HWCFilter *This = impl_from_IBaseFilter(iface); - - if (This->m_state == State_Stopped) { - HRESULT hr; - hr = IBaseFilter_Pause(iface); - if (FAILED(hr)) { - ERR("HWCFilter_Run : Failed to IBaseFilter_Pause, ret=0xld%\n", hr); - return hr; - } - } - - This->m_state = State_Running; - return S_OK; -} - -static STDMETHODIMP HWCFilter_EnumPins(IBaseFilter *iface, IEnumPins **ppEnum) -{ - if (ppEnum == NULL) { - return E_POINTER; - } - - HWCEnumPins_Construct(iface, 0, ppEnum); - return *ppEnum == NULL ? E_OUTOFMEMORY : S_OK; -} - -static STDMETHODIMP HWCFilter_FindPin(IBaseFilter *iface, LPCWSTR Id, - IPin **ppPin) -{ - HWCFilter *This = impl_from_IBaseFilter(iface); - - if (ppPin == NULL) { - return E_POINTER; - } - - if (memcmp((void *)Id, (void *)HWCPinName, sizeof(HWCPinName))) { - return VFW_E_NOT_FOUND; - } - - if (!This->m_pPin) { - HWCInPin_Construct(iface, &This->m_pPin); - } - *ppPin = This->m_pPin; - - IPin_AddRef(This->m_pPin); - return S_OK; -} - -static STDMETHODIMP HWCFilter_QueryFilterInfo(IBaseFilter *iface, - FILTER_INFO *pInfo) -{ - HWCFilter *This = impl_from_IBaseFilter(iface); - - if (pInfo == NULL) { - return E_POINTER; - } - - memcpy((void *)pInfo->achName, - (void *)HWCFilterName, - sizeof(HWCFilterName)); - pInfo->pGraph = This->m_pFilterGraph; - if (This->m_pFilterGraph) { - IFilterGraph_AddRef(This->m_pFilterGraph); - } - return S_OK; -} - -static STDMETHODIMP HWCFilter_JoinFilterGraph(IBaseFilter *iface, - IFilterGraph *pGraph, - LPCWSTR pName) -{ - HWCFilter *This = impl_from_IBaseFilter(iface); - - This->m_pFilterGraph = pGraph; - return S_OK; -} - -static STDMETHODIMP HWCFilter_QueryVendorInfo(IBaseFilter *iface, - LPWSTR *pVendorInfo) -{ - return E_NOTIMPL; -} - -static IBaseFilterVtbl HWCFilter_Vtbl = { - HWCFilter_QueryInterface, - HWCFilter_AddRef, - HWCFilter_Release, - HWCFilter_GetClassID, - HWCFilter_Stop, - HWCFilter_Pause, - HWCFilter_Run, - HWCFilter_GetState, - HWCFilter_SetSyncSource, - HWCFilter_GetSyncSource, - HWCFilter_EnumPins, - HWCFilter_FindPin, - HWCFilter_QueryFilterInfo, - HWCFilter_JoinFilterGraph, - HWCFilter_QueryVendorInfo -}; - -static STDMETHODIMP HWCFilter_Construct(IBaseFilter **ppv) -{ - HWCFilter *This = (HWCFilter *)g_malloc0(sizeof(HWCFilter)); - - if (!This) { - ERR("failed to HWCFilter_Construct, E_OUTOFMEMORY\n"); - return E_OUTOFMEMORY; - } - - This->IBaseFilter_iface.lpVtbl = &HWCFilter_Vtbl; - This->m_pFilterGraph = NULL; - This->m_state = State_Stopped; - This->m_cRef = 1; - HWCInPin_Construct(&This->IBaseFilter_iface, &This->m_pPin); - *ppv = &This->IBaseFilter_iface; - - return S_OK; -} - -/********************************************************** - * - * Virtual device implementations - * - **********************************************************/ - - -/* - * Declaration global variables for Win32 COM Interfaces - */ -IGraphBuilder *g_pGB ; -ICaptureGraphBuilder2 *g_pCGB; -IMediaControl *g_pMediaControl; - -IPin *g_pOutputPin; -IPin *g_pInputPin; -IBaseFilter *g_pDstFilter; -IBaseFilter *g_pSrcFilter; - -IGrabCallback *g_pCallback; - -/* V4L2 defines copy from videodev2.h */ -#define V4L2_CTRL_FLAG_SLIDER 0x0020 - -#define V4L2_CTRL_CLASS_USER 0x00980000 -#define V4L2_CID_BASE (V4L2_CTRL_CLASS_USER | 0x900) -#define V4L2_CID_BRIGHTNESS (V4L2_CID_BASE+0) -#define V4L2_CID_CONTRAST (V4L2_CID_BASE+1) -#define V4L2_CID_SATURATION (V4L2_CID_BASE+2) -#define V4L2_CID_SHARPNESS (V4L2_CID_BASE+27) - -#define V4L2_PIX_FMT_YUYV MAKEFOURCC('Y', 'U', 'Y', 'V') /* 16 YUV 4:2:2 */ -#define V4L2_PIX_FMT_YUV420 MAKEFOURCC('Y', 'U', '1', '2') /* 12 YUV 4:2:0 */ -#define V4L2_PIX_FMT_YVU420 MAKEFOURCC('Y', 'V', '1', '2') /* 12 YVU 4:2:0 */ -#define V4L2_PIX_FMT_RGB24 MAKEFOURCC('R', 'G', 'B', '3') /* 24 RGB-8-8-8 */ - -typedef struct tagMaruCamConvertPixfmt { - uint32_t fmt; /* fourcc */ - uint32_t bpp; /* bits per pixel, 0 for compressed formats */ - uint32_t needs_conversion; -} MaruCamConvertPixfmt; - -static MaruCamConvertPixfmt supported_dst_pixfmts[] = { - { V4L2_PIX_FMT_YUYV, 16, 0 }, - { V4L2_PIX_FMT_YUV420, 12, 0 }, - { V4L2_PIX_FMT_YVU420, 12, 0 }, -}; - -typedef struct tagMaruCamConvertFrameInfo { - uint32_t width; - uint32_t height; -} MaruCamConvertFrameInfo; - -static MaruCamConvertFrameInfo supported_dst_frames[] = { - { 640, 480 }, - { 352, 288 }, - { 320, 240 }, - { 176, 144 }, - { 160, 120 }, -}; - -#define MARUCAM_CTRL_VALUE_MAX 20 -#define MARUCAM_CTRL_VALUE_MIN 1 -#define MARUCAM_CTRL_VALUE_MID 10 -#define MARUCAM_CTRL_VALUE_STEP 1 - -struct marucam_qctrl { - uint32_t id; - uint32_t hit; - long min; - long max; - long step; - long init_val; -}; - -static struct marucam_qctrl qctrl_tbl[] = { - { V4L2_CID_BRIGHTNESS, 0, }, - { V4L2_CID_CONTRAST, 0, }, - { V4L2_CID_SATURATION, 0, }, - { V4L2_CID_SHARPNESS, 0, }, -}; - -static MaruCamState *g_state; - -static uint32_t ready_count; -static uint32_t cur_fmt_idx; -static uint32_t cur_frame_idx; -static void *grab_buf; -static uint32_t g_dwSrcFmt; - - -/* - * Helper functions - converting image formats, converting values - */ - -static uint32_t get_bytesperline(uint32_t pixfmt, uint32_t width) -{ - uint32_t bytesperline; - - switch (pixfmt) { - case V4L2_PIX_FMT_YUV420: - case V4L2_PIX_FMT_YVU420: - bytesperline = (width * 12) >> 3; - break; - case V4L2_PIX_FMT_YUYV: - default: - bytesperline = width * 2; - break; - } - - return bytesperline; -} - -static uint32_t get_sizeimage(uint32_t pixfmt, uint32_t width, uint32_t height) -{ - return get_bytesperline(pixfmt, width) * height; -} - -void yuyv_to_yuv420(const unsigned char *src, unsigned char *dest, - uint32_t width, uint32_t height, uint32_t yvu); -void rgb24_to_yuv420(const unsigned char *src, unsigned char *dest, - uint32_t width, uint32_t height, uint32_t yvu); -void rgb24_to_yuyv(unsigned char *src, unsigned char *dest, - uint32_t width, uint32_t height); -void yuv420_to_yvu420(unsigned char *src, unsigned char *dest, - uint32_t width, uint32_t height); -void yuv420_to_yuyv(unsigned char *src, unsigned char *dest, - uint32_t width, uint32_t height); - -static long value_convert_from_guest(long min, long max, long value) -{ - double rate = 0.0; - long dist = 0, ret = 0; - - dist = max - min; - - if (dist < MARUCAM_CTRL_VALUE_MAX) { - rate = (double)MARUCAM_CTRL_VALUE_MAX / (double)dist; - ret = min + (int32_t)(value / rate); - } else { - rate = (double)dist / (double)MARUCAM_CTRL_VALUE_MAX; - ret = min + (int32_t)(rate * value); - } - return ret; -} - -static long value_convert_to_guest(long min, long max, long value) -{ - double rate = 0.0; - long dist = 0, ret = 0; - - dist = max - min; - - if (dist < MARUCAM_CTRL_VALUE_MAX) { - rate = (double)MARUCAM_CTRL_VALUE_MAX / (double)dist; - ret = (int32_t)((double)(value - min) * rate); - } else { - rate = (double)dist / (double)MARUCAM_CTRL_VALUE_MAX; - ret = (int32_t)((double)(value - min) / rate); - } - - return ret; -} - -/* - * Callback function for grab frames - */ -static STDMETHODIMP marucam_device_callbackfn(ULONG dwSize, BYTE *pBuffer) -{ - void *tmp_buf; - uint32_t width, height, fmt, imgsize; - - width = supported_dst_frames[cur_frame_idx].width; - height = supported_dst_frames[cur_frame_idx].height; - fmt = supported_dst_pixfmts[cur_fmt_idx].fmt; - imgsize = get_sizeimage(fmt, width, height); - - if (imgsize > (uint32_t)dwSize) { - ERR("Image size is mismatched\n"); - return E_FAIL; - } - - switch (g_dwSrcFmt) { - case V4L2_PIX_FMT_YUYV: - switch (fmt) { - case V4L2_PIX_FMT_YUV420: - yuyv_to_yuv420(pBuffer, grab_buf, width, height, 0); - break; - case V4L2_PIX_FMT_YVU420: - yuyv_to_yuv420(pBuffer, grab_buf, width, height, 1); - break; - case V4L2_PIX_FMT_YUYV: - memcpy(grab_buf, (void *)pBuffer, (size_t)dwSize); - break; - default: - ERR("Invalid pixel format\n"); - return E_FAIL; - } - break; - case V4L2_PIX_FMT_RGB24: - switch (fmt) { - case V4L2_PIX_FMT_YUV420: - rgb24_to_yuv420(pBuffer, grab_buf, width, height, 0); - break; - case V4L2_PIX_FMT_YVU420: - rgb24_to_yuv420(pBuffer, grab_buf, width, height, 1); - break; - case V4L2_PIX_FMT_YUYV: - rgb24_to_yuyv(pBuffer, grab_buf, width, height); - break; - default: - ERR("Invalid pixel format\n"); - return E_FAIL; - } - break; - case V4L2_PIX_FMT_YUV420: - switch (fmt) { - case V4L2_PIX_FMT_YUV420: - memcpy(grab_buf, (void *)pBuffer, (size_t)dwSize); - break; - case V4L2_PIX_FMT_YVU420: - yuv420_to_yvu420(pBuffer, grab_buf, width, height); - break; - case V4L2_PIX_FMT_YUYV: - yuv420_to_yuyv(pBuffer, grab_buf, width, height); - break; - default: - ERR("Invalid pixel format\n"); - return E_FAIL; - } - break; - default: - ERR("Invalid pixel format\n"); - return E_FAIL; - } - - qemu_mutex_lock(&g_state->thread_mutex); - if (g_state->streamon) { - if (ready_count < MARUCAM_SKIPFRAMES) { - /* skip a frame cause first some frame are distorted */ - ++ready_count; - TRACE("skip %d frame\n", ready_count); - qemu_mutex_unlock(&g_state->thread_mutex); - return S_OK; - } - if (g_state->req_frame == 0) { - TRACE("there is no request\n"); - qemu_mutex_unlock(&g_state->thread_mutex); - return S_OK; - } - tmp_buf = g_state->vaddr + g_state->buf_size * (g_state->req_frame - 1); - memcpy(tmp_buf, grab_buf, g_state->buf_size); - g_state->req_frame = 0; /* clear request */ - g_state->isr |= 0x01; /* set a flag of rasing a interrupt */ - qemu_bh_schedule(g_state->tx_bh); - } - qemu_mutex_unlock(&g_state->thread_mutex); - return S_OK; -} - -/* - * Internal functions for manipulate interfaces - */ - -static STDMETHODIMP_(void) CloseInterfaces(void) -{ - if (g_pMediaControl) { - g_pMediaControl->lpVtbl->Stop(g_pMediaControl); - } - - if (g_pOutputPin) { - g_pOutputPin->lpVtbl->Disconnect(g_pOutputPin); - } - - SAFE_RELEASE(g_pGB); - SAFE_RELEASE(g_pCGB); - SAFE_RELEASE(g_pMediaControl); - SAFE_RELEASE(g_pOutputPin); - SAFE_RELEASE(g_pInputPin); - SAFE_RELEASE(g_pDstFilter); - SAFE_RELEASE(g_pSrcFilter); - SAFE_RELEASE(g_pCallback); -} - -static STDMETHODIMP_(void) DeleteMediaType(AM_MEDIA_TYPE *pmt) -{ - if (pmt == NULL) { - return; - } - - if (pmt->cbFormat != 0) { - CoTaskMemFree((PVOID)pmt->pbFormat); - pmt->cbFormat = 0; - pmt->pbFormat = NULL; - } - if (pmt->pUnk != NULL) { - pmt->pUnk->lpVtbl->Release(pmt->pUnk); - pmt->pUnk = NULL; - } - - CoTaskMemFree((PVOID)pmt); -} - -static STDMETHODIMP GetPin(IBaseFilter *pFilter, - PIN_DIRECTION PinDir, IPin **ppPin) -{ - HRESULT hr; - IEnumPins *pEnum = NULL; - IPin *pPin = NULL; - - if (ppPin == NULL) { - return E_POINTER; - } - - hr = pFilter->lpVtbl->EnumPins(pFilter, &pEnum); - if (FAILED(hr)) { - return hr; - } - - while (pEnum->lpVtbl->Next(pEnum, 1, &pPin, 0) == S_OK) { - PIN_DIRECTION PinDirThis; - hr = pPin->lpVtbl->QueryDirection(pPin, &PinDirThis); - if (FAILED(hr)) { - SAFE_RELEASE(pPin); - SAFE_RELEASE(pEnum); - return hr; - } - if (PinDir == PinDirThis) { - *ppPin = pPin; - SAFE_RELEASE(pEnum); - return S_OK; - } - SAFE_RELEASE(pPin); - } - - SAFE_RELEASE(pEnum); - return S_FALSE; -} - -static STDMETHODIMP GraphBuilder_Init(void) -{ - HRESULT hr; - - hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC, - &IID_IGraphBuilder, (void **)&g_pGB); - if (FAILED(hr)) { - ERR("Failed to create instance of GraphBuilder, 0x%x\n", hr); - return hr; - } - - hr = CoCreateInstance(&CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC, - &IID_ICaptureGraphBuilder2, (void **)&g_pCGB); - if (FAILED(hr)) { - ERR("Failed to create instance of CaptureGraphBuilder2, 0x%x\n", hr); - return hr; - } - - hr = g_pCGB->lpVtbl->SetFiltergraph(g_pCGB, g_pGB); - if (FAILED(hr)) { - ERR("Failed to SetFiltergraph, 0x%x\n", hr); - return hr; - } - - hr = g_pGB->lpVtbl->QueryInterface(g_pGB, &IID_IMediaControl, - (void **)&g_pMediaControl); - if (FAILED(hr)) { - ERR("Failed to QueryInterface for IMediaControl, 0x%x\n", hr); - return hr; - } - - hr = HWCGrabCallback_Construct(&g_pCallback); - if (g_pCallback == NULL) { - hr = E_OUTOFMEMORY; - } - - hr = ((HWCGrabCallback *)g_pCallback)->SetCallback(g_pCallback, - (CallbackFn)marucam_device_callbackfn); - - return hr; -} - -static STDMETHODIMP BindSourceFilter(void) -{ - HRESULT hr; - ICreateDevEnum *pCreateDevEnum = NULL; - IEnumMoniker *pEnumMK = NULL; - IMoniker *pMoniKer; - - hr = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC, - &IID_ICreateDevEnum, - (void **)&pCreateDevEnum); - if (FAILED(hr)) { - ERR("Failed to create instance of CreateDevEnum, 0x%x\n", hr); - return hr; - } - - hr = pCreateDevEnum->lpVtbl->CreateClassEnumerator(pCreateDevEnum, - &CLSID_VideoInputDeviceCategory, - &pEnumMK, 0); - if (FAILED(hr)) { - ERR("Failed to get VideoInputDeviceCategory, 0x%x\n", hr); - SAFE_RELEASE(pCreateDevEnum); - return hr; - } - - if (!pEnumMK) { - ERR("ClassEnumerator moniker is NULL\n"); - SAFE_RELEASE(pCreateDevEnum); - return E_FAIL; - } - pEnumMK->lpVtbl->Reset(pEnumMK); - - hr = pEnumMK->lpVtbl->Next(pEnumMK, 1, &pMoniKer, NULL); - if (hr == S_FALSE) { - hr = E_FAIL; - } - if (SUCCEEDED(hr)) { - IPropertyBag *pBag = NULL; - hr = pMoniKer->lpVtbl->BindToStorage(pMoniKer, 0, 0, - &IID_IPropertyBag, - (void **)&pBag); - if (SUCCEEDED(hr)) { - VARIANT var; - var.vt = VT_BSTR; - hr = pBag->lpVtbl->Read(pBag, L"FriendlyName", &var, NULL); - if (hr == NOERROR) { - hr = pMoniKer->lpVtbl->BindToObject(pMoniKer, NULL, NULL, - &IID_IBaseFilter, - (void **)&g_pSrcFilter); - if (FAILED(hr)) { - ERR("Counldn't bind moniker to filter object!!\n"); - } else { - g_pSrcFilter->lpVtbl->AddRef(g_pSrcFilter); - } - SysFreeString(var.bstrVal); - } - SAFE_RELEASE(pBag); - } - SAFE_RELEASE(pMoniKer); - } - - if (SUCCEEDED(hr)) { - hr = g_pGB->lpVtbl->AddFilter(g_pGB, g_pSrcFilter, L"Video Capture"); - if (hr != S_OK && hr != S_FALSE) { - ERR("Counldn't add Video Capture filter to our graph!\n"); - SAFE_RELEASE(g_pSrcFilter); - } - } - SAFE_RELEASE(pEnumMK); - SAFE_RELEASE(pCreateDevEnum); - - return hr; -} - -static STDMETHODIMP BindTargetFilter(void) -{ - HRESULT hr; - hr = HWCFilter_Construct(&g_pDstFilter); - - if (SUCCEEDED(hr) && g_pDstFilter) { - hr = g_pGB->lpVtbl->AddFilter(g_pGB, g_pDstFilter, L"HWCFilter"); - if (FAILED(hr)) { - ERR("Counldn't add HWCFilterr to our graph!\n"); - SAFE_RELEASE(g_pDstFilter); - } - } - return hr; -} - -static STDMETHODIMP ConnectFilters(void) -{ - HRESULT hr; - - hr = GetPin(g_pSrcFilter, PINDIR_OUTPUT , &g_pOutputPin); - if (FAILED(hr)) { - ERR("Failed to get output pin. 0x%x\n", hr); - return hr; - } - - hr = GetPin(g_pDstFilter, PINDIR_INPUT , &g_pInputPin); - if (FAILED(hr)) { - ERR("Failed to get input pin. 0x%x\n", hr); - return hr; - } - - hr = g_pGB->lpVtbl->Connect(g_pGB, g_pOutputPin, g_pInputPin); - if (FAILED(hr)) { - ERR("Failed to connect pins. 0x%x\n", hr); - } - return hr; -} - -static STDMETHODIMP DisconnectPins(void) -{ - HRESULT hr; - - hr = g_pGB->lpVtbl->Disconnect(g_pGB, g_pOutputPin); - if (FAILED(hr)) { - ERR("Failed to disconnect output pin. 0x%x\n", hr); - return hr; - } - - hr = g_pGB->lpVtbl->Disconnect(g_pGB, g_pInputPin); - if (FAILED(hr)) { - ERR("Failed to disconnect input pin. 0x%x\n", hr); - } - - return hr; -} - -static STDMETHODIMP RemoveFilters(void) -{ - HRESULT hr; - - hr = g_pGB->lpVtbl->RemoveFilter(g_pGB, g_pSrcFilter); - if (FAILED(hr)) { - ERR("Failed to remove source filer. 0x%x\n", hr); - return hr; - } - - hr = g_pGB->lpVtbl->RemoveFilter(g_pGB, g_pDstFilter); - if (FAILED(hr)) { - ERR("Failed to remove destination filer. 0x%x\n", hr); - } - - return hr; -} - -/* default fps is 15 */ -#define MARUCAM_DEFAULT_FRAMEINTERVAL 666666 - -static STDMETHODIMP SetFormat(uint32_t dwWidth, uint32_t dwHeight, - uint32_t dwDstFmt, uint32_t *dwSrcFmt) -{ - HRESULT hr; - IAMStreamConfig *pSConfig; - int iCount = 0, iSize = 0; - DWORD dwYUY2 = MAKEFOURCC('Y', 'U', 'Y', '2'); - DWORD dwI420 = MAKEFOURCC('I', '4', '2', '0'); - - if (dwSrcFmt == NULL) { - ERR("invalid the source format pointer\n"); - return E_FAIL; - } - - hr = g_pCGB->lpVtbl->FindInterface(g_pCGB, &PIN_CATEGORY_CAPTURE, 0, - g_pSrcFilter, &IID_IAMStreamConfig, - (void **)&pSConfig); - if (FAILED(hr)) { - ERR("failed to FindInterface method\n"); - return hr; - } - - hr = pSConfig->lpVtbl->GetNumberOfCapabilities(pSConfig, &iCount, &iSize); - if (FAILED(hr)) { - ERR("failed to GetNumberOfCapabilities method\n"); - SAFE_RELEASE(pSConfig); - return hr; - } - - if (iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS)) { - int iFormat = 0; - for (iFormat = 0; iFormat < iCount; iFormat++) { - VIDEO_STREAM_CONFIG_CAPS scc; - AM_MEDIA_TYPE *pmtConfig; - - hr = pSConfig->lpVtbl->GetStreamCaps(pSConfig, iFormat, - &pmtConfig, (BYTE *)&scc); - if (hr == S_OK) { - if (IsEqualIID(&pmtConfig->formattype, &FORMAT_VideoInfo)) { - VIDEOINFOHEADER *pvi = - (VIDEOINFOHEADER *)pmtConfig->pbFormat; - if ((pvi->bmiHeader.biWidth == (LONG)dwWidth) && - (pvi->bmiHeader.biHeight == (LONG)dwHeight)) { - if (pvi->bmiHeader.biCompression == dwYUY2) { - *dwSrcFmt = V4L2_PIX_FMT_YUYV; - } else if ((pvi->bmiHeader.biCompression == BI_RGB) && - (pvi->bmiHeader.biBitCount == 24)) { - *dwSrcFmt = V4L2_PIX_FMT_RGB24; - } else if (pvi->bmiHeader.biCompression == dwI420) { - *dwSrcFmt = V4L2_PIX_FMT_YUV420; - } else { /* not support format */ - DeleteMediaType(pmtConfig); - continue; - } - /* use minimum FPS(maximum frameinterval) - with non-VT system */ -#ifdef CONFIG_HAX - if (!hax_enabled()) { - pvi->AvgTimePerFrame = - (REFERENCE_TIME)scc.MaxFrameInterval; - } else { - pvi->AvgTimePerFrame = - (REFERENCE_TIME)MARUCAM_DEFAULT_FRAMEINTERVAL; - } -#else - pvi->AvgTimePerFrame = - (REFERENCE_TIME)scc.MaxFrameInterval; -#endif - hr = pSConfig->lpVtbl->SetFormat(pSConfig, pmtConfig); - DeleteMediaType(pmtConfig); - break; - } - } - DeleteMediaType(pmtConfig); - } - } - if (iFormat >= iCount) { - ERR("Failed to Set format. " - "Maybe connected webcam does not support the (%ldx%ld) " - "resolution or image formats(YUY2, RGB24, I420).\n", - dwWidth, dwHeight); - hr = E_FAIL; - } - } - SAFE_RELEASE(pSConfig); - return hr; -} - -static STDMETHODIMP QueryVideoProcAmp(long nProperty, long *pMin, long *pMax, - long *pStep, long *pDefault) -{ - HRESULT hr; - long Flags; - IAMVideoProcAmp *pProcAmp = NULL; - - hr = g_pSrcFilter->lpVtbl->QueryInterface(g_pSrcFilter, - &IID_IAMVideoProcAmp, - (void **)&pProcAmp); - if (FAILED(hr)) { - return hr; - } - - hr = pProcAmp->lpVtbl->GetRange(pProcAmp, nProperty, pMin, pMax, - pStep, pDefault, &Flags); - - SAFE_RELEASE(pProcAmp); - return hr; -} - -static STDMETHODIMP GetVideoProcAmp(long nProperty, long *pValue) -{ - HRESULT hr; - long Flags; - IAMVideoProcAmp *pProcAmp = NULL; - - hr = g_pSrcFilter->lpVtbl->QueryInterface(g_pSrcFilter, - &IID_IAMVideoProcAmp, - (void **)&pProcAmp); - if (FAILED(hr)) { - return hr; - } - - hr = pProcAmp->lpVtbl->Get(pProcAmp, nProperty, pValue, &Flags); - if (FAILED(hr)) { - ERR("Failed to get property for video\n"); - } - - SAFE_RELEASE(pProcAmp); - return hr; -} - -static STDMETHODIMP SetVideoProcAmp(long nProperty, long value) -{ - HRESULT hr; - - IAMVideoProcAmp *pProcAmp = NULL; - hr = g_pSrcFilter->lpVtbl->QueryInterface(g_pSrcFilter, - &IID_IAMVideoProcAmp, - (void **)&pProcAmp); - if (FAILED(hr)) { - return hr; - } - - hr = pProcAmp->lpVtbl->Set(pProcAmp, nProperty, value, - VideoProcAmp_Flags_Manual); - if (FAILED(hr)) { - ERR("Failed to set property for video\n"); - } - SAFE_RELEASE(pProcAmp); - return hr; -} - -static char *__wchar_to_char(const WCHAR *pwstr) -{ - char *pstr = NULL; - int len = 0; - - len = wcslen(pwstr) + 1; - pstr = (char *)g_malloc0(sizeof(char) * len); - wcstombs(pstr, pwstr, len + 1); - - return pstr; -} - -int marucam_device_check(int log_flag) -{ - struct timeval t1, t2; - int ret = 0; - char *device_name = NULL; - HRESULT hr = E_FAIL; - ICreateDevEnum *pCreateDevEnum = NULL; - IGraphBuilder *pGB = NULL; - ICaptureGraphBuilder2 *pCGB = NULL; - IBaseFilter *pSrcFilter = NULL; - IEnumMoniker *pEnumMK = NULL; - IMoniker *pMoniKer = NULL; - IAMStreamConfig *pSConfig = NULL; - int iCount = 0, iSize = 0; - - gettimeofday(&t1, NULL); - hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); - if (FAILED(hr)) { - fprintf(stdout, "[Webcam] failed to CoInitailizeEx\n"); - gettimeofday(&t2, NULL); - fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } - - hr = CoCreateInstance(&CLSID_FilterGraph, NULL, - CLSCTX_INPROC, - &IID_IGraphBuilder, - (void **)&pGB); - if (FAILED(hr)) { - fprintf(stdout, "[Webcam] Failed to create GraphBuilder, 0x%x\n", hr); - CoUninitialize(); - gettimeofday(&t2, NULL); - fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } - - hr = CoCreateInstance(&CLSID_CaptureGraphBuilder2, NULL, - CLSCTX_INPROC, - &IID_ICaptureGraphBuilder2, - (void **)&pCGB); - if (FAILED(hr)) { - fprintf(stdout, - "[Webcam] Failed to create CaptureGraphBuilder2, 0x%x\n", hr); - SAFE_RELEASE(pGB); - CoUninitialize(); - gettimeofday(&t2, NULL); - fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } - - hr = pCGB->lpVtbl->SetFiltergraph(pCGB, pGB); - if (FAILED(hr)) { - fprintf(stdout, "[Webcam] Failed to SetFiltergraph, 0x%x\n", hr); - SAFE_RELEASE(pCGB); - SAFE_RELEASE(pGB); - CoUninitialize(); - gettimeofday(&t2, NULL); - fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } - - hr = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, - CLSCTX_INPROC, - &IID_ICreateDevEnum, - (void **)&pCreateDevEnum); - if (FAILED(hr)) { - fprintf(stdout, - "[Webcam] failed to create instance of CLSID_SystemDeviceEnum\n"); - SAFE_RELEASE(pCGB); - SAFE_RELEASE(pGB); - CoUninitialize(); - gettimeofday(&t2, NULL); - fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } - - hr = pCreateDevEnum->lpVtbl->CreateClassEnumerator(pCreateDevEnum, - &CLSID_VideoInputDeviceCategory, &pEnumMK, 0); - if (FAILED(hr)) { - fprintf(stdout, "[Webcam] failed to create class enumerator\n"); - SAFE_RELEASE(pCreateDevEnum); - SAFE_RELEASE(pCGB); - SAFE_RELEASE(pGB); - CoUninitialize(); - gettimeofday(&t2, NULL); - fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } - - if (!pEnumMK) { - fprintf(stdout, "[Webcam] class enumerator is NULL!!\n"); - SAFE_RELEASE(pCreateDevEnum); - SAFE_RELEASE(pCGB); - SAFE_RELEASE(pGB); - CoUninitialize(); - gettimeofday(&t2, NULL); - fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } - pEnumMK->lpVtbl->Reset(pEnumMK); - - hr = pEnumMK->lpVtbl->Next(pEnumMK, 1, &pMoniKer, NULL); - if (FAILED(hr) || (hr == S_FALSE)) { - fprintf(stdout, "[Webcam] enum moniker returns a invalid value.\n"); - SAFE_RELEASE(pEnumMK); - SAFE_RELEASE(pCreateDevEnum); - SAFE_RELEASE(pCGB); - SAFE_RELEASE(pGB); - CoUninitialize(); - gettimeofday(&t2, NULL); - fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } - - IPropertyBag *pBag = NULL; - hr = pMoniKer->lpVtbl->BindToStorage(pMoniKer, 0, 0, - &IID_IPropertyBag, - (void **)&pBag); - if (FAILED(hr)) { - fprintf(stdout, "[Webcam] failed to bind to storage.\n"); - SAFE_RELEASE(pEnumMK); - SAFE_RELEASE(pCreateDevEnum); - SAFE_RELEASE(pCGB); - SAFE_RELEASE(pGB); - CoUninitialize(); - gettimeofday(&t2, NULL); - fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } else { - VARIANT var; - var.vt = VT_BSTR; - hr = pBag->lpVtbl->Read(pBag, L"FriendlyName", &var, NULL); - if (hr == S_OK) { - ret = 1; - if (!log_flag) { - SysFreeString(var.bstrVal); - SAFE_RELEASE(pBag); - SAFE_RELEASE(pMoniKer); - SAFE_RELEASE(pEnumMK); - SAFE_RELEASE(pCreateDevEnum); - SAFE_RELEASE(pCGB); - SAFE_RELEASE(pGB); - CoUninitialize(); - gettimeofday(&t2, NULL); - fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } - device_name = __wchar_to_char(var.bstrVal); - fprintf(stdout, "[Webcam] Device name : %s\n", device_name); - g_free(device_name); - hr = pMoniKer->lpVtbl->BindToObject(pMoniKer, NULL, NULL, - &IID_IBaseFilter, - (void **)&pSrcFilter); - if (FAILED(hr)) { - fprintf(stdout, - "[Webcam] Counldn't bind moniker to filter object!!\n"); - SysFreeString(var.bstrVal); - SAFE_RELEASE(pBag); - SAFE_RELEASE(pMoniKer); - SAFE_RELEASE(pEnumMK); - SAFE_RELEASE(pCreateDevEnum); - SAFE_RELEASE(pCGB); - SAFE_RELEASE(pGB); - CoUninitialize(); - gettimeofday(&t2, NULL); - fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } else { - pSrcFilter->lpVtbl->AddRef(pSrcFilter); - } - SysFreeString(var.bstrVal); - } - SAFE_RELEASE(pBag); - } - SAFE_RELEASE(pMoniKer); - - hr = pGB->lpVtbl->AddFilter(pGB, pSrcFilter, L"Video Capture"); - if (hr != S_OK && hr != S_FALSE) { - fprintf(stdout, - "[Webcam] Counldn't add Video Capture filter to our graph!\n"); - SAFE_RELEASE(pSrcFilter); - SAFE_RELEASE(pEnumMK); - SAFE_RELEASE(pCreateDevEnum); - SAFE_RELEASE(pCGB); - SAFE_RELEASE(pGB); - CoUninitialize(); - gettimeofday(&t2, NULL); - fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } - - hr = pCGB->lpVtbl->FindInterface(pCGB, &PIN_CATEGORY_CAPTURE, 0, - pSrcFilter, &IID_IAMStreamConfig, - (void **)&pSConfig); - if (FAILED(hr)) { - fprintf(stdout, "[Webcam] failed to FindInterface method\n"); - SAFE_RELEASE(pSrcFilter); - SAFE_RELEASE(pEnumMK); - SAFE_RELEASE(pCreateDevEnum); - SAFE_RELEASE(pCGB); - SAFE_RELEASE(pGB); - CoUninitialize(); - gettimeofday(&t2, NULL); - fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } - - hr = pSConfig->lpVtbl->GetNumberOfCapabilities(pSConfig, &iCount, &iSize); - if (FAILED(hr)) { - fprintf(stdout, "[Webcam] failed to GetNumberOfCapabilities method\n"); - SAFE_RELEASE(pSConfig); - SAFE_RELEASE(pSrcFilter); - SAFE_RELEASE(pEnumMK); - SAFE_RELEASE(pCreateDevEnum); - SAFE_RELEASE(pCGB); - SAFE_RELEASE(pGB); - CoUninitialize(); - gettimeofday(&t2, NULL); - fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } - - if (iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS)) { - int iFormat = 0; - for (iFormat = 0; iFormat < iCount; iFormat++) { - VIDEO_STREAM_CONFIG_CAPS scc; - AM_MEDIA_TYPE *pmtConfig; - - hr = pSConfig->lpVtbl->GetStreamCaps(pSConfig, iFormat, &pmtConfig, - (BYTE *)&scc); - if (hr == S_OK) { - if (IsEqualIID(&pmtConfig->formattype, &FORMAT_VideoInfo)) { - VIDEOINFOHEADER *pvi = - (VIDEOINFOHEADER *)pmtConfig->pbFormat; - if (pvi->bmiHeader.biCompression == BI_RGB) { - fprintf(stdout, "[Webcam] RGB BitCount: %d, %ux%u\n", - pvi->bmiHeader.biBitCount, - pvi->bmiHeader.biWidth, - pvi->bmiHeader.biHeight); - } else { - fprintf(stdout, - "[Webcam] PixelFormat: %c%c%c%c, %ux%u\n", - (char)(pvi->bmiHeader.biCompression), - (char)(pvi->bmiHeader.biCompression >> 8), - (char)(pvi->bmiHeader.biCompression >> 16), - (char)(pvi->bmiHeader.biCompression >> 24), - pvi->bmiHeader.biWidth, - pvi->bmiHeader.biHeight); - } - } - DeleteMediaType(pmtConfig); - } - } - } - - hr = pGB->lpVtbl->RemoveFilter(pGB, pSrcFilter); - if (FAILED(hr)) { - fprintf(stdout, "[Webcam] Failed to remove source filer. 0x%x\n", hr); - } - - SAFE_RELEASE(pSConfig); - SAFE_RELEASE(pSrcFilter); - SAFE_RELEASE(pCGB); - SAFE_RELEASE(pGB); - SAFE_RELEASE(pEnumMK); - SAFE_RELEASE(pCreateDevEnum); - CoUninitialize(); - gettimeofday(&t2, NULL); - fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - - return ret; -} - -/* MARUCAM_CMD_INIT */ -void marucam_device_init(MaruCamState *state) -{ - g_state = state; -} - -void marucam_device_exit(MaruCamState *state) -{ -} - -/* MARUCAM_CMD_OPEN */ -void marucam_device_open(MaruCamState *state) -{ - HRESULT hr; - uint32_t dwHeight, dwWidth, dwDstFmt; - MaruCamParam *param = state->param; - param->top = 0; - - hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); - if (FAILED(hr)) { - ERR("CoInitailizeEx\n"); - ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr); - param->errCode = EINVAL; - return; - } - - hr = GraphBuilder_Init(); - if (FAILED(hr)) { - ERR("GraphBuilder_Init\n"); - DisconnectPins(); - RemoveFilters(); - CloseInterfaces(); - CoUninitialize(); - param->errCode = EINVAL; - ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr); - return; - } - - hr = BindSourceFilter(); - if (FAILED(hr)) { - ERR("BindSourceFilter\n"); - DisconnectPins(); - RemoveFilters(); - CloseInterfaces(); - CoUninitialize(); - param->errCode = EINVAL; - ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr); - return; - } - - hr = BindTargetFilter(); - if (FAILED(hr)) { - ERR("BindTargetFilter\n"); - DisconnectPins(); - RemoveFilters(); - CloseInterfaces(); - CoUninitialize(); - param->errCode = EINVAL; - ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr); - return; - } - - hr = ConnectFilters(); - if (FAILED(hr)) { - ERR("ConnectFilters\n"); - DisconnectPins(); - RemoveFilters(); - CloseInterfaces(); - CoUninitialize(); - param->errCode = EINVAL; - ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr); - return; - } - - cur_frame_idx = 0; - cur_fmt_idx = 0; - - dwHeight = supported_dst_frames[cur_frame_idx].height; - dwWidth = supported_dst_frames[cur_frame_idx].width; - dwDstFmt = supported_dst_pixfmts[cur_fmt_idx].fmt; - hr = SetFormat(dwWidth, dwHeight, dwDstFmt, &g_dwSrcFmt); - if (hr != S_OK) { - ERR("failed to Set default values\n"); - DisconnectPins(); - RemoveFilters(); - CloseInterfaces(); - CoUninitialize(); - param->errCode = EINVAL; - ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr); - return; - } - - INFO("Opened\n"); - return; -} - -/* MARUCAM_CMD_CLOSE */ -void marucam_device_close(MaruCamState *state) -{ - MaruCamParam *param = state->param; - param->top = 0; - - DisconnectPins(); - RemoveFilters(); - CloseInterfaces(); - CoUninitialize(); - INFO("Closed\n"); -} - -/* MARUCAM_CMD_START_PREVIEW */ -void marucam_device_start_preview(MaruCamState *state) -{ - HRESULT hr; - uint32_t pixfmt, width, height; - MaruCamParam *param = state->param; - param->top = 0; - - ready_count = 0; - width = supported_dst_frames[cur_frame_idx].width; - height = supported_dst_frames[cur_frame_idx].height; - pixfmt = supported_dst_pixfmts[cur_fmt_idx].fmt; - state->buf_size = get_sizeimage(pixfmt, width, height); - - INFO("Pixfmt(%c%c%c%c), W:H(%d:%d), buf size(%u)\n", - (char)(pixfmt), (char)(pixfmt >> 8), - (char)(pixfmt >> 16), (char)(pixfmt >> 24), - width, height, state->buf_size); - INFO("Starting preview\n"); - - assert(g_pCallback != NULL); - hr = ((HWCInPin *)g_pInputPin)->SetGrabCallbackIF(g_pInputPin, - g_pCallback); - if (FAILED(hr)) { - ERR("Failed to set IGrabCallback interface.\n"); - param->errCode = EINVAL; - return; - } - - if (grab_buf) { - g_free(grab_buf); - grab_buf = NULL; - } - grab_buf = (void *)g_malloc0(state->buf_size); - if (grab_buf == NULL) { - param->errCode = ENOMEM; - return; - } - - hr = g_pMediaControl->lpVtbl->Run(g_pMediaControl); - if (FAILED(hr)) { - ERR("Failed to run media control. hr=0x%x\n", hr); - param->errCode = EINVAL; - return; - } - - qemu_mutex_lock(&state->thread_mutex); - state->streamon = 1; - qemu_mutex_unlock(&state->thread_mutex); - - INFO("Streaming on ......\n"); -} - -/* MARUCAM_CMD_STOP_PREVIEW */ -void marucam_device_stop_preview(MaruCamState *state) -{ - HRESULT hr; - MaruCamParam *param = state->param; - param->top = 0; - - INFO("...... Streaming off\n"); - qemu_mutex_lock(&state->thread_mutex); - state->streamon = 0; - qemu_mutex_unlock(&state->thread_mutex); - - hr = ((HWCInPin *)g_pInputPin)->SetGrabCallbackIF(g_pInputPin, NULL); - if (FAILED(hr)) { - ERR("Failed to set IGrabCallback interface.\n"); - param->errCode = EINVAL; - return; - } - - hr = g_pMediaControl->lpVtbl->Stop(g_pMediaControl); - if (FAILED(hr)) { - ERR("Failed to stop media control.\n"); - param->errCode = EINVAL; - return; - } - - if (grab_buf) { - g_free(grab_buf); - grab_buf = NULL; - } - state->buf_size = 0; - - INFO("Stopping preview\n"); -} - -/* MARUCAM_CMD_S_PARAM */ -void marucam_device_s_param(MaruCamState *state) -{ - MaruCamParam *param = state->param; - - /* We use default FPS of the webcam */ - param->top = 0; -} - -/* MARUCAM_CMD_G_PARAM */ -void marucam_device_g_param(MaruCamState *state) -{ - MaruCamParam *param = state->param; - - /* We use default FPS of the webcam - * return a fixed value on guest ini file (1/30). - */ - param->top = 0; - param->stack[0] = 0x1000; /* V4L2_CAP_TIMEPERFRAME */ - param->stack[1] = 1; /* numerator */ - param->stack[2] = 30; /* denominator */ -} - -/* MARUCAM_CMD_S_FMT */ -void marucam_device_s_fmt(MaruCamState *state) -{ - uint32_t width, height, pixfmt, pidx, fidx; - MaruCamParam *param = state->param; - - param->top = 0; - width = param->stack[0]; - height = param->stack[1]; - pixfmt = param->stack[2]; - - for (fidx = 0; fidx < ARRAY_SIZE(supported_dst_frames); fidx++) { - if ((supported_dst_frames[fidx].width == width) && - (supported_dst_frames[fidx].height == height)) { - break; - } - } - if (fidx == ARRAY_SIZE(supported_dst_frames)) { - param->errCode = EINVAL; - return; - } - for (pidx = 0; pidx < ARRAY_SIZE(supported_dst_pixfmts); pidx++) { - if (supported_dst_pixfmts[pidx].fmt == pixfmt) { - break; - } - } - if (pidx == ARRAY_SIZE(supported_dst_pixfmts)) { - param->errCode = EINVAL; - return; - } - - if ((supported_dst_frames[cur_frame_idx].width != width) && - (supported_dst_frames[cur_frame_idx].height != height)) { - HRESULT hr = SetFormat(width, height, pixfmt, &g_dwSrcFmt); - if (FAILED(hr)) { - param->errCode = EINVAL; - return; - } - } - - cur_frame_idx = fidx; - cur_fmt_idx = pidx; - - pixfmt = supported_dst_pixfmts[cur_fmt_idx].fmt; - width = supported_dst_frames[cur_frame_idx].width; - height = supported_dst_frames[cur_frame_idx].height; - - param->stack[0] = width; - param->stack[1] = height; - param->stack[2] = 1; /* V4L2_FIELD_NONE */ - param->stack[3] = pixfmt; - param->stack[4] = get_bytesperline(pixfmt, width); - param->stack[5] = get_sizeimage(pixfmt, width, height); - param->stack[6] = 0; - param->stack[7] = 0; - - TRACE("Set format...\n"); -} - -/* MARUCAM_CMD_G_FMT */ -void marucam_device_g_fmt(MaruCamState *state) -{ - uint32_t width, height, pixfmt; - MaruCamParam *param = state->param; - - param->top = 0; - pixfmt = supported_dst_pixfmts[cur_fmt_idx].fmt; - width = supported_dst_frames[cur_frame_idx].width; - height = supported_dst_frames[cur_frame_idx].height; - - param->stack[0] = width; - param->stack[1] = height; - param->stack[2] = 1; /* V4L2_FIELD_NONE */ - param->stack[3] = pixfmt; - param->stack[4] = get_bytesperline(pixfmt, width); - param->stack[5] = get_sizeimage(pixfmt, width, height); - param->stack[6] = 0; - param->stack[7] = 0; - - TRACE("Get format...\n"); -} - -void marucam_device_try_fmt(MaruCamState *state) -{ - uint32_t width, height, pixfmt, i; - MaruCamParam *param = state->param; - - param->top = 0; - width = param->stack[0]; - height = param->stack[1]; - pixfmt = param->stack[2]; - - for (i = 0; i < ARRAY_SIZE(supported_dst_frames); i++) { - if ((supported_dst_frames[i].width == width) && - (supported_dst_frames[i].height == height)) { - break; - } - } - if (i == ARRAY_SIZE(supported_dst_frames)) { - param->errCode = EINVAL; - return; - } - for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) { - if (supported_dst_pixfmts[i].fmt == pixfmt) { - break; - } - } - if (i == ARRAY_SIZE(supported_dst_pixfmts)) { - param->errCode = EINVAL; - return; - } - - param->stack[0] = width; - param->stack[1] = height; - param->stack[2] = 1; /* V4L2_FIELD_NONE */ - param->stack[3] = pixfmt; - param->stack[4] = get_bytesperline(pixfmt, width); - param->stack[5] = get_sizeimage(pixfmt, width, height); - param->stack[6] = 0; - param->stack[7] = 0; -} - -void marucam_device_enum_fmt(MaruCamState *state) -{ - uint32_t index; - MaruCamParam *param = state->param; - - param->top = 0; - index = param->stack[0]; - - if (index >= ARRAY_SIZE(supported_dst_pixfmts)) { - param->errCode = EINVAL; - return; - } - param->stack[1] = 0; /* flags = NONE */ - param->stack[2] = supported_dst_pixfmts[index].fmt; /* pixelformat */ - /* set description */ - switch (supported_dst_pixfmts[index].fmt) { - case V4L2_PIX_FMT_YUYV: - memcpy(¶m->stack[3], "YUYV", 32); - break; - case V4L2_PIX_FMT_YUV420: - memcpy(¶m->stack[3], "YU12", 32); - break; - case V4L2_PIX_FMT_YVU420: - memcpy(¶m->stack[3], "YV12", 32); - break; - default: - ERR("Invalid pixel format\n"); - param->errCode = EINVAL; - break; - } -} - -void marucam_device_qctrl(MaruCamState *state) -{ - HRESULT hr; - uint32_t id, i; - long property, min, max, step, def_val, set_val; - char name[32] = {0,}; - MaruCamParam *param = state->param; - - param->top = 0; - id = param->stack[0]; - - switch (id) { - case V4L2_CID_BRIGHTNESS: - TRACE("V4L2_CID_BRIGHTNESS\n"); - property = VideoProcAmp_Brightness; - memcpy((void *)name, (void *)"brightness", 32); - i = 0; - break; - case V4L2_CID_CONTRAST: - TRACE("V4L2_CID_CONTRAST\n"); - property = VideoProcAmp_Contrast; - memcpy((void *)name, (void *)"contrast", 32); - i = 1; - break; - case V4L2_CID_SATURATION: - TRACE("V4L2_CID_SATURATION\n"); - property = VideoProcAmp_Saturation; - memcpy((void *)name, (void *)"saturation", 32); - i = 2; - break; - case V4L2_CID_SHARPNESS: - TRACE("V4L2_CID_SHARPNESS\n"); - property = VideoProcAmp_Sharpness; - memcpy((void *)name, (void *)"sharpness", 32); - i = 3; - break; - default: - ERR("Invalid control ID\n"); - param->errCode = EINVAL; - return; - } - hr = QueryVideoProcAmp(property, &min, &max, &step, &def_val); - if (FAILED(hr)) { - param->errCode = EINVAL; - ERR("failed to query video controls [HRESULT : 0x%x]\n", hr); - return; - } else { - qctrl_tbl[i].hit = 1; - qctrl_tbl[i].min = min; - qctrl_tbl[i].max = max; - qctrl_tbl[i].step = step; - qctrl_tbl[i].init_val = def_val; - - if ((qctrl_tbl[i].min + qctrl_tbl[i].max) == 0) { - set_val = 0; - } else { - set_val = (qctrl_tbl[i].min + qctrl_tbl[i].max) / 2; - } - hr = SetVideoProcAmp(property, set_val); - if (FAILED(hr)) { - param->errCode = EINVAL; - ERR("failed to set video control value, [HRESULT : 0x%x]\n", hr); - return; - } - } - - param->stack[0] = id; - param->stack[1] = MARUCAM_CTRL_VALUE_MIN; /* minimum */ - param->stack[2] = MARUCAM_CTRL_VALUE_MAX; /* maximum */ - param->stack[3] = MARUCAM_CTRL_VALUE_STEP; /* step */ - param->stack[4] = MARUCAM_CTRL_VALUE_MID; /* default_value */ - param->stack[5] = V4L2_CTRL_FLAG_SLIDER; - /* name field setting */ - memcpy(¶m->stack[6], (void *)name, sizeof(name)/sizeof(name[0])); -} - -void marucam_device_s_ctrl(MaruCamState *state) -{ - HRESULT hr; - uint32_t i; - long property, set_val; - MaruCamParam *param = state->param; - - param->top = 0; - - switch (param->stack[0]) { - case V4L2_CID_BRIGHTNESS: - i = 0; - property = VideoProcAmp_Brightness; - break; - case V4L2_CID_CONTRAST: - i = 1; - property = VideoProcAmp_Contrast; - break; - case V4L2_CID_SATURATION: - i = 2; - property = VideoProcAmp_Saturation; - break; - case V4L2_CID_SHARPNESS: - i = 3; - property = VideoProcAmp_Sharpness; - break; - default: - param->errCode = EINVAL; - return; - } - set_val = value_convert_from_guest(qctrl_tbl[i].min, - qctrl_tbl[i].max, (long)param->stack[1]); - hr = SetVideoProcAmp(property, set_val); - if (FAILED(hr)) { - param->errCode = EINVAL; - ERR("failed to set video control value, [HRESULT : 0x%x]\n", hr); - return; - } -} - -void marucam_device_g_ctrl(MaruCamState *state) -{ - HRESULT hr; - uint32_t i; - long property, get_val; - MaruCamParam *param = state->param; - - param->top = 0; - switch (param->stack[0]) { - case V4L2_CID_BRIGHTNESS: - i = 0; - property = VideoProcAmp_Brightness; - break; - case V4L2_CID_CONTRAST: - i = 1; - property = VideoProcAmp_Contrast; - break; - case V4L2_CID_SATURATION: - i = 2; - property = VideoProcAmp_Saturation; - break; - case V4L2_CID_SHARPNESS: - i = 3; - property = VideoProcAmp_Sharpness; - break; - default: - param->errCode = EINVAL; - return; - } - - hr = GetVideoProcAmp(property, &get_val); - if (FAILED(hr)) { - param->errCode = EINVAL; - ERR("failed to get video control value!!!, [HRESULT : 0x%x]\n", hr); - return; - } - param->stack[0] = (uint32_t)value_convert_to_guest(qctrl_tbl[i].min, - qctrl_tbl[i].max, get_val); -} - -void marucam_device_enum_fsizes(MaruCamState *state) -{ - uint32_t index, pixfmt, i; - MaruCamParam *param = state->param; - - param->top = 0; - index = param->stack[0]; - pixfmt = param->stack[1]; - - if (index >= ARRAY_SIZE(supported_dst_frames)) { - param->errCode = EINVAL; - return; - } - for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) { - if (supported_dst_pixfmts[i].fmt == pixfmt) { - break; - } - } - - if (i == ARRAY_SIZE(supported_dst_pixfmts)) { - param->errCode = EINVAL; - return; - } - - param->stack[0] = supported_dst_frames[index].width; - param->stack[1] = supported_dst_frames[index].height; -} - -void marucam_device_enum_fintv(MaruCamState *state) -{ - MaruCamParam *param = state->param; - - param->top = 0; - - /* switch by index(param->stack[0]) */ - switch (param->stack[0]) { - case 0: - param->stack[1] = 30; /* denominator */ - break; - default: - param->errCode = EINVAL; - return; - } - param->stack[0] = 1; /* numerator */ -} - -void yuyv_to_yuv420(const unsigned char *src, unsigned char *dest, - uint32_t width, uint32_t height, uint32_t yvu) -{ - uint32_t i, j; - const unsigned char *src1; - unsigned char *udest, *vdest; - - /* copy the Y values */ - src1 = src; - for (i = 0; i < height; i++) { - for (j = 0; j < width; j += 2) { - *dest++ = src1[0]; - *dest++ = src1[2]; - src1 += 4; - } - } - - /* copy the U and V values */ - src++; /* point to V */ - src1 = src + width * 2; /* next line */ - if (yvu) { - vdest = dest; - udest = dest + width * height / 4; - } else { - udest = dest; - vdest = dest + width * height / 4; - } - for (i = 0; i < height; i += 2) { - for (j = 0; j < width; j += 2) { - *udest++ = ((int) src[0] + src1[0]) / 2; /* U */ - *vdest++ = ((int) src[2] + src1[2]) / 2; /* V */ - src += 4; - src1 += 4; - } - src = src1; - src1 += width * 2; - } -} - -#define RGB2Y(r, g, b, y) \ - (y) = ((8453 * (r) + 16594 * (g) + 3223 * (b) + 524288) >> 15) - -#define RGB2UV(r, g, b, u, v) \ - do { \ - (u) = ((-4878 * (r) - 9578 * (g) + 14456 * (b) + 4210688) >> 15); \ - (v) = ((14456 * (r) - 12105 * (g) - 2351 * (b) + 4210688) >> 15); \ - } while (0) - -#define CLIP(color) \ - (unsigned char)(((color) > 0xFF) ? 0xff : (((color) < 0) ? 0 : (color))) - -void rgb24_to_yuv420(const unsigned char *src, unsigned char *dest, - uint32_t width, uint32_t height, uint32_t yvu) -{ - uint32_t x, y; - unsigned char *udest, *vdest; - uint32_t bytesperline = width * 3; - - /* Y */ - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - RGB2Y(src[2], src[1], src[0], *dest++); - src += 3; - } - src += bytesperline - 3 * width; - } - src -= height * bytesperline; - - /* U + V */ - if (yvu) { - vdest = dest; - udest = dest + width * height / 4; - } else { - udest = dest; - vdest = dest + width * height / 4; - } - - for (y = 0; y < height / 2; y++) { - for (x = 0; x < width / 2; x++) { - uint32_t avg_src[3]; - - avg_src[0] = (src[0] + src[3] + src[bytesperline] + - src[bytesperline + 3]) / 4; - avg_src[1] = (src[1] + src[4] + src[bytesperline + 1] + - src[bytesperline + 4]) / 4; - avg_src[2] = (src[2] + src[5] + src[bytesperline + 2] + - src[bytesperline + 5]) / 4; - RGB2UV(avg_src[2], avg_src[1], avg_src[0], *udest++, *vdest++); - src += 6; - } - src += 2 * bytesperline - 3 * width; - } -} - -void rgb24_to_yuyv(unsigned char *src, unsigned char *dest, - uint32_t width, uint32_t height) -{ - uint32_t i = 0; - - for (i = 0; i < (width * height * 3); i = i + 6) { - /* y */ - *dest++ = CLIP(0.299 * (src[i + 2] - 128) + - 0.587 * (src[i + 1] - 128) + - 0.114 * (src[i] - 128) + 128); - /* u */ - *dest++ = CLIP(((-0.147 * (src[i + 2] - 128) - - 0.289 * (src[i + 1] - 128) + - 0.436 * (src[i] - 128) + 128) + - (-0.147 * (src[i + 5] - 128) - - 0.289 * (src[i + 4] - 128) + - 0.436 * (src[i + 3] - 128) + 128)) / 2); - /* y1 */ - *dest++ = CLIP(0.299 * (src[i + 5] - 128) + - 0.587 * (src[i + 4] - 128) + - 0.114 * (src[i + 3] - 128) + 128); - /* v */ - *dest++ = CLIP(((0.615 * (src[i + 2] - 128) - - 0.515 * (src[i + 1] - 128) - - 0.100 * (src[i] - 128) + 128) + - (0.615 * (src[i + 5] - 128) - - 0.515 * (src[i + 4] - 128) - - 0.100 * (src[i + 3] - 128) + 128)) / 2); - } -} - -void yuv420_to_yvu420(unsigned char *src, unsigned char *dest, - uint32_t width, uint32_t height) -{ - unsigned char *psrc_y, *pdst_y; - unsigned char *psrc_u, *pdst_u; - unsigned char *psrc_v, *pdst_v; - - psrc_y = src; - psrc_u = psrc_y + (width * height); - psrc_v = psrc_u + (width * height / 4); - - pdst_y = dest; - pdst_v = pdst_y + (width * height); - pdst_u = pdst_v + (width * height / 4); - - memcpy(pdst_y, psrc_y, width * height); - memcpy(pdst_v, psrc_v, width * height / 4); - memcpy(pdst_u, psrc_u, width * height / 4); -} - -void yuv420_to_yuyv(unsigned char *src, unsigned char *dest, - uint32_t width, uint32_t height) -{ - unsigned char *py; - unsigned char *pu; - unsigned char *pv; - - uint32_t linesize = width * 2; - uint32_t uvlinesize = width / 2; - uint32_t offset = 0; - uint32_t offset1 = 0; - uint32_t offsety = 0; - uint32_t offsety1 = 0; - uint32_t offsetuv = 0; - uint32_t h = 0; - uint32_t w = 0; - uint32_t wy = 0; - uint32_t huv = 0; - uint32_t wuv = 0; - - py = src; - pu = py + (width * height); - pv = pu + (width * height / 4); - - for (h = 0; h < height; h += 2) { - wy = 0; - wuv = 0; - offset = h * linesize; - offset1 = (h + 1) * linesize; - offsety = h * width; - offsety1 = (h + 1) * width; - offsetuv = huv * uvlinesize; - - for (w = 0; w < linesize; w += 4) { - /* y00 */ - dest[w + offset] = py[wy + offsety]; - /* u0 */ - dest[(w + 1) + offset] = pu[wuv + offsetuv]; - /* y01 */ - dest[(w + 2) + offset] = py[(wy + 1) + offsety]; - /* v0 */ - dest[(w + 3) + offset] = pv[wuv + offsetuv]; - - /* y10 */ - dest[w + offset1] = py[wy + offsety1]; - /* u0 */ - dest[(w + 1) + offset1] = pu[wuv + offsetuv]; - /* y11 */ - dest[(w + 2) + offset1] = py[(wy + 1) + offsety1]; - /* v0 */ - dest[(w + 3) + offset1] = pv[wuv + offsetuv]; - - wuv++; - wy += 2; - } - huv++; - } -} +/* + * Implementation of MARU Virtual Camera device by PCI bus on Windows. + * + * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * JinHyung Jo + * YeongKyoon Lee + * + * 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 + * + */ + + +#include "qemu-common.h" +#include "maru_camera_common.h" +#include "tizen/src/debug_ch.h" + +#define CINTERFACE +#define COBJMACROS +#include "ocidl.h" +#include "errors.h" /* for VFW_E_XXXX */ +#include "mmsystem.h" /* for MAKEFOURCC macro */ +#include "maru_camera_win32_interface.h" + +MULTI_DEBUG_CHANNEL(tizen, camera_win32); + +/* + * COM Interface implementations + * + */ + +#define SAFE_RELEASE(x) \ + do { \ + if (x) { \ + (x)->lpVtbl->Release(x); \ + x = NULL; \ + } \ + } while (0) + +typedef HRESULT (STDAPICALLTYPE *CallbackFn)(ULONG dwSize, BYTE *pBuffer); + +/* + * HWCGrabCallback + */ + +typedef struct HWCGrabCallback { + IGrabCallback IGrabCallback_iface; + long m_cRef; + CallbackFn m_pCallback; + STDMETHODIMP (*SetCallback)(IGrabCallback *iface, CallbackFn pCallbackFn); +} HWCGrabCallback; + +static inline HWCGrabCallback *impl_from_IGrabCallback(IGrabCallback *iface) +{ + return CONTAINING_RECORD(iface, HWCGrabCallback, IGrabCallback_iface); +} + +static STDMETHODIMP HWCGrabCallback_QueryInterface(IGrabCallback *iface, + REFIID riid, void **ppv) +{ + if (IsEqualIID(riid, &IID_IUnknown)) { + *ppv = (IUnknown *)iface; + } else if (IsEqualIID(riid, &IID_IGrabCallback)) { + *ppv = (IGrabCallback *)iface; + } else { + *ppv = NULL; + return E_NOINTERFACE; + } + + IGrabCallback_AddRef(iface); + return S_OK; +} + +static STDMETHODIMP_(ULONG) HWCGrabCallback_AddRef(IGrabCallback *iface) +{ + HWCGrabCallback *This = impl_from_IGrabCallback(iface); + + return InterlockedIncrement(&This->m_cRef); +} + +static STDMETHODIMP_(ULONG) HWCGrabCallback_Release(IGrabCallback *iface) +{ + HWCGrabCallback *This = impl_from_IGrabCallback(iface); + + if (InterlockedDecrement(&This->m_cRef) == 0) { + This->m_pCallback = NULL; + g_free((void *)This); + This = NULL; + return 0; + } + + return This->m_cRef; +} + +static STDMETHODIMP HWCGrabCallback_Grab(IGrabCallback *iface, + ULONG dwSize, BYTE *pBuffer) +{ + HWCGrabCallback *This = impl_from_IGrabCallback(iface); + + if (This->m_pCallback) { + HRESULT hr = This->m_pCallback(dwSize, pBuffer); + if (FAILED(hr)) { + return E_FAIL; + } else { + return S_OK; + } + } + + return E_FAIL; +} + +static STDMETHODIMP HWCGrabCallback_SetCallback(IGrabCallback *iface, + CallbackFn pCallbackFn) +{ + HWCGrabCallback *This = impl_from_IGrabCallback(iface); + + This->m_pCallback = pCallbackFn; + return S_OK; +} + +static IGrabCallbackVtbl HWCGrabCallback_Vtbl = { + HWCGrabCallback_QueryInterface, + HWCGrabCallback_AddRef, + HWCGrabCallback_Release, + HWCGrabCallback_Grab +}; + +static STDMETHODIMP HWCGrabCallback_Construct(IGrabCallback **ppv) +{ + HWCGrabCallback *This = + (HWCGrabCallback *)g_malloc0(sizeof(HWCGrabCallback)); + + if (!This) { + ERR("failed to HWCGrabCallback_Construct, E_OUTOFMEMORY\n"); + return E_OUTOFMEMORY; + } + + This->IGrabCallback_iface.lpVtbl = &HWCGrabCallback_Vtbl; + This->m_cRef = 1; + This->m_pCallback = NULL; + This->SetCallback = HWCGrabCallback_SetCallback; + *ppv = &This->IGrabCallback_iface; + return S_OK; +} + +/* + * HWCPin + */ + +typedef struct HWCInPin { + IPin IPin_iface; + IMemInputPin IMemInputPin_iface; + IBaseFilter *m_pCFilter; + IPin *m_pConnectedPin; + IGrabCallback *m_pCallback; + IMemAllocator *m_pAllocator; + BOOL m_bReadOnly; + long m_cRef; + STDMETHODIMP (*SetGrabCallbackIF)(IPin *iface, IGrabCallback *pCaptureCB); +} HWCInPin; + +static inline HWCInPin *impl_from_IPin(IPin *iface) +{ + return CONTAINING_RECORD(iface, HWCInPin, IPin_iface); +} + +static inline HWCInPin *impl_from_IMemInputPin(IMemInputPin *iface) +{ + return CONTAINING_RECORD(iface, HWCInPin, IMemInputPin_iface); +} + +static STDMETHODIMP HWCPin_QueryInterface(IPin *iface, REFIID riid, void **ppv) +{ + HWCInPin *This = impl_from_IPin(iface); + + if (IsEqualIID(riid, &IID_IUnknown)) { + *ppv = (IUnknown *)(&This->IPin_iface); + IPin_AddRef((IPin *)*ppv); + } else if (IsEqualIID(riid, &IID_IPin)) { + *ppv = (IPin *)(&This->IPin_iface); + IPin_AddRef((IPin *)*ppv); + } else if (IsEqualIID(riid, &IID_IMemInputPin)) { + *ppv = (IMemInputPin *)(&This->IMemInputPin_iface); + IPin_AddRef((IMemInputPin *)*ppv); + } else { + *ppv = NULL; + return E_NOINTERFACE; + } + + return S_OK; +} + +static STDMETHODIMP_(ULONG) HWCPin_AddRef(IPin *iface) +{ + HWCInPin *This = impl_from_IPin(iface); + + return InterlockedIncrement(&This->m_cRef); +} + +static STDMETHODIMP_(ULONG) HWCPin_Release(IPin *iface) +{ + HWCInPin *This = impl_from_IPin(iface); + + if (InterlockedDecrement(&This->m_cRef) == 0) { + if (This->m_pCallback) { + SAFE_RELEASE(This->m_pCallback); + } + if (This->m_pConnectedPin) { + SAFE_RELEASE(This->m_pConnectedPin); + } + if (This->m_pAllocator) { + IMemAllocator_Decommit(This->m_pAllocator); + SAFE_RELEASE(This->m_pAllocator); + } + g_free((void *)This); + This = NULL; + return 0; + } + return This->m_cRef; +} + +static STDMETHODIMP HWCPin_Connect(IPin *iface, + IPin *pReceivePin, + const AM_MEDIA_TYPE *pmt) +{ + HWCInPin *This = impl_from_IPin(iface); + + if (!pReceivePin) { + return E_POINTER; + } + + if (This->m_pConnectedPin) { + return VFW_E_ALREADY_CONNECTED; + } + + if (!pmt) { + return S_OK; + } + return S_FALSE; +} + +static STDMETHODIMP HWCPin_ReceiveConnection(IPin *iface, IPin *pConnector, + const AM_MEDIA_TYPE *pmt) +{ + PIN_DIRECTION pd; + FILTER_STATE fs; + HWCInPin *This = impl_from_IPin(iface); + + if (pConnector == NULL || pmt == NULL) { + return E_POINTER; + } + + if (This->m_pConnectedPin) { + return VFW_E_ALREADY_CONNECTED; + } + IBaseFilter_GetState(This->m_pCFilter, 0, &fs); + if (fs != State_Stopped) { + return VFW_E_NOT_STOPPED; + } + IPin_QueryDirection(pConnector, &pd); + if (pd == PINDIR_INPUT) { + return VFW_E_INVALID_DIRECTION; + } + + This->m_pConnectedPin = pConnector; + IPin_AddRef(This->m_pConnectedPin); + return S_OK; +} + +static STDMETHODIMP HWCPin_Disconnect(IPin *iface) +{ + HWCInPin *This = impl_from_IPin(iface); + + HRESULT hr; + FILTER_STATE fs; + IBaseFilter_GetState(This->m_pCFilter, 0, &fs); + if (fs != State_Stopped) { + return VFW_E_NOT_STOPPED; + } + if (This->m_pConnectedPin == NULL) { + hr = S_FALSE; + } else { + if (This->m_pAllocator) { + hr = IMemAllocator_Decommit(This->m_pAllocator); + if (FAILED(hr)) { + return hr; + } + SAFE_RELEASE(This->m_pAllocator); + } + SAFE_RELEASE(This->m_pConnectedPin); + hr = S_OK; + } + return hr; +} + +static STDMETHODIMP HWCPin_ConnectedTo(IPin *iface, IPin **ppPin) +{ + HWCInPin *This = impl_from_IPin(iface); + + if (ppPin == NULL) { + return E_POINTER; + } + + if (This->m_pConnectedPin == NULL) { + *ppPin = NULL; + return VFW_E_NOT_CONNECTED; + } else { + *ppPin = This->m_pConnectedPin; + IPin_AddRef(This->m_pConnectedPin); + } + return S_OK; +} + +static STDMETHODIMP HWCPin_ConnectionMediaType(IPin *iface, AM_MEDIA_TYPE *pmt) +{ + if (pmt == NULL) { + return E_POINTER; + } + return VFW_E_NOT_CONNECTED; +} + +static STDMETHODIMP HWCPin_QueryPinInfo(IPin *iface, PIN_INFO *pInfo) +{ + HWCInPin *This = impl_from_IPin(iface); + + if (pInfo == NULL) { + return E_POINTER; + } + + pInfo->pFilter = This->m_pCFilter; + if (This->m_pCFilter) { + IBaseFilter_AddRef(This->m_pCFilter); + } + memcpy((void *)pInfo->achName, (void *)HWCPinName, sizeof(HWCPinName)); + pInfo->dir = PINDIR_INPUT; + return S_OK; +} + +static STDMETHODIMP HWCPin_QueryDirection(IPin *iface, PIN_DIRECTION *pPinDir) +{ + if (pPinDir == NULL) { + return E_POINTER; + } + *pPinDir = PINDIR_INPUT; + return S_OK; +} + +static STDMETHODIMP HWCPin_QueryId(IPin *iface, LPWSTR *Id) +{ + PVOID pId; + if (Id == NULL) { + return E_POINTER; + } + pId = CoTaskMemAlloc(sizeof(HWCPinName)); + memcpy((void *)pId, (void *)HWCPinName, sizeof(HWCPinName)); + *Id = (LPWSTR)pId; + return S_OK; +} + +static STDMETHODIMP HWCPin_QueryAccept(IPin *iface, const AM_MEDIA_TYPE *pmt) +{ + if (pmt == NULL) { + return E_POINTER; + } + return S_OK; +} + +static STDMETHODIMP HWCPin_EnumMediaTypes(IPin *iface, + IEnumMediaTypes **ppEnum) +{ + if (ppEnum == NULL) { + return E_POINTER; + } + return E_NOTIMPL; +} + +static STDMETHODIMP HWCPin_QueryInternalConnections(IPin *iface, + IPin **ppPin, + ULONG *nPin) +{ + return E_NOTIMPL; +} + +static STDMETHODIMP HWCPin_EndOfStream(IPin *iface) +{ + return S_OK; +} + +static STDMETHODIMP HWCPin_BeginFlush(IPin *iface) +{ + return S_OK; +} + +static STDMETHODIMP HWCPin_EndFlush(IPin *iface) +{ + return S_OK; +} + +static STDMETHODIMP HWCPin_NewSegment(IPin *iface, REFERENCE_TIME tStart, + REFERENCE_TIME tStop, double dRate) +{ + return S_OK; +} + +static STDMETHODIMP HWCMemInputPin_QueryInterface(IMemInputPin *iface, + REFIID riid, void **ppv) +{ + HWCInPin *This = impl_from_IMemInputPin(iface); + + if (IsEqualIID(riid, &IID_IUnknown)) { + *ppv = (IUnknown *)(&This->IMemInputPin_iface); + IPin_AddRef((IPin *)*ppv); + } else if (IsEqualIID(riid, &IID_IPin)) { + *ppv = (IPin *)(&This->IPin_iface); + IPin_AddRef((IPin *)*ppv); + } else if (IsEqualIID(riid, &IID_IMemInputPin)) { + *ppv = (IMemInputPin *)(&This->IMemInputPin_iface); + IPin_AddRef((IMemInputPin *)*ppv); + } else { + *ppv = NULL; + return E_NOINTERFACE; + } + + return S_OK; +} + +static STDMETHODIMP_(ULONG) HWCMemInputPin_AddRef(IMemInputPin *iface) +{ + HWCInPin *This = impl_from_IMemInputPin(iface); + + return InterlockedIncrement(&This->m_cRef); +} + +static STDMETHODIMP_(ULONG) HWCMemInputPin_Release(IMemInputPin *iface) +{ + HWCInPin *This = impl_from_IMemInputPin(iface); + + if (InterlockedDecrement(&This->m_cRef) == 0) { + if (This->m_pCallback) { + SAFE_RELEASE(This->m_pCallback); + } + if (This->m_pConnectedPin) { + SAFE_RELEASE(This->m_pConnectedPin); + } + if (This->m_pAllocator) { + IMemAllocator_Decommit(This->m_pAllocator); + SAFE_RELEASE(This->m_pAllocator); + } + g_free((void *)This); + This = NULL; + return 0; + } + return This->m_cRef; +} + +static STDMETHODIMP HWCMemInputPin_GetAllocator(IMemInputPin *iface, + IMemAllocator **ppAllocator) +{ + HWCInPin *This = impl_from_IMemInputPin(iface); + + if (ppAllocator == NULL) { + return E_POINTER; + } + + if (This->m_pAllocator == NULL) { + HRESULT hr = CoCreateInstance(&CLSID_MemoryAllocator, NULL, + CLSCTX_INPROC_SERVER, + &IID_IMemAllocator, + (void **)&(This->m_pAllocator)); + if (FAILED(hr)) { + ERR("Failed to CoCreateInstance for retrieving MemoryAllocator\n"); + return hr; + } + } + ASSERT(This->m_pAllocator != NULL); + *ppAllocator = This->m_pAllocator; + IMemAllocator_AddRef(This->m_pAllocator); + + return S_OK; +} + +static STDMETHODIMP HWCMemInputPin_NotifyAllocator(IMemInputPin *iface, + IMemAllocator *pAllocator, + BOOL bReadOnly) +{ + HWCInPin *This = impl_from_IMemInputPin(iface); + + if (pAllocator == NULL) { + return E_POINTER; + } + + IMemAllocator *pOldAllocator = This->m_pAllocator; + IMemAllocator_AddRef(pAllocator); + This->m_pAllocator = pAllocator; + + if (pOldAllocator != NULL) { + SAFE_RELEASE(pOldAllocator); + } + + This->m_bReadOnly = bReadOnly; + + return S_OK; +} + +static STDMETHODIMP HWCMemInputPin_GetAllocatorRequirements( + IMemInputPin *iface, + ALLOCATOR_PROPERTIES *pProps) +{ + return E_NOTIMPL; +} + +static STDMETHODIMP HWCMemInputPin_Receive(IMemInputPin *iface, + IMediaSample *pSample) +{ + HWCInPin *This = impl_from_IMemInputPin(iface); + + if (pSample == NULL) { + ERR("pSample is NULL\n"); + return E_POINTER; + } + if (This->m_pCallback != NULL) { + HRESULT hr; + BYTE *pBuffer = NULL; + DWORD dwSize = 0; + dwSize = IMediaSample_GetSize(pSample); + hr = IMediaSample_GetPointer(pSample, &pBuffer); + if (FAILED(hr)) { + ERR("Receive function : " + "failed to IMediaSample_GetPointer, 0x%ld\n", hr); + return hr; + } + hr = IGrabCallback_Grab(This->m_pCallback, dwSize, pBuffer); + if (FAILED(hr)) { + ERR("Receive function : failed to IGrabCallback_Grab, 0x%ld\n", + hr); + return hr; + } + } + return S_OK; +} + +static STDMETHODIMP HWCMemInputPin_ReceiveMultiple(IMemInputPin *iface, + IMediaSample **pSamples, + long nSamples, + long *nSamplesProcessed) +{ + HRESULT hr = S_OK; + + if (pSamples == NULL) { + return E_POINTER; + } + + *nSamplesProcessed = 0; + + while (nSamples-- > 0) { + hr = IMemInputPin_Receive(iface, pSamples[*nSamplesProcessed]); + if (hr != S_OK) { + break; + } + (*nSamplesProcessed)++; + } + return hr; +} + +static STDMETHODIMP HWCMemInputPin_ReceiveCanBlock(IMemInputPin *iface) +{ + return S_FALSE; +} + +static STDMETHODIMP HWCPin_SetCallback(IPin *iface, IGrabCallback *pCaptureCB) +{ + HWCInPin *This = impl_from_IPin(iface); + + if (pCaptureCB == NULL) { + SAFE_RELEASE(This->m_pCallback); + } else { + This->m_pCallback = pCaptureCB; + IGrabCallback_AddRef(This->m_pCallback); + } + + return S_OK; +} + + +static IPinVtbl HWCPin_Vtbl = { + HWCPin_QueryInterface, + HWCPin_AddRef, + HWCPin_Release, + HWCPin_Connect, + HWCPin_ReceiveConnection, + HWCPin_Disconnect, + HWCPin_ConnectedTo, + HWCPin_ConnectionMediaType, + HWCPin_QueryPinInfo, + HWCPin_QueryDirection, + HWCPin_QueryId, + HWCPin_QueryAccept, + HWCPin_EnumMediaTypes, + HWCPin_QueryInternalConnections, + HWCPin_EndOfStream, + HWCPin_BeginFlush, + HWCPin_EndFlush, + HWCPin_NewSegment +}; + +static IMemInputPinVtbl HWCMemInputPin_Vtbl = { + HWCMemInputPin_QueryInterface, + HWCMemInputPin_AddRef, + HWCMemInputPin_Release, + HWCMemInputPin_GetAllocator, + HWCMemInputPin_NotifyAllocator, + HWCMemInputPin_GetAllocatorRequirements, + HWCMemInputPin_Receive, + HWCMemInputPin_ReceiveMultiple, + HWCMemInputPin_ReceiveCanBlock +}; + +static STDMETHODIMP HWCInPin_Construct(IBaseFilter *pFilter, IPin **ppv) +{ + HWCInPin *This = (HWCInPin *)g_malloc0(sizeof(HWCInPin)); + + if (!This) { + ERR("failed to HWCInPin_Construct, E_OUTOFMEMORY\n"); + return E_OUTOFMEMORY; + } + + This->IPin_iface.lpVtbl = &HWCPin_Vtbl; + This->IMemInputPin_iface.lpVtbl = &HWCMemInputPin_Vtbl; + This->m_bReadOnly = FALSE; + This->m_pCFilter = pFilter; + This->m_pConnectedPin = NULL; + This->m_pCallback = NULL; + This->m_pAllocator = NULL; + This->m_cRef = 1; + This->SetGrabCallbackIF = HWCPin_SetCallback; + *ppv = &This->IPin_iface; + + return S_OK; +} + +/* + * HWCEnumPins + */ + +typedef struct HWCEnumPins { + IEnumPins IEnumPins_iface; + IBaseFilter *m_pFilter; + int m_nPos; + long m_cRef; +} HWCEnumPins; + +static inline HWCEnumPins *impl_from_IEnumPins(IEnumPins *iface) +{ + return CONTAINING_RECORD(iface, HWCEnumPins, IEnumPins_iface); +} + +static STDMETHODIMP HWCEnumPins_QueryInterface(IEnumPins *iface, + REFIID riid, void **ppv) +{ + if (ppv == NULL) { + return E_POINTER; + } + + if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IEnumPins)) { + *ppv = iface; + } else { + *ppv = NULL; + return E_NOINTERFACE; + } + + IEnumPins_AddRef(iface); + return S_OK; +} + +static STDMETHODIMP_(ULONG) HWCEnumPins_AddRef(IEnumPins *iface) +{ + HWCEnumPins *This = impl_from_IEnumPins(iface); + + return InterlockedIncrement(&This->m_cRef); +} + +static STDMETHODIMP_(ULONG) HWCEnumPins_Release(IEnumPins *iface) +{ + HWCEnumPins *This = impl_from_IEnumPins(iface); + + if (InterlockedDecrement(&This->m_cRef) == 0) { + if (This->m_pFilter) { + SAFE_RELEASE(This->m_pFilter); + } + This->m_nPos = 0; + g_free((void *)This); + This = NULL; + return 0; + } + return This->m_cRef; +} + +static STDMETHODIMP HWCEnumPins_Next(IEnumPins *iface, ULONG cPins, + IPin **ppPins, ULONG *pcFetched) +{ + ULONG fetched; + HWCEnumPins *This = impl_from_IEnumPins(iface); + + if (ppPins == NULL) { + return E_POINTER; + } + + if (This->m_nPos < 1 && cPins > 0) { + IPin *pPin; + IBaseFilter_FindPin(This->m_pFilter, HWCPinName, &pPin); + *ppPins = pPin; + fetched = 1; + This->m_nPos++; + } else { + fetched = 0; + } + + if (pcFetched != NULL) { + *pcFetched = fetched; + } + + return (fetched == cPins) ? S_OK : S_FALSE; +} + +static STDMETHODIMP HWCEnumPins_Skip(IEnumPins *iface, ULONG cPins) +{ + HWCEnumPins *This = impl_from_IEnumPins(iface); + This->m_nPos += cPins; + return (This->m_nPos >= 1) ? S_FALSE : S_OK; +} + +static STDMETHODIMP HWCEnumPins_Reset(IEnumPins *iface) +{ + HWCEnumPins *This = impl_from_IEnumPins(iface); + This->m_nPos = 0; + return S_OK; +} + +static STDMETHODIMP HWCEnumPins_Construct(IBaseFilter *pFilter, + int nPos, IEnumPins **ppv); + +static STDMETHODIMP HWCEnumPins_Clone(IEnumPins *iface, IEnumPins **ppEnum) +{ + HWCEnumPins *This = impl_from_IEnumPins(iface); + + if (ppEnum == NULL) { + return E_POINTER; + } + + HWCEnumPins_Construct(This->m_pFilter, This->m_nPos, ppEnum); + if (*ppEnum == NULL) { + ERR("failed to HWCEnumPins_Construct in clone, E_OUTOFMEMORY\n"); + return E_OUTOFMEMORY; + } + + return S_OK; +} + +static IEnumPinsVtbl HWCEnumPins_Vtbl = { + HWCEnumPins_QueryInterface, + HWCEnumPins_AddRef, + HWCEnumPins_Release, + HWCEnumPins_Next, + HWCEnumPins_Skip, + HWCEnumPins_Reset, + HWCEnumPins_Clone +}; + + +static STDMETHODIMP HWCEnumPins_Construct(IBaseFilter *pFilter, + int nPos, IEnumPins **ppv) +{ + HWCEnumPins *This = (HWCEnumPins *)g_malloc0(sizeof(HWCEnumPins)); + + if (!This) { + ERR("failed to HWCEnumPins_Construct, E_OUTOFMEMORY\n"); + return E_OUTOFMEMORY; + } + + This->IEnumPins_iface.lpVtbl = &HWCEnumPins_Vtbl; + This->m_pFilter = pFilter; + if (This->m_pFilter) { + IBaseFilter_AddRef(This->m_pFilter); + } + This->m_cRef = 1; + This->m_nPos = nPos; + *ppv = &This->IEnumPins_iface; + + return S_OK; +} + +/* + * HWCFilter + */ + +typedef struct HWCFilter { + IBaseFilter IBaseFilter_iface; + IPin *m_pPin; + IFilterGraph *m_pFilterGraph; + FILTER_STATE m_state; + long m_cRef; +} HWCFilter; + +static inline HWCFilter *impl_from_IBaseFilter(IBaseFilter *iface) +{ + return CONTAINING_RECORD(iface, HWCFilter, IBaseFilter_iface); +} + +static STDMETHODIMP HWCFilter_QueryInterface(IBaseFilter *iface, + REFIID riid, void **ppv) +{ + if (IsEqualIID(riid, &IID_IUnknown)) { + *ppv = (IUnknown *)iface; + } else if (IsEqualIID(riid, &IID_IPersist)) { + *ppv = (IPersist *)iface; + } else if (IsEqualIID(riid, &IID_IMediaFilter)) { + *ppv = (IMediaFilter *)iface; + } else if (IsEqualIID(riid, &IID_IBaseFilter)) { + *ppv = (IBaseFilter *)iface; + } else { + *ppv = NULL; + return E_NOINTERFACE; + } + + IBaseFilter_AddRef(iface); + return S_OK; +} + +static STDMETHODIMP_(ULONG) HWCFilter_AddRef(IBaseFilter *iface) +{ + HWCFilter *This = impl_from_IBaseFilter(iface); + + return InterlockedIncrement(&This->m_cRef); +} + +static STDMETHODIMP_(ULONG) HWCFilter_Release(IBaseFilter *iface) +{ + HWCFilter *This = impl_from_IBaseFilter(iface); + + if (InterlockedDecrement(&This->m_cRef) == 0) { + if (This->m_pPin) { + SAFE_RELEASE(This->m_pPin); + } + g_free((void *)This); + This = NULL; + return 0; + } + return This->m_cRef; +} + +static STDMETHODIMP HWCFilter_GetClassID(IBaseFilter *iface, CLSID *pClsID) +{ + if (pClsID == NULL) { + return E_POINTER; + } + return E_NOTIMPL; +} + +static STDMETHODIMP HWCFilter_GetState(IBaseFilter *iface, DWORD dwMSecs, + FILTER_STATE *State) +{ + HWCFilter *This = impl_from_IBaseFilter(iface); + *State = This->m_state; + return S_OK; +} + +static STDMETHODIMP HWCFilter_SetSyncSource(IBaseFilter *iface, + IReferenceClock *pClock) +{ + return S_OK; +} + +static STDMETHODIMP HWCFilter_GetSyncSource(IBaseFilter *iface, + IReferenceClock **pClock) +{ + *pClock = NULL; + return S_OK; +} + +static STDMETHODIMP HWCFilter_Stop(IBaseFilter *iface) +{ + HWCFilter *This = impl_from_IBaseFilter(iface); + + IPin_EndFlush(This->m_pPin); + This->m_state = State_Stopped; + return S_OK; +} + +static STDMETHODIMP HWCFilter_Pause(IBaseFilter *iface) +{ + HWCFilter *This = impl_from_IBaseFilter(iface); + This->m_state = State_Paused; + return S_OK; +} + +static STDMETHODIMP HWCFilter_Run(IBaseFilter *iface, REFERENCE_TIME tStart) +{ + HWCFilter *This = impl_from_IBaseFilter(iface); + + if (This->m_state == State_Stopped) { + HRESULT hr; + hr = IBaseFilter_Pause(iface); + if (FAILED(hr)) { + ERR("HWCFilter_Run : Failed to IBaseFilter_Pause, ret=0xld%\n", hr); + return hr; + } + } + + This->m_state = State_Running; + return S_OK; +} + +static STDMETHODIMP HWCFilter_EnumPins(IBaseFilter *iface, IEnumPins **ppEnum) +{ + if (ppEnum == NULL) { + return E_POINTER; + } + + HWCEnumPins_Construct(iface, 0, ppEnum); + return *ppEnum == NULL ? E_OUTOFMEMORY : S_OK; +} + +static STDMETHODIMP HWCFilter_FindPin(IBaseFilter *iface, LPCWSTR Id, + IPin **ppPin) +{ + HWCFilter *This = impl_from_IBaseFilter(iface); + + if (ppPin == NULL) { + return E_POINTER; + } + + if (memcmp((void *)Id, (void *)HWCPinName, sizeof(HWCPinName))) { + return VFW_E_NOT_FOUND; + } + + if (!This->m_pPin) { + HWCInPin_Construct(iface, &This->m_pPin); + } + *ppPin = This->m_pPin; + + IPin_AddRef(This->m_pPin); + return S_OK; +} + +static STDMETHODIMP HWCFilter_QueryFilterInfo(IBaseFilter *iface, + FILTER_INFO *pInfo) +{ + HWCFilter *This = impl_from_IBaseFilter(iface); + + if (pInfo == NULL) { + return E_POINTER; + } + + memcpy((void *)pInfo->achName, + (void *)HWCFilterName, + sizeof(HWCFilterName)); + pInfo->pGraph = This->m_pFilterGraph; + if (This->m_pFilterGraph) { + IFilterGraph_AddRef(This->m_pFilterGraph); + } + return S_OK; +} + +static STDMETHODIMP HWCFilter_JoinFilterGraph(IBaseFilter *iface, + IFilterGraph *pGraph, + LPCWSTR pName) +{ + HWCFilter *This = impl_from_IBaseFilter(iface); + + This->m_pFilterGraph = pGraph; + return S_OK; +} + +static STDMETHODIMP HWCFilter_QueryVendorInfo(IBaseFilter *iface, + LPWSTR *pVendorInfo) +{ + return E_NOTIMPL; +} + +static IBaseFilterVtbl HWCFilter_Vtbl = { + HWCFilter_QueryInterface, + HWCFilter_AddRef, + HWCFilter_Release, + HWCFilter_GetClassID, + HWCFilter_Stop, + HWCFilter_Pause, + HWCFilter_Run, + HWCFilter_GetState, + HWCFilter_SetSyncSource, + HWCFilter_GetSyncSource, + HWCFilter_EnumPins, + HWCFilter_FindPin, + HWCFilter_QueryFilterInfo, + HWCFilter_JoinFilterGraph, + HWCFilter_QueryVendorInfo +}; + +static STDMETHODIMP HWCFilter_Construct(IBaseFilter **ppv) +{ + HWCFilter *This = (HWCFilter *)g_malloc0(sizeof(HWCFilter)); + + if (!This) { + ERR("failed to HWCFilter_Construct, E_OUTOFMEMORY\n"); + return E_OUTOFMEMORY; + } + + This->IBaseFilter_iface.lpVtbl = &HWCFilter_Vtbl; + This->m_pFilterGraph = NULL; + This->m_state = State_Stopped; + This->m_cRef = 1; + HWCInPin_Construct(&This->IBaseFilter_iface, &This->m_pPin); + *ppv = &This->IBaseFilter_iface; + + return S_OK; +} + +/********************************************************** + * + * Virtual device implementations + * + **********************************************************/ + + +/* + * Declaration global variables for Win32 COM Interfaces + */ +IGraphBuilder *g_pGB ; +ICaptureGraphBuilder2 *g_pCGB; +IMediaControl *g_pMediaControl; + +IPin *g_pOutputPin; +IPin *g_pInputPin; +IBaseFilter *g_pDstFilter; +IBaseFilter *g_pSrcFilter; + +IGrabCallback *g_pCallback; + +/* V4L2 defines copy from videodev2.h */ +#define V4L2_CTRL_FLAG_SLIDER 0x0020 + +#define V4L2_CTRL_CLASS_USER 0x00980000 +#define V4L2_CID_BASE (V4L2_CTRL_CLASS_USER | 0x900) +#define V4L2_CID_BRIGHTNESS (V4L2_CID_BASE+0) +#define V4L2_CID_CONTRAST (V4L2_CID_BASE+1) +#define V4L2_CID_SATURATION (V4L2_CID_BASE+2) +#define V4L2_CID_SHARPNESS (V4L2_CID_BASE+27) + +#define V4L2_PIX_FMT_YUYV MAKEFOURCC('Y', 'U', 'Y', 'V') /* 16 YUV 4:2:2 */ +#define V4L2_PIX_FMT_YUV420 MAKEFOURCC('Y', 'U', '1', '2') /* 12 YUV 4:2:0 */ +#define V4L2_PIX_FMT_YVU420 MAKEFOURCC('Y', 'V', '1', '2') /* 12 YVU 4:2:0 */ +#define V4L2_PIX_FMT_RGB24 MAKEFOURCC('R', 'G', 'B', '3') /* 24 RGB-8-8-8 */ + +typedef struct tagMaruCamConvertPixfmt { + uint32_t fmt; /* fourcc */ + uint32_t bpp; /* bits per pixel, 0 for compressed formats */ + uint32_t needs_conversion; +} MaruCamConvertPixfmt; + +static MaruCamConvertPixfmt supported_dst_pixfmts[] = { + { V4L2_PIX_FMT_YUYV, 16, 0 }, + { V4L2_PIX_FMT_YUV420, 12, 0 }, + { V4L2_PIX_FMT_YVU420, 12, 0 }, +}; + +typedef struct tagMaruCamConvertFrameInfo { + uint32_t width; + uint32_t height; +} MaruCamConvertFrameInfo; + +static MaruCamConvertFrameInfo supported_dst_frames[] = { + { 640, 480 }, + { 352, 288 }, + { 320, 240 }, + { 176, 144 }, + { 160, 120 }, +}; + +#define MARUCAM_CTRL_VALUE_MAX 20 +#define MARUCAM_CTRL_VALUE_MIN 1 +#define MARUCAM_CTRL_VALUE_MID 10 +#define MARUCAM_CTRL_VALUE_STEP 1 + +struct marucam_qctrl { + uint32_t id; + uint32_t hit; + long min; + long max; + long step; + long init_val; +}; + +static struct marucam_qctrl qctrl_tbl[] = { + { V4L2_CID_BRIGHTNESS, 0, }, + { V4L2_CID_CONTRAST, 0, }, + { V4L2_CID_SATURATION, 0, }, + { V4L2_CID_SHARPNESS, 0, }, +}; + +static MaruCamState *g_state; + +static uint32_t ready_count; +static uint32_t cur_fmt_idx; +static uint32_t cur_frame_idx; +static void *grab_buf; +static uint32_t g_dwSrcFmt; + + +/* + * Helper functions - converting image formats, converting values + */ + +static uint32_t get_bytesperline(uint32_t pixfmt, uint32_t width) +{ + uint32_t bytesperline; + + switch (pixfmt) { + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_YVU420: + bytesperline = (width * 12) >> 3; + break; + case V4L2_PIX_FMT_YUYV: + default: + bytesperline = width * 2; + break; + } + + return bytesperline; +} + +static uint32_t get_sizeimage(uint32_t pixfmt, uint32_t width, uint32_t height) +{ + return get_bytesperline(pixfmt, width) * height; +} + +void yuyv_to_yuv420(const unsigned char *src, unsigned char *dest, + uint32_t width, uint32_t height, uint32_t yvu); +void rgb24_to_yuv420(const unsigned char *src, unsigned char *dest, + uint32_t width, uint32_t height, uint32_t yvu); +void rgb24_to_yuyv(unsigned char *src, unsigned char *dest, + uint32_t width, uint32_t height); +void yuv420_to_yvu420(unsigned char *src, unsigned char *dest, + uint32_t width, uint32_t height); +void yuv420_to_yuyv(unsigned char *src, unsigned char *dest, + uint32_t width, uint32_t height); + +static long value_convert_from_guest(long min, long max, long value) +{ + double rate = 0.0; + long dist = 0, ret = 0; + + dist = max - min; + + if (dist < MARUCAM_CTRL_VALUE_MAX) { + rate = (double)MARUCAM_CTRL_VALUE_MAX / (double)dist; + ret = min + (int32_t)(value / rate); + } else { + rate = (double)dist / (double)MARUCAM_CTRL_VALUE_MAX; + ret = min + (int32_t)(rate * value); + } + return ret; +} + +static long value_convert_to_guest(long min, long max, long value) +{ + double rate = 0.0; + long dist = 0, ret = 0; + + dist = max - min; + + if (dist < MARUCAM_CTRL_VALUE_MAX) { + rate = (double)MARUCAM_CTRL_VALUE_MAX / (double)dist; + ret = (int32_t)((double)(value - min) * rate); + } else { + rate = (double)dist / (double)MARUCAM_CTRL_VALUE_MAX; + ret = (int32_t)((double)(value - min) / rate); + } + + return ret; +} + +/* + * Callback function for grab frames + */ +static STDMETHODIMP marucam_device_callbackfn(ULONG dwSize, BYTE *pBuffer) +{ + void *tmp_buf; + uint32_t width, height, fmt, imgsize; + + width = supported_dst_frames[cur_frame_idx].width; + height = supported_dst_frames[cur_frame_idx].height; + fmt = supported_dst_pixfmts[cur_fmt_idx].fmt; + imgsize = get_sizeimage(fmt, width, height); + + if (imgsize > (uint32_t)dwSize) { + ERR("Image size is mismatched\n"); + return E_FAIL; + } + + switch (g_dwSrcFmt) { + case V4L2_PIX_FMT_YUYV: + switch (fmt) { + case V4L2_PIX_FMT_YUV420: + yuyv_to_yuv420(pBuffer, grab_buf, width, height, 0); + break; + case V4L2_PIX_FMT_YVU420: + yuyv_to_yuv420(pBuffer, grab_buf, width, height, 1); + break; + case V4L2_PIX_FMT_YUYV: + memcpy(grab_buf, (void *)pBuffer, (size_t)dwSize); + break; + default: + ERR("Invalid pixel format\n"); + return E_FAIL; + } + break; + case V4L2_PIX_FMT_RGB24: + switch (fmt) { + case V4L2_PIX_FMT_YUV420: + rgb24_to_yuv420(pBuffer, grab_buf, width, height, 0); + break; + case V4L2_PIX_FMT_YVU420: + rgb24_to_yuv420(pBuffer, grab_buf, width, height, 1); + break; + case V4L2_PIX_FMT_YUYV: + rgb24_to_yuyv(pBuffer, grab_buf, width, height); + break; + default: + ERR("Invalid pixel format\n"); + return E_FAIL; + } + break; + case V4L2_PIX_FMT_YUV420: + switch (fmt) { + case V4L2_PIX_FMT_YUV420: + memcpy(grab_buf, (void *)pBuffer, (size_t)dwSize); + break; + case V4L2_PIX_FMT_YVU420: + yuv420_to_yvu420(pBuffer, grab_buf, width, height); + break; + case V4L2_PIX_FMT_YUYV: + yuv420_to_yuyv(pBuffer, grab_buf, width, height); + break; + default: + ERR("Invalid pixel format\n"); + return E_FAIL; + } + break; + default: + ERR("Invalid pixel format\n"); + return E_FAIL; + } + + qemu_mutex_lock(&g_state->thread_mutex); + if (g_state->streamon) { + if (ready_count < MARUCAM_SKIPFRAMES) { + /* skip a frame cause first some frame are distorted */ + ++ready_count; + TRACE("skip %d frame\n", ready_count); + qemu_mutex_unlock(&g_state->thread_mutex); + return S_OK; + } + if (g_state->req_frame == 0) { + TRACE("there is no request\n"); + qemu_mutex_unlock(&g_state->thread_mutex); + return S_OK; + } + tmp_buf = g_state->vaddr + g_state->buf_size * (g_state->req_frame - 1); + memcpy(tmp_buf, grab_buf, g_state->buf_size); + g_state->req_frame = 0; /* clear request */ + g_state->isr |= 0x01; /* set a flag of rasing a interrupt */ + qemu_bh_schedule(g_state->tx_bh); + } + qemu_mutex_unlock(&g_state->thread_mutex); + return S_OK; +} + +/* + * Internal functions for manipulate interfaces + */ + +static STDMETHODIMP_(void) CloseInterfaces(void) +{ + if (g_pMediaControl) { + g_pMediaControl->lpVtbl->Stop(g_pMediaControl); + } + + if (g_pOutputPin) { + g_pOutputPin->lpVtbl->Disconnect(g_pOutputPin); + } + + SAFE_RELEASE(g_pGB); + SAFE_RELEASE(g_pCGB); + SAFE_RELEASE(g_pMediaControl); + SAFE_RELEASE(g_pOutputPin); + SAFE_RELEASE(g_pInputPin); + SAFE_RELEASE(g_pDstFilter); + SAFE_RELEASE(g_pSrcFilter); + SAFE_RELEASE(g_pCallback); +} + +static STDMETHODIMP_(void) DeleteMediaType(AM_MEDIA_TYPE *pmt) +{ + if (pmt == NULL) { + return; + } + + if (pmt->cbFormat != 0) { + CoTaskMemFree((PVOID)pmt->pbFormat); + pmt->cbFormat = 0; + pmt->pbFormat = NULL; + } + if (pmt->pUnk != NULL) { + pmt->pUnk->lpVtbl->Release(pmt->pUnk); + pmt->pUnk = NULL; + } + + CoTaskMemFree((PVOID)pmt); +} + +static STDMETHODIMP GetPin(IBaseFilter *pFilter, + PIN_DIRECTION PinDir, IPin **ppPin) +{ + HRESULT hr; + IEnumPins *pEnum = NULL; + IPin *pPin = NULL; + + if (ppPin == NULL) { + return E_POINTER; + } + + hr = pFilter->lpVtbl->EnumPins(pFilter, &pEnum); + if (FAILED(hr)) { + return hr; + } + + while (pEnum->lpVtbl->Next(pEnum, 1, &pPin, 0) == S_OK) { + PIN_DIRECTION PinDirThis; + hr = pPin->lpVtbl->QueryDirection(pPin, &PinDirThis); + if (FAILED(hr)) { + SAFE_RELEASE(pPin); + SAFE_RELEASE(pEnum); + return hr; + } + if (PinDir == PinDirThis) { + *ppPin = pPin; + SAFE_RELEASE(pEnum); + return S_OK; + } + SAFE_RELEASE(pPin); + } + + SAFE_RELEASE(pEnum); + return S_FALSE; +} + +static STDMETHODIMP GraphBuilder_Init(void) +{ + HRESULT hr; + + hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC, + &IID_IGraphBuilder, (void **)&g_pGB); + if (FAILED(hr)) { + ERR("Failed to create instance of GraphBuilder, 0x%x\n", hr); + return hr; + } + + hr = CoCreateInstance(&CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC, + &IID_ICaptureGraphBuilder2, (void **)&g_pCGB); + if (FAILED(hr)) { + ERR("Failed to create instance of CaptureGraphBuilder2, 0x%x\n", hr); + return hr; + } + + hr = g_pCGB->lpVtbl->SetFiltergraph(g_pCGB, g_pGB); + if (FAILED(hr)) { + ERR("Failed to SetFiltergraph, 0x%x\n", hr); + return hr; + } + + hr = g_pGB->lpVtbl->QueryInterface(g_pGB, &IID_IMediaControl, + (void **)&g_pMediaControl); + if (FAILED(hr)) { + ERR("Failed to QueryInterface for IMediaControl, 0x%x\n", hr); + return hr; + } + + hr = HWCGrabCallback_Construct(&g_pCallback); + if (g_pCallback == NULL) { + hr = E_OUTOFMEMORY; + } + + hr = ((HWCGrabCallback *)g_pCallback)->SetCallback(g_pCallback, + (CallbackFn)marucam_device_callbackfn); + + return hr; +} + +static STDMETHODIMP BindSourceFilter(void) +{ + HRESULT hr; + ICreateDevEnum *pCreateDevEnum = NULL; + IEnumMoniker *pEnumMK = NULL; + IMoniker *pMoniKer; + + hr = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC, + &IID_ICreateDevEnum, + (void **)&pCreateDevEnum); + if (FAILED(hr)) { + ERR("Failed to create instance of CreateDevEnum, 0x%x\n", hr); + return hr; + } + + hr = pCreateDevEnum->lpVtbl->CreateClassEnumerator(pCreateDevEnum, + &CLSID_VideoInputDeviceCategory, + &pEnumMK, 0); + if (FAILED(hr)) { + ERR("Failed to get VideoInputDeviceCategory, 0x%x\n", hr); + SAFE_RELEASE(pCreateDevEnum); + return hr; + } + + if (!pEnumMK) { + ERR("ClassEnumerator moniker is NULL\n"); + SAFE_RELEASE(pCreateDevEnum); + return E_FAIL; + } + pEnumMK->lpVtbl->Reset(pEnumMK); + + hr = pEnumMK->lpVtbl->Next(pEnumMK, 1, &pMoniKer, NULL); + if (hr == S_FALSE) { + hr = E_FAIL; + } + if (SUCCEEDED(hr)) { + IPropertyBag *pBag = NULL; + hr = pMoniKer->lpVtbl->BindToStorage(pMoniKer, 0, 0, + &IID_IPropertyBag, + (void **)&pBag); + if (SUCCEEDED(hr)) { + VARIANT var; + var.vt = VT_BSTR; + hr = pBag->lpVtbl->Read(pBag, L"FriendlyName", &var, NULL); + if (hr == NOERROR) { + hr = pMoniKer->lpVtbl->BindToObject(pMoniKer, NULL, NULL, + &IID_IBaseFilter, + (void **)&g_pSrcFilter); + if (FAILED(hr)) { + ERR("Counldn't bind moniker to filter object!!\n"); + } else { + g_pSrcFilter->lpVtbl->AddRef(g_pSrcFilter); + } + SysFreeString(var.bstrVal); + } + SAFE_RELEASE(pBag); + } + SAFE_RELEASE(pMoniKer); + } + + if (SUCCEEDED(hr)) { + hr = g_pGB->lpVtbl->AddFilter(g_pGB, g_pSrcFilter, L"Video Capture"); + if (hr != S_OK && hr != S_FALSE) { + ERR("Counldn't add Video Capture filter to our graph!\n"); + SAFE_RELEASE(g_pSrcFilter); + } + } + SAFE_RELEASE(pEnumMK); + SAFE_RELEASE(pCreateDevEnum); + + return hr; +} + +static STDMETHODIMP BindTargetFilter(void) +{ + HRESULT hr; + hr = HWCFilter_Construct(&g_pDstFilter); + + if (SUCCEEDED(hr) && g_pDstFilter) { + hr = g_pGB->lpVtbl->AddFilter(g_pGB, g_pDstFilter, L"HWCFilter"); + if (FAILED(hr)) { + ERR("Counldn't add HWCFilterr to our graph!\n"); + SAFE_RELEASE(g_pDstFilter); + } + } + return hr; +} + +static STDMETHODIMP ConnectFilters(void) +{ + HRESULT hr; + + hr = GetPin(g_pSrcFilter, PINDIR_OUTPUT , &g_pOutputPin); + if (FAILED(hr)) { + ERR("Failed to get output pin. 0x%x\n", hr); + return hr; + } + + hr = GetPin(g_pDstFilter, PINDIR_INPUT , &g_pInputPin); + if (FAILED(hr)) { + ERR("Failed to get input pin. 0x%x\n", hr); + return hr; + } + + hr = g_pGB->lpVtbl->Connect(g_pGB, g_pOutputPin, g_pInputPin); + if (FAILED(hr)) { + ERR("Failed to connect pins. 0x%x\n", hr); + } + return hr; +} + +static STDMETHODIMP DisconnectPins(void) +{ + HRESULT hr; + + hr = g_pGB->lpVtbl->Disconnect(g_pGB, g_pOutputPin); + if (FAILED(hr)) { + ERR("Failed to disconnect output pin. 0x%x\n", hr); + return hr; + } + + hr = g_pGB->lpVtbl->Disconnect(g_pGB, g_pInputPin); + if (FAILED(hr)) { + ERR("Failed to disconnect input pin. 0x%x\n", hr); + } + + return hr; +} + +static STDMETHODIMP RemoveFilters(void) +{ + HRESULT hr; + + hr = g_pGB->lpVtbl->RemoveFilter(g_pGB, g_pSrcFilter); + if (FAILED(hr)) { + ERR("Failed to remove source filer. 0x%x\n", hr); + return hr; + } + + hr = g_pGB->lpVtbl->RemoveFilter(g_pGB, g_pDstFilter); + if (FAILED(hr)) { + ERR("Failed to remove destination filer. 0x%x\n", hr); + } + + return hr; +} + +/* default fps is 15 */ +#define MARUCAM_DEFAULT_FRAMEINTERVAL 666666 + +static STDMETHODIMP SetFormat(uint32_t dwWidth, uint32_t dwHeight, + uint32_t dwDstFmt, uint32_t *dwSrcFmt) +{ + HRESULT hr; + IAMStreamConfig *pSConfig; + int iCount = 0, iSize = 0; + DWORD dwYUY2 = MAKEFOURCC('Y', 'U', 'Y', '2'); + DWORD dwI420 = MAKEFOURCC('I', '4', '2', '0'); + + if (dwSrcFmt == NULL) { + ERR("invalid the source format pointer\n"); + return E_FAIL; + } + + hr = g_pCGB->lpVtbl->FindInterface(g_pCGB, &PIN_CATEGORY_CAPTURE, 0, + g_pSrcFilter, &IID_IAMStreamConfig, + (void **)&pSConfig); + if (FAILED(hr)) { + ERR("failed to FindInterface method\n"); + return hr; + } + + hr = pSConfig->lpVtbl->GetNumberOfCapabilities(pSConfig, &iCount, &iSize); + if (FAILED(hr)) { + ERR("failed to GetNumberOfCapabilities method\n"); + SAFE_RELEASE(pSConfig); + return hr; + } + + if (iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS)) { + int iFormat = 0; + for (iFormat = 0; iFormat < iCount; iFormat++) { + VIDEO_STREAM_CONFIG_CAPS scc; + AM_MEDIA_TYPE *pmtConfig; + + hr = pSConfig->lpVtbl->GetStreamCaps(pSConfig, iFormat, + &pmtConfig, (BYTE *)&scc); + if (hr == S_OK) { + if (IsEqualIID(&pmtConfig->formattype, &FORMAT_VideoInfo)) { + VIDEOINFOHEADER *pvi = + (VIDEOINFOHEADER *)pmtConfig->pbFormat; + if ((pvi->bmiHeader.biWidth == (LONG)dwWidth) && + (pvi->bmiHeader.biHeight == (LONG)dwHeight)) { + if (pvi->bmiHeader.biCompression == dwYUY2) { + *dwSrcFmt = V4L2_PIX_FMT_YUYV; + } else if ((pvi->bmiHeader.biCompression == BI_RGB) && + (pvi->bmiHeader.biBitCount == 24)) { + *dwSrcFmt = V4L2_PIX_FMT_RGB24; + } else if (pvi->bmiHeader.biCompression == dwI420) { + *dwSrcFmt = V4L2_PIX_FMT_YUV420; + } else { /* not support format */ + DeleteMediaType(pmtConfig); + continue; + } + /* use minimum FPS(maximum frameinterval) + with non-VT system */ +#ifdef CONFIG_HAX + if (!hax_enabled()) { + pvi->AvgTimePerFrame = + (REFERENCE_TIME)scc.MaxFrameInterval; + } else { + pvi->AvgTimePerFrame = + (REFERENCE_TIME)MARUCAM_DEFAULT_FRAMEINTERVAL; + } +#else + pvi->AvgTimePerFrame = + (REFERENCE_TIME)scc.MaxFrameInterval; +#endif + hr = pSConfig->lpVtbl->SetFormat(pSConfig, pmtConfig); + DeleteMediaType(pmtConfig); + break; + } + } + DeleteMediaType(pmtConfig); + } + } + if (iFormat >= iCount) { + ERR("Failed to Set format. " + "Maybe connected webcam does not support the (%ldx%ld) " + "resolution or image formats(YUY2, RGB24, I420).\n", + dwWidth, dwHeight); + hr = E_FAIL; + } + } + SAFE_RELEASE(pSConfig); + return hr; +} + +static STDMETHODIMP QueryVideoProcAmp(long nProperty, long *pMin, long *pMax, + long *pStep, long *pDefault) +{ + HRESULT hr; + long Flags; + IAMVideoProcAmp *pProcAmp = NULL; + + hr = g_pSrcFilter->lpVtbl->QueryInterface(g_pSrcFilter, + &IID_IAMVideoProcAmp, + (void **)&pProcAmp); + if (FAILED(hr)) { + return hr; + } + + hr = pProcAmp->lpVtbl->GetRange(pProcAmp, nProperty, pMin, pMax, + pStep, pDefault, &Flags); + + SAFE_RELEASE(pProcAmp); + return hr; +} + +static STDMETHODIMP GetVideoProcAmp(long nProperty, long *pValue) +{ + HRESULT hr; + long Flags; + IAMVideoProcAmp *pProcAmp = NULL; + + hr = g_pSrcFilter->lpVtbl->QueryInterface(g_pSrcFilter, + &IID_IAMVideoProcAmp, + (void **)&pProcAmp); + if (FAILED(hr)) { + return hr; + } + + hr = pProcAmp->lpVtbl->Get(pProcAmp, nProperty, pValue, &Flags); + if (FAILED(hr)) { + ERR("Failed to get property for video\n"); + } + + SAFE_RELEASE(pProcAmp); + return hr; +} + +static STDMETHODIMP SetVideoProcAmp(long nProperty, long value) +{ + HRESULT hr; + + IAMVideoProcAmp *pProcAmp = NULL; + hr = g_pSrcFilter->lpVtbl->QueryInterface(g_pSrcFilter, + &IID_IAMVideoProcAmp, + (void **)&pProcAmp); + if (FAILED(hr)) { + return hr; + } + + hr = pProcAmp->lpVtbl->Set(pProcAmp, nProperty, value, + VideoProcAmp_Flags_Manual); + if (FAILED(hr)) { + ERR("Failed to set property for video\n"); + } + SAFE_RELEASE(pProcAmp); + return hr; +} + +static char *__wchar_to_char(const WCHAR *pwstr) +{ + char *pstr = NULL; + int len = 0; + + len = wcslen(pwstr) + 1; + pstr = (char *)g_malloc0(sizeof(char) * len); + wcstombs(pstr, pwstr, len + 1); + + return pstr; +} + +int marucam_device_check(int log_flag) +{ + struct timeval t1, t2; + int ret = 0; + char *device_name = NULL; + HRESULT hr = E_FAIL; + ICreateDevEnum *pCreateDevEnum = NULL; + IGraphBuilder *pGB = NULL; + ICaptureGraphBuilder2 *pCGB = NULL; + IBaseFilter *pSrcFilter = NULL; + IEnumMoniker *pEnumMK = NULL; + IMoniker *pMoniKer = NULL; + IAMStreamConfig *pSConfig = NULL; + int iCount = 0, iSize = 0; + + gettimeofday(&t1, NULL); + hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + if (FAILED(hr)) { + fprintf(stdout, "[Webcam] failed to CoInitailizeEx\n"); + gettimeofday(&t2, NULL); + fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } + + hr = CoCreateInstance(&CLSID_FilterGraph, NULL, + CLSCTX_INPROC, + &IID_IGraphBuilder, + (void **)&pGB); + if (FAILED(hr)) { + fprintf(stdout, "[Webcam] Failed to create GraphBuilder, 0x%x\n", hr); + CoUninitialize(); + gettimeofday(&t2, NULL); + fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } + + hr = CoCreateInstance(&CLSID_CaptureGraphBuilder2, NULL, + CLSCTX_INPROC, + &IID_ICaptureGraphBuilder2, + (void **)&pCGB); + if (FAILED(hr)) { + fprintf(stdout, + "[Webcam] Failed to create CaptureGraphBuilder2, 0x%x\n", hr); + SAFE_RELEASE(pGB); + CoUninitialize(); + gettimeofday(&t2, NULL); + fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } + + hr = pCGB->lpVtbl->SetFiltergraph(pCGB, pGB); + if (FAILED(hr)) { + fprintf(stdout, "[Webcam] Failed to SetFiltergraph, 0x%x\n", hr); + SAFE_RELEASE(pCGB); + SAFE_RELEASE(pGB); + CoUninitialize(); + gettimeofday(&t2, NULL); + fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } + + hr = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, + CLSCTX_INPROC, + &IID_ICreateDevEnum, + (void **)&pCreateDevEnum); + if (FAILED(hr)) { + fprintf(stdout, + "[Webcam] failed to create instance of CLSID_SystemDeviceEnum\n"); + SAFE_RELEASE(pCGB); + SAFE_RELEASE(pGB); + CoUninitialize(); + gettimeofday(&t2, NULL); + fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } + + hr = pCreateDevEnum->lpVtbl->CreateClassEnumerator(pCreateDevEnum, + &CLSID_VideoInputDeviceCategory, &pEnumMK, 0); + if (FAILED(hr)) { + fprintf(stdout, "[Webcam] failed to create class enumerator\n"); + SAFE_RELEASE(pCreateDevEnum); + SAFE_RELEASE(pCGB); + SAFE_RELEASE(pGB); + CoUninitialize(); + gettimeofday(&t2, NULL); + fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } + + if (!pEnumMK) { + fprintf(stdout, "[Webcam] class enumerator is NULL!!\n"); + SAFE_RELEASE(pCreateDevEnum); + SAFE_RELEASE(pCGB); + SAFE_RELEASE(pGB); + CoUninitialize(); + gettimeofday(&t2, NULL); + fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } + pEnumMK->lpVtbl->Reset(pEnumMK); + + hr = pEnumMK->lpVtbl->Next(pEnumMK, 1, &pMoniKer, NULL); + if (FAILED(hr) || (hr == S_FALSE)) { + fprintf(stdout, "[Webcam] enum moniker returns a invalid value.\n"); + SAFE_RELEASE(pEnumMK); + SAFE_RELEASE(pCreateDevEnum); + SAFE_RELEASE(pCGB); + SAFE_RELEASE(pGB); + CoUninitialize(); + gettimeofday(&t2, NULL); + fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } + + IPropertyBag *pBag = NULL; + hr = pMoniKer->lpVtbl->BindToStorage(pMoniKer, 0, 0, + &IID_IPropertyBag, + (void **)&pBag); + if (FAILED(hr)) { + fprintf(stdout, "[Webcam] failed to bind to storage.\n"); + SAFE_RELEASE(pEnumMK); + SAFE_RELEASE(pCreateDevEnum); + SAFE_RELEASE(pCGB); + SAFE_RELEASE(pGB); + CoUninitialize(); + gettimeofday(&t2, NULL); + fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } else { + VARIANT var; + var.vt = VT_BSTR; + hr = pBag->lpVtbl->Read(pBag, L"FriendlyName", &var, NULL); + if (hr == S_OK) { + ret = 1; + if (!log_flag) { + SysFreeString(var.bstrVal); + SAFE_RELEASE(pBag); + SAFE_RELEASE(pMoniKer); + SAFE_RELEASE(pEnumMK); + SAFE_RELEASE(pCreateDevEnum); + SAFE_RELEASE(pCGB); + SAFE_RELEASE(pGB); + CoUninitialize(); + gettimeofday(&t2, NULL); + fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } + device_name = __wchar_to_char(var.bstrVal); + fprintf(stdout, "[Webcam] Device name : %s\n", device_name); + g_free(device_name); + hr = pMoniKer->lpVtbl->BindToObject(pMoniKer, NULL, NULL, + &IID_IBaseFilter, + (void **)&pSrcFilter); + if (FAILED(hr)) { + fprintf(stdout, + "[Webcam] Counldn't bind moniker to filter object!!\n"); + SysFreeString(var.bstrVal); + SAFE_RELEASE(pBag); + SAFE_RELEASE(pMoniKer); + SAFE_RELEASE(pEnumMK); + SAFE_RELEASE(pCreateDevEnum); + SAFE_RELEASE(pCGB); + SAFE_RELEASE(pGB); + CoUninitialize(); + gettimeofday(&t2, NULL); + fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } else { + pSrcFilter->lpVtbl->AddRef(pSrcFilter); + } + SysFreeString(var.bstrVal); + } + SAFE_RELEASE(pBag); + } + SAFE_RELEASE(pMoniKer); + + hr = pGB->lpVtbl->AddFilter(pGB, pSrcFilter, L"Video Capture"); + if (hr != S_OK && hr != S_FALSE) { + fprintf(stdout, + "[Webcam] Counldn't add Video Capture filter to our graph!\n"); + SAFE_RELEASE(pSrcFilter); + SAFE_RELEASE(pEnumMK); + SAFE_RELEASE(pCreateDevEnum); + SAFE_RELEASE(pCGB); + SAFE_RELEASE(pGB); + CoUninitialize(); + gettimeofday(&t2, NULL); + fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } + + hr = pCGB->lpVtbl->FindInterface(pCGB, &PIN_CATEGORY_CAPTURE, 0, + pSrcFilter, &IID_IAMStreamConfig, + (void **)&pSConfig); + if (FAILED(hr)) { + fprintf(stdout, "[Webcam] failed to FindInterface method\n"); + SAFE_RELEASE(pSrcFilter); + SAFE_RELEASE(pEnumMK); + SAFE_RELEASE(pCreateDevEnum); + SAFE_RELEASE(pCGB); + SAFE_RELEASE(pGB); + CoUninitialize(); + gettimeofday(&t2, NULL); + fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } + + hr = pSConfig->lpVtbl->GetNumberOfCapabilities(pSConfig, &iCount, &iSize); + if (FAILED(hr)) { + fprintf(stdout, "[Webcam] failed to GetNumberOfCapabilities method\n"); + SAFE_RELEASE(pSConfig); + SAFE_RELEASE(pSrcFilter); + SAFE_RELEASE(pEnumMK); + SAFE_RELEASE(pCreateDevEnum); + SAFE_RELEASE(pCGB); + SAFE_RELEASE(pGB); + CoUninitialize(); + gettimeofday(&t2, NULL); + fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } + + if (iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS)) { + int iFormat = 0; + for (iFormat = 0; iFormat < iCount; iFormat++) { + VIDEO_STREAM_CONFIG_CAPS scc; + AM_MEDIA_TYPE *pmtConfig; + + hr = pSConfig->lpVtbl->GetStreamCaps(pSConfig, iFormat, &pmtConfig, + (BYTE *)&scc); + if (hr == S_OK) { + if (IsEqualIID(&pmtConfig->formattype, &FORMAT_VideoInfo)) { + VIDEOINFOHEADER *pvi = + (VIDEOINFOHEADER *)pmtConfig->pbFormat; + if (pvi->bmiHeader.biCompression == BI_RGB) { + fprintf(stdout, "[Webcam] RGB BitCount: %d, %ux%u\n", + pvi->bmiHeader.biBitCount, + pvi->bmiHeader.biWidth, + pvi->bmiHeader.biHeight); + } else { + fprintf(stdout, + "[Webcam] PixelFormat: %c%c%c%c, %ux%u\n", + (char)(pvi->bmiHeader.biCompression), + (char)(pvi->bmiHeader.biCompression >> 8), + (char)(pvi->bmiHeader.biCompression >> 16), + (char)(pvi->bmiHeader.biCompression >> 24), + pvi->bmiHeader.biWidth, + pvi->bmiHeader.biHeight); + } + } + DeleteMediaType(pmtConfig); + } + } + } + + hr = pGB->lpVtbl->RemoveFilter(pGB, pSrcFilter); + if (FAILED(hr)) { + fprintf(stdout, "[Webcam] Failed to remove source filer. 0x%x\n", hr); + } + + SAFE_RELEASE(pSConfig); + SAFE_RELEASE(pSrcFilter); + SAFE_RELEASE(pCGB); + SAFE_RELEASE(pGB); + SAFE_RELEASE(pEnumMK); + SAFE_RELEASE(pCreateDevEnum); + CoUninitialize(); + gettimeofday(&t2, NULL); + fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + + return ret; +} + +/* MARUCAM_CMD_INIT */ +void marucam_device_init(MaruCamState *state) +{ + g_state = state; +} + +void marucam_device_exit(MaruCamState *state) +{ +} + +/* MARUCAM_CMD_OPEN */ +void marucam_device_open(MaruCamState *state) +{ + HRESULT hr; + uint32_t dwHeight, dwWidth, dwDstFmt; + MaruCamParam *param = state->param; + param->top = 0; + + hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + if (FAILED(hr)) { + ERR("CoInitailizeEx\n"); + ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr); + param->errCode = EINVAL; + return; + } + + hr = GraphBuilder_Init(); + if (FAILED(hr)) { + ERR("GraphBuilder_Init\n"); + DisconnectPins(); + RemoveFilters(); + CloseInterfaces(); + CoUninitialize(); + param->errCode = EINVAL; + ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr); + return; + } + + hr = BindSourceFilter(); + if (FAILED(hr)) { + ERR("BindSourceFilter\n"); + DisconnectPins(); + RemoveFilters(); + CloseInterfaces(); + CoUninitialize(); + param->errCode = EINVAL; + ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr); + return; + } + + hr = BindTargetFilter(); + if (FAILED(hr)) { + ERR("BindTargetFilter\n"); + DisconnectPins(); + RemoveFilters(); + CloseInterfaces(); + CoUninitialize(); + param->errCode = EINVAL; + ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr); + return; + } + + hr = ConnectFilters(); + if (FAILED(hr)) { + ERR("ConnectFilters\n"); + DisconnectPins(); + RemoveFilters(); + CloseInterfaces(); + CoUninitialize(); + param->errCode = EINVAL; + ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr); + return; + } + + cur_frame_idx = 0; + cur_fmt_idx = 0; + + dwHeight = supported_dst_frames[cur_frame_idx].height; + dwWidth = supported_dst_frames[cur_frame_idx].width; + dwDstFmt = supported_dst_pixfmts[cur_fmt_idx].fmt; + hr = SetFormat(dwWidth, dwHeight, dwDstFmt, &g_dwSrcFmt); + if (hr != S_OK) { + ERR("failed to Set default values\n"); + DisconnectPins(); + RemoveFilters(); + CloseInterfaces(); + CoUninitialize(); + param->errCode = EINVAL; + ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr); + return; + } + + INFO("Opened\n"); + return; +} + +/* MARUCAM_CMD_CLOSE */ +void marucam_device_close(MaruCamState *state) +{ + MaruCamParam *param = state->param; + param->top = 0; + + DisconnectPins(); + RemoveFilters(); + CloseInterfaces(); + CoUninitialize(); + INFO("Closed\n"); +} + +/* MARUCAM_CMD_START_PREVIEW */ +void marucam_device_start_preview(MaruCamState *state) +{ + HRESULT hr; + uint32_t pixfmt, width, height; + MaruCamParam *param = state->param; + param->top = 0; + + ready_count = 0; + width = supported_dst_frames[cur_frame_idx].width; + height = supported_dst_frames[cur_frame_idx].height; + pixfmt = supported_dst_pixfmts[cur_fmt_idx].fmt; + state->buf_size = get_sizeimage(pixfmt, width, height); + + INFO("Pixfmt(%c%c%c%c), W:H(%d:%d), buf size(%u)\n", + (char)(pixfmt), (char)(pixfmt >> 8), + (char)(pixfmt >> 16), (char)(pixfmt >> 24), + width, height, state->buf_size); + INFO("Starting preview\n"); + + assert(g_pCallback != NULL); + hr = ((HWCInPin *)g_pInputPin)->SetGrabCallbackIF(g_pInputPin, + g_pCallback); + if (FAILED(hr)) { + ERR("Failed to set IGrabCallback interface.\n"); + param->errCode = EINVAL; + return; + } + + if (grab_buf) { + g_free(grab_buf); + grab_buf = NULL; + } + grab_buf = (void *)g_malloc0(state->buf_size); + if (grab_buf == NULL) { + param->errCode = ENOMEM; + return; + } + + hr = g_pMediaControl->lpVtbl->Run(g_pMediaControl); + if (FAILED(hr)) { + ERR("Failed to run media control. hr=0x%x\n", hr); + param->errCode = EINVAL; + return; + } + + qemu_mutex_lock(&state->thread_mutex); + state->streamon = 1; + qemu_mutex_unlock(&state->thread_mutex); + + INFO("Streaming on ......\n"); +} + +/* MARUCAM_CMD_STOP_PREVIEW */ +void marucam_device_stop_preview(MaruCamState *state) +{ + HRESULT hr; + MaruCamParam *param = state->param; + param->top = 0; + + INFO("...... Streaming off\n"); + qemu_mutex_lock(&state->thread_mutex); + state->streamon = 0; + qemu_mutex_unlock(&state->thread_mutex); + + hr = ((HWCInPin *)g_pInputPin)->SetGrabCallbackIF(g_pInputPin, NULL); + if (FAILED(hr)) { + ERR("Failed to set IGrabCallback interface.\n"); + param->errCode = EINVAL; + return; + } + + hr = g_pMediaControl->lpVtbl->Stop(g_pMediaControl); + if (FAILED(hr)) { + ERR("Failed to stop media control.\n"); + param->errCode = EINVAL; + return; + } + + if (grab_buf) { + g_free(grab_buf); + grab_buf = NULL; + } + state->buf_size = 0; + + INFO("Stopping preview\n"); +} + +/* MARUCAM_CMD_S_PARAM */ +void marucam_device_s_param(MaruCamState *state) +{ + MaruCamParam *param = state->param; + + /* We use default FPS of the webcam */ + param->top = 0; +} + +/* MARUCAM_CMD_G_PARAM */ +void marucam_device_g_param(MaruCamState *state) +{ + MaruCamParam *param = state->param; + + /* We use default FPS of the webcam + * return a fixed value on guest ini file (1/30). + */ + param->top = 0; + param->stack[0] = 0x1000; /* V4L2_CAP_TIMEPERFRAME */ + param->stack[1] = 1; /* numerator */ + param->stack[2] = 30; /* denominator */ +} + +/* MARUCAM_CMD_S_FMT */ +void marucam_device_s_fmt(MaruCamState *state) +{ + uint32_t width, height, pixfmt, pidx, fidx; + MaruCamParam *param = state->param; + + param->top = 0; + width = param->stack[0]; + height = param->stack[1]; + pixfmt = param->stack[2]; + + for (fidx = 0; fidx < ARRAY_SIZE(supported_dst_frames); fidx++) { + if ((supported_dst_frames[fidx].width == width) && + (supported_dst_frames[fidx].height == height)) { + break; + } + } + if (fidx == ARRAY_SIZE(supported_dst_frames)) { + param->errCode = EINVAL; + return; + } + for (pidx = 0; pidx < ARRAY_SIZE(supported_dst_pixfmts); pidx++) { + if (supported_dst_pixfmts[pidx].fmt == pixfmt) { + break; + } + } + if (pidx == ARRAY_SIZE(supported_dst_pixfmts)) { + param->errCode = EINVAL; + return; + } + + if ((supported_dst_frames[cur_frame_idx].width != width) && + (supported_dst_frames[cur_frame_idx].height != height)) { + HRESULT hr = SetFormat(width, height, pixfmt, &g_dwSrcFmt); + if (FAILED(hr)) { + param->errCode = EINVAL; + return; + } + } + + cur_frame_idx = fidx; + cur_fmt_idx = pidx; + + pixfmt = supported_dst_pixfmts[cur_fmt_idx].fmt; + width = supported_dst_frames[cur_frame_idx].width; + height = supported_dst_frames[cur_frame_idx].height; + + param->stack[0] = width; + param->stack[1] = height; + param->stack[2] = 1; /* V4L2_FIELD_NONE */ + param->stack[3] = pixfmt; + param->stack[4] = get_bytesperline(pixfmt, width); + param->stack[5] = get_sizeimage(pixfmt, width, height); + param->stack[6] = 0; + param->stack[7] = 0; + + TRACE("Set format...\n"); +} + +/* MARUCAM_CMD_G_FMT */ +void marucam_device_g_fmt(MaruCamState *state) +{ + uint32_t width, height, pixfmt; + MaruCamParam *param = state->param; + + param->top = 0; + pixfmt = supported_dst_pixfmts[cur_fmt_idx].fmt; + width = supported_dst_frames[cur_frame_idx].width; + height = supported_dst_frames[cur_frame_idx].height; + + param->stack[0] = width; + param->stack[1] = height; + param->stack[2] = 1; /* V4L2_FIELD_NONE */ + param->stack[3] = pixfmt; + param->stack[4] = get_bytesperline(pixfmt, width); + param->stack[5] = get_sizeimage(pixfmt, width, height); + param->stack[6] = 0; + param->stack[7] = 0; + + TRACE("Get format...\n"); +} + +void marucam_device_try_fmt(MaruCamState *state) +{ + uint32_t width, height, pixfmt, i; + MaruCamParam *param = state->param; + + param->top = 0; + width = param->stack[0]; + height = param->stack[1]; + pixfmt = param->stack[2]; + + for (i = 0; i < ARRAY_SIZE(supported_dst_frames); i++) { + if ((supported_dst_frames[i].width == width) && + (supported_dst_frames[i].height == height)) { + break; + } + } + if (i == ARRAY_SIZE(supported_dst_frames)) { + param->errCode = EINVAL; + return; + } + for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) { + if (supported_dst_pixfmts[i].fmt == pixfmt) { + break; + } + } + if (i == ARRAY_SIZE(supported_dst_pixfmts)) { + param->errCode = EINVAL; + return; + } + + param->stack[0] = width; + param->stack[1] = height; + param->stack[2] = 1; /* V4L2_FIELD_NONE */ + param->stack[3] = pixfmt; + param->stack[4] = get_bytesperline(pixfmt, width); + param->stack[5] = get_sizeimage(pixfmt, width, height); + param->stack[6] = 0; + param->stack[7] = 0; +} + +void marucam_device_enum_fmt(MaruCamState *state) +{ + uint32_t index; + MaruCamParam *param = state->param; + + param->top = 0; + index = param->stack[0]; + + if (index >= ARRAY_SIZE(supported_dst_pixfmts)) { + param->errCode = EINVAL; + return; + } + param->stack[1] = 0; /* flags = NONE */ + param->stack[2] = supported_dst_pixfmts[index].fmt; /* pixelformat */ + /* set description */ + switch (supported_dst_pixfmts[index].fmt) { + case V4L2_PIX_FMT_YUYV: + memcpy(¶m->stack[3], "YUYV", 32); + break; + case V4L2_PIX_FMT_YUV420: + memcpy(¶m->stack[3], "YU12", 32); + break; + case V4L2_PIX_FMT_YVU420: + memcpy(¶m->stack[3], "YV12", 32); + break; + default: + ERR("Invalid pixel format\n"); + param->errCode = EINVAL; + break; + } +} + +void marucam_device_qctrl(MaruCamState *state) +{ + HRESULT hr; + uint32_t id, i; + long property, min, max, step, def_val, set_val; + char name[32] = {0,}; + MaruCamParam *param = state->param; + + param->top = 0; + id = param->stack[0]; + + switch (id) { + case V4L2_CID_BRIGHTNESS: + TRACE("V4L2_CID_BRIGHTNESS\n"); + property = VideoProcAmp_Brightness; + memcpy((void *)name, (void *)"brightness", 32); + i = 0; + break; + case V4L2_CID_CONTRAST: + TRACE("V4L2_CID_CONTRAST\n"); + property = VideoProcAmp_Contrast; + memcpy((void *)name, (void *)"contrast", 32); + i = 1; + break; + case V4L2_CID_SATURATION: + TRACE("V4L2_CID_SATURATION\n"); + property = VideoProcAmp_Saturation; + memcpy((void *)name, (void *)"saturation", 32); + i = 2; + break; + case V4L2_CID_SHARPNESS: + TRACE("V4L2_CID_SHARPNESS\n"); + property = VideoProcAmp_Sharpness; + memcpy((void *)name, (void *)"sharpness", 32); + i = 3; + break; + default: + ERR("Invalid control ID\n"); + param->errCode = EINVAL; + return; + } + hr = QueryVideoProcAmp(property, &min, &max, &step, &def_val); + if (FAILED(hr)) { + param->errCode = EINVAL; + ERR("failed to query video controls [HRESULT : 0x%x]\n", hr); + return; + } else { + qctrl_tbl[i].hit = 1; + qctrl_tbl[i].min = min; + qctrl_tbl[i].max = max; + qctrl_tbl[i].step = step; + qctrl_tbl[i].init_val = def_val; + + if ((qctrl_tbl[i].min + qctrl_tbl[i].max) == 0) { + set_val = 0; + } else { + set_val = (qctrl_tbl[i].min + qctrl_tbl[i].max) / 2; + } + hr = SetVideoProcAmp(property, set_val); + if (FAILED(hr)) { + param->errCode = EINVAL; + ERR("failed to set video control value, [HRESULT : 0x%x]\n", hr); + return; + } + } + + param->stack[0] = id; + param->stack[1] = MARUCAM_CTRL_VALUE_MIN; /* minimum */ + param->stack[2] = MARUCAM_CTRL_VALUE_MAX; /* maximum */ + param->stack[3] = MARUCAM_CTRL_VALUE_STEP; /* step */ + param->stack[4] = MARUCAM_CTRL_VALUE_MID; /* default_value */ + param->stack[5] = V4L2_CTRL_FLAG_SLIDER; + /* name field setting */ + memcpy(¶m->stack[6], (void *)name, sizeof(name)/sizeof(name[0])); +} + +void marucam_device_s_ctrl(MaruCamState *state) +{ + HRESULT hr; + uint32_t i; + long property, set_val; + MaruCamParam *param = state->param; + + param->top = 0; + + switch (param->stack[0]) { + case V4L2_CID_BRIGHTNESS: + i = 0; + property = VideoProcAmp_Brightness; + break; + case V4L2_CID_CONTRAST: + i = 1; + property = VideoProcAmp_Contrast; + break; + case V4L2_CID_SATURATION: + i = 2; + property = VideoProcAmp_Saturation; + break; + case V4L2_CID_SHARPNESS: + i = 3; + property = VideoProcAmp_Sharpness; + break; + default: + param->errCode = EINVAL; + return; + } + set_val = value_convert_from_guest(qctrl_tbl[i].min, + qctrl_tbl[i].max, (long)param->stack[1]); + hr = SetVideoProcAmp(property, set_val); + if (FAILED(hr)) { + param->errCode = EINVAL; + ERR("failed to set video control value, [HRESULT : 0x%x]\n", hr); + return; + } +} + +void marucam_device_g_ctrl(MaruCamState *state) +{ + HRESULT hr; + uint32_t i; + long property, get_val; + MaruCamParam *param = state->param; + + param->top = 0; + switch (param->stack[0]) { + case V4L2_CID_BRIGHTNESS: + i = 0; + property = VideoProcAmp_Brightness; + break; + case V4L2_CID_CONTRAST: + i = 1; + property = VideoProcAmp_Contrast; + break; + case V4L2_CID_SATURATION: + i = 2; + property = VideoProcAmp_Saturation; + break; + case V4L2_CID_SHARPNESS: + i = 3; + property = VideoProcAmp_Sharpness; + break; + default: + param->errCode = EINVAL; + return; + } + + hr = GetVideoProcAmp(property, &get_val); + if (FAILED(hr)) { + param->errCode = EINVAL; + ERR("failed to get video control value!!!, [HRESULT : 0x%x]\n", hr); + return; + } + param->stack[0] = (uint32_t)value_convert_to_guest(qctrl_tbl[i].min, + qctrl_tbl[i].max, get_val); +} + +void marucam_device_enum_fsizes(MaruCamState *state) +{ + uint32_t index, pixfmt, i; + MaruCamParam *param = state->param; + + param->top = 0; + index = param->stack[0]; + pixfmt = param->stack[1]; + + if (index >= ARRAY_SIZE(supported_dst_frames)) { + param->errCode = EINVAL; + return; + } + for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) { + if (supported_dst_pixfmts[i].fmt == pixfmt) { + break; + } + } + + if (i == ARRAY_SIZE(supported_dst_pixfmts)) { + param->errCode = EINVAL; + return; + } + + param->stack[0] = supported_dst_frames[index].width; + param->stack[1] = supported_dst_frames[index].height; +} + +void marucam_device_enum_fintv(MaruCamState *state) +{ + MaruCamParam *param = state->param; + + param->top = 0; + + /* switch by index(param->stack[0]) */ + switch (param->stack[0]) { + case 0: + param->stack[1] = 30; /* denominator */ + break; + default: + param->errCode = EINVAL; + return; + } + param->stack[0] = 1; /* numerator */ +} + +void yuyv_to_yuv420(const unsigned char *src, unsigned char *dest, + uint32_t width, uint32_t height, uint32_t yvu) +{ + uint32_t i, j; + const unsigned char *src1; + unsigned char *udest, *vdest; + + /* copy the Y values */ + src1 = src; + for (i = 0; i < height; i++) { + for (j = 0; j < width; j += 2) { + *dest++ = src1[0]; + *dest++ = src1[2]; + src1 += 4; + } + } + + /* copy the U and V values */ + src++; /* point to V */ + src1 = src + width * 2; /* next line */ + if (yvu) { + vdest = dest; + udest = dest + width * height / 4; + } else { + udest = dest; + vdest = dest + width * height / 4; + } + for (i = 0; i < height; i += 2) { + for (j = 0; j < width; j += 2) { + *udest++ = ((int) src[0] + src1[0]) / 2; /* U */ + *vdest++ = ((int) src[2] + src1[2]) / 2; /* V */ + src += 4; + src1 += 4; + } + src = src1; + src1 += width * 2; + } +} + +#define RGB2Y(r, g, b, y) \ + (y) = ((8453 * (r) + 16594 * (g) + 3223 * (b) + 524288) >> 15) + +#define RGB2UV(r, g, b, u, v) \ + do { \ + (u) = ((-4878 * (r) - 9578 * (g) + 14456 * (b) + 4210688) >> 15); \ + (v) = ((14456 * (r) - 12105 * (g) - 2351 * (b) + 4210688) >> 15); \ + } while (0) + +#define CLIP(color) \ + (unsigned char)(((color) > 0xFF) ? 0xff : (((color) < 0) ? 0 : (color))) + +void rgb24_to_yuv420(const unsigned char *src, unsigned char *dest, + uint32_t width, uint32_t height, uint32_t yvu) +{ + uint32_t x, y; + unsigned char *udest, *vdest; + uint32_t bytesperline = width * 3; + + /* Y */ + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + RGB2Y(src[2], src[1], src[0], *dest++); + src += 3; + } + src += bytesperline - 3 * width; + } + src -= height * bytesperline; + + /* U + V */ + if (yvu) { + vdest = dest; + udest = dest + width * height / 4; + } else { + udest = dest; + vdest = dest + width * height / 4; + } + + for (y = 0; y < height / 2; y++) { + for (x = 0; x < width / 2; x++) { + uint32_t avg_src[3]; + + avg_src[0] = (src[0] + src[3] + src[bytesperline] + + src[bytesperline + 3]) / 4; + avg_src[1] = (src[1] + src[4] + src[bytesperline + 1] + + src[bytesperline + 4]) / 4; + avg_src[2] = (src[2] + src[5] + src[bytesperline + 2] + + src[bytesperline + 5]) / 4; + RGB2UV(avg_src[2], avg_src[1], avg_src[0], *udest++, *vdest++); + src += 6; + } + src += 2 * bytesperline - 3 * width; + } +} + +void rgb24_to_yuyv(unsigned char *src, unsigned char *dest, + uint32_t width, uint32_t height) +{ + uint32_t i = 0; + + for (i = 0; i < (width * height * 3); i = i + 6) { + /* y */ + *dest++ = CLIP(0.299 * (src[i + 2] - 128) + + 0.587 * (src[i + 1] - 128) + + 0.114 * (src[i] - 128) + 128); + /* u */ + *dest++ = CLIP(((-0.147 * (src[i + 2] - 128) - + 0.289 * (src[i + 1] - 128) + + 0.436 * (src[i] - 128) + 128) + + (-0.147 * (src[i + 5] - 128) - + 0.289 * (src[i + 4] - 128) + + 0.436 * (src[i + 3] - 128) + 128)) / 2); + /* y1 */ + *dest++ = CLIP(0.299 * (src[i + 5] - 128) + + 0.587 * (src[i + 4] - 128) + + 0.114 * (src[i + 3] - 128) + 128); + /* v */ + *dest++ = CLIP(((0.615 * (src[i + 2] - 128) - + 0.515 * (src[i + 1] - 128) - + 0.100 * (src[i] - 128) + 128) + + (0.615 * (src[i + 5] - 128) - + 0.515 * (src[i + 4] - 128) - + 0.100 * (src[i + 3] - 128) + 128)) / 2); + } +} + +void yuv420_to_yvu420(unsigned char *src, unsigned char *dest, + uint32_t width, uint32_t height) +{ + unsigned char *psrc_y, *pdst_y; + unsigned char *psrc_u, *pdst_u; + unsigned char *psrc_v, *pdst_v; + + psrc_y = src; + psrc_u = psrc_y + (width * height); + psrc_v = psrc_u + (width * height / 4); + + pdst_y = dest; + pdst_v = pdst_y + (width * height); + pdst_u = pdst_v + (width * height / 4); + + memcpy(pdst_y, psrc_y, width * height); + memcpy(pdst_v, psrc_v, width * height / 4); + memcpy(pdst_u, psrc_u, width * height / 4); +} + +void yuv420_to_yuyv(unsigned char *src, unsigned char *dest, + uint32_t width, uint32_t height) +{ + unsigned char *py; + unsigned char *pu; + unsigned char *pv; + + uint32_t linesize = width * 2; + uint32_t uvlinesize = width / 2; + uint32_t offset = 0; + uint32_t offset1 = 0; + uint32_t offsety = 0; + uint32_t offsety1 = 0; + uint32_t offsetuv = 0; + uint32_t h = 0; + uint32_t w = 0; + uint32_t wy = 0; + uint32_t huv = 0; + uint32_t wuv = 0; + + py = src; + pu = py + (width * height); + pv = pu + (width * height / 4); + + for (h = 0; h < height; h += 2) { + wy = 0; + wuv = 0; + offset = h * linesize; + offset1 = (h + 1) * linesize; + offsety = h * width; + offsety1 = (h + 1) * width; + offsetuv = huv * uvlinesize; + + for (w = 0; w < linesize; w += 4) { + /* y00 */ + dest[w + offset] = py[wy + offsety]; + /* u0 */ + dest[(w + 1) + offset] = pu[wuv + offsetuv]; + /* y01 */ + dest[(w + 2) + offset] = py[(wy + 1) + offsety]; + /* v0 */ + dest[(w + 3) + offset] = pv[wuv + offsetuv]; + + /* y10 */ + dest[w + offset1] = py[wy + offsety1]; + /* u0 */ + dest[(w + 1) + offset1] = pu[wuv + offsetuv]; + /* y11 */ + dest[(w + 2) + offset1] = py[(wy + 1) + offsety1]; + /* v0 */ + dest[(w + 3) + offset1] = pv[wuv + offsetuv]; + + wuv++; + wy += 2; + } + huv++; + } +} diff --git a/tizen/src/hw/maru_device_ids.h b/tizen/src/hw/maru_device_ids.h index 0fc77de5f9..8a2a0bd8e9 100644 --- a/tizen/src/hw/maru_device_ids.h +++ b/tizen/src/hw/maru_device_ids.h @@ -1,7 +1,7 @@ /* * Maru Device IDs * - * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: * SeokYeon Hwang @@ -49,8 +49,9 @@ #define PCI_DEVICE_ID_VIRTUAL_CODEC 0x101C /* Device ID 0x1000 through 0x103F inclusive is a virtio device */ #define PCI_DEVICE_ID_VIRTIO_TOUCHSCREEN 0x101D -#define PCI_DEVICE_ID_VIRTIO_KEYBOARD 0x1020 +#define PCI_DEVICE_ID_VIRTIO_KEYBOARD 0x1020 #define PCI_DEVICE_ID_VIRTIO_ESM 0x1024 +#define PCI_DEVICE_ID_VIRTIO_HWKEY 0x1028 /* Virtio */ /* @@ -82,5 +83,6 @@ #define VIRTIO_ID_TOUCHSCREEN 11 #define VIRTIO_ID_KEYBOARD 12 #define VIRTIO_ID_ESM 13 +#define VIRTIO_ID_HWKEY 14 #endif /* MARU_DEVICE_IDS_H_ */ diff --git a/tizen/src/hw/maru_overlay.c b/tizen/src/hw/maru_overlay.c index 43194b4233..7072f586c3 100644 --- a/tizen/src/hw/maru_overlay.c +++ b/tizen/src/hw/maru_overlay.c @@ -1,17 +1,10 @@ -/* +/* * Maru overlay device for VGA * - * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved. * - * Contact: - * SeokYeon Hwang - * SangJin Kim - * MunKyu Im - * KiTae Kim + * Contact: * JinHyung Jo - * SungMin Ha - * JiHye Kim - * GiWoong Kim * YeongKyoon Lee * DongKyun Yun * DoHyung Hong @@ -29,12 +22,14 @@ * * 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. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. * * Contributors: * - S-Core Co., Ltd * */ + #include "pc.h" #include "pci.h" #include "maru_device_ids.h" @@ -43,20 +38,20 @@ MULTI_DEBUG_CHANNEL(qemu, maru_overlay); -#define QEMU_DEV_NAME "MARU_OVERLAY" +#define QEMU_DEV_NAME "MARU_OVERLAY" -#define OVERLAY_MEM_SIZE (8192 * 1024) // 4MB(overlay0) + 4MB(overlay1) -#define OVERLAY_REG_SIZE 256 -#define OVERLAY1_REG_OFFSET (OVERLAY_REG_SIZE / 2) +#define OVERLAY_MEM_SIZE (8192 * 1024) /* 4MB(overlay0) + 4MB(overlay1) */ +#define OVERLAY_REG_SIZE 256 +#define OVERLAY1_REG_OFFSET (OVERLAY_REG_SIZE / 2) enum { - OVERLAY_POWER = 0x00, - OVERLAY_POSITION = 0x04, // left top position - OVERLAY_SIZE = 0x08, // width and height + OVERLAY_POWER = 0x00, + OVERLAY_POSITION = 0x04, /* left top position */ + OVERLAY_SIZE = 0x08, /* width and height */ }; -uint8_t* overlay_ptr; +uint8_t *overlay_ptr; uint8_t overlay0_power; uint16_t overlay0_left; @@ -75,11 +70,12 @@ typedef struct OverlayState { MemoryRegion mem_addr; MemoryRegion mmio_addr; - } OverlayState; -static uint64_t overlay_reg_read(void *opaque, target_phys_addr_t addr, unsigned size) +static uint64_t overlay_reg_read(void *opaque, + target_phys_addr_t addr, + unsigned size) { switch (addr) { case OVERLAY_POWER: @@ -118,7 +114,10 @@ static uint64_t overlay_reg_read(void *opaque, target_phys_addr_t addr, unsigned return 0; } -static void overlay_reg_write(void *opaque, target_phys_addr_t addr, uint64_t val, unsigned size) +static void overlay_reg_write(void *opaque, + target_phys_addr_t addr, + uint64_t val, + unsigned size) { switch (addr) { case OVERLAY_POWER: @@ -190,7 +189,10 @@ static int overlay_initfn(PCIDevice *dev) memory_region_init_ram(&s->mem_addr, "maru_overlay.ram", OVERLAY_MEM_SIZE); overlay_ptr = memory_region_get_ram_ptr(&s->mem_addr); - memory_region_init_io (&s->mmio_addr, &overlay_mmio_ops, s, "maru_overlay_mmio", OVERLAY_REG_SIZE); + memory_region_init_io(&s->mmio_addr, &overlay_mmio_ops, + s, + "maru_overlay_mmio", + OVERLAY_REG_SIZE); /* setup memory space */ /* memory #0 device memory (overlay surface) */ diff --git a/tizen/src/hw/maru_overlay.h b/tizen/src/hw/maru_overlay.h index 673e0d6622..24a4529560 100644 --- a/tizen/src/hw/maru_overlay.h +++ b/tizen/src/hw/maru_overlay.h @@ -1,17 +1,10 @@ /* * Maru overlay device for VGA * - * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: - * SeokYeon Hwang - * SangJin Kim - * MunKyu Im - * KiTae Kim * JinHyung Jo - * SungMin Ha - * JiHye Kim - * GiWoong Kim * YeongKyoon Lee * DoHyung Hong * Hyunjun Son @@ -28,7 +21,8 @@ * * 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. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. * * Contributors: * - S-Core Co., Ltd @@ -41,7 +35,7 @@ #include "qemu-common.h" -extern uint8_t* overlay_ptr; +extern uint8_t *overlay_ptr; extern uint8_t overlay0_power; extern uint16_t overlay0_left; extern uint16_t overlay0_top; @@ -54,6 +48,6 @@ extern uint16_t overlay1_top; extern uint16_t overlay1_width; extern uint16_t overlay1_height; -DeviceState *pci_maru_overlay_init( PCIBus *bus ); +DeviceState *pci_maru_overlay_init(PCIBus *bus); #endif /* MARU_OVERLAY_H_ */ diff --git a/tizen/src/hw/maru_vga.c b/tizen/src/hw/maru_vga.c index 144cfbdb65..fbb7f81bf5 100644 --- a/tizen/src/hw/maru_vga.c +++ b/tizen/src/hw/maru_vga.c @@ -2,7 +2,7 @@ * Maru vga device * Based on qemu/hw/vga.c * - * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: * GiWoong Kim @@ -56,11 +56,12 @@ #include #include #include "maru_err_table.h" +#include "emul_state.h" #endif #ifdef CONFIG_USE_SHM void *shared_memory = (void*) 0; -int shmid; +int skin_shmid; #endif @@ -1872,37 +1873,23 @@ void maru_vga_common_init(VGACommonState *s) vga_dirty_log_start(s); #ifdef CONFIG_USE_SHM - int mykey; - void *temp; - - shmid = shmget((key_t)SHMKEY, (size_t)MAXLEN, 0666 | IPC_CREAT); - if (shmid == -1) { - ERR("shmget failed\n"); - perror("maru_vga: "); - exit(1); - } - - temp = shmat(shmid, (char*)0x0, 0); - if (temp == (void *)-1) { - ERR("shmat failed\n"); - perror("maru_vga: "); - exit(1); - } + /* base + 1 = sdb port */ + /* base + 2 = shared memory key */ + int mykey = get_emul_vm_base_port() + 2; - mykey = atoi(temp); - shmdt(temp); INFO("shared memory key: %d, vga ram_size : %d\n", mykey, s->vram_size); - shmid = shmget((key_t)mykey, (size_t)s->vram_size, 0666 | IPC_CREAT); - if (shmid == -1) { + skin_shmid = shmget((key_t)mykey, (size_t)s->vram_size, 0666 | IPC_CREAT); + if (skin_shmid == -1) { ERR("shmget failed\n"); perror("maru_vga: "); - maru_register_exit_msg(MARU_EXIT_UNKNOWN, (char*)"Cannot launch this VM.\n" - "Shared memory is not enough."); + maru_register_exit_msg(MARU_EXIT_UNKNOWN, + (char*) "Cannot launch this VM.\n" + "Shared memory is not enough."); exit(0); } - shared_memory = shmat(shmid, (void*)0, 0); + shared_memory = shmat(skin_shmid, (void*)0, 0); if (shared_memory == (void *)-1) { ERR("shmat failed\n"); perror("maru_vga: "); @@ -1923,7 +1910,7 @@ void maru_vga_common_fini(void) perror("maru_vga: "); } - if (shmctl(shmid, IPC_RMID, 0) == -1) { + if (shmctl(skin_shmid, IPC_RMID, 0) == -1) { ERR("shmctl failed\n"); perror("maru_vga: "); } diff --git a/tizen/src/hw/maru_virtio_hwkey.c b/tizen/src/hw/maru_virtio_hwkey.c new file mode 100644 index 0000000000..29f541b955 --- /dev/null +++ b/tizen/src/hw/maru_virtio_hwkey.c @@ -0,0 +1,263 @@ +/* + * Maru Virtio HW Key Device + * + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * GiWoong Kim + * YeongKyoon Lee + * + * 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 + * + */ + + +#include +#include "console.h" +#include "emul_state.h" +#include "maru_virtio_hwkey.h" +#include "maru_device_ids.h" +#include "debug_ch.h" + +MULTI_DEBUG_CHANNEL(qemu, hwkey); + +#define DEVICE_NAME "virtio-hwkey" + +/* + * HW key event queue + */ +typedef struct HwKeyEventEntry { + unsigned int index; + EmulHwKeyEvent hwkey; + + QTAILQ_ENTRY(HwKeyEventEntry) node; +} HwKeyEventEntry; + +/* the maximum number of HW key event that can be put into a queue */ +#define MAX_HWKEY_EVENT_CNT 64 + +static HwKeyEventEntry _events_buf[MAX_HWKEY_EVENT_CNT]; +static QTAILQ_HEAD(, HwKeyEventEntry) events_queue = + QTAILQ_HEAD_INITIALIZER(events_queue); + +static unsigned int event_ringbuf_cnt; /* _events_buf */ +static unsigned int event_queue_cnt; /* events_queue */ + +/* + * VirtQueueElement queue + */ +typedef struct ElementEntry { + unsigned int el_index; + unsigned int sg_index; + VirtQueueElement elem; + + QTAILQ_ENTRY(ElementEntry) node; +} ElementEntry; + +static ElementEntry _elem_buf[10]; +static QTAILQ_HEAD(, ElementEntry) elem_queue = + QTAILQ_HEAD_INITIALIZER(elem_queue); + +static unsigned int elem_ringbuf_cnt; /* _elem_buf */ +static unsigned int elem_queue_cnt; /* elem_queue */ + +VirtIOHwKey *vhk; + +/* lock for between communication thread and IO thread */ +static pthread_mutex_t event_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t elem_mutex = PTHREAD_MUTEX_INITIALIZER; + +void maru_hwkey_event(int event_type, int keycode) +{ + HwKeyEventEntry *entry = NULL; + + if (unlikely(event_queue_cnt >= MAX_HWKEY_EVENT_CNT)) { + INFO("full hwkey event queue, lose event\n", event_queue_cnt); + + qemu_bh_schedule(vhk->bh); + return; + } + + entry = &(_events_buf[event_ringbuf_cnt % MAX_HWKEY_EVENT_CNT]); + event_ringbuf_cnt++; + + /* hwkey event is copied into the queue */ + entry->hwkey.keycode = keycode; + entry->hwkey.event_type = event_type; + + pthread_mutex_lock(&event_mutex); + + entry->index = ++event_queue_cnt; // 1 ~ + + QTAILQ_INSERT_TAIL(&events_queue, entry, node); + + pthread_mutex_unlock(&event_mutex); + + /* call maru_virtio_hwkey_notify */ + qemu_bh_schedule(vhk->bh); + + TRACE("hwkey event (%d) : keycode=%d, event_type=%d\n", + entry->index, entry->hwkey.keycode, entry->hwkey.event_type); +} + +static void maru_virtio_hwkey_handle(VirtIODevice *vdev, VirtQueue *vq) +{ + int virt_sg_index = 0; + ElementEntry *elem_entry = NULL; + + TRACE("maru_virtio_hwkey_handle\n"); + + if (unlikely(virtio_queue_empty(vhk->vq))) { + TRACE("virtqueue is empty\n"); + return; + } + + while (true) { + elem_entry = &(_elem_buf[elem_ringbuf_cnt % 10]); + elem_ringbuf_cnt++; + + virt_sg_index = virtqueue_pop(vhk->vq, &elem_entry->elem); + if (virt_sg_index == 0) { + elem_ringbuf_cnt--; + break; + } else if (virt_sg_index < 0) { + ERR("virtqueue is broken\n"); + elem_ringbuf_cnt--; + return; + } + + pthread_mutex_lock(&elem_mutex); + + elem_entry->el_index = ++elem_queue_cnt; + elem_entry->sg_index = (unsigned int)virt_sg_index; + + /* save VirtQueueElement */ + QTAILQ_INSERT_TAIL(&elem_queue, elem_entry, node); + /* call maru_virtio_hwkey_notify */ + qemu_bh_schedule(vhk->bh); + + pthread_mutex_unlock(&elem_mutex); + } +} + +void maru_virtio_hwkey_notify(void) +{ + HwKeyEventEntry *event_entry = NULL; + ElementEntry *elem_entry = NULL; + VirtQueueElement *element = NULL; + void *vbuf = NULL; + + TRACE("maru_virtio_hwkey_notify\n"); + + if (unlikely(!virtio_queue_ready(vhk->vq))) { + ERR("virtio queue is not ready\n"); + return; + } + + while (true) { + if (event_queue_cnt == 0) { + TRACE("no event\n"); + break; + } + + elem_entry = QTAILQ_FIRST(&elem_queue); + + if ( elem_entry->sg_index > 0) { + /* get hwkey event from host queue */ + event_entry = QTAILQ_FIRST(&events_queue); + + TRACE("hwkey(%d) : keycode=%d, event_type=%d | \ + event_queue_cnt=%d\n", + event_entry->index, + event_entry->hwkey.keycode, event_entry->hwkey.event_type, + event_queue_cnt); + + element = &elem_entry->elem; + vbuf = element->in_sg[elem_entry->sg_index - 1].iov_base; + + /* copy event into virtio buffer */ + memcpy(vbuf, &(event_entry->hwkey), sizeof(EmulHwKeyEvent)); + + virtqueue_push(vhk->vq, element, sizeof(EmulHwKeyEvent)); + virtio_notify(&vhk->vdev, vhk->vq); + } + + pthread_mutex_lock(&event_mutex); + + /* remove host event */ + QTAILQ_REMOVE(&events_queue, event_entry, node); + event_queue_cnt--; + + pthread_mutex_unlock(&event_mutex); + } +} + +static uint32_t virtio_hwkey_get_features( + VirtIODevice *vdev, uint32_t request_features) +{ + // TODO: + return request_features; +} + +static void maru_hwkey_bh(void *opaque) +{ + maru_virtio_hwkey_notify(); +} + +VirtIODevice *maru_virtio_hwkey_init(DeviceState *dev) +{ + INFO("initialize the hwkey device\n"); + + vhk = (VirtIOHwKey *)virtio_common_init(DEVICE_NAME, + VIRTIO_ID_HWKEY, 0 /*config_size*/, sizeof(VirtIOHwKey)); + + if (vhk == NULL) { + ERR("failed to initialize the hwkey device\n"); + return NULL; + } + + vhk->vdev.get_features = virtio_hwkey_get_features; + vhk->vq = virtio_add_queue(&vhk->vdev, 64, maru_virtio_hwkey_handle); + + vhk->qdev = dev; + + /* reset the counters */ + event_queue_cnt = event_ringbuf_cnt = 0; + elem_queue_cnt = elem_ringbuf_cnt = 0; + + /* bottom-half */ + vhk->bh = qemu_bh_new(maru_hwkey_bh, vhk); + + return &(vhk->vdev); +} + +void maru_virtio_hwkey_exit(VirtIODevice *vdev) +{ + VirtIOHwKey *vhk = (VirtIOHwKey *)vdev; + + INFO("exit the hwkey device\n"); + + if (vhk->bh) { + qemu_bh_delete(vhk->bh); + } + + virtio_cleanup(vdev); + + pthread_mutex_destroy(&event_mutex); +} + diff --git a/tizen/src/hw/maru_virtio_hwkey.h b/tizen/src/hw/maru_virtio_hwkey.h new file mode 100644 index 0000000000..d80866aa3d --- /dev/null +++ b/tizen/src/hw/maru_virtio_hwkey.h @@ -0,0 +1,60 @@ +/* + * Maru Virtio HW Key Device + * + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * GiWoong Kim + * YeongKyoon Lee + * + * 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 + * + */ + + +#ifndef MARU_HWKEY_H_ +#define MARU_HWKEY_H_ + +#include "console.h" +#include "hw/virtio.h" + +typedef struct VirtIOHwKey +{ + VirtIODevice vdev; + /* simply a queue into which buffers are posted + by the guest for consumption by the host */ + VirtQueue *vq; + + QEMUBH *bh; + DeviceState *qdev; +} VirtIOHwKey; + +/* This structure must match the kernel definitions */ +typedef struct EmulHwKeyEvent { + uint8_t event_type; + uint32_t keycode; +} EmulHwKeyEvent; + + +VirtIODevice *maru_virtio_hwkey_init(DeviceState *dev); +void maru_virtio_hwkey_exit(VirtIODevice *vdev); + +void maru_hwkey_event(int event_type, int keycode); +void maru_virtio_hwkey_notify(void); + +#endif /* MARU_HWKEY_H_ */ diff --git a/tizen/src/hw/maru_virtio_keyboard.c b/tizen/src/hw/maru_virtio_keyboard.c index e331070606..97f4d2a0d2 100644 --- a/tizen/src/hw/maru_virtio_keyboard.c +++ b/tizen/src/hw/maru_virtio_keyboard.c @@ -5,6 +5,7 @@ * * Contact: * Kitae Kim + * GiWoong Kim * SeokYeon Hwang * YeongKyoon Lee * @@ -27,11 +28,11 @@ * */ -#include "mloop_event.h" #include "maru_device_ids.h" #include "maru_virtio_keyboard.h" #include "tizen/src/debug_ch.h" + MULTI_DEBUG_CHANNEL(qemu, virtio-kbd); VirtQueueElement elem; @@ -60,22 +61,13 @@ void virtio_keyboard_notify(void *opaque) EmulKbdEvent *kbdevt; int index = 0; int written_cnt = 0; - int *rptr = NULL; if (!vkbd) { ERR("VirtIOKeyboard is NULL.\n"); return; } - qemu_mutex_lock(&vkbd->event_mutex); - written_cnt = vkbd->kbdqueue.wptr; TRACE("[Enter] virtqueue notifier. %d\n", written_cnt); - qemu_mutex_unlock(&vkbd->event_mutex); - if (written_cnt < 0) { - TRACE("there is no input data to copy to guest.\n"); - return; - } - rptr = &vkbd->kbdqueue.rptr; if (!virtio_queue_ready(vkbd->vq)) { INFO("virtqueue is not ready.\n"); @@ -83,30 +75,32 @@ void virtio_keyboard_notify(void *opaque) } if (vkbd->kbdqueue.rptr == VIRTIO_KBD_QUEUE_SIZE) { - *rptr = 0; + vkbd->kbdqueue.rptr = 0; } + qemu_mutex_lock(&vkbd->event_mutex); + written_cnt = vkbd->kbdqueue.wptr; + while ((written_cnt--)) { - index = *rptr; - kbdevt = &vkbd->kbdqueue.kbdevent[index]; + kbdevt = &vkbd->kbdqueue.kbdevent[vkbd->kbdqueue.rptr]; /* Copy keyboard data into guest side. */ - TRACE("copy: keycode %d, type %d, index %d\n", + TRACE("copy: keycode %d, type %d, elem_index %d\n", kbdevt->code, kbdevt->type, index); - memcpy(elem.in_sg[index].iov_base, kbdevt, sizeof(EmulKbdEvent)); + memcpy(elem.in_sg[index++].iov_base, kbdevt, sizeof(EmulKbdEvent)); memset(kbdevt, 0x00, sizeof(EmulKbdEvent)); - qemu_mutex_lock(&vkbd->event_mutex); if (vkbd->kbdqueue.wptr > 0) { vkbd->kbdqueue.wptr--; + TRACE("written_cnt: %d, wptr: %d, qemu_index: %d\n", written_cnt, vkbd->kbdqueue.wptr, vkbd->kbdqueue.rptr); } - qemu_mutex_unlock(&vkbd->event_mutex); - (*rptr)++; - if (*rptr == VIRTIO_KBD_QUEUE_SIZE) { - *rptr = 0; + vkbd->kbdqueue.rptr++; + if (vkbd->kbdqueue.rptr == VIRTIO_KBD_QUEUE_SIZE) { + vkbd->kbdqueue.rptr = 0; } } + qemu_mutex_unlock(&vkbd->event_mutex); virtqueue_push(vkbd->vq, &elem, sizeof(EmulKbdEvent)); virtio_notify(&vkbd->vdev, vkbd->vq); @@ -198,16 +192,17 @@ static void virtio_keyboard_event(void *opaque, int keycode) vkbd->extension_key = 1; } + qemu_mutex_lock(&vkbd->event_mutex); memcpy(&vkbd->kbdqueue.kbdevent[(*index)++], &kbdevt, sizeof(kbdevt)); TRACE("event: keycode %d, type %d, index %d.\n", kbdevt.code, kbdevt.type, ((*index) - 1)); - qemu_mutex_lock(&vkbd->event_mutex); vkbd->kbdqueue.wptr++; qemu_mutex_unlock(&vkbd->event_mutex); TRACE("[Leave] input_event handler. cnt:%d\n", vkbd->kbdqueue.wptr); - mloop_evcmd_keyboard(vkbd); + + qemu_bh_schedule(vkbd->bh); } static uint32_t virtio_keyboard_get_features(VirtIODevice *vdev, @@ -217,6 +212,11 @@ static uint32_t virtio_keyboard_get_features(VirtIODevice *vdev, return 0; } +static void virtio_keyboard_bh(void *opaque) +{ + virtio_keyboard_notify(opaque); +} + VirtIODevice *virtio_keyboard_init(DeviceState *dev) { VirtIOKeyboard *vkbd; @@ -238,6 +238,9 @@ VirtIODevice *virtio_keyboard_init(DeviceState *dev) vkbd->vq = virtio_add_queue(&vkbd->vdev, 64, virtio_keyboard_handle); vkbd->qdev = dev; + /* bottom half */ + vkbd->bh = qemu_bh_new(virtio_keyboard_bh, vkbd); + /* register keyboard handler */ qemu_add_kbd_event_handler(virtio_keyboard_event, vkbd); @@ -249,6 +252,12 @@ void virtio_keyboard_exit(VirtIODevice *vdev) VirtIOKeyboard *vkbd = (VirtIOKeyboard *)vdev; INFO("destroy device\n"); + qemu_remove_kbd_event_handler(); + + if (vkbd->bh) { + qemu_bh_delete(vkbd->bh); + } + qemu_mutex_destroy(&vkbd->event_mutex); virtio_cleanup(vdev); diff --git a/tizen/src/hw/maru_virtio_keyboard.h b/tizen/src/hw/maru_virtio_keyboard.h index 0e06e6a8be..a744760cd8 100644 --- a/tizen/src/hw/maru_virtio_keyboard.h +++ b/tizen/src/hw/maru_virtio_keyboard.h @@ -5,6 +5,7 @@ * * Contact: * Kitae Kim + * GiWoong Kim * SeokYeon Hwang * YeongKyoon Lee * @@ -59,6 +60,7 @@ typedef struct VirtIOKeyboard { VirtIOKbdQueue kbdqueue; QemuMutex event_mutex; + QEMUBH *bh; } VirtIOKeyboard; VirtIODevice *virtio_keyboard_init(DeviceState *dev); diff --git a/tizen/src/hw/maru_virtio_touchscreen.c b/tizen/src/hw/maru_virtio_touchscreen.c index 9c08fb7d7c..f5b041b5a4 100644 --- a/tizen/src/hw/maru_virtio_touchscreen.c +++ b/tizen/src/hw/maru_virtio_touchscreen.c @@ -1,7 +1,7 @@ /* * Maru Virtio Touchscreen Device * - * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved * * Contact: * GiWoong Kim @@ -31,7 +31,6 @@ #include "console.h" #include "maru_virtio_touchscreen.h" #include "maru_device_ids.h" -#include "mloop_event.h" #include "debug_ch.h" MULTI_DEBUG_CHANNEL(qemu, touchscreen); @@ -92,7 +91,7 @@ void virtio_touchscreen_event(void *opaque, int x, int y, int z, int buttons_sta if (unlikely(event_queue_cnt >= MAX_TOUCH_EVENT_CNT)) { INFO("full touch event queue, lose event\n", event_queue_cnt); - mloop_evcmd_touch(); + qemu_bh_schedule(ts->bh); return; } @@ -114,7 +113,7 @@ void virtio_touchscreen_event(void *opaque, int x, int y, int z, int buttons_sta pthread_mutex_unlock(&event_mutex); /* call maru_virtio_touchscreen_notify */ - mloop_evcmd_touch(); + qemu_bh_schedule(ts->bh); TRACE("touch event (%d) : x=%d, y=%d, z=%d, state=%d\n", entry->index, entry->touch.x, entry->touch.y, entry->touch.z, entry->touch.state); @@ -183,7 +182,9 @@ static void maru_virtio_touchscreen_handle(VirtIODevice *vdev, VirtQueue *vq) if (ts->waitBuf == true) { ts->waitBuf = false; - mloop_evcmd_touch(); // call maru_virtio_touchscreen_notify + + /* call maru_virtio_touchscreen_notify */ + qemu_bh_schedule(ts->bh); } pthread_mutex_unlock(&elem_mutex); @@ -274,6 +275,13 @@ static uint32_t virtio_touchscreen_get_features( return request_features; } +static void maru_touchscreen_bh(void *opaque) +{ + //TouchscreenState *ts = (TouchscreenState *)opaque; + + maru_virtio_touchscreen_notify(); +} + VirtIODevice *maru_virtio_touchscreen_init(DeviceState *dev) { INFO("initialize the touchscreen device\n"); @@ -297,6 +305,9 @@ VirtIODevice *maru_virtio_touchscreen_init(DeviceState *dev) ts->waitBuf = false; + /* bottom halves */ + ts->bh = qemu_bh_new(maru_touchscreen_bh, ts); + #if 1 /* register a event handler */ ts->eh_entry = qemu_add_mouse_event_handler( @@ -316,6 +327,13 @@ void maru_virtio_touchscreen_exit(VirtIODevice *vdev) qemu_remove_mouse_event_handler(ts->eh_entry); } + if (ts->bh) { + qemu_bh_delete(ts->bh); + } + virtio_cleanup(vdev); + + pthread_mutex_destroy(&event_mutex); + pthread_mutex_destroy(&elem_mutex); } diff --git a/tizen/src/hw/maru_virtio_touchscreen.h b/tizen/src/hw/maru_virtio_touchscreen.h index ad7756cf25..b78abadc6d 100644 --- a/tizen/src/hw/maru_virtio_touchscreen.h +++ b/tizen/src/hw/maru_virtio_touchscreen.h @@ -1,7 +1,7 @@ /* - * Maru Virtual Virtio Touchscreen emulation + * Maru Virtio Touchscreen Device * - * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved * * Contact: * GiWoong Kim @@ -41,6 +41,7 @@ typedef struct TouchscreenState VirtQueue *vq; bool waitBuf; + QEMUBH *bh; DeviceState *qdev; QEMUPutMouseEntry *eh_entry; } TouchscreenState; diff --git a/tizen/src/hw/opengl_exec.c b/tizen/src/hw/opengl_exec.c index db336b339f..5085d4a293 100644 --- a/tizen/src/hw/opengl_exec.c +++ b/tizen/src/hw/opengl_exec.c @@ -628,17 +628,12 @@ static void unbind_qsurface(GLState *state, state->current_qsurface = NULL; } -/* Find the qsurface with required drawable in active & pending qsurfaces */ +/* Find the qsurface with required drawable in all pixmap/pbuffer surfaces */ QGloSurface* find_qsurface_from_client_drawable(ProcessState *process, ClientGLXDrawable client_drawable) { - /* search for surfaces in current conetxt */ int i; - QGloSurface *qsurface = get_qsurface_from_client_drawable(process->current_state, client_drawable); - - if (qsurface) - return qsurface; + QGloSurface *qsurface; - /* search the pending surfaces */ for ( i = 0; i < process->nb_qsurf; i++ ) { qsurface = process->pending_qsurfaces[i]; @@ -700,14 +695,13 @@ static int link_drawable(ProcessState *process, ClientGLXDrawable drawable) return 0; } -/* Need to create pixmap surface when guest do so, as guest may use it before - * MakeCurrent. As no context available at this point, we do the follwoing: +/* Need to create pixmap/pbuffer surface when guest do so, as guest may use it + * before MakeCurrent. As no context available at this point, do the following: * 1. Create one light-weight context just for surface creation. * 2. Store this qsurface, and link it with right context when MakeCurrent */ static void keep_qsurface(ProcessState *process, QGloSurface *qsurface) { - int i; process->pending_qsurfaces = g_realloc(process->pending_qsurfaces, (process->nb_qsurf + 1) * sizeof(QGloSurface*)); @@ -760,8 +754,9 @@ static int link_qsurface(ProcessState *process, GLState *glstate, ClientGLXDrawa return 0; } -/* Pixmap can be used as texture via glEGLImageTargetTexture2DOES, so need keep - * the mapping between them to add proper action when bind the texture again +/* Pixmap and Pbuffer can be used as texture via glEGLImageTargetTexture2DOES + * and glXBindTexImage, so need keep the mapping between them to add proper + * action when bind the texture again */ static void del_pixmap_texture_mapping(GLState *state, unsigned int texture) @@ -780,6 +775,23 @@ static void del_pixmap_texture_mapping(GLState *state, } } +static void remove_pixmap_texture_mapping(GLState *state, + ClientGLXDrawable drawable) +{ + int i; + for ( i = 0; i < MAX_PIXMAP_TEXTURE; i++ ) + { + if ( state->pixmapTextures[i].used && + state->pixmapTextures[i].drawable == drawable ) + { + state->pixmapTextures[i].used = 0; + state->pixmapTextures[i].texture = 0; + state->pixmapTextures[i].drawable = 0; + return; + } + } +} + static int add_pixmap_texture_mapping(GLState *state, unsigned int texture, ClientGLXDrawable drawable) { @@ -796,8 +808,7 @@ static int add_pixmap_texture_mapping(GLState *state, } } - if ( i >= MAX_PIXMAP_TEXTURE ) - return 0; + return 0; } static ClientGLXDrawable find_pixmap_texture(GLState *state, @@ -1759,7 +1770,7 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args ret.i = glo_surface_makecurrent(glstate->current_qsurface->surface); /* if (reset_texture)*/ -/* glo_surface_as_texture(old_glstate->current_qsurface->surface);*/ +/* glo_surface_as_texture(process->current_state->context, old_glstate->current_qsurface->surface);*/ } } break; @@ -2030,8 +2041,10 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args keep_qsurface(process, qsurface); /* If this pixmap is linked as texture previously */ - if (link_drawable(process, client_drawable)) - glo_surface_as_texture(qsurface->surface); + if (link_drawable(process, client_drawable)) + glo_surface_as_texture(process->current_state->context, + qsurface->surface); + ret.i = client_drawable; @@ -2040,6 +2053,17 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args } case glXDestroyPixmap_func: { + /* glXPixmap same as input Pixmap */ + ClientGLXDrawable client_drawable = to_drawable(args[1]); + QGloSurface *qsurface = find_qsurface_from_client_drawable(process, client_drawable); + if ( qsurface && + qsurface != process->current_state->current_qsurface && + qsurface->glstate == NULL && + qsurface->type == SURFACE_PIXMAP ) + { + glo_surface_destroy(qsurface->surface); + g_free(qsurface); + } break; } case glEGLImageTargetTexture2DOES_fake_func: @@ -2063,10 +2087,93 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args } } else - glo_surface_as_texture(qsurface->surface); + glo_surface_as_texture(process->current_state->context, qsurface->surface); + break; + } + case glXBindTexImageARB_fake_func: + { + ClientGLXDrawable client_drawable = to_drawable(args[1]); + QGloSurface *qsurface = find_qsurface_from_client_drawable(process, client_drawable); + ret.i = 0; + + + if ( qsurface ) + { + add_pixmap_texture_mapping(process->current_state, + process->current_state->bindTexture2D, + client_drawable); + glo_surface_as_texture(process->current_state->context, qsurface->surface); + ret.i = 1; + } + else + DEBUGF( "Not found pbuffer surface for BindTexImage!\n"); + + break; + } + case glXReleaseTexImageARB_fake_func: + { + ClientGLXDrawable client_drawable = to_drawable(args[1]); + QGloSurface *qsurface = find_qsurface_from_client_drawable(process, client_drawable); + + if ( qsurface ) + { + remove_pixmap_texture_mapping(process->current_state, + client_drawable); + glo_surface_release_texture(qsurface->surface); + } + + break; + } + case glXCreatePbuffer_func: + { + int client_fbconfig = args[1]; + + ret.i = 0; + const GLXFBConfig *fbconfig = get_fbconfig(process, client_fbconfig); + + if (fbconfig) { + + /* Create a light-weight context just for creating surface */ + GloContext *context = __glo_context_create(fbconfig->formatFlags); + + QGloSurface *qsurface = calloc(1, sizeof(QGloSurface)); + + /* get the width and height */ + int width, height; + glo_geometry_get_from_glx((int*)args[2], &width, &height); + + DEBUGF( "glXCreatePbuffer: %dX%d.\n", width, height); + qsurface->surface = glo_surface_create(width, height, context); + /* Use GloSurface handler as no input client_drawable, and + * keep only low 32bit of handler on x86_64 host. */ + qsurface->client_drawable = (int)qsurface->surface; + qsurface->type = SURFACE_PBUFFER; + qsurface->status = SURFACE_PENDING; + /* qsurface->ref = 1;*/ + + /* Keep this surface, will link it with context in MakeCurrent */ + keep_qsurface(process, qsurface); + + ret.i = qsurface->client_drawable; + + } + break; + } + case glXDestroyPbuffer_func: + { + ClientGLXDrawable client_drawable = to_drawable(args[1]); + QGloSurface *qsurface = find_qsurface_from_client_drawable(process, client_drawable); + if ( qsurface && + qsurface != process->current_state->current_qsurface && + qsurface->glstate == NULL && + qsurface->type == SURFACE_PBUFFER ) + { + glo_surface_destroy(qsurface->surface); + g_free(qsurface); + } break; - } + } /* Begin of texture stuff */ case glBindTexture_func: @@ -2102,7 +2209,7 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args if ( qsurface ) { - glo_surface_as_texture(qsurface->surface); + glo_surface_as_texture(process->current_state->context, qsurface->surface); fprintf(stderr, "edwin:bindtexture: drawable=0x%x,qsurface=%p.\n", drawable, qsurface); } } diff --git a/tizen/src/hw/opengl_func.h b/tizen/src/hw/opengl_func.h index 3b302175ab..e29f0d901f 100644 --- a/tizen/src/hw/opengl_func.h +++ b/tizen/src/hw/opengl_func.h @@ -428,9 +428,9 @@ static const int glXBindTexImageATI_signature[] = { TYPE_NONE, 0, 3, TYPE_IN_IGNORED_POINTER, TYPE_INT, TYPE_INT }; static const int glXReleaseTexImageATI_signature[] = { TYPE_NONE, 0, 3, TYPE_IN_IGNORED_POINTER, TYPE_INT, TYPE_INT }; -static const int glXBindTexImageARB_signature[] = +static const int glXBindTexImageARB_fake_signature[] = { TYPE_INT, 0, 3, TYPE_IN_IGNORED_POINTER, TYPE_INT, TYPE_INT }; -static const int glXReleaseTexImageARB_signature[] = +static const int glXReleaseTexImageARB_fake_signature[] = { TYPE_INT, 0, 3, TYPE_IN_IGNORED_POINTER, TYPE_INT, TYPE_INT }; static const int glEGLImageTargetTexture2DOES_fake_signature[] = diff --git a/tizen/src/maru_common.h b/tizen/src/maru_common.h index caddfdbcb4..3aacef95c7 100644 --- a/tizen/src/maru_common.h +++ b/tizen/src/maru_common.h @@ -31,17 +31,31 @@ */ /** - * @file emulator.h - * @brief - header of file these are config structures and defines in emulator + * @file maru_common.h + * @brief - header file that covers maru common features */ #ifndef __MARU_COMMON_H__ #define __MARU_COMMON_H__ -#include "config-host.h" #include #include #include +#include + +#include +#include +#include + +#include "config-host.h" + +#if !defined(PATH_MAX) +#if defined(MAX_PATH) +#define PATH_MAX MAX_PATH +#else +#define PATH_MAX 256 +#endif +#endif // W/A for preserve larger continuous heap for RAM. extern void *preallocated_ptr; diff --git a/tizen/src/maru_display.h b/tizen/src/maru_display.h index 4e9b23bf4d..bebf480437 100644 --- a/tizen/src/maru_display.h +++ b/tizen/src/maru_display.h @@ -28,8 +28,8 @@ */ -#ifndef MARU_DISPLAY_H_ -#define MARU_DISPLAY_H_ +#ifndef __MARU_DISPLAY_H__ +#define __MARU_DISPLAY_H__ #include "console.h" @@ -45,4 +45,4 @@ void maruskin_init(uint64 swt_handle, int lcd_size_width, int lcd_size_height, b DisplaySurface* get_qemu_display_surface(void); MaruScreenshot* get_maru_screenshot(void); -#endif /* MARU_DISPLAY_H_ */ +#endif /* __MARU_DISPLAY_H__ */ diff --git a/tizen/src/maru_sdl.c b/tizen/src/maru_sdl.c index eb33eaba19..140680dd56 100644 --- a/tizen/src/maru_sdl.c +++ b/tizen/src/maru_sdl.c @@ -37,8 +37,12 @@ #include "maru_sdl_rotozoom.h" #include "maru_finger.h" #include "hw/maru_pm.h" +#include "hw/maru_brightness.h" #include "debug_ch.h" -//#include "SDL_opengl.h" +#if defined(CONFIG_LINUX) +#include +#endif +/* #include "SDL_opengl.h" */ #ifdef MANGLE_OPENGL_SYMBOLS #include "gl_mangled.h" @@ -60,6 +64,10 @@ static int current_screen_height; static int sdl_initialized; static int sdl_alteration; +extern int g_shmid; +extern char *g_shared_memory; + +static int sdl_skip_update; #if 0 static int sdl_opengl = 0; //0 : just SDL surface, 1 : using SDL with OpenGL @@ -165,6 +173,7 @@ void qemu_ds_sdl_refresh(DisplayState *ds) pthread_mutex_unlock(&sdl_mutex); vga_hw_invalidate(); + sdl_skip_update = 0; break; } @@ -173,7 +182,21 @@ void qemu_ds_sdl_refresh(DisplayState *ds) } } + /* If the LCD is turned off, + the screen does not update until the LCD is turned on */ + if (sdl_skip_update && brightness_off) { + return; + } + + /* Usually, continuously updated. + When the LCD is turned off, + once updates the screen for a black screen. */ vga_hw_update(); + if (brightness_off) { + sdl_skip_update = 1; + } else { + sdl_skip_update = 0; + } #ifdef TARGET_ARM #ifdef SDL_THREAD @@ -466,7 +489,7 @@ static void qemu_update(void) SDL_BlitSurface((SDL_Surface *)mts->finger_point_surface, NULL, surface_screen, &rect); } } - } //end of draw multi-touch + } /* end of draw multi-touch */ } SDL_UpdateRect(surface_screen, 0, 0, 0, 0); @@ -490,7 +513,8 @@ static void* run_qemu_update(void* arg) } #endif -void maruskin_sdl_init(uint64 swt_handle, int lcd_size_width, int lcd_size_height, bool is_resize) +void maruskin_sdl_init(uint64 swt_handle, + int lcd_size_width, int lcd_size_height, bool is_resize) { gchar SDL_windowhack[32]; SDL_SysWMinfo info; @@ -554,6 +578,18 @@ void maruskin_sdl_quit(void) sdl_alteration = -1; SDL_Quit(); + +#ifdef SDL_THREAD + pthread_cond_destroy(&sdl_cond); +#endif + pthread_mutex_destroy(&sdl_mutex); + +#if defined(CONFIG_LINUX) + if (shmctl(g_shmid, IPC_RMID, 0) == -1) { + ERR("shmctl failed\n"); + perror("maru_sdl.c: "); + } +#endif } @@ -565,7 +601,8 @@ void maruskin_sdl_resize(void) memset(&ev, 0, sizeof(ev)); ev.resize.type = SDL_VIDEORESIZE; - //This function is thread safe, and can be called from other threads safely. + /* This function is thread safe, + and can be called from other threads safely. */ SDL_PushEvent(&ev); } diff --git a/tizen/src/mloop_event.c b/tizen/src/mloop_event.c index 9561408eb6..d4a61eb7b3 100644 --- a/tizen/src/mloop_event.c +++ b/tizen/src/mloop_event.c @@ -43,11 +43,12 @@ #include "mloop_event.h" #include "console.h" #include "emul_state.h" -#include "tizen/src/debug_ch.h" +#include "debug_ch.h" #include "monitor.h" #include "pci.h" #include "sysemu.h" +#include "emulator.h" #include "guest_debug.h" #include "skin/maruskin_server.h" #include "hw/maru_virtio_touchscreen.h" @@ -385,7 +386,7 @@ static void mloop_evhandle_ramdump(struct mloop_evpack* pack) char dump_fullpath[MAX_PATH]; char dump_filename[MAX_PATH]; - char* dump_path = g_path_get_dirname(get_logpath()); + char* dump_path = g_path_get_dirname(get_log_path()); sprintf(dump_filename, "0x%08x%s0x%08x%s", rm->ram_addr, "-", rm->ram_addr + size, "_RAM.dump"); diff --git a/tizen/src/mloop_event.h b/tizen/src/mloop_event.h index cd6c6f594a..ddfbc25ec3 100644 --- a/tizen/src/mloop_event.h +++ b/tizen/src/mloop_event.h @@ -42,6 +42,7 @@ void mloop_evcmd_usbdisk(char *img); void mloop_evcmd_hostkbd(int on); int mloop_evcmd_get_usbkbd_status(void); +int mloop_evcmd_get_hostkbd_status(void); void mloop_evcmd_set_usbkbd(void *dev); void mloop_evcmd_set_usbdisk(void *dev); diff --git a/tizen/src/ns_event.h b/tizen/src/ns_event.h index 7841e91682..54655c9006 100644 --- a/tizen/src/ns_event.h +++ b/tizen/src/ns_event.h @@ -1,21 +1,3 @@ -/* - * 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. - * - */ - #ifndef _NS_EVENT_H_ #define _NS_EVENT_H_ diff --git a/tizen/src/ns_event.m b/tizen/src/ns_event.m index c2f8724fb2..9e71f07481 100644 --- a/tizen/src/ns_event.m +++ b/tizen/src/ns_event.m @@ -1,21 +1,3 @@ -/* - * 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. - * - */ - #import #import "ns_event.h" diff --git a/tizen/src/option.c b/tizen/src/option.c deleted file mode 100644 index 50979e023e..0000000000 --- a/tizen/src/option.c +++ /dev/null @@ -1,641 +0,0 @@ -/* - * Emulator - * - * Copyright (C) 2011, 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: - * SeokYeon Hwang - * MunKyu Im - * GiWoong Kim - * YeongKyoon Lee - * HyunJun Son - * - * 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 - * - */ - -/** - @file option.c - @brief collection of dialog function - */ - -#include "option.h" -#include "emulator.h" -#include "maru_common.h" -#if defined (CONFIG_LINUX) -#include -#include -#include -#include -#include -#include -#include -#elif defined (CONFIG_WIN32) -#include -#include -#include -#include -#elif defined (CONFIG_DARWIN) -#include -CFDictionaryRef proxySettings; -#endif -#include - -#include "debug_ch.h" - -#define HTTP_PROTOCOL "http=" -#define HTTP_PREFIX "http://" -#define HTTPS_PROTOCOL "https=" -#define FTP_PROTOCOL "ftp=" -#define SOCKS_PROTOCOL "socks=" -#define DIRECT "DIRECT" -#define PROXY "PROXY" -#define MAXPORTLEN 6 -MULTI_DEBUG_CHANNEL(tizen, option); -#if defined(CONFIG_WIN32) -BYTE *url; -#endif -const char *pactempfile = ".autoproxy"; - -/** - @brief get host DNS server address - @param dns1: return value (first dns server address) - @param dns2: return value (second dns server address) - @return always 0 - */ -int gethostDNS(char *dns1, char *dns2) -{ -#ifndef _WIN32 - FILE *resolv; - char buf[255]; - memset(buf, 0, sizeof(char)*255); - - resolv = fopen("/etc/resolv.conf", "r"); - if (resolv <= 0) { - ERR( "Can't open \"/etc/resolv.conf.\"\n"); - fclose(resolv); - return 1; - } - - while(fscanf(resolv , "%s", buf) != EOF) { - if(strcmp(buf, "nameserver") == 0) - { - if(fscanf(resolv , "%s", dns1) <= 0) { - // do nothing... - } - break; - } - } - - while(fscanf(resolv , "%s", buf) != EOF) { - if(strcmp(buf, "nameserver") == 0) - { - if(fscanf(resolv , "%s", dns2) <= 0) { - // do nothing... - } - break; - } - } - - fclose(resolv); -#else - PIP_ADAPTER_ADDRESSES pAdapterAddr; - PIP_ADAPTER_ADDRESSES pAddr; - PIP_ADAPTER_DNS_SERVER_ADDRESS pDnsAddr; - unsigned long nBufferLength = sizeof(IP_ADAPTER_ADDRESSES); - pAdapterAddr = (PIP_ADAPTER_ADDRESSES)malloc(nBufferLength); - memset(pAdapterAddr, 0x00, nBufferLength); - - while (GetAdaptersAddresses(AF_INET, 0, NULL, pAdapterAddr, &nBufferLength) - == ERROR_BUFFER_OVERFLOW) { - free(pAdapterAddr); - pAdapterAddr = (PIP_ADAPTER_ADDRESSES)malloc(nBufferLength); - memset(pAdapterAddr, 0x00, nBufferLength); - } - - pAddr = pAdapterAddr; - for (; pAddr != NULL; pAddr = pAddr->Next) { - pDnsAddr = pAddr->FirstDnsServerAddress; - for (; pDnsAddr != NULL; pDnsAddr = pDnsAddr->Next) { - struct sockaddr_in *pSockAddr = (struct sockaddr_in*)pDnsAddr->Address.lpSockaddr; - if(*dns1 == 0) { - strcpy(dns1, inet_ntoa(pSockAddr->sin_addr)); - continue; - } - if(*dns2 == 0) { - strcpy(dns2, inet_ntoa(pSockAddr->sin_addr)); - continue; - } - } - } - free(pAdapterAddr); -#endif - - // by caramis... change DNS address if localhost has DNS server or DNS cache. - if(!strncmp(dns1, "127.0.0.1", 9) || !strncmp(dns1, "localhost", 9)) { - strncpy(dns1, "10.0.2.2", 9); - } - if(!strncmp(dns2, "127.0.0.1", 9) || !strncmp(dns2, "localhost", 9)) { - strncpy(dns2, "10.0.2.2", 9); - } - - return 0; -} - -#if defined (CONFIG_DARWIN) -static char *cfstring_to_cstring(CFStringRef str) { - if (str == NULL) { - return NULL; - } - - CFIndex length = CFStringGetLength(str); - CFIndex maxSize = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8); - char *buffer = (char *)malloc(maxSize); - if (CFStringGetCString(str, buffer, maxSize, kCFStringEncodingUTF8)) - return buffer; - return NULL; -} - -static int cfnumber_to_int(CFNumberRef num) { - if (!num) - return 0; - - int value; - CFNumberGetValue(num, kCFNumberIntType, &value); - return value; -} -#endif - -static size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) -{ - size_t written; - written = fwrite(ptr, size, nmemb, stream); - return written; -} - -static void download_url(char *url) -{ - CURL *curl; - FILE *fp; - CURLcode res; - - curl = curl_easy_init(); - if (curl) { - fp = fopen(pactempfile,"wb"); - curl_easy_setopt(curl, CURLOPT_URL, url); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); - //just in case network does not work. - curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 3000); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); - res = curl_easy_perform(curl); - if(res != 0) { - ERR("Fail to download pac file: %s\n", url); - } - curl_easy_cleanup(curl); - fclose(fp); - } - - return; -} - -#if defined (CONFIG_DARWIN) -static void getmacproxy(char *http_proxy, char *https_proxy, char *ftp_proxy, char *socks_proxy) -{ - char *hostname; - int port; - CFNumberRef isEnable; - CFStringRef proxyHostname; - CFNumberRef proxyPort; - CFDictionaryRef proxySettings; - proxySettings = SCDynamicStoreCopyProxies(NULL); - - isEnable = CFDictionaryGetValue(proxySettings, kSCPropNetProxiesHTTPEnable); - if (cfnumber_to_int(isEnable)) { - // Get proxy hostname - proxyHostname = CFDictionaryGetValue(proxySettings, kSCPropNetProxiesHTTPProxy); - hostname = cfstring_to_cstring(proxyHostname); - // Get proxy port - proxyPort = CFDictionaryGetValue(proxySettings, kSCPropNetProxiesHTTPPort); - port = cfnumber_to_int(proxyPort); - // Save hostname & port - snprintf(http_proxy, MAXLEN, "%s:%d", hostname, port); - - free(hostname); - } else { - INFO("http proxy is null\n"); - } - - isEnable = CFDictionaryGetValue(proxySettings, kSCPropNetProxiesHTTPSEnable); - if (cfnumber_to_int(isEnable)) { - // Get proxy hostname - proxyHostname = CFDictionaryGetValue(proxySettings, kSCPropNetProxiesHTTPSProxy); - hostname = cfstring_to_cstring(proxyHostname); - // Get proxy port - proxyPort = CFDictionaryGetValue(proxySettings, kSCPropNetProxiesHTTPSPort); - port = cfnumber_to_int(proxyPort); - // Save hostname & port - snprintf(https_proxy, MAXLEN, "%s:%d", hostname, port); - - free(hostname); - } else { - INFO("https proxy is null\n"); - } - - isEnable = CFDictionaryGetValue(proxySettings, kSCPropNetProxiesFTPEnable); - if (cfnumber_to_int(isEnable)) { - // Get proxy hostname - proxyHostname = CFDictionaryGetValue(proxySettings, kSCPropNetProxiesFTPProxy); - hostname = cfstring_to_cstring(proxyHostname); - // Get proxy port - proxyPort = CFDictionaryGetValue(proxySettings, kSCPropNetProxiesFTPPort); - port = cfnumber_to_int(proxyPort); - // Save hostname & port - snprintf(ftp_proxy, MAXLEN, "%s:%d", hostname, port); - - free(hostname); - } else { - INFO("ftp proxy is null\n"); - } - - isEnable = CFDictionaryGetValue(proxySettings, kSCPropNetProxiesSOCKSEnable); - if (cfnumber_to_int(isEnable)) { - // Get proxy hostname - proxyHostname = CFDictionaryGetValue(proxySettings, kSCPropNetProxiesSOCKSProxy); - hostname = cfstring_to_cstring(proxyHostname); - // Get proxy port - proxyPort = CFDictionaryGetValue(proxySettings, kSCPropNetProxiesSOCKSPort); - port = cfnumber_to_int(proxyPort); - // Save hostname & port - snprintf(socks_proxy, MAXLEN, "%s:%d", hostname, port); - - free(hostname); - } else { - INFO("socks proxy is null\n"); - } - CFRelease(proxySettings); -} -#endif - -static void remove_string(char *src, char *dst, const char *toremove) -{ - int len = strlen(toremove); - int i, j; - int max_len = strlen(src); - - for(i = len, j = 0; i < max_len; i++) - { - dst[j++] = src[i]; - } - - dst[j] = '\0'; -} - -#if defined (CONFIG_LINUX) -static void getlinuxproxy(char *http_proxy, char *https_proxy, char *ftp_proxy, char *socks_proxy) -{ - char buf[MAXLEN] = {0,}; - char buf_port[MAXPORTLEN] = {0,}; - char buf_proxy[MAXLEN] = {0,}; - char *buf_proxy_bak; - char *proxy; - FILE *output; - int MAXPROXYLEN = MAXLEN + MAXPORTLEN; - - output = popen("gconftool-2 --get /system/http_proxy/host", "r"); - if(fscanf(output, "%s", buf) > 0) { - snprintf(buf_proxy, MAXLEN, "%s", buf); - } - pclose(output); - - output = popen("gconftool-2 --get /system/http_proxy/port", "r"); - if(fscanf(output, "%s", buf_port) <= 0) { - //for abnormal case: if can't find the key of http port, get from environment value. - buf_proxy_bak = getenv("http_proxy"); - INFO("http_proxy from env: %s\n", buf_proxy_bak); - if(buf_proxy_bak != NULL) { - proxy = malloc(MAXLEN); - remove_string(buf_proxy_bak, proxy, HTTP_PREFIX); - strncpy(http_proxy, proxy, strlen(proxy)-1); - INFO("final http_proxy value: %s\n", http_proxy); - free(proxy); - } - else { - INFO("http_proxy is not set on env.\n"); - pclose(output); - return; - } - - } - else { - snprintf(http_proxy, MAXPROXYLEN, "%s:%s", buf_proxy, buf_port); - memset(buf_proxy, 0, MAXLEN); - INFO("http_proxy: %s\n", http_proxy); - } - pclose(output); - - memset(buf, 0, MAXLEN); - - output = popen("gconftool-2 --get /system/proxy/secure_host", "r"); - if(fscanf(output, "%s", buf) > 0) { - snprintf(buf_proxy, MAXLEN, "%s", buf); - } - pclose(output); - - output = popen("gconftool-2 --get /system/proxy/secure_port", "r"); - if(fscanf(output, "%s", buf) > 0) { - snprintf(https_proxy, MAXPROXYLEN, "%s:%s", buf_proxy, buf); - } - pclose(output); - memset(buf, 0, MAXLEN); - memset(buf_proxy, 0, MAXLEN); - INFO("https_proxy : %s\n", https_proxy); - - output = popen("gconftool-2 --get /system/proxy/ftp_host", "r"); - if(fscanf(output, "%s", buf) > 0) { - snprintf(buf_proxy, MAXLEN, "%s", buf); - } - pclose(output); - - output = popen("gconftool-2 --get /system/proxy/ftp_port", "r"); - if(fscanf(output, "%s", buf) > 0) { - snprintf(ftp_proxy, MAXPROXYLEN, "%s:%s", buf_proxy, buf); - } - pclose(output); - memset(buf, 0, MAXLEN); - memset(buf_proxy, 0, MAXLEN); - INFO("ftp_proxy : %s\n", ftp_proxy); - - output = popen("gconftool-2 --get /system/proxy/socks_host", "r"); - if(fscanf(output, "%s", buf) > 0) { - snprintf(buf_proxy, MAXLEN, "%s", buf); - } - pclose(output); - - output = popen("gconftool-2 --get /system/proxy/socks_port", "r"); - if(fscanf(output, "%s", buf) > 0) { - snprintf(socks_proxy, MAXPROXYLEN, "%s:%s", buf_proxy, buf); - } - pclose(output); - INFO("socks_proxy : %s\n", socks_proxy); -} -#endif - -static int getautoproxy(char *http_proxy, char *https_proxy, char *ftp_proxy, char *socks_proxy) -{ - char type[MAXLEN]; - char proxy[MAXLEN]; - char line[MAXLEN]; - FILE *fp_pacfile; - char *p = NULL; -#if defined(CONFIG_LINUX) - FILE *output; - char buf[MAXLEN]; - - output = popen("gconftool-2 --get /system/proxy/autoconfig_url", "r"); - if(fscanf(output, "%s", buf) > 0) { - INFO("pac address: %s\n", buf); - download_url(buf); - } - pclose(output); -#elif defined(CONFIG_WIN32) - INFO("pac address: %s\n", (char*)url); - download_url((char*)url); -#elif defined(CONFIG_DARWIN) - CFStringRef pacURL = (CFStringRef)CFDictionaryGetValue(proxySettings, - kSCPropNetProxiesProxyAutoConfigURLString); - if (pacURL) { - char url[MAXLEN] = {}; - CFStringGetCString(pacURL, url, sizeof url, kCFStringEncodingASCII); - INFO("pac address: %s\n", (char*)url); - download_url(url); - } -#endif - fp_pacfile = fopen(pactempfile, "r"); - if(fp_pacfile != NULL) { - while(fgets(line, MAXLEN, fp_pacfile) != NULL) { - if( (strstr(line, "return") != NULL) && (strstr(line, "if") == NULL)) { - INFO("line found %s", line); - sscanf(line, "%*[^\"]\"%s %s", type, proxy); - } - } - - if(g_str_has_prefix(type, DIRECT)) { - INFO("auto proxy is set to direct mode\n"); - fclose(fp_pacfile); - } - else if(g_str_has_prefix(type, PROXY)) { - INFO("auto proxy is set to proxy mode\n"); - INFO("type: %s, proxy: %s\n", type, proxy); - p = strtok(proxy, "\";"); - if(p != NULL) { - INFO("auto proxy to set: %s\n",p); - strcpy(http_proxy, p); - strcpy(https_proxy, p); - strcpy(ftp_proxy, p); - strcpy(socks_proxy, p); - } - fclose(fp_pacfile); - } - else - { - ERR("pac file is not wrong! It could be the wrong pac address or pac file format\n"); - fclose(fp_pacfile); - } - } - else { - ERR("fail to get pacfile fp\n"); - return -1; - } - - remove(pactempfile); - return 0; -} - - -/** - @brief get host proxy server address - @param proxy: return value (proxy server address) - @return always 0 - */ -int gethostproxy(char *http_proxy, char *https_proxy, char *ftp_proxy, char *socks_proxy) -{ -#if defined(CONFIG_LINUX) - char buf[MAXLEN]; - FILE *output; - - output = popen("gconftool-2 --get /system/proxy/mode", "r"); - if(fscanf(output, "%s", buf) > 0) { - //priority : auto > manual > none - if (strcmp(buf, "auto") == 0) { - INFO("AUTO PROXY MODE\n"); - getautoproxy(http_proxy, https_proxy, ftp_proxy, socks_proxy); - } - else if (strcmp(buf, "manual") == 0) { - INFO("MANUAL PROXY MODE\n"); - getlinuxproxy(http_proxy, https_proxy, ftp_proxy, socks_proxy); - } - else if (strcmp(buf, "none") == 0) { - INFO("DIRECT PROXY MODE\n"); - } - } - pclose(output); - -#elif defined(CONFIG_WIN32) - HKEY hKey; - int nRet; - LONG lRet; - BYTE *proxyenable, *proxyserver; - char *p; - char *real_proxy; - - DWORD dwLength = 0; - nRet = RegOpenKeyEx(HKEY_CURRENT_USER, - "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", - 0, KEY_QUERY_VALUE, &hKey); - if (nRet != ERROR_SUCCESS) { - ERR("Failed to open registry from %s\n", - "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"); - return 0; - } - //check auto proxy key exists - lRet = RegQueryValueEx(hKey, "AutoConfigURL", 0, NULL, NULL, &dwLength); - if (lRet != ERROR_SUCCESS && dwLength == 0) { - ERR("Failed to query value from %s\n", - "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\AutoConfigURL"); - } - else { - //if exists - url = (char*)malloc(dwLength); - if (url == NULL) { - ERR( "Failed to allocate a buffer\n"); - } - else { - memset(url, 0x00, dwLength); - lRet = RegQueryValueEx(hKey, "AutoConfigURL", 0, NULL, url, &dwLength); - if (lRet == ERROR_SUCCESS && dwLength != 0) { - getautoproxy(http_proxy, https_proxy, ftp_proxy, socks_proxy); - RegCloseKey(hKey); - return 0; - } - } - } - //check manual proxy key exists - lRet = RegQueryValueEx(hKey, "ProxyEnable", 0, NULL, NULL, &dwLength); - if (lRet != ERROR_SUCCESS && dwLength == 0) { - ERR(stderr, "Failed to query value from %s\n", - "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\ProxyEnable"); - RegCloseKey(hKey); - return 0; - } - proxyenable = (BYTE*)malloc(dwLength); - if (proxyenable == NULL) { - ERR( "Failed to allocate a buffer\n"); - RegCloseKey(hKey); - return 0; - } - - lRet = RegQueryValueEx(hKey, "ProxyEnable", 0, NULL, proxyenable, &dwLength); - if (lRet != ERROR_SUCCESS) { - free(proxyenable); - ERR("Failed to query value from %s\n", - "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\ProxyEnable"); - RegCloseKey(hKey); - return 0; - } - if (*(char*)proxyenable == 0) { - free(proxyenable); - RegCloseKey(hKey); - return 0; - } - - dwLength = 0; - lRet = RegQueryValueEx(hKey, "ProxyServer", 0, NULL, NULL, &dwLength); - if (lRet != ERROR_SUCCESS && dwLength == 0) { - ERR("Failed to query value from from %s\n", - "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"); - RegCloseKey(hKey); - return 0; - } - - proxyserver = (BYTE*)malloc(dwLength); - if (proxyserver == NULL) { - ERR( "Failed to allocate a buffer\n"); - RegCloseKey(hKey); - return 0; - } - - memset(proxyserver, 0x00, dwLength); - lRet = RegQueryValueEx(hKey, "ProxyServer", 0, NULL, proxyserver, &dwLength); - if (lRet != ERROR_SUCCESS) { - free(proxyserver); - ERR( "Failed to query value from from %s\n", - "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"); - RegCloseKey(hKey); - return 0; - } - - if((char*)proxyserver != NULL) { - INFO("proxy value: %s\n", (char*)proxyserver); - real_proxy = malloc(MAXLEN); - - for(p = strtok((char*)proxyserver, ";"); p; p = strtok(NULL, ";")){ - if(strstr(p, HTTP_PROTOCOL)) { - remove_string(p, real_proxy, HTTP_PROTOCOL); - strcpy(http_proxy, real_proxy); - } - else if(strstr(p, HTTPS_PROTOCOL)) { - remove_string(p, real_proxy, HTTPS_PROTOCOL); - strcpy(https_proxy, real_proxy); - } - else if(strstr(p, FTP_PROTOCOL)) { - remove_string(p, real_proxy, FTP_PROTOCOL); - strcpy(ftp_proxy, real_proxy); - } - else if(strstr(p, SOCKS_PROTOCOL)) { - remove_string(p, real_proxy, SOCKS_PROTOCOL); - strcpy(socks_proxy, real_proxy); - } - else { - INFO("all protocol uses the same proxy server: %s\n", p); - strcpy(http_proxy, p); - strcpy(https_proxy, p); - strcpy(ftp_proxy, p); - strcpy(socks_proxy, p); - } - } - free(real_proxy); - } - else { - INFO("proxy is null\n"); - return 0; - } - RegCloseKey(hKey); -#elif defined (CONFIG_DARWIN) - int ret; - proxySettings = SCDynamicStoreCopyProxies(NULL); - if(proxySettings) { - INFO("AUTO PROXY MODE\n"); - ret = getautoproxy(http_proxy, https_proxy, ftp_proxy, socks_proxy); - if(strlen(http_proxy) == 0 && ret < 0) { - INFO("MANUAL PROXY MODE\n"); - getmacproxy(http_proxy, https_proxy, ftp_proxy, socks_proxy); - } - } -#endif - return 0; -} diff --git a/tizen/src/osutil-darwin.c b/tizen/src/osutil-darwin.c new file mode 100644 index 0000000000..8948496005 --- /dev/null +++ b/tizen/src/osutil-darwin.c @@ -0,0 +1,337 @@ +/* + * Emulator + * + * Copyright (C) 2012, 2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * SeokYeon Hwang + * MunKyu Im + * GiWoong Kim + * YeongKyoon Lee + * HyunJun Son + * + * 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 + * + */ + +/** + @file osutil-darwin.c + @brief Collection of utilities for darwin + */ + +#include "maru_common.h" +#include "osutil.h" +#include "emulator.h" +#include "debug_ch.h" +#include "maru_err_table.h" +#include "sdb.h" + +#ifndef CONFIG_DARWIN +#error +#endif + +#include +#include +#include +#include + +MULTI_DEBUG_CHANNEL(qemu, osutil); + +extern int tizen_base_port; +CFDictionaryRef proxySettings; + +static char *cfstring_to_cstring(CFStringRef str) { + if (str == NULL) { + return NULL; + } + + CFIndex length = CFStringGetLength(str); + CFIndex maxSize = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8); + char *buffer = (char *)malloc(maxSize); + if (CFStringGetCString(str, buffer, maxSize, kCFStringEncodingUTF8)) + return buffer; + return NULL; +} + +static int cfnumber_to_int(CFNumberRef num) { + if (!num) + return 0; + + int value; + CFNumberGetValue(num, kCFNumberIntType, &value); + return value; +} + +void check_vm_lock_os(void) +{ + /* TODO: */ +} + +void make_vm_lock_os(void) +{ + int shmid; + char *shared_memory; + + shmid = shmget((key_t)SHMKEY, MAXLEN, 0666|IPC_CREAT); + if (shmid == -1) { + ERR("shmget failed\n"); + perror("osutil-darwin: "); + return; + } + + shared_memory = shmat(shmid, (char *)0x00, 0); + if (shared_memory == (void *)-1) { + ERR("shmat failed\n"); + perror("osutil-darwin: "); + return; + } + sprintf(shared_memory, "%d", tizen_base_port + 2); + INFO("shared memory key: %d, value: %s\n", SHMKEY, (char *)shared_memory); + + if (shmdt(shared_memory) == -1) { + ERR("shmdt failed\n"); + perror("osutil-darwin: "); + } +} + +void set_bin_path_os(gchar * exec_argv) +{ + gchar *file_name = NULL; + + if (!exec_argv) { + return; + } + + char *data = g_strdup(exec_argv); + if (!data) { + ERR("Fail to strdup for paring a binary directory.\n"); + return; + } + + file_name = g_strrstr(data, "/"); + if (!file_name) { + free(data); + return; + } + + g_strlcpy(bin_path, data, strlen(data) - strlen(file_name) + 1); + + g_strlcat(bin_path, "/", PATH_MAX); + free(data); +} + + +void print_system_info_os(void) +{ + INFO("* Mac\n"); + + /* uname */ + INFO("* Host machine uname :\n"); + char uname_cmd[MAXLEN] = "uname -a >> "; + strcat(uname_cmd, log_path); + if(system(uname_cmd) < 0) { + INFO("system function command '%s' \ + returns error !", uname_cmd); + } + + /* hw information */ + int mib[2]; + size_t len; + char *sys_info; + int sys_num = 0; + + mib[0] = CTL_HW; + mib[1] = HW_MODEL; + sysctl(mib, 2, NULL, &len, NULL, 0); + sys_info = malloc(len * sizeof(char)); + if (sysctl(mib, 2, sys_info, &len, NULL, 0) >= 0) { + INFO("* Machine model : %s\n", sys_info); + } + free(sys_info); + + mib[0] = CTL_HW; + mib[1] = HW_MACHINE; + sysctl(mib, 2, NULL, &len, NULL, 0); + sys_info = malloc(len * sizeof(char)); + if (sysctl(mib, 2, sys_info, &len, NULL, 0) >= 0) { + INFO("* Machine class : %s\n", sys_info); + } + free(sys_info); + + mib[0] = CTL_HW; + mib[1] = HW_NCPU; + len = sizeof(sys_num); + if (sysctl(mib, 2, &sys_num, &len, NULL, 0) >= 0) { + INFO("* Number of processors : %d\n", sys_num); + } + + mib[0] = CTL_HW; + mib[1] = HW_PHYSMEM; + len = sizeof(sys_num); + if (sysctl(mib, 2, &sys_num, &len, NULL, 0) >= 0) { + INFO("* Total memory : %llu bytes\n", sys_num); + } +} + +static int get_auto_proxy(char *http_proxy, char *https_proxy, char *ftp_proxy, char *socks_proxy) +{ + char type[MAXLEN]; + char proxy[MAXLEN]; + char line[MAXLEN]; + FILE *fp_pacfile; + char *p = NULL; + + CFStringRef pacURL = (CFStringRef)CFDictionaryGetValue(proxySettings, + kSCPropNetProxiesProxyAutoConfigURLString); + if (pacURL) { + char url[MAXLEN] = {}; + CFStringGetCString(pacURL, url, sizeof url, kCFStringEncodingASCII); + INFO("pac address: %s\n", (char*)url); + download_url(url); + } + + fp_pacfile = fopen(pac_tempfile, "r"); + if(fp_pacfile != NULL) { + while(fgets(line, MAXLEN, fp_pacfile) != NULL) { + if( (strstr(line, "return") != NULL) && (strstr(line, "if") == NULL)) { + INFO("line found %s", line); + sscanf(line, "%*[^\"]\"%s %s", type, proxy); + } + } + + if(g_str_has_prefix(type, DIRECT)) { + INFO("auto proxy is set to direct mode\n"); + fclose(fp_pacfile); + } + else if(g_str_has_prefix(type, PROXY)) { + INFO("auto proxy is set to proxy mode\n"); + INFO("type: %s, proxy: %s\n", type, proxy); + p = strtok(proxy, "\";"); + if(p != NULL) { + INFO("auto proxy to set: %s\n",p); + strcpy(http_proxy, p); + strcpy(https_proxy, p); + strcpy(ftp_proxy, p); + strcpy(socks_proxy, p); + } + fclose(fp_pacfile); + } + else + { + ERR("pac file is not wrong! It could be the wrong pac address or pac file format\n"); + fclose(fp_pacfile); + } + } + else { + ERR("fail to get pacfile fp\n"); + return -1; + } + + remove(pac_tempfile); + return 0; +} + +static void get_proxy(char *http_proxy, char *https_proxy, char *ftp_proxy, char *socks_proxy) +{ + char *hostname; + int port; + CFNumberRef isEnable; + CFStringRef proxyHostname; + CFNumberRef proxyPort; + CFDictionaryRef proxySettings; + proxySettings = SCDynamicStoreCopyProxies(NULL); + + isEnable = CFDictionaryGetValue(proxySettings, kSCPropNetProxiesHTTPEnable); + if (cfnumber_to_int(isEnable)) { + // Get proxy hostname + proxyHostname = CFDictionaryGetValue(proxySettings, kSCPropNetProxiesHTTPProxy); + hostname = cfstring_to_cstring(proxyHostname); + // Get proxy port + proxyPort = CFDictionaryGetValue(proxySettings, kSCPropNetProxiesHTTPPort); + port = cfnumber_to_int(proxyPort); + // Save hostname & port + snprintf(http_proxy, MAXLEN, "%s:%d", hostname, port); + + free(hostname); + } else { + INFO("http proxy is null\n"); + } + + isEnable = CFDictionaryGetValue(proxySettings, kSCPropNetProxiesHTTPSEnable); + if (cfnumber_to_int(isEnable)) { + // Get proxy hostname + proxyHostname = CFDictionaryGetValue(proxySettings, kSCPropNetProxiesHTTPSProxy); + hostname = cfstring_to_cstring(proxyHostname); + // Get proxy port + proxyPort = CFDictionaryGetValue(proxySettings, kSCPropNetProxiesHTTPSPort); + port = cfnumber_to_int(proxyPort); + // Save hostname & port + snprintf(https_proxy, MAXLEN, "%s:%d", hostname, port); + + free(hostname); + } else { + INFO("https proxy is null\n"); + } + + isEnable = CFDictionaryGetValue(proxySettings, kSCPropNetProxiesFTPEnable); + if (cfnumber_to_int(isEnable)) { + // Get proxy hostname + proxyHostname = CFDictionaryGetValue(proxySettings, kSCPropNetProxiesFTPProxy); + hostname = cfstring_to_cstring(proxyHostname); + // Get proxy port + proxyPort = CFDictionaryGetValue(proxySettings, kSCPropNetProxiesFTPPort); + port = cfnumber_to_int(proxyPort); + // Save hostname & port + snprintf(ftp_proxy, MAXLEN, "%s:%d", hostname, port); + + free(hostname); + } else { + INFO("ftp proxy is null\n"); + } + + isEnable = CFDictionaryGetValue(proxySettings, kSCPropNetProxiesSOCKSEnable); + if (cfnumber_to_int(isEnable)) { + // Get proxy hostname + proxyHostname = CFDictionaryGetValue(proxySettings, kSCPropNetProxiesSOCKSProxy); + hostname = cfstring_to_cstring(proxyHostname); + // Get proxy port + proxyPort = CFDictionaryGetValue(proxySettings, kSCPropNetProxiesSOCKSPort); + port = cfnumber_to_int(proxyPort); + // Save hostname & port + snprintf(socks_proxy, MAXLEN, "%s:%d", hostname, port); + + free(hostname); + } else { + INFO("socks proxy is null\n"); + } + CFRelease(proxySettings); +} + +void get_host_proxy_os(char *http_proxy, char *https_proxy, char *ftp_proxy, char *socks_proxy) +{ + int ret; + proxySettings = SCDynamicStoreCopyProxies(NULL); + if(proxySettings) { + INFO("AUTO PROXY MODE\n"); + ret = get_auto_proxy(http_proxy, https_proxy, ftp_proxy, socks_proxy); + if(strlen(http_proxy) == 0 && ret < 0) { + INFO("MANUAL PROXY MODE\n"); + get_proxy(http_proxy, https_proxy, ftp_proxy, socks_proxy); + } + } +} diff --git a/tizen/src/osutil-linux.c b/tizen/src/osutil-linux.c new file mode 100644 index 0000000000..0de15e5a97 --- /dev/null +++ b/tizen/src/osutil-linux.c @@ -0,0 +1,354 @@ +/* + * Emulator + * + * Copyright (C) 2012, 2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * SeokYeon Hwang + * MunKyu Im + * GiWoong Kim + * YeongKyoon Lee + * HyunJun Son + * + * 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 + * + */ + +/** + @file osutil-linux.c + @brief Collection of utilities for linux + */ + +#include "maru_common.h" +#include "osutil.h" +#include "emulator.h" +#include "debug_ch.h" +#include "maru_err_table.h" +#include "sdb.h" + +#ifndef CONFIG_LINUX +#error +#endif + +#include +#include +#include +#include +#include +#include +#include + +MULTI_DEBUG_CHANNEL(emulator, osutil); + +extern char tizen_target_img_path[]; +extern int tizen_base_port; +int g_shmid; +char *g_shared_memory; + +void check_vm_lock_os(void) +{ + int shm_id; + void *shm_addr; + uint32_t port; + int val; + struct shmid_ds shm_info; + + for (port = 26100; port < 26200; port += 10) { + shm_id = shmget((key_t)port, 0, 0); + if (shm_id != -1) { + shm_addr = shmat(shm_id, (void *)0, 0); + if ((void *)-1 == shm_addr) { + ERR("error occured at shmat()\n"); + break; + } + + val = shmctl(shm_id, IPC_STAT, &shm_info); + if (val != -1) { + INFO("count of process that use shared memory : %d\n", + shm_info.shm_nattch); + if ((shm_info.shm_nattch > 0) && + g_strcmp0(tizen_target_img_path, (char *)shm_addr) == 0) { + if (check_port_bind_listen(port + 1) > 0) { + shmdt(shm_addr); + continue; + } + shmdt(shm_addr); + maru_register_exit_msg(MARU_EXIT_UNKNOWN, + "Can not execute this VM.\n" + "The same name is running now."); + exit(0); + } else { + shmdt(shm_addr); + } + } + } + } +} + +void make_vm_lock_os(void) +{ + + g_shmid = shmget((key_t)tizen_base_port, MAXLEN, 0666|IPC_CREAT); + if (g_shmid == -1) { + ERR("shmget failed\n"); + return; + } + + g_shared_memory = shmat(g_shmid, (char *)0x00, 0); + if (g_shared_memory == (void *)-1) { + ERR("shmat failed\n"); + return; + } + g_sprintf(g_shared_memory, "%s", tizen_target_img_path); + INFO("shared memory key: %d value: %s\n", + tizen_base_port, (char *)g_shared_memory); +} + +void set_bin_path_os(gchar * exec_argv) +{ + gchar link_path[PATH_MAX] = { 0, }; + char *file_name = NULL; + + ssize_t len = readlink("/proc/self/exe", link_path, sizeof(link_path) - 1); + + if (len < 0 || len > sizeof(link_path)) { + perror("set_bin_path error : "); + return; + } + + link_path[len] = '\0'; + + file_name = g_strrstr(link_path, "/"); + g_strlcpy(bin_path, link_path, strlen(link_path) - strlen(file_name) + 1); + + g_strlcat(bin_path, "/", PATH_MAX); +} + +void print_system_info_os(void) +{ + INFO("* Linux\n"); + + /* depends on building */ + INFO("* QEMU build machine linux kernel version : (%d, %d, %d)\n", + LINUX_VERSION_CODE >> 16, + (LINUX_VERSION_CODE >> 8) & 0xff, + LINUX_VERSION_CODE & 0xff); + + /* depends on launching */ + struct utsname host_uname_buf; + if (uname(&host_uname_buf) == 0) { + INFO("* Host machine uname : %s %s %s %s %s\n", + host_uname_buf.sysname, host_uname_buf.nodename, + host_uname_buf.release, host_uname_buf.version, + host_uname_buf.machine); + } + + struct sysinfo sys_info; + if (sysinfo(&sys_info) == 0) { + INFO("* Total Ram : %llu kB, Free: %llu kB\n", + sys_info.totalram * (unsigned long long)sys_info.mem_unit / 1024, + sys_info.freeram * (unsigned long long)sys_info.mem_unit / 1024); + } + + /* get linux distribution information */ + INFO("* Linux distribution infomation :\n"); + char lsb_release_cmd[MAXLEN] = "lsb_release -d -r -c >> "; + strcat(lsb_release_cmd, log_path); + if(system(lsb_release_cmd) < 0) { + INFO("system function command '%s' \ + returns error !", lsb_release_cmd); + } + + /* pci device description */ + INFO("* PCI devices :\n"); + char lspci_cmd[MAXLEN] = "lspci >> "; + strcat(lspci_cmd, log_path); + if(system(lspci_cmd) < 0) { + INFO("system function command '%s' \ + returns error !", lspci_cmd); + } +} + +static int get_auto_proxy(char *http_proxy, char *https_proxy, char *ftp_proxy, char *socks_proxy) +{ + char type[MAXLEN]; + char proxy[MAXLEN]; + char line[MAXLEN]; + FILE *fp_pacfile; + char *p = NULL; + FILE *output; + char buf[MAXLEN]; + + output = popen("gconftool-2 --get /system/proxy/autoconfig_url", "r"); + if(fscanf(output, "%s", buf) > 0) { + INFO("pac address: %s\n", buf); + download_url(buf); + } + pclose(output); + fp_pacfile = fopen(pac_tempfile, "r"); + if(fp_pacfile != NULL) { + while(fgets(line, MAXLEN, fp_pacfile) != NULL) { + if( (strstr(line, "return") != NULL) && (strstr(line, "if") == NULL)) { + INFO("line found %s", line); + sscanf(line, "%*[^\"]\"%s %s", type, proxy); + } + } + + if(g_str_has_prefix(type, DIRECT)) { + INFO("auto proxy is set to direct mode\n"); + fclose(fp_pacfile); + } + else if(g_str_has_prefix(type, PROXY)) { + INFO("auto proxy is set to proxy mode\n"); + INFO("type: %s, proxy: %s\n", type, proxy); + p = strtok(proxy, "\";"); + if(p != NULL) { + INFO("auto proxy to set: %s\n",p); + strcpy(http_proxy, p); + strcpy(https_proxy, p); + strcpy(ftp_proxy, p); + strcpy(socks_proxy, p); + } + fclose(fp_pacfile); + } + else + { + ERR("pac file is not wrong! It could be the wrong pac address or pac file format\n"); + fclose(fp_pacfile); + } + } + else { + ERR("fail to get pacfile fp\n"); + return -1; + } + + remove(pac_tempfile); + return 0; +} + +static void get_proxy(char *http_proxy, char *https_proxy, char *ftp_proxy, char *socks_proxy) +{ + char buf[MAXLEN] = {0,}; + char buf_port[MAXPORTLEN] = {0,}; + char buf_proxy[MAXLEN] = {0,}; + char *buf_proxy_bak; + char *proxy; + FILE *output; + int MAXPROXYLEN = MAXLEN + MAXPORTLEN; + + output = popen("gconftool-2 --get /system/http_proxy/host", "r"); + if(fscanf(output, "%s", buf) > 0) { + snprintf(buf_proxy, MAXLEN, "%s", buf); + } + pclose(output); + + output = popen("gconftool-2 --get /system/http_proxy/port", "r"); + if(fscanf(output, "%s", buf_port) <= 0) { + //for abnormal case: if can't find the key of http port, get from environment value. + buf_proxy_bak = getenv("http_proxy"); + INFO("http_proxy from env: %s\n", buf_proxy_bak); + if(buf_proxy_bak != NULL) { + proxy = malloc(MAXLEN); + remove_string(buf_proxy_bak, proxy, HTTP_PREFIX); + strncpy(http_proxy, proxy, strlen(proxy)-1); + INFO("final http_proxy value: %s\n", http_proxy); + free(proxy); + } + else { + INFO("http_proxy is not set on env.\n"); + pclose(output); + return; + } + + } + else { + snprintf(http_proxy, MAXPROXYLEN, "%s:%s", buf_proxy, buf_port); + memset(buf_proxy, 0, MAXLEN); + INFO("http_proxy: %s\n", http_proxy); + } + pclose(output); + + memset(buf, 0, MAXLEN); + + output = popen("gconftool-2 --get /system/proxy/secure_host", "r"); + if(fscanf(output, "%s", buf) > 0) { + snprintf(buf_proxy, MAXLEN, "%s", buf); + } + pclose(output); + + output = popen("gconftool-2 --get /system/proxy/secure_port", "r"); + if(fscanf(output, "%s", buf) > 0) { + snprintf(https_proxy, MAXPROXYLEN, "%s:%s", buf_proxy, buf); + } + pclose(output); + memset(buf, 0, MAXLEN); + memset(buf_proxy, 0, MAXLEN); + INFO("https_proxy : %s\n", https_proxy); + + output = popen("gconftool-2 --get /system/proxy/ftp_host", "r"); + if(fscanf(output, "%s", buf) > 0) { + snprintf(buf_proxy, MAXLEN, "%s", buf); + } + pclose(output); + + output = popen("gconftool-2 --get /system/proxy/ftp_port", "r"); + if(fscanf(output, "%s", buf) > 0) { + snprintf(ftp_proxy, MAXPROXYLEN, "%s:%s", buf_proxy, buf); + } + pclose(output); + memset(buf, 0, MAXLEN); + memset(buf_proxy, 0, MAXLEN); + INFO("ftp_proxy : %s\n", ftp_proxy); + + output = popen("gconftool-2 --get /system/proxy/socks_host", "r"); + if(fscanf(output, "%s", buf) > 0) { + snprintf(buf_proxy, MAXLEN, "%s", buf); + } + pclose(output); + + output = popen("gconftool-2 --get /system/proxy/socks_port", "r"); + if(fscanf(output, "%s", buf) > 0) { + snprintf(socks_proxy, MAXPROXYLEN, "%s:%s", buf_proxy, buf); + } + pclose(output); + INFO("socks_proxy : %s\n", socks_proxy); +} + + +void get_host_proxy_os(char *http_proxy, char *https_proxy, char *ftp_proxy, char *socks_proxy) +{ + char buf[MAXLEN]; + FILE *output; + + output = popen("gconftool-2 --get /system/proxy/mode", "r"); + if(fscanf(output, "%s", buf) > 0) { + //priority : auto > manual > none + if (strcmp(buf, "auto") == 0) { + INFO("AUTO PROXY MODE\n"); + get_auto_proxy(http_proxy, https_proxy, ftp_proxy, socks_proxy); + } + else if (strcmp(buf, "manual") == 0) { + INFO("MANUAL PROXY MODE\n"); + get_proxy(http_proxy, https_proxy, ftp_proxy, socks_proxy); + } + else if (strcmp(buf, "none") == 0) { + INFO("DIRECT PROXY MODE\n"); + } + } + pclose(output); +} diff --git a/tizen/src/osutil-win32.c b/tizen/src/osutil-win32.c new file mode 100644 index 0000000000..3dbde81adf --- /dev/null +++ b/tizen/src/osutil-win32.c @@ -0,0 +1,358 @@ +/* + * Emulator + * + * Copyright (C) 2012, 2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * SeokYeon Hwang + * MunKyu Im + * GiWoong Kim + * YeongKyoon Lee + * HyunJun Son + * + * 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 + * + */ + +/** + @file osutil-win32.c + @brief Collection of utilities for win32 + */ + +#include "maru_common.h" +#include "osutil.h" +#include "emulator.h" +#include "debug_ch.h" +#include "maru_err_table.h" +#include "sdb.h" + +#ifndef CONFIG_WIN32 +#error +#endif + +#include + +MULTI_DEBUG_CHANNEL (emulator, osutil); + +extern char tizen_target_img_path[]; +extern int tizen_base_port; + +static const char *pactempfile = ".autoproxy"; + +void check_vm_lock_os(void) +{ + uint32_t port; + char *base_port = NULL; + char *pBuf; + HANDLE hMapFile; + for (port = 26100; port < 26200; port += 10) { + base_port = g_strdup_printf("%d", port); + hMapFile = OpenFileMapping(FILE_MAP_READ, TRUE, base_port); + if (hMapFile == NULL) { + INFO("port %s is not used.\n", base_port); + continue; + } else { + pBuf = (char *)MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 50); + if (pBuf == NULL) { + ERR("Could not map view of file (%d).\n", GetLastError()); + CloseHandle(hMapFile); + } + + if (strcmp(pBuf, tizen_target_img_path) == 0) { + maru_register_exit_msg(MARU_EXIT_UNKNOWN, + "Can not execute this VM.\n" + "The same name is running now."); + UnmapViewOfFile(pBuf); + CloseHandle(hMapFile); + free(base_port); + exit(0); + } else { + UnmapViewOfFile(pBuf); + } + } + + CloseHandle(hMapFile); + free(base_port); + } +} + +void make_vm_lock_os(void) +{ + HANDLE hMapFile; + char *pBuf; + char *port_in_use; + char *shared_memory; + + shared_memory = g_strdup_printf("%s", tizen_target_img_path); + port_in_use = g_strdup_printf("%d", tizen_base_port); + hMapFile = CreateFileMapping( + INVALID_HANDLE_VALUE, /* use paging file */ + NULL, /* default security */ + PAGE_READWRITE, /* read/write access */ + 0, /* maximum object size (high-order DWORD) */ + 50, /* maximum object size (low-order DWORD) */ + port_in_use); /* name of mapping object */ + if (hMapFile == NULL) { + ERR("Could not create file mapping object (%d).\n", GetLastError()); + return; + } + pBuf = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 50); + + if (pBuf == NULL) { + ERR("Could not map view of file (%d).\n", GetLastError()); + CloseHandle(hMapFile); + return; + } + + CopyMemory((PVOID)pBuf, shared_memory, strlen(shared_memory)); + free(port_in_use); + free(shared_memory); +} + +void set_bin_path_os(gchar * exec_argv) +{ + gchar link_path[PATH_MAX] = { 0, }; + gchar *file_name = NULL; + + if (!GetModuleFileName(NULL, link_path, PATH_MAX)) { + return; + } + + file_name = g_strrstr(link_path, "\\"); + g_strlcpy(bin_path, link_path, strlen(link_path) - strlen(file_name) + 1); + + g_strlcat(bin_path, "\\", PATH_MAX); +} + +void print_system_info_os(void) +{ + INFO("* Windows\n"); + + /* Retrieves information about the current os */ + OSVERSIONINFO osvi; + ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + + if (GetVersionEx(&osvi)) { + INFO("* MajorVersion : %d, MinorVersion : %d, BuildNumber : %d, " + "PlatformId : %d, CSDVersion : %s\n", osvi.dwMajorVersion, + osvi.dwMinorVersion, osvi.dwBuildNumber, + osvi.dwPlatformId, osvi.szCSDVersion); + } + + /* Retrieves information about the current system */ + SYSTEM_INFO sysi; + ZeroMemory(&sysi, sizeof(SYSTEM_INFO)); + + GetSystemInfo(&sysi); + INFO("* Processor type : %d, Number of processors : %d\n", + sysi.dwProcessorType, sysi.dwNumberOfProcessors); + + MEMORYSTATUSEX memInfo; + memInfo.dwLength = sizeof(MEMORYSTATUSEX); + GlobalMemoryStatusEx(&memInfo); + INFO("* Total Ram : %llu kB, Free: %lld kB\n", + memInfo.ullTotalPhys / 1024, memInfo.ullAvailPhys / 1024); +} + +static int get_auto_proxy(BYTE *url, char *http_proxy, char *https_proxy, char *ftp_proxy, char *socks_proxy) +{ + char type[MAXLEN]; + char proxy[MAXLEN]; + char line[MAXLEN]; + FILE *fp_pacfile; + char *p = NULL; + + INFO("pac address: %s\n", (char*)url); + download_url((char*)url); + + fp_pacfile = fopen(pactempfile, "r"); + if(fp_pacfile != NULL) { + while(fgets(line, MAXLEN, fp_pacfile) != NULL) { + if( (strstr(line, "return") != NULL) && (strstr(line, "if") == NULL)) { + INFO("line found %s", line); + sscanf(line, "%*[^\"]\"%s %s", type, proxy); + } + } + + if(g_str_has_prefix(type, DIRECT)) { + INFO("auto proxy is set to direct mode\n"); + fclose(fp_pacfile); + } + else if(g_str_has_prefix(type, PROXY)) { + INFO("auto proxy is set to proxy mode\n"); + INFO("type: %s, proxy: %s\n", type, proxy); + p = strtok(proxy, "\";"); + if(p != NULL) { + INFO("auto proxy to set: %s\n",p); + strcpy(http_proxy, p); + strcpy(https_proxy, p); + strcpy(ftp_proxy, p); + strcpy(socks_proxy, p); + } + fclose(fp_pacfile); + } + else + { + ERR("pac file is not wrong! It could be the wrong pac address or pac file format\n"); + fclose(fp_pacfile); + } + } + else { + ERR("fail to get pacfile fp\n"); + return -1; + } + + remove(pactempfile); + + return 0; +} + +void get_host_proxy_os(char *http_proxy, char *https_proxy, char *ftp_proxy, char *socks_proxy) +{ + HKEY hKey; + int nRet; + LONG lRet; + BYTE *proxyenable, *proxyserver; + char *p; + char *real_proxy; + BYTE *url; + + DWORD dwLength = 0; + nRet = RegOpenKeyEx(HKEY_CURRENT_USER, + "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", + 0, KEY_QUERY_VALUE, &hKey); + if (nRet != ERROR_SUCCESS) { + ERR("Failed to open registry from %s\n", + "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"); + return 0; + } + //check auto proxy key exists + lRet = RegQueryValueEx(hKey, "AutoConfigURL", 0, NULL, NULL, &dwLength); + if (lRet != ERROR_SUCCESS && dwLength == 0) { + ERR("Failed to query value from %s\n", + "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\AutoConfigURL"); + } + else { + //if exists + url = (char*)malloc(dwLength); + if (url == NULL) { + ERR( "Failed to allocate a buffer\n"); + } + else { + memset(url, 0x00, dwLength); + lRet = RegQueryValueEx(hKey, "AutoConfigURL", 0, NULL, url, &dwLength); + if (lRet == ERROR_SUCCESS && dwLength != 0) { + get_auto_proxy(url, http_proxy, https_proxy, ftp_proxy, socks_proxy); + RegCloseKey(hKey); + return 0; + } + } + } + //check manual proxy key exists + lRet = RegQueryValueEx(hKey, "ProxyEnable", 0, NULL, NULL, &dwLength); + if (lRet != ERROR_SUCCESS && dwLength == 0) { + ERR(stderr, "Failed to query value from %s\n", + "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\ProxyEnable"); + RegCloseKey(hKey); + return 0; + } + proxyenable = (BYTE*)malloc(dwLength); + if (proxyenable == NULL) { + ERR( "Failed to allocate a buffer\n"); + RegCloseKey(hKey); + return 0; + } + + lRet = RegQueryValueEx(hKey, "ProxyEnable", 0, NULL, proxyenable, &dwLength); + if (lRet != ERROR_SUCCESS) { + free(proxyenable); + ERR("Failed to query value from %s\n", + "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\ProxyEnable"); + RegCloseKey(hKey); + return 0; + } + if (*(char*)proxyenable == 0) { + free(proxyenable); + RegCloseKey(hKey); + return 0; + } + + dwLength = 0; + lRet = RegQueryValueEx(hKey, "ProxyServer", 0, NULL, NULL, &dwLength); + if (lRet != ERROR_SUCCESS && dwLength == 0) { + ERR("Failed to query value from from %s\n", + "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"); + RegCloseKey(hKey); + return 0; + } + + proxyserver = (BYTE*)malloc(dwLength); + if (proxyserver == NULL) { + ERR( "Failed to allocate a buffer\n"); + RegCloseKey(hKey); + return 0; + } + + memset(proxyserver, 0x00, dwLength); + lRet = RegQueryValueEx(hKey, "ProxyServer", 0, NULL, proxyserver, &dwLength); + if (lRet != ERROR_SUCCESS) { + free(proxyserver); + ERR( "Failed to query value from from %s\n", + "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"); + RegCloseKey(hKey); + return 0; + } + + if((char*)proxyserver != NULL) { + INFO("proxy value: %s\n", (char*)proxyserver); + real_proxy = malloc(MAXLEN); + + for(p = strtok((char*)proxyserver, ";"); p; p = strtok(NULL, ";")){ + if(strstr(p, HTTP_PROTOCOL)) { + remove_string(p, real_proxy, HTTP_PROTOCOL); + strcpy(http_proxy, real_proxy); + } + else if(strstr(p, HTTPS_PROTOCOL)) { + remove_string(p, real_proxy, HTTPS_PROTOCOL); + strcpy(https_proxy, real_proxy); + } + else if(strstr(p, FTP_PROTOCOL)) { + remove_string(p, real_proxy, FTP_PROTOCOL); + strcpy(ftp_proxy, real_proxy); + } + else if(strstr(p, SOCKS_PROTOCOL)) { + remove_string(p, real_proxy, SOCKS_PROTOCOL); + strcpy(socks_proxy, real_proxy); + } + else { + INFO("all protocol uses the same proxy server: %s\n", p); + strcpy(http_proxy, p); + strcpy(https_proxy, p); + strcpy(ftp_proxy, p); + strcpy(socks_proxy, p); + } + } + free(real_proxy); + } + else { + INFO("proxy is null\n"); + return 0; + } + RegCloseKey(hKey); +} diff --git a/tizen/src/osutil.c b/tizen/src/osutil.c new file mode 100644 index 0000000000..10877c61a7 --- /dev/null +++ b/tizen/src/osutil.c @@ -0,0 +1,91 @@ +/* + * Emulator + * + * Copyright (C) 2012, 2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * SeokYeon Hwang + * MunKyu Im + * GiWoong Kim + * YeongKyoon Lee + * HyunJun Son + * + * 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 + * + */ + +/** + @file osutil.c + @brief Common functions for osutil + */ + +#include "osutil.h" +#include "debug_ch.h" + +#include +#include + +MULTI_DEBUG_CHANNEL(emulator, osutil); + +const char *pac_tempfile = ".autoproxy"; + +inline size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) +{ + size_t written; + written = fwrite(ptr, size, nmemb, stream); + return written; +} + +inline void download_url(char *url) +{ + CURL *curl; + FILE *fp; + CURLcode res; + + curl = curl_easy_init(); + if (curl) { + fp = fopen(pac_tempfile,"wb"); + curl_easy_setopt(curl, CURLOPT_URL, url); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); + //just in case network does not work. + curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 3000); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); + res = curl_easy_perform(curl); + if(res != 0) { + ERR("Fail to download pac file: %s\n", url); + } + curl_easy_cleanup(curl); + fclose(fp); + } + + return; +} + +inline void remove_string(char *src, char *dst, const char *toremove) +{ + int len = strlen(toremove); + int i, j; + int max_len = strlen(src); + + for(i = len, j = 0; i < max_len; i++) + { + dst[j++] = src[i]; + } + + dst[j] = '\0'; +} diff --git a/tizen/src/osutil.h b/tizen/src/osutil.h new file mode 100644 index 0000000000..a0acb9b2c6 --- /dev/null +++ b/tizen/src/osutil.h @@ -0,0 +1,62 @@ +/* + * Emulator + * + * Copyright (C) 2011, 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * SeokYeon Hwang + * MunKyu Im + * GiWoong Kim + * YeongKyoon Lee + * HyunJun Son + * + * 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 + * + */ + +#ifndef __OSUTIL_H__ +#define __OSUTIL_H__ + +#include "maru_common.h" + +#define HTTP_PROTOCOL "http=" +#define HTTP_PREFIX "http://" +#define HTTPS_PROTOCOL "https=" +#define FTP_PROTOCOL "ftp=" +#define SOCKS_PROTOCOL "socks=" +#define DIRECT "DIRECT" +#define PROXY "PROXY" +#define MAXPORTLEN 6 + +extern const char *pac_tempfile; + +void check_vm_lock_os(void); +void make_vm_lock_os(void); + +void set_bin_path_os(gchar *); + +void print_system_info_os(void); + +void get_host_proxy_os(char *, char *, char *, char *); + +inline void download_url(char *); +inline size_t write_data(void *, size_t, size_t, FILE *); +inline void remove_string(char *, char *, const char *); + +#endif // __OS_UTIL_H__ + diff --git a/tizen/src/sdb.c b/tizen/src/sdb.c index fa51d18060..26bbea8fe1 100644 --- a/tizen/src/sdb.c +++ b/tizen/src/sdb.c @@ -11,18 +11,6 @@ */ -#ifdef _WIN32 -#include -#include -#include -#else /* !_WIN32 */ -#include -#include -#include -#include -#include -#endif /* !_WIN32 */ - #include "emulator.h" #include "net/slirp.h" #include "qemu_socket.h" @@ -30,128 +18,14 @@ #include "nbd.h" #include "tizen/src/debug_ch.h" -//DEFAULT_DEBUG_CHANNEL(qemu); MULTI_DEBUG_CHANNEL(qemu, sdb); extern char tizen_target_path[]; - -/* QSOCKET_CALL is used to deal with the fact that EINTR happens pretty - * easily in QEMU since we use SIGALRM to implement periodic timers - */ - -#ifdef _WIN32 -# define QSOCKET_CALL(_ret,_cmd) \ - do { _ret = (_cmd); } while ( _ret < 0 && WSAGetLastError() == WSAEINTR ) -#else -# define QSOCKET_CALL(_ret,_cmd) \ - do { \ - errno = 0; \ - do { _ret = (_cmd); } while ( _ret < 0 && errno == EINTR ); \ - } while (0); -#endif - -#ifdef _WIN32 - -#include - -static int winsock_error; - -#define WINSOCK_ERRORS_LIST \ - EE(WSA_INVALID_HANDLE,EINVAL,"invalid handle") \ -EE(WSA_NOT_ENOUGH_MEMORY,ENOMEM,"not enough memory") \ -EE(WSA_INVALID_PARAMETER,EINVAL,"invalid parameter") \ -EE(WSAEINTR,EINTR,"interrupted function call") \ -EE(WSAEALREADY,EALREADY,"operation already in progress") \ -EE(WSAEBADF,EBADF,"bad file descriptor") \ -EE(WSAEACCES,EACCES,"permission denied") \ -EE(WSAEFAULT,EFAULT,"bad address") \ -EE(WSAEINVAL,EINVAL,"invalid argument") \ -EE(WSAEMFILE,EMFILE,"too many opened files") \ -EE(WSAEWOULDBLOCK,EWOULDBLOCK,"resource temporarily unavailable") \ -EE(WSAEINPROGRESS,EINPROGRESS,"operation now in progress") \ -EE(WSAEALREADY,EAGAIN,"operation already in progress") \ -EE(WSAENOTSOCK,EBADF,"socket operation not on socket") \ -EE(WSAEDESTADDRREQ,EDESTADDRREQ,"destination address required") \ -EE(WSAEMSGSIZE,EMSGSIZE,"message too long") \ -EE(WSAEPROTOTYPE,EPROTOTYPE,"wrong protocol type for socket") \ -EE(WSAENOPROTOOPT,ENOPROTOOPT,"bad protocol option") \ -EE(WSAEADDRINUSE,EADDRINUSE,"address already in use") \ -EE(WSAEADDRNOTAVAIL,EADDRNOTAVAIL,"cannot assign requested address") \ -EE(WSAENETDOWN,ENETDOWN,"network is down") \ -EE(WSAENETUNREACH,ENETUNREACH,"network unreachable") \ -EE(WSAENETRESET,ENETRESET,"network dropped connection on reset") \ -EE(WSAECONNABORTED,ECONNABORTED,"software caused connection abort") \ -EE(WSAECONNRESET,ECONNRESET,"connection reset by peer") \ -EE(WSAENOBUFS,ENOBUFS,"no buffer space available") \ -EE(WSAEISCONN,EISCONN,"socket is already connected") \ -EE(WSAENOTCONN,ENOTCONN,"socket is not connected") \ -EE(WSAESHUTDOWN,ESHUTDOWN,"cannot send after socket shutdown") \ -EE(WSAETOOMANYREFS,ETOOMANYREFS,"too many references") \ -EE(WSAETIMEDOUT,ETIMEDOUT,"connection timed out") \ -EE(WSAECONNREFUSED,ECONNREFUSED,"connection refused") \ -EE(WSAELOOP,ELOOP,"cannot translate name") \ -EE(WSAENAMETOOLONG,ENAMETOOLONG,"name too long") \ -EE(WSAEHOSTDOWN,EHOSTDOWN,"host is down") \ -EE(WSAEHOSTUNREACH,EHOSTUNREACH,"no route to host") \ - -typedef struct { - int winsock; - int unix; - const char* string; -} WinsockError; - -static const WinsockError _winsock_errors[] = { -#define EE(w,u,s) { w, u, s }, - WINSOCK_ERRORS_LIST -#undef EE - { -1, -1, NULL } -}; - -/* this function reads the latest winsock error code and updates - * errno to a matching value. It also returns the new value of - * errno. - */ -static int _fix_errno( void ) -{ - const WinsockError* werr = _winsock_errors; - int unix = EINVAL; /* generic error code */ - - winsock_error = WSAGetLastError(); - - for ( ; werr->string != NULL; werr++ ) { - if (werr->winsock == winsock_error) { - unix = werr->unix; - break; - } - } - errno = unix; - return -1; -} - -#else -static int _fix_errno( void ) -{ - return -1; -} - -#endif - -#define SOCKET_CALL(cmd) \ - int ret; \ -QSOCKET_CALL(ret, (cmd)); \ -if (ret < 0) \ -return _fix_errno(); \ -return ret; \ - -int socket_send(int fd, const void* buf, int buflen) -{ - SOCKET_CALL(send(fd, buf, buflen, 0)) -} +extern int tizen_base_port; #ifdef _WIN32 - static void -socket_close_handler( void* _fd ) +static void socket_close_handler( void* _fd ) { int fd = (int)_fd; int ret; @@ -169,8 +43,7 @@ socket_close_handler( void* _fd ) closesocket( fd ); } - void -socket_close( int fd ) +void socket_close( int fd ) { int old_errno = errno; @@ -185,8 +58,7 @@ socket_close( int fd ) #include - void -socket_close( int fd ) +void socket_close( int fd ) { int old_errno = errno; @@ -341,9 +213,9 @@ int sdb_loopback_client(int port, int type) } void notify_sdb_daemon_start(void) { - + int s; - /* + /* * send a simple message to the SDB host server to tell it we just started. * it should be listening on port 26099. */ @@ -362,12 +234,14 @@ void notify_sdb_daemon_start(void) { /* length is hex host:emulator:port: -> 0x13 = 20 */ sprintf(tmp, "00%2xhost:emulator:%d:%s", 20 + strlen(targetname), tizen_base_port + 1, targetname); INFO("message to send to SDB server: %s\n", tmp); - if (socket_send(s, tmp, MAXPACKETLEN) < 0) { + if (send(s, tmp, MAXPACKETLEN,0) < 0) { ERR( "message sending to SDB server error!\n"); + perror("sdb.c: "); } - if (s >= 0) + if (s >= 0){ socket_close(s); - + } + free(targetname); } diff --git a/tizen/src/sdb.h b/tizen/src/sdb.h index 8c0e719aca..e85a69b591 100644 --- a/tizen/src/sdb.h +++ b/tizen/src/sdb.h @@ -14,98 +14,25 @@ #include -#define SDB_HOST_PORT 26099 - #ifdef _WIN32 -# ifndef EINTR -# define EINTR 10004 -# endif -# ifndef EAGAIN -# define EAGAIN 10035 -# endif -# ifndef EWOULDBLOCK -# define EWOULDBLOCK EAGAIN -# endif -# ifndef EINPROGRESS -# define EINPROGRESS 10036 -# endif -# ifndef EALREADY -# define EALREADY 10037 -# endif -# ifndef EDESTADDRREQ -# define EDESTADDRREQ 10039 -# endif -# ifndef EMSGSIZE -# define EMSGSIZE 10040 -# endif -# ifndef EPROTOTYPE -# define EPROTOTYPE 10041 -# endif -# ifndef ENOPROTOOPT -# define ENOPROTOOPT 10042 -# endif -# ifndef EAFNOSUPPORT -# define EAFNOSUPPORT 10047 -# endif -# ifndef EADDRINUSE -# define EADDRINUSE 10048 -# endif -# ifndef EADDRNOTAVAIL -# define EADDRNOTAVAIL 10049 -# endif -# ifndef ENETDOWN -# define ENETDOWN 10050 -# endif -# ifndef ENETUNREACH -# define ENETUNREACH 10051 -# endif -# ifndef ENETRESET -# define ENETRESET 10052 -# endif -# ifndef ECONNABORTED -# define ECONNABORTED 10053 -# endif -# ifndef ECONNRESET -# define ECONNRESET 10054 -# endif -# ifndef ENOBUFS -# define ENOBUFS 10055 -# endif -# ifndef EISCONN -# define EISCONN 10056 -# endif -# ifndef ENOTCONN -# define ENOTCONN 10057 -# endif -# ifndef ESHUTDOWN -# define ESHUTDOWN 10058 -# endif -# ifndef ETOOMANYREFS -# define ETOOMANYREFS 10059 -# endif -# ifndef ETIMEDOUT -# define ETIMEDOUT 10060 -# endif -# ifndef ECONNREFUSED -# define ECONNREFUSED 10061 -# endif -# ifndef ELOOP -# define ELOOP 10062 -# endif -# ifndef EHOSTDOWN -# define EHOSTDOWN 10064 -# endif -# ifndef EHOSTUNREACH -# define EHOSTUNREACH 10065 -# endif -#endif /* _WIN32 */ +#include +#include +#include +#else /* !_WIN32 */ +#include +#include +#include +#include +#include +#endif /* !_WIN32 */ + + +#define SDB_HOST_PORT 26099 #define SDB_TCP_EMULD_INDEX 3 /* emulator daemon port */ #define SDB_TCP_OPENGL_INDEX 4 /* opengl server port */ #define SDB_UDP_SENSOR_INDEX 3 /* sensor server port */ -extern int tizen_base_port; - void sdb_setup(void); int get_sdb_base_port(void); int inet_strtoip(const char* str, uint32_t *ip); diff --git a/tizen/src/skin/client/build.xml b/tizen/src/skin/client/build.xml index f74021db50..0880e75bc6 100644 --- a/tizen/src/skin/client/build.xml +++ b/tizen/src/skin/client/build.xml @@ -85,14 +85,19 @@ - + - + - + + + + + + diff --git a/tizen/src/skin/client/native_src/share.c b/tizen/src/skin/client/native_src/share.c index a67ea6b2e3..a22fd035c4 100644 --- a/tizen/src/skin/client/native_src/share.c +++ b/tizen/src/skin/client/native_src/share.c @@ -1,7 +1,7 @@ /** + * Transmit the framebuffer from shared memory by JNI * - * - * Copyright ( C ) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: * GiWoong Kim @@ -36,39 +36,29 @@ #include "org_tizen_emulator_skin_EmulatorShmSkin.h" #define MAXLEN 512 -#define SHMKEY 26099 void *shared_memory = (void *)0; int shmid; JNIEXPORT jint JNICALL Java_org_tizen_emulator_skin_EmulatorShmSkin_shmget - (JNIEnv *env, jobject obj, jint vga_ram_size) + (JNIEnv *env, jobject obj, jint shmkey, jint vga_ram_size) { - void *temp; - int keyval; - shmid = shmget((key_t)SHMKEY, (size_t)MAXLEN, 0666 | IPC_CREAT); - if (shmid == -1) { - fprintf(stderr, "share.c: shmget failed\n"); - exit(1); - } - - temp = shmat(shmid, (char*)0x0, 0); - if (temp == (void *)-1) { - fprintf(stderr, "share.c: shmat failed\n"); - exit(1); - } - keyval = atoi(temp); - shmdt(temp); + fprintf(stdout, "share.c: shared memory key = %d\n", shmkey); + fflush(stdout); - shmid = shmget((key_t)keyval, (size_t)vga_ram_size, 0666 | IPC_CREAT); + shmid = shmget((key_t)shmkey, (size_t)vga_ram_size, 0666 | IPC_CREAT); if (shmid == -1) { + fprintf(stderr, "share.c: shmget failed\n"); + fflush(stderr); return 1; } - /* We now make the shared memory accessible to the program. */ + /* We now make the shared memory accessible to the program */ shared_memory = shmat(shmid, (void *)0, 0); if (shared_memory == (void *)-1) { + fprintf(stderr, "share.c: shmat failed\n"); + fflush(stderr); return 2; } @@ -76,29 +66,42 @@ JNIEXPORT jint JNICALL Java_org_tizen_emulator_skin_EmulatorShmSkin_shmget } JNIEXPORT jint JNICALL Java_org_tizen_emulator_skin_EmulatorShmSkin_shmdt - (JNIEnv *env, jobject obj) + (JNIEnv *env, jobject obj) { /* Lastly, the shared memory is detached */ if (shmdt(shared_memory) == -1) { + fprintf(stderr, "share.c: shmdt failed\n"); + fflush(stderr); + perror("share.c: "); return 1; } + /* + if (shmctl(shmid, IPC_RMID, 0) == -1) { + fprintf(stderr, "share.c: shmctl failed\n"); + fflush(stderr); + perror("share.c: "); + } + */ + return 0; } JNIEXPORT jint JNICALL Java_org_tizen_emulator_skin_EmulatorShmSkin_getPixels - (JNIEnv *env, jobject obj, jintArray array) + (JNIEnv *env, jobject obj, jintArray array) { int i = 0; int len = (*env)->GetArrayLength(env, array); if (len <= 0) { + fprintf(stderr, "share.c: get length failed\n"); + fflush(stderr); return -1; } int *framebuffer = (int *)shared_memory; jint value = 0xFFFFFFFF; - for(i = 0; i < len; i++) { + for (i = 0; i < len; i++) { value = framebuffer[i]; (*env)->SetIntArrayRegion(env, array, i, 1, &value); } diff --git a/tizen/src/skin/client/resource/images/key-window/scroll_back.png b/tizen/src/skin/client/resource/images/key-window/scroll_back.png new file mode 100644 index 0000000000000000000000000000000000000000..5f8c37780578a37b8b7f2744cb0461a833649826 GIT binary patch literal 2791 zcmVKLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} t0000INklKLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z0004*<0}Sjo+geD3eUhL) zfflJmbYx_T=`2L=&CT6L!_3ak{@`@qIluD{V+?=?JOM9&`66EKjAx9&0$R0N?Kz4f z`u#pa2(;F`SG8It&vQ1L4M~!ql=@}?KgQ$n_jbF@@p$BVy>joOlx0~o8Vy>l7Kg)u z>2&&20K;Cd$9lcydcE?MZnqoT?Uun{05B9lQ%cGCeE#J0x1^LvDFK=l0HqXCN|aKB zVTkLxD5X$J;kqti7=B;?DgZ@MptZ*LeS#n$j$=H}!}C1iI3@@JeBVcFO;Hp82mq}$ zd7hJH8A*~5MG=$91OUfzNRoss%XqM5;=>VOu~<+P1*6djfZ1%uYPBlo{NQMeL2F$u zCr#6`&~mx_aFz!nfHxsTvtF-rxm-#pP18?XbsPsF1i)JbnD2Hwy4^0eZI|xv!x)2Y z+jKe|_WM1+ZwqJ%A)bfBA)e=v=lMThP6)y2bYecAljnK&(X$Wy0$%^~KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z0004)Nklv$Mk{cz6VAR+)h@CDcd@)z%Kj4vY8fJfW5 zUq+)5?RFd2b$L&h%Z2TBOPZ!=tv}enr}23FvD@vUlp@b_ilX?#B0{Ux!gXDCyWI~9 zcn*SqEXyd00;SZuE{cLI%Lsx1;Q0Y)0OWbj|HyG1fQAL2l%gz4%CaPmV?58RYR~hC zKLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z0004mNklYwOWlZ3~?L>5h+YG#t;MnB0`#`FAngd(P#vo=b@BB zL<*slLMeqYhW&p3SpyZ%^UzxJKjL{FKt%yKj*}yfW1=X^?I?2hP$~7=YPG1>>jXhic)!!> z#AdT$wOVnz-Rj(*{2BNPr2lyG^v-#<*79=z?-zz%C%;Ps00000NkvXXu0mjfX+Pq| literal 0 HcmV?d00001 diff --git a/tizen/src/skin/client/resource/images/key-window/scroll_button_up_hover.png b/tizen/src/skin/client/resource/images/key-window/scroll_button_up_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..a362b4e7f1c1e6165df703886e24d6c4534e04a7 GIT binary patch literal 3184 zcmV-$43G1PP)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z0004-Nkl{-mWXU#?_1z-TbfiFP4sjsKUP)eZzwPLY&8IQ-b z+iipp#Bt243WWkvN)Cqu^ZA@8ihgN;Gnq_2>-9R<>y;n~cutW?(=^KEGPPQb^ZCqd zHv1!hQLEKrzuyxC0q^v9JUAYYbUGb?kpQY;7;?YgbEIy!3&3u-%X(oL5{4l_RRBa$ zlr{k9^?D44LjdA9X1m>HXHgUZAOMmi$pY#3`&gER@B08)mPL{zY&IKGFTh87tCSMc zG_h?P-}iAG2gh;neIMJlF-;RGWd_I*UDsu`TCrZQxm+#)Os7)@g8{DV=7<77DMcK| zD5Y2~m$@`O&%^V)>|4?R1@I$;sFq5l>|O6vsZKLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z0004C25-Cc^<$^9cTh%S#}p~Fc<)^Ua#-o8;u4)vkst?BG2=xIUEj| zPNx89ty!&BRZl4eKpmhgOSIMij7B4ZAV3HKKoA6!Wyx~6cR)=QFPB^7i&dk|bO%7q;6id7d+$&oRc}I1anr z?r&7Bbv0==o82uVj$`6DuIk&D>cCkk)ilOb`9G6oS-0h!E#TMTaKLdKj4^1fANm&a zcsv5kYQVE)S?~RRpH{1dZQES$w^FTELu<|HbYipFP?qJ_8{`8&fsg+j`Nx&KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z0004qNklD7|3dlFfhBp6S&pf zL3awR0hJavVo;3vdNC>^q-P$yP1UP2tp#hXqD5W0BUav{P)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z0002ENklIVvKiYzM9!D1GtFDK}67X9aI%&wh18|tEvjz_x*kt z2Dm$3xjV*j1T*hxnx^%9&XJj|2_K3v;v)dCfCVhzJ3*2ppb)}?=-m+!nE63@p8sW8 zhB+c46h(ouEUyfpsq1)5cW&*Lzdi00000NkvXXu0mjf DHZp-< literal 0 HcmV?d00001 diff --git a/tizen/src/skin/client/skins/emul-320x480/default.dbi b/tizen/src/skin/client/skins/emul-320x480/default.dbi index 112e2a7971..418f443691 100644 --- a/tizen/src/skin/client/skins/emul-320x480/default.dbi +++ b/tizen/src/skin/client/skins/emul-320x480/default.dbi @@ -14,16 +14,16 @@ - 101 - HOME + 139 + Home Home - 103 - POWER + 116 + Power Power @@ -31,7 +31,7 @@ 115 - VOLUME_UP + Volume + Volume + @@ -39,7 +39,7 @@ 114 - VOLUME_DOWN + Volume - Volume - @@ -57,16 +57,16 @@ - 101 - HOME + 139 + Home Home - 103 - POWER + 116 + Power Power @@ -74,7 +74,7 @@ 115 - VOLUME_UP + Volume + Volume + @@ -82,7 +82,7 @@ 114 - VOLUME_DOWN + Volume - Volume - @@ -100,16 +100,16 @@ - 101 - HOME + 139 + Home Home - 103 - POWER + 116 + Power Power @@ -117,7 +117,7 @@ 115 - VOLUME_UP + Volume + Volume + @@ -125,7 +125,7 @@ 114 - VOLUME_DOWN + Volume - Volume - @@ -143,16 +143,16 @@ - 101 - HOME + 139 + Home Home - 103 - POWER + 116 + Power Power @@ -160,7 +160,7 @@ 115 - VOLUME_UP + Volume + Volume + @@ -168,7 +168,7 @@ 114 - VOLUME_DOWN + Volume - Volume - diff --git a/tizen/src/skin/client/skins/emul-480x800/default.dbi b/tizen/src/skin/client/skins/emul-480x800/default.dbi index 6658fd0bfc..34bd212222 100644 --- a/tizen/src/skin/client/skins/emul-480x800/default.dbi +++ b/tizen/src/skin/client/skins/emul-480x800/default.dbi @@ -14,16 +14,16 @@ - 101 - HOME + 139 + Home Home - 103 - POWER + 116 + Power Power @@ -31,7 +31,7 @@ 115 - VOLUME_UP + Volume + Volume + @@ -39,7 +39,7 @@ 114 - VOLUME_DOWN + Volume - Volume - @@ -57,16 +57,16 @@ - 101 - HOME + 139 + Home Home - 103 - POWER + 116 + Power Power @@ -74,7 +74,7 @@ 115 - VOLUME_UP + Volume + Volume + @@ -82,7 +82,7 @@ 114 - VOLUME_DOWN + Volume - Volume - @@ -100,16 +100,16 @@ - 101 - HOME + 139 + Home Home - 103 - POWER + 116 + Power Power @@ -117,7 +117,7 @@ 115 - VOLUME_UP + Volume + Volume + @@ -125,7 +125,7 @@ 114 - VOLUME_DOWN + Volume - Volume - @@ -143,16 +143,16 @@ - 101 - HOME + 139 + Home Home - 103 - POWER + 116 + Power Power @@ -160,7 +160,7 @@ 115 - VOLUME_UP + Volume + Volume + @@ -168,7 +168,7 @@ 114 - VOLUME_DOWN + Volume - Volume - diff --git a/tizen/src/skin/client/skins/emul-600x1024/default.dbi b/tizen/src/skin/client/skins/emul-600x1024/default.dbi index 16947ce099..c2b2b0dd09 100644 --- a/tizen/src/skin/client/skins/emul-600x1024/default.dbi +++ b/tizen/src/skin/client/skins/emul-600x1024/default.dbi @@ -14,16 +14,16 @@ - 101 - HOME + 139 + Home Home - 103 - POWER + 116 + Power Power @@ -31,7 +31,7 @@ 115 - VOLUME_UP + Volume + Volume + @@ -39,7 +39,7 @@ 114 - VOLUME_DOWN + Volume - Volume - @@ -57,16 +57,16 @@ - 101 - HOME + 139 + Home Home - 103 - POWER + 116 + Power Power @@ -74,7 +74,7 @@ 115 - VOLUME_UP + Volume + Volume + @@ -82,7 +82,7 @@ 114 - VOLUME_DOWN + Volume - Volume - @@ -100,16 +100,16 @@ - 101 - HOME + 139 + Home Home - 103 - POWER + 116 + Power Power @@ -117,7 +117,7 @@ 115 - VOLUME_UP + Volume + Volume + @@ -125,7 +125,7 @@ 114 - VOLUME_DOWN + Volume - Volume - @@ -143,16 +143,16 @@ - 101 - HOME + 139 + Home Home - 103 - POWER + 116 + Power Power @@ -160,7 +160,7 @@ 115 - VOLUME_UP + Volume + Volume + @@ -168,7 +168,7 @@ 114 - VOLUME_DOWN + Volume - Volume - diff --git a/tizen/src/skin/client/skins/emul-720x1280/default.dbi b/tizen/src/skin/client/skins/emul-720x1280/default.dbi index c54e83d619..aa0c011a5c 100644 --- a/tizen/src/skin/client/skins/emul-720x1280/default.dbi +++ b/tizen/src/skin/client/skins/emul-720x1280/default.dbi @@ -14,16 +14,16 @@ - 101 - HOME + 139 + Home Home - 103 - POWER + 116 + Power Power @@ -31,7 +31,7 @@ 115 - VOLUME_UP + Volume + Volume + @@ -39,7 +39,7 @@ 114 - VOLUME_DOWN + Volume - Volume - @@ -57,16 +57,16 @@ - 101 - HOME + 139 + Home Home - 103 - POWER + 116 + Power Power @@ -74,7 +74,7 @@ 115 - VOLUME_UP + Volume + Volume + @@ -82,7 +82,7 @@ 114 - VOLUME_DOWN + Volume - Volume - @@ -100,16 +100,16 @@ - 101 - HOME + 139 + Home Home - 103 - POWER + 116 + Power Power @@ -117,7 +117,7 @@ 115 - VOLUME_UP + Volume + Volume + @@ -125,7 +125,7 @@ 114 - VOLUME_DOWN + Volume - Volume - @@ -143,16 +143,16 @@ - 101 - HOME + 139 + Home Home - 103 - POWER + 116 + Power Power @@ -160,7 +160,7 @@ 115 - VOLUME_UP + Volume + Volume + @@ -168,7 +168,7 @@ 114 - VOLUME_DOWN + Volume - Volume - diff --git a/tizen/src/skin/client/skins/emul-general/default.dbi b/tizen/src/skin/client/skins/emul-general/default.dbi index 0b98aecc66..82cee6484f 100644 --- a/tizen/src/skin/client/skins/emul-general/default.dbi +++ b/tizen/src/skin/client/skins/emul-general/default.dbi @@ -8,14 +8,14 @@ - 101 + 139 Home Home - 103 + 116 Power Power diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorFingers.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorFingers.java index b7ebb4106c..ccc6c90837 100644 --- a/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorFingers.java +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorFingers.java @@ -53,7 +53,10 @@ public class EmulatorFingers { private static final int GREEN_MASK = 0x00FF0000; private static final int BLUE_MASK = 0xFF000000; private static final int COLOR_DEPTH = 32; - private Logger logger = SkinLogger.getSkinLogger( EmulatorFingers.class ).getLogger(); + + private Logger logger = + SkinLogger.getSkinLogger(EmulatorFingers.class).getLogger(); + private int multiTouchEnable; private int maxTouchPoint; protected int fingerCnt; @@ -69,18 +72,18 @@ public class EmulatorFingers { protected SocketCommunicator communicator; protected EmulatorSkin emulatorSkin; ArrayList FingerPointList; - + EmulatorSkinState currentState; - + EmulatorFingers(EmulatorSkinState currentState) { this.currentState = currentState; initMultiTouchState(); } - - protected void setCommunicator(SocketCommunicator communicator) { + + protected void setCommunicator(SocketCommunicator communicator) { this.communicator = communicator; } - + //private fingerPointSurface; protected class FingerPoint { int id; @@ -88,14 +91,14 @@ public class EmulatorFingers { int originY; int x; int y; - + FingerPoint(int originX, int originY, int x, int y) { this.originX = originX; this.originY = -originY; this.x = x; this.y = y; } - + FingerPoint(int id, int originX, int originY, int x, int y) { this.id = id; this.originX = originX; @@ -104,24 +107,26 @@ public class EmulatorFingers { this.y = y; } } - + public FingerPoint getFingerPointFromSlot(int index) { - if(index < 0 || index > this.fingerCntMax) { + if (index < 0 || index > this.fingerCntMax) { return null; } + return FingerPointList.get(index); } - + public FingerPoint getFingerPointSearch(int x, int y) { int i; FingerPoint fingerPoint = null; - int fingerRegion = (this.fingerPointSize ) + 2; + int fingerRegion = (this.fingerPointSize) + 2; //logger.info("x: "+x+ "y: "+ y + " fingerRegion: " + fingerRegion); - for(i = this.fingerCnt -1; i >= 0; i--) { + + for (i = this.fingerCnt - 1; i >= 0; i--) { fingerPoint = getFingerPointFromSlot(i); - - if(fingerPoint != null) { - if(x >= (fingerPoint.x - fingerRegion) && + + if (fingerPoint != null) { + if (x >= (fingerPoint.x - fingerRegion) && x < (fingerPoint.x + fingerRegion) && y >= (fingerPoint.y - fingerRegion) && y < (fingerPoint.y + fingerRegion)) { @@ -130,372 +135,408 @@ public class EmulatorFingers { } } } + return null; } - + protected void setEmulatorSkin(EmulatorSkin emulatorSkin) { this.emulatorSkin = emulatorSkin; } - + public void initMultiTouchState() { this.multiTouchEnable = 0; this.fingerCntMax = this.currentState.getMaxTouchPoint(); - if(this.fingerCntMax > MAX_FINGER_CNT) { + + if (this.fingerCntMax > MAX_FINGER_CNT) { this.fingerCntMax = MAX_FINGER_CNT; setMaxTouchPoint(this.fingerCntMax); } + logger.info("maxTouchPoint="+ this.fingerCntMax); this.fingerCnt = 0; - + if (this.fingerSlot != null) { this.fingerSlot = null; } - + FingerPointList = new ArrayList(); int i; - for(i = 0; i <= fingerCntMax; i++) { + for (i = 0; i <= fingerCntMax; i++) { FingerPointList.add(new FingerPoint(-1, -1, -1, -1)); } this.fingerPointSize = 32; - this.fingerPointSizeHalf = this.fingerPointSize / 2 ; - + this.fingerPointSizeHalf = this.fingerPointSize / 2; + this.fingerPointOutlineColor = new Color(Display.getCurrent(), 0xDD, 0xDD, 0xDD); this.fingerPointColor = new Color(Display.getCurrent(), 0x0F, 0x0F, 0x0F); PaletteData palette = new PaletteData(RED_MASK, GREEN_MASK, BLUE_MASK); - - this.imageData = new ImageData(fingerPointSize + 4, fingerPointSize + 4, COLOR_DEPTH, palette); + + this.imageData = new ImageData( + fingerPointSize + 4, fingerPointSize + 4, COLOR_DEPTH, palette); this.imageData.transparentPixel = 0; this.fingerSlotimage = new Image(Display.getCurrent(), imageData); GC gc = new GC(this.fingerSlotimage); - + gc.setForeground(this.fingerPointOutlineColor); - gc.drawOval(0, 0, this.fingerPointSize+2 , this.fingerPointSize+2); - + gc.drawOval(0, 0, this.fingerPointSize + 2, this.fingerPointSize + 2); + gc.setBackground(this.fingerPointColor); - gc.fillOval(2, 2 , this.fingerPointSize, this.fingerPointSize); - + gc.fillOval(2, 2, this.fingerPointSize, this.fingerPointSize); + gc.dispose(); } - + public void setMultiTouchEnable(int multiTouchEnable) { this.multiTouchEnable = multiTouchEnable; } - + public int getMultiTouchEnable() { return this.multiTouchEnable; } - + protected int addFingerPoint(int originX, int originY, int x, int y) { if (this.fingerCnt == this.fingerCntMax) { - logger.info("support multi-touch up to " + this.fingerCntMax +" fingers"); + logger.info("support multi-touch up to " + + this.fingerCntMax + " fingers"); return -1; } this.fingerCnt += 1; - + FingerPointList.get(fingerCnt -1).id = this.fingerCnt; FingerPointList.get(fingerCnt -1).originX = originX; FingerPointList.get(fingerCnt -1).originY = originY; FingerPointList.get(fingerCnt -1).x = x; FingerPointList.get(fingerCnt -1).y = y; logger.info(this.fingerCnt + " finger touching"); - + return this.fingerCnt; - } - + protected void drawImage(PaintEvent e, int currentAngle) { //by mq - for(int i=0; i < this.fingerCnt; i++) { + for (int i = 0; i < this.fingerCnt; i++) { this.fingerSlot = this.getFingerPointFromSlot(i); e.gc.setAlpha(0x7E); // logger.info("OriginX: "+ this.fingerSlot.originX + ",OriginY: " + (this.fingerSlot.originY)); // logger.info("x: "+ this.fingerSlot.x + ",y: " + (this.fingerSlot.y)); - + e.gc.drawImage(this.fingerSlotimage, this.fingerSlot.originX - fingerPointSizeHalf - 2, this.fingerSlot.originY - fingerPointSizeHalf - 2); e.gc.setAlpha(0xFF); } } - - public void maruFingerProcessing1(int touchType, int originX, int originY, int x, int y) { + + public void maruFingerProcessing1( + int touchType, int originX, int originY, int x, int y) { FingerPoint finger = null; MouseEventData mouseEventData; - if (touchType == MouseEventType.PRESS.value() || touchType == MouseEventType.DRAG.value()) { /* pressed */ - if (grabFingerID > 0) { - finger = getFingerPointFromSlot(grabFingerID - 1); - if (finger != null) { - finger.originX = originX; - finger.originY = originY; - finger.x = x; - finger.y = y; - if (finger.id != 0) { - logger.info(String.format("id %d finger multi-touch dragging = (%d, %d)", this.grabFingerID, x, y)); - mouseEventData = new MouseEventData( + + if (touchType == MouseEventType.PRESS.value() || + touchType == MouseEventType.DRAG.value()) { /* pressed */ + if (grabFingerID > 0) { + finger = getFingerPointFromSlot(grabFingerID - 1); + if (finger != null) { + finger.originX = originX; + finger.originY = originY; + finger.x = x; + finger.y = y; + + if (finger.id != 0) { + logger.info(String.format( + "id %d finger multi-touch dragging = (%d, %d)", + this.grabFingerID, x, y)); + + mouseEventData = new MouseEventData( MouseButtonType.LEFT.value(), MouseEventType.PRESS.value(), - originX, originY, x, y, grabFingerID -1); - communicator.sendToQEMU( SendCommand.SEND_MOUSE_EVENT, mouseEventData ); - } - } - return; - } - - if(this.fingerCnt == 0) { - //first finger touch input - if(addFingerPoint(originX, originY, x, y) == -1) { - return; - } - + originX, originY, x, y, grabFingerID - 1); + communicator.sendToQEMU(SendCommand.SEND_MOUSE_EVENT, mouseEventData); + } + } + + return; + } + + if (this.fingerCnt == 0) + { /* first finger touch input */ + if (addFingerPoint(originX, originY, x, y) == -1) { + return; + } + mouseEventData = new MouseEventData( MouseButtonType.LEFT.value(), MouseEventType.PRESS.value(), originX, originY, x, y, 0); - communicator.sendToQEMU( SendCommand.SEND_MOUSE_EVENT, mouseEventData ); - } - //check the position of previous touch event - else if ((finger = getFingerPointSearch(x, y)) != null) { - //finger point is selected - this.grabFingerID = finger.id; - logger.info(String.format("id %d finger is grabbed\n", this.grabFingerID)); - } - //Let's assume that this event is last finger touch input - else if (this.fingerCnt == this.fingerCntMax) { - finger = getFingerPointFromSlot(this.fingerCntMax -1); - if(finger != null) { + communicator.sendToQEMU(SendCommand.SEND_MOUSE_EVENT, mouseEventData); + } + else if ((finger = getFingerPointSearch(x, y)) != null) + { /* check the position of previous touch event */ + /* finger point is selected */ + this.grabFingerID = finger.id; + logger.info(String.format("id %d finger is grabbed\n", this.grabFingerID)); + } + else if (this.fingerCnt == this.fingerCntMax) + { /* Let's assume that this event is last finger touch input */ + finger = getFingerPointFromSlot(this.fingerCntMax - 1); + if (finger != null) { mouseEventData = new MouseEventData( MouseButtonType.LEFT.value(), MouseEventType.RELEASE.value(), - originX, originY, finger.x, finger.y, this.fingerCntMax -1); - communicator.sendToQEMU( SendCommand.SEND_MOUSE_EVENT, mouseEventData ); - + originX, originY, finger.x, finger.y, this.fingerCntMax - 1); + communicator.sendToQEMU(SendCommand.SEND_MOUSE_EVENT, mouseEventData); + finger.originX = originX; finger.originY = originY; finger.x = x; finger.y = y; - if(finger.id != 0) { + + if (finger.id != 0) { mouseEventData = new MouseEventData( MouseButtonType.LEFT.value(), MouseEventType.PRESS.value(), - originX, originY, x, y, this.fingerCntMax -1); - communicator.sendToQEMU( SendCommand.SEND_MOUSE_EVENT, mouseEventData ); - + originX, originY, x, y, this.fingerCntMax - 1); + communicator.sendToQEMU(SendCommand.SEND_MOUSE_EVENT, mouseEventData); } - } - } - else { //one more finger - addFingerPoint(originX, originY, x, y); - mouseEventData = new MouseEventData( + } + } + else + { /* one more finger */ + addFingerPoint(originX, originY, x, y); + mouseEventData = new MouseEventData( MouseButtonType.LEFT.value(), MouseEventType.PRESS.value(), - originX, originY, x, y, this.fingerCnt -1); - communicator.sendToQEMU( SendCommand.SEND_MOUSE_EVENT, mouseEventData ); - - } - } - else if (touchType == MouseEventType.RELEASE.value()) { /* released */ + originX, originY, x, y, this.fingerCnt - 1); + communicator.sendToQEMU(SendCommand.SEND_MOUSE_EVENT, mouseEventData); + } + } else if (touchType == MouseEventType.RELEASE.value()) { /* released */ logger.info("mouse up for multi touch"); this.grabFingerID = 0; } - } - - public void maruFingerProcessing2(int touchType, int originX, int originY, int x, int y) { + + public void maruFingerProcessing2( + int touchType, int originX, int originY, int x, int y) { FingerPoint finger = null; MouseEventData mouseEventData; - if (touchType == MouseEventType.PRESS.value() || touchType == MouseEventType.DRAG.value()) { /* pressed */ - if(this.grabFingerID > 0) { + + if (touchType == MouseEventType.PRESS.value() || + touchType == MouseEventType.DRAG.value()) { /* pressed */ + if (this.grabFingerID > 0) { finger = getFingerPointFromSlot(grabFingerID - 1); - if(finger != null) { + if (finger != null) { int originDistanceX = originX - finger.originX; int originDistanceY = originY - finger.originY; int distanceX = x - finger.x; int distanceY = y - finger.y; - + int currrntScreenW = currentState.getCurrentResolutionWidth(); int currrntScreenH = currentState.getCurrentResolutionHeight(); int tempFingerX, tempFingerY; - + int i; /* bounds checking */ - for(i = 0; i < this.fingerCnt; i++) { - finger = getFingerPointFromSlot(i); - if (finger != null) { - tempFingerX = finger.x + distanceX; - tempFingerY = finger.y + distanceY; - if (tempFingerX > currrntScreenW || tempFingerX < 0 - || tempFingerY > currrntScreenH || tempFingerY < 0) { - logger.info(String.format("id %d finger is out of bounds (%d, %d)\n", i + 1, tempFingerX, tempFingerY)); - return; - } - } - } - - for(i = 0; i < this.fingerCnt; i++) { - finger = getFingerPointFromSlot(i); - - if (finger != null) { - finger.originX += originDistanceX; - finger.originY += originDistanceY; - finger.x += distanceX; - finger.y += distanceY; - if (finger.id != 0) { - mouseEventData = new MouseEventData( - MouseButtonType.LEFT.value(), MouseEventType.PRESS.value(), - originX, originY, finger.x, finger.y, i); - communicator.sendToQEMU( SendCommand.SEND_MOUSE_EVENT, mouseEventData ); - //logger.info(String.format("id %d finger multi-touch dragging = (%d, %d)", i + 1, finger.x, finger.y)); - } - try { + for (i = 0; i < this.fingerCnt; i++) { + finger = getFingerPointFromSlot(i); + if (finger != null) { + tempFingerX = finger.x + distanceX; + tempFingerY = finger.y + distanceY; + + if (tempFingerX > currrntScreenW || tempFingerX < 0 || + tempFingerY > currrntScreenH || tempFingerY < 0) { + logger.info(String.format( + "id %d finger is out of bounds (%d, %d)\n", + i + 1, tempFingerX, tempFingerY)); + return; + } + } + } + + for (i = 0; i < this.fingerCnt; i++) { + finger = getFingerPointFromSlot(i); + if (finger != null) { + finger.originX += originDistanceX; + finger.originY += originDistanceY; + finger.x += distanceX; + finger.y += distanceY; + + if (finger.id != 0) { + mouseEventData = new MouseEventData( + MouseButtonType.LEFT.value(), MouseEventType.PRESS.value(), + originX, originY, finger.x, finger.y, i); + communicator.sendToQEMU(SendCommand.SEND_MOUSE_EVENT, mouseEventData); + + /* logger.info(String.format( + "id %d finger multi-touch dragging = (%d, %d)", + i + 1, finger.x, finger.y));*/ + } + + try { Thread.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); - } - } - } - } - return; - } - + } + } + } + + return; + } + if (this.fingerCnt == 0) - { //first finger touch input + { /* first finger touch input */ if (this.addFingerPoint(originX, originY, x, y) == -1) { - return; - } + return; + } + mouseEventData = new MouseEventData( MouseButtonType.LEFT.value(), MouseEventType.PRESS.value(), originX, originY, x, y, 0); - communicator.sendToQEMU( SendCommand.SEND_MOUSE_EVENT, mouseEventData ); - } - else if((finger = this.getFingerPointSearch(x, y)) != null) //check the position of previous touch event - { - //finger point is selected - this.grabFingerID = finger.id; + communicator.sendToQEMU(SendCommand.SEND_MOUSE_EVENT, mouseEventData); + } + else if ((finger = this.getFingerPointSearch(x, y)) != null) + { /* check the position of previous touch event */ + /* finger point is selected */ + this.grabFingerID = finger.id; logger.info(String.format("id %d finger is grabbed\n", this.grabFingerID)); - - } - else if(this.fingerCnt == this.fingerCntMax) //Let's assume that this event is last finger touch input - { - //do nothing - } - else //one more finger - { - addFingerPoint(originX, originY, x, y); - mouseEventData = new MouseEventData( + } + else if (this.fingerCnt == this.fingerCntMax) + { /* Let's assume that this event is last finger touch input */ + /* do nothing */ + } + else /* one more finger */ + { + addFingerPoint(originX, originY, x, y); + mouseEventData = new MouseEventData( MouseButtonType.LEFT.value(), MouseEventType.PRESS.value(), - originX, originY, x, y, this.fingerCnt -1); - communicator.sendToQEMU( SendCommand.SEND_MOUSE_EVENT, mouseEventData ); - } - }else if (touchType == MouseEventType.RELEASE.value()) { /* released */ + originX, originY, x, y, this.fingerCnt - 1); + communicator.sendToQEMU(SendCommand.SEND_MOUSE_EVENT, mouseEventData); + } + } else if (touchType == MouseEventType.RELEASE.value()) { /* released */ logger.info("mouse up for multi touch"); this.grabFingerID = 0; - } - + } } - - private Boolean CalculateOriginCoordinates(int ScaledLcdWitdh, int ScaledLcdHeight, double scaleFactor, int rotationType, FingerPoint finger) { - + + private Boolean CalculateOriginCoordinates( + int ScaledLcdWitdh, int ScaledLcdHeight, + double scaleFactor, int rotationType, FingerPoint finger) { + int pointX, pointY, rotatedPointX, rotatedPointY, flag; - flag = 0; -// logger.info("ScaledLcdWitdh:"+ScaledLcdWitdh+" ScaledLcdHeight:"+ScaledLcdHeight+ " scaleFactor:"+ scaleFactor+" rotationType:"+rotationType); - rotatedPointX = pointX = (int)(finger.x * scaleFactor); - rotatedPointY = pointY = (int)(finger.y * scaleFactor); -// logger.info("rotatedPointX:"+rotatedPointX+" rotatedPointY:"+rotatedPointY); - if (rotationType == RotationInfo.LANDSCAPE.id()) { - rotatedPointX = pointY; - rotatedPointY = ScaledLcdWitdh - pointX; - } else if (rotationType == RotationInfo.REVERSE_PORTRAIT.id()) { - rotatedPointX = ScaledLcdWitdh - pointX; - rotatedPointY = ScaledLcdHeight - pointY; - } else if (rotationType == RotationInfo.REVERSE_LANDSCAPE.id()) { - rotatedPointX = ScaledLcdHeight - pointY; - rotatedPointY = pointX; - } else { - //PORTRAIT: do nothing - } - - - if (finger.originX != rotatedPointX) { - logger.info("finger.originX: " +finger.originX); - finger.originX = rotatedPointX; - flag = 1; - } - if (finger.originY != rotatedPointY) { - logger.info("finger.originY: " +finger.originY); - finger.originY = rotatedPointY; - flag = 1; - } - - if (flag != 0) { - return true; - } - - return false; + flag = 0; + + /* logger.info("ScaledLcdWitdh:" + ScaledLcdWitdh + + " ScaledLcdHeight:" + ScaledLcdHeight + + " scaleFactor:" + scaleFactor + " rotationType:" + rotationType); */ + + rotatedPointX = pointX = (int)(finger.x * scaleFactor); + rotatedPointY = pointY = (int)(finger.y * scaleFactor); + + /* logger.info("rotatedPointX:" + rotatedPointX + + " rotatedPointY:" + rotatedPointY); */ + + if (rotationType == RotationInfo.LANDSCAPE.id()) { + rotatedPointX = pointY; + rotatedPointY = ScaledLcdWitdh - pointX; + } else if (rotationType == RotationInfo.REVERSE_PORTRAIT.id()) { + rotatedPointX = ScaledLcdWitdh - pointX; + rotatedPointY = ScaledLcdHeight - pointY; + } else if (rotationType == RotationInfo.REVERSE_LANDSCAPE.id()) { + rotatedPointX = ScaledLcdHeight - pointY; + rotatedPointY = pointX; + } else { + /* PORTRAIT: do nothing */ + } + + if (finger.originX != rotatedPointX) { + logger.info("finger.originX: " +finger.originX); + finger.originX = rotatedPointX; + flag = 1; + } + if (finger.originY != rotatedPointY) { + logger.info("finger.originY: " +finger.originY); + finger.originY = rotatedPointY; + flag = 1; + } + + if (flag != 0) { + return true; + } + + return false; } - - public int rearrangeFingerPoints(int lcdWidth, int lcdHeight, double scaleFactor, int rotationType) { - int i = 0; - int count = 0; - FingerPoint finger = null; - - if (this.multiTouchEnable == 0) { - return 0; - } - scaleFactor = scaleFactor/100; - lcdWidth *= scaleFactor; - lcdHeight *= scaleFactor; - - for (i = 0; i < this.fingerCnt; i++) { - finger = getFingerPointFromSlot(i); - if (finger != null && finger.id != 0) { - if (CalculateOriginCoordinates(lcdWidth, lcdHeight, - scaleFactor, rotationType, finger) == true) { - count++; - } - } - } - - if (count != 0) { - this.grabFingerID = 0; - } - - return count; + + public int rearrangeFingerPoints( + int lcdWidth, int lcdHeight, double scaleFactor, int rotationType) { + int i = 0; + int count = 0; + FingerPoint finger = null; + + if (this.multiTouchEnable == 0) { + return 0; + } + + scaleFactor = scaleFactor / 100; + lcdWidth *= scaleFactor; + lcdHeight *= scaleFactor; + + for (i = 0; i < this.fingerCnt; i++) { + finger = getFingerPointFromSlot(i); + if (finger != null && finger.id != 0) { + if (CalculateOriginCoordinates( + lcdWidth, lcdHeight, scaleFactor, rotationType, finger) == true) { + count++; + } + } + } + + if (count != 0) { + this.grabFingerID = 0; + } + + return count; } - + public void clearFingerSlot() { int i = 0; FingerPoint finger = null; - for(i = 0; i < this.fingerCnt; i++) { + + for (i = 0; i < this.fingerCnt; i++) { finger = getFingerPointFromSlot(i); - if(finger != null && finger.id != 0) { - logger.info(String.format("clear %d, %d, %d", finger.x, finger.y, finger.id -1)); + if (finger != null && finger.id != 0) { + logger.info(String.format( + "clear %d, %d, %d", finger.x, finger.y, finger.id - 1)); + MouseEventData mouseEventData = new MouseEventData( MouseButtonType.LEFT.value(), MouseEventType.RELEASE.value(), - 0, 0, finger.x, finger.y, finger.id -1); - communicator.sendToQEMU( SendCommand.SEND_MOUSE_EVENT, mouseEventData ); + 0, 0, finger.x, finger.y, finger.id - 1); + communicator.sendToQEMU(SendCommand.SEND_MOUSE_EVENT, mouseEventData); } + finger.id = 0; finger.originX = finger.originY = finger.x = finger.y = -1; } + this.grabFingerID = 0; this.fingerCnt = 0; logger.info("clear multi touch"); } - + public void cleanup_multiTouchState() { this.multiTouchEnable = 0; clearFingerSlot(); fingerSlotimage.dispose(); } - + public int getMaxTouchPoint() { - if(this.maxTouchPoint <= 0 ) { + if (this.maxTouchPoint <= 0) { setMaxTouchPoint(1); } + return this.maxTouchPoint; } - + public void setMaxTouchPoint(int cnt) { - if(cnt <=0) { - cnt =1; + if (cnt <=0) { + cnt = 1; } + this.maxTouchPoint = cnt; } } diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorSdlSkin.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorSdlSkin.java index b1c76c9c36..149137ca02 100644 --- a/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorSdlSkin.java +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorSdlSkin.java @@ -118,6 +118,18 @@ public class EmulatorSdlSkin extends EmulatorSkin { return windowHandleId; } + @Override + public void displayOn() { + logger.info("display on"); + /* do nothing */ + } + + @Override + public void displayOff() { + logger.info("display off"); + /* do nothing */ + } + @Override protected void openScreenShotWindow() { if (screenShotDialog != null) { diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorShmSkin.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorShmSkin.java index 66415d864a..6cd1bde18e 100644 --- a/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorShmSkin.java +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorShmSkin.java @@ -1,7 +1,7 @@ /** * Emulator Skin Process * - * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: * GiWoong Kim @@ -40,6 +40,7 @@ import org.eclipse.swt.graphics.PaletteData; import org.eclipse.swt.graphics.Transform; import org.eclipse.swt.widgets.Display; 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.image.ImageRegistry.IconName; import org.tizen.emulator.skin.info.SkinInformation; @@ -57,7 +58,7 @@ public class EmulatorShmSkin extends EmulatorSkin { public static final int COLOR_DEPTH = 32; /* define JNI functions */ - public native int shmget(int size); + public native int shmget(int shmkey, int size); public native int shmdt(); public native int getPixels(int[] array); @@ -74,6 +75,7 @@ public class EmulatorShmSkin extends EmulatorSkin { private volatile boolean stopRequest; private Runnable runnable; + private int intervalWait; public PollFBThread(int lcdWidth, int lcdHeight) { this.display = Display.getDefault(); @@ -83,23 +85,37 @@ public class EmulatorShmSkin extends EmulatorSkin { this.imageData = new ImageData(lcdWidth, lcdHeight, COLOR_DEPTH, paletteData); this.framebuffer = new Image(Display.getDefault(), imageData); + setWaitIntervalTime(30); + this.runnable = new Runnable() { + @Override public void run() { // logger.info("update display framebuffer"); - if(lcdCanvas.isDisposed() == false) { + if (lcdCanvas.isDisposed() == false) { lcdCanvas.redraw(); } } }; } + public synchronized void setWaitIntervalTime(int ms) { + intervalWait = ms; + } + + public synchronized int getWaitIntervalTime() { + return intervalWait; + } + + @Override public void run() { stopRequest = false; + Image temp; + while (!stopRequest) { - synchronized (this) { + synchronized(this) { try { - this.wait(30); /* 30ms */ + this.wait(intervalWait); /* ms */ } catch (InterruptedException e) { e.printStackTrace(); break; @@ -113,7 +129,7 @@ public class EmulatorShmSkin extends EmulatorSkin { imageData.setPixels(0, i, lcdWidth, array, i * lcdWidth); } - Image temp = framebuffer; + temp = framebuffer; framebuffer = new Image(display, imageData); temp.dispose(); @@ -131,6 +147,10 @@ public class EmulatorShmSkin extends EmulatorSkin { public void stopRequest() { stopRequest = true; + + synchronized(pollThread) { + pollThread.notify(); + } } } @@ -149,15 +169,20 @@ public class EmulatorShmSkin extends EmulatorSkin { super.finger.setMultiTouchEnable(0); super.finger.clearFingerSlot(); super.finger.cleanup_multiTouchState(); - + super.skinFinalize(); } public long initLayout() { super.initLayout(); + /* base + 1 = sdb port */ + /* base + 2 = shared memory key */ + int shmkey = config.getArgInt(ArgsConstants.NET_BASE_PORT) + 2; + logger.info("shmkey = " + shmkey); + /* initialize shared memory */ - int result = shmget( + int result = shmget(shmkey, currentState.getCurrentResolutionWidth() * currentState.getCurrentResolutionHeight()); logger.info("shmget native function returned " + result); @@ -168,7 +193,7 @@ public class EmulatorShmSkin extends EmulatorSkin { currentState.getCurrentResolutionHeight()); lcdCanvas.addPaintListener(new PaintListener() { - public void paintControl(PaintEvent e) { + public void paintControl(PaintEvent e) { //TODO: optimize /* e.gc.setAdvanced(true); if (!e.gc.getAdvanced()) { logger.info("Advanced graphics not supported"); @@ -176,18 +201,27 @@ public class EmulatorShmSkin extends EmulatorSkin { int x = lcdCanvas.getSize().x; int y = lcdCanvas.getSize().y; + + if (pollThread.getWaitIntervalTime() == 0) { + logger.info("draw black screen"); + + e.gc.drawRectangle(-1, -1, x + 1, y + 1); + return; + } + if (currentState.getCurrentAngle() == 0) { /* portrait */ e.gc.drawImage(pollThread.framebuffer, 0, 0, pollThread.lcdWidth, pollThread.lcdHeight, 0, 0, x, y); - + if (finger.getMultiTouchEnable() == 1) { finger.rearrangeFingerPoints(currentState.getCurrentResolutionWidth(), currentState.getCurrentResolutionHeight(), currentState.getCurrentScale(), currentState.getCurrentRotationId()); } - finger.drawImage(e, currentState.getCurrentAngle()); + + finger.drawImage(e, currentState.getCurrentAngle()); return; } @@ -210,15 +244,14 @@ public class EmulatorShmSkin extends EmulatorSkin { y = temp; transform.translate(x * -1, 0); } - - //draw finger image - //for when rotate while use multi touch + + /* draw finger image for when rotate while use multitouch */ if (finger.getMultiTouchEnable() == 1) { finger.rearrangeFingerPoints(currentState.getCurrentResolutionWidth(), currentState.getCurrentResolutionHeight(), currentState.getCurrentScale(), currentState.getCurrentRotationId()); - } + } //save current transform as "oldtransform" e.gc.getTransform(oldtransform); //set to new transfrom @@ -228,7 +261,7 @@ public class EmulatorShmSkin extends EmulatorSkin { 0, 0, x, y); //back to old transform e.gc.setTransform(oldtransform); - + transform.dispose(); finger.drawImage(e, currentState.getCurrentAngle()); } @@ -239,6 +272,35 @@ public class EmulatorShmSkin extends EmulatorSkin { return 0; } + @Override + public void displayOn() { + logger.info("display on"); + + if (pollThread.isAlive()) { + pollThread.setWaitIntervalTime(30); + + synchronized(pollThread) { + pollThread.notify(); + } + } + } + + @Override + public void displayOff() { + logger.info("display off"); + + if (pollThread.isAlive()) { + pollThread.setWaitIntervalTime(0); + + shell.getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + lcdCanvas.redraw(); + } + }); + } + } + @Override protected void openScreenShotWindow() { if (screenShotDialog != null) { diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorSkin.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorSkin.java index 0cd3002200..6744202fc1 100644 --- a/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorSkin.java +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorSkin.java @@ -1,7 +1,7 @@ /** * Emulator Skin Process * - * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: * GiWoong Kim @@ -65,6 +65,7 @@ import org.eclipse.swt.widgets.Shell; import org.tizen.emulator.skin.comm.ICommunicator.KeyEventType; import org.tizen.emulator.skin.comm.ICommunicator.MouseButtonType; import org.tizen.emulator.skin.comm.ICommunicator.MouseEventType; +import org.tizen.emulator.skin.comm.ICommunicator.RotationInfo; import org.tizen.emulator.skin.comm.ICommunicator.Scale; import org.tizen.emulator.skin.comm.ICommunicator.SendCommand; import org.tizen.emulator.skin.comm.sock.SocketCommunicator; @@ -75,6 +76,7 @@ import org.tizen.emulator.skin.comm.sock.data.MouseEventData; import org.tizen.emulator.skin.config.EmulatorConfig; import org.tizen.emulator.skin.config.EmulatorConfig.ArgsConstants; import org.tizen.emulator.skin.config.EmulatorConfig.SkinPropertiesConstants; +import org.tizen.emulator.skin.custom.ColorTag; import org.tizen.emulator.skin.custom.CustomProgressBar; import org.tizen.emulator.skin.custom.KeyWindow; import org.tizen.emulator.skin.dbi.ColorsType; @@ -122,6 +124,33 @@ public class EmulatorSkin { } + public enum SkinBasicColor { + BLUE(0, 174, 239), + YELLOW(246, 226, 0), + LIME(0, 246, 12), + VIOLET(168, 43, 255), + ORANGE(246, 110, 0), + MAGENTA(245, 48, 233), + PURPLE(94, 73, 255), + GREEN(179, 246, 0), + RED(245, 48, 48), + CYON(29, 223, 221); + + private int channelRed; + private int channelGreen; + private int channelBlue; + + SkinBasicColor(int r, int g, int b) { + channelRed = r; + channelGreen = g; + channelBlue = b; + } + + public RGB color() { + return new RGB(channelRed, channelGreen, channelBlue); + } + } + private static Logger logger = SkinLogger.getSkinLogger(EmulatorSkin.class).getLogger(); @@ -144,11 +173,11 @@ public class EmulatorSkin { private boolean isOnKbd; private Menu contextMenu; + public Color colorVM; private MenuItem keyWindowItem; /* key window menu */ public KeyWindow keyWindow; public int recentlyDocked; - public Color colorPairTag; - public Canvas pairTagCanvas; + public ColorTag pairTag; public CustomProgressBar bootingProgress; public ScreenShotDialog screenShotDialog; @@ -205,10 +234,7 @@ public class EmulatorSkin { this.displayCanvasStyle = displayCanvasStyle; /* generate a pair tag color of key window */ - int red = (int) (Math.random() * 256); - int green = (int) (Math.random() * 256); - int blue = (int) (Math.random() * 256); - this.colorPairTag = new Color(shell.getDisplay(), new RGB(red, green, blue)); + setColorVM(); this.currentState = state; } @@ -218,6 +244,22 @@ public class EmulatorSkin { this.finger.setCommunicator(this.communicator); } + private void setColorVM() { + int portNumber = config.getArgInt(ArgsConstants.NET_BASE_PORT) % 100; + + if (portNumber >= 26200) { + int red = (int) (Math.random() * 256); + int green = (int) (Math.random() * 256); + int blue = (int) (Math.random() * 256); + this.colorVM = new Color(shell.getDisplay(), new RGB(red, green, blue)); + } else { + int vmIndex = (portNumber % 100) / 10; + + SkinBasicColor colors[] = SkinBasicColor.values(); + this.colorVM = new Color(shell.getDisplay(), colors[vmIndex].color()); + } + } + public long initLayout() { imageRegistry = ImageRegistry.getInstance(); @@ -316,8 +358,15 @@ public class EmulatorSkin { return (new Color(shell.getDisplay(), new RGB(255, 255, 255))); } - public SkinReopenPolicy open() { + public Color getColorVM() { + return colorVM; + } + + public ImageRegistry getImageRegistry() { + return imageRegistry; + } + public SkinReopenPolicy open() { if (null == this.communicator) { logger.severe("communicator is null."); return null; @@ -345,7 +394,6 @@ public class EmulatorSkin { } return new SkinReopenPolicy(reopenSkin, isAboutToReopen); - } protected void skinFinalize() { @@ -378,9 +426,9 @@ public class EmulatorSkin { closeKeyWindow(); } - /* dispose the color tag */ - if (colorPairTag != null) { - colorPairTag.dispose(); + /* dispose the color */ + if (colorVM != null) { + colorVM.dispose(); } /* save config only for emulator close */ @@ -445,24 +493,39 @@ public class EmulatorSkin { @Override public void shellIconified(ShellEvent event) { - /* do nothing */ - } - - @Override - public void shellDeiconified(ShellEvent event) { - logger.info("deiconified"); + logger.info("iconified"); + /* synchronization of minimization */ shell.getDisplay().asyncExec(new Runnable() { @Override public void run() { if (isKeyWindow == true && keyWindow != null) { - if (keyWindow.getShell().getMinimized() == true) { - keyWindow.getShell().setMinimized(false); + if (keyWindow.getShell().getMinimized() == false) { + keyWindow.getShell().setVisible(false); + /* the tool style window is exposed + when even it was minimized */ + keyWindow.getShell().setMinimized(true); } } } }); } + + @Override + public void shellDeiconified(ShellEvent event) { + logger.info("deiconified"); + + if (isKeyWindow == true && keyWindow != null) { + if (keyWindow.getShell().getMinimized() == true) { + keyWindow.getShell().setMinimized(false); + keyWindow.getShell().setVisible(true); + } + } + + DisplayStateData lcdStateData = new DisplayStateData( + currentState.getCurrentScale(), currentState.getCurrentRotationId()); + communicator.sendToQEMU(SendCommand.CHANGE_LCD_STATE, lcdStateData); + } }; shell.addShellListener(shellListener); @@ -928,7 +991,7 @@ public class EmulatorSkin { private synchronized boolean addPressedKey(KeyEventData pressData) { for (KeyEventData data : pressedKeyEventList) { if (data.keycode == pressData.keycode && - data.stateMask == pressData.stateMask && + //data.stateMask == pressData.stateMask && data.keyLocation == pressData.keyLocation) { return false; } @@ -942,7 +1005,7 @@ public class EmulatorSkin { for (KeyEventData data : pressedKeyEventList) { if (data.keycode == releaseData.keycode && - data.stateMask == releaseData.stateMask && + //data.stateMask == releaseData.stateMask && data.keyLocation == releaseData.keyLocation) { pressedKeyEventList.remove(data); @@ -987,7 +1050,23 @@ public class EmulatorSkin { } protected void openScreenShotWindow() { - //TODO: abstract + /* abstract */ + } + + public void dispalyBrightness(boolean on) { + if (on == true) { + displayOn(); + } else { + displayOff(); + } + } + + protected void displayOn() { + /* abstract */ + } + + protected void displayOff() { + /* abstract */ } public boolean isSelectKeyWindow() { @@ -999,7 +1078,7 @@ public class EmulatorSkin { if (recreate == false) { /* show the key window */ keyWindowItem.setSelection(isKeyWindow = true); - pairTagCanvas.setVisible(true); + pairTag.setVisible(true); keyWindow.getShell().setVisible(true); SkinUtil.setTopMost(keyWindow.getShell(), isOnTop); @@ -1025,20 +1104,19 @@ public class EmulatorSkin { return; } - keyWindow = new KeyWindow(this, shell, colorPairTag, - communicator, keyMapList); + keyWindow = new KeyWindow(this, shell, communicator, keyMapList); keyWindowItem.setSelection(isKeyWindow = true); SkinUtil.setTopMost(keyWindow.getShell(), isOnTop); - pairTagCanvas.setVisible(true); + pairTag.setVisible(true); keyWindow.open(dockValue); } public void hideKeyWindow() { keyWindowItem.setSelection(isKeyWindow = false); - pairTagCanvas.setVisible(false); + pairTag.setVisible(false); if (keyWindow != null) { keyWindow.getShell().setVisible(false); @@ -1047,7 +1125,7 @@ public class EmulatorSkin { public void closeKeyWindow() { keyWindowItem.setSelection(isKeyWindow = false); - pairTagCanvas.setVisible(false); + pairTag.setVisible(false); if (keyWindow != null) { keyWindow.getShell().close(); @@ -1262,6 +1340,33 @@ public class EmulatorSkin { } + /* temp : swap rotation menu names */ + if (currentState.getCurrentResolutionWidth() > + currentState.getCurrentResolutionHeight()) + { + for (MenuItem m : rotationList) { + short rotationId = (Short) m.getData(); + + if (rotationId == RotationInfo.PORTRAIT.id()) { + String landscape = SkinRotation.getRotation( + RotationInfo.LANDSCAPE.id()).getName().value(); + m.setText(landscape); + } else if (rotationId == RotationInfo.LANDSCAPE.id()) { + String portrait = SkinRotation.getRotation( + RotationInfo.PORTRAIT.id()).getName().value(); + m.setText(portrait); + } else if (rotationId == RotationInfo.REVERSE_PORTRAIT.id()) { + String landscapeReverse = SkinRotation.getRotation( + RotationInfo.REVERSE_LANDSCAPE.id()).getName().value(); + m.setText(landscapeReverse); + } else if (rotationId == RotationInfo.REVERSE_LANDSCAPE.id()) { + String portraitReverse = SkinRotation.getRotation( + RotationInfo.REVERSE_PORTRAIT.id()).getName().value(); + m.setText(portraitReverse); + } + } + } + SelectionAdapter selectionAdapter = new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { @@ -1537,7 +1642,7 @@ public class EmulatorSkin { isOpen = true; logger.info("Open the about dialog"); - AboutDialog dialog = new AboutDialog(shell); + AboutDialog dialog = new AboutDialog(shell, config); dialog.open(); isOpen = false; } diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorSkinMain.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorSkinMain.java index facefd51c9..d93a1bda2e 100644 --- a/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorSkinMain.java +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorSkinMain.java @@ -29,8 +29,10 @@ package org.tizen.emulator.skin; +import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; +import java.io.FileReader; import java.io.IOException; import java.net.Socket; import java.util.HashMap; @@ -57,6 +59,7 @@ import org.tizen.emulator.skin.log.SkinLogger; import org.tizen.emulator.skin.log.SkinLogger.SkinLogLevel; import org.tizen.emulator.skin.util.IOUtil; import org.tizen.emulator.skin.util.JaxbUtil; +import org.tizen.emulator.skin.util.SkinUtil; import org.tizen.emulator.skin.util.StringUtil; import org.tizen.emulator.skin.util.SwtUtil; @@ -173,8 +176,11 @@ public class EmulatorSkinMain { } boolean skinPhoneShape = true; - String skinInfoResolutionW = skinInfoProperties.getProperty(SkinInfoConstants.RESOLUTION_WIDTH); - String skinInfoResolutionH = skinInfoProperties.getProperty(SkinInfoConstants.RESOLUTION_HEIGHT); + String skinInfoResolutionW = + skinInfoProperties.getProperty(SkinInfoConstants.RESOLUTION_WIDTH); + String skinInfoResolutionH = + skinInfoProperties.getProperty(SkinInfoConstants.RESOLUTION_HEIGHT); + if (skinInfoResolutionW.equalsIgnoreCase("all") || skinInfoResolutionH.equalsIgnoreCase("all")) { skinPhoneShape = false; @@ -184,10 +190,10 @@ public class EmulatorSkinMain { /* set emulator window skin property */ String skinPropFilePath = vmPath + File.separator + SKIN_PROPERTIES_FILE_NAME; - Properties skinProperties = loadProperties( skinPropFilePath, true ); - if ( null == skinProperties ) { - logger.severe( "Fail to load skin properties file." ); - System.exit( -1 ); + Properties skinProperties = loadProperties(skinPropFilePath, true); + if (null == skinProperties) { + logger.severe("Fail to load skin properties file."); + System.exit(-1); } /* set emulator window config property */ @@ -219,9 +225,30 @@ public class EmulatorSkinMain { System.exit(-1); } + /* collect configurations */ EmulatorConfig config = new EmulatorConfig(argsMap, dbiContents, skinProperties, skinPropFilePath, configProperties); + /* load SDK version */ + String strVersion = "Undefined"; + String versionFilePath = SkinUtil.getSdkVersionFilePath(); + + File file = new File(versionFilePath); + if (file.exists() && file.isFile()) { + BufferedReader reader = new BufferedReader( + new FileReader(versionFilePath)); + + strVersion = reader.readLine(); + + reader.close(); + } else { + logger.info("cannot find version file" + versionFilePath); + } + + logger.info("SDK version : " + strVersion); + config.setSkinProperty( + EmulatorConfig.SkinInfoConstants.SDK_VERSION_NAME, strVersion); + /* load image resource */ ImageRegistry.getInstance().initialize(config); diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/comm/ICommunicator.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/comm/ICommunicator.java index 9a6f3fbd5d..30ca206f43 100644 --- a/tizen/src/skin/client/src/org/tizen/emulator/skin/comm/ICommunicator.java +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/comm/ICommunicator.java @@ -263,6 +263,7 @@ public interface ICommunicator extends Runnable { DETAIL_INFO_DATA((short) 3), RAMDUMP_COMPLETE((short) 4), BOOTING_PROGRESS((short) 5), + BRIGHTNESS_VALUE((short) 6), SENSOR_DAEMON_START((short) 800), SHUTDOWN((short) 999); diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/comm/sock/SocketCommunicator.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/comm/sock/SocketCommunicator.java index 14d20e7367..5f3e7348d2 100644 --- a/tizen/src/skin/client/src/org/tizen/emulator/skin/comm/sock/SocketCommunicator.java +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/comm/sock/SocketCommunicator.java @@ -73,9 +73,10 @@ public class SocketCommunicator implements ICommunicator { private Timer timer; private DataTranfer() { + /* do nothing */ } - private void setData( byte[] data ) { + private void setData(byte[] data) { this.receivedData = data; isTransferState = false; } @@ -116,10 +117,14 @@ public class SocketCommunicator implements ICommunicator { private DataTranfer screenShotDataTransfer; private DataTranfer detailInfoTransfer; private DataTranfer progressDataTransfer; + private DataTranfer brightnessDataTransfer; private Thread sendThread; private LinkedList sendQueue; + private ByteArrayOutputStream bao; + private DataOutputStream dataOutputStream; + public SocketCommunicator(EmulatorConfig config, int uId, EmulatorSkin skin) { this.config = config; @@ -138,6 +143,10 @@ public class SocketCommunicator implements ICommunicator { this.progressDataTransfer.sleep = SCREENSHOT_WAIT_INTERVAL; this.progressDataTransfer.maxWaitTime = SCREENSHOT_WAIT_LIMIT; + this.brightnessDataTransfer = new DataTranfer(); + this.brightnessDataTransfer.sleep = SCREENSHOT_WAIT_INTERVAL; + this.brightnessDataTransfer.maxWaitTime = SCREENSHOT_WAIT_LIMIT; + this.heartbeatCount = new AtomicInteger(0); //this.heartbeatExecutor = Executors.newSingleThreadScheduledExecutor(); this.heartbeatTimer = new Timer(); @@ -154,6 +163,8 @@ public class SocketCommunicator implements ICommunicator { logger.log( Level.SEVERE, e.getMessage(), e ); } + this.bao = new ByteArrayOutputStream(); + this.dataOutputStream = new DataOutputStream(bao); } public void setInitialData(long data) { @@ -257,9 +268,8 @@ public class SocketCommunicator implements ICommunicator { heartbeatTimer.schedule(heartbeatExecutor, 1, HEART_BEAT_INTERVAL * 1000); } - while ( true ) { - - if ( isTerminated ) { + while (true) { + if (isTerminated) { break; } @@ -269,16 +279,17 @@ public class SocketCommunicator implements ICommunicator { short cmd = dis.readShort(); int length = dis.readInt(); - if ( logger.isLoggable( Level.FINE ) ) { - logger.fine( "[Socket] read - reqId:" + reqId + ", command:" + cmd + ", dataLength:" + length ); + 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 ) { - logger.severe( "unknown command:" + cmd ); + command = ReceiveCommand.getValue(cmd); + } catch (IllegalArgumentException e) { + logger.severe("unknown command:" + cmd); continue; } @@ -309,7 +320,7 @@ public class SocketCommunicator implements ICommunicator { break; } case BOOTING_PROGRESS: { - logger.info("received BOOTING_PROGRESS from QEMU."); + //logger.info("received BOOTING_PROGRESS from QEMU."); resetDataTransfer(progressDataTransfer); receiveData(progressDataTransfer, length); @@ -331,7 +342,7 @@ public class SocketCommunicator implements ICommunicator { if (value == 100 | value == 0) { /* this means progressbar will be - dispose soon */ + disposed soon */ if (skin.bootingProgress != null) { skin.bootingProgress = null; } @@ -341,27 +352,53 @@ public class SocketCommunicator implements ICommunicator { break; } + case BRIGHTNESS_VALUE: { + //logger.info("received BRIGHTNESS_VALUE from QEMU."); + + resetDataTransfer(brightnessDataTransfer); + receiveData(brightnessDataTransfer, length); + + byte[] receivedData = getReceivedData(brightnessDataTransfer); + if (null != receivedData) { + String strValue = new String(receivedData, 0, length - 1); + + int value = 1; + try { + value = Integer.parseInt(strValue); + } catch (NumberFormatException e) { + e.printStackTrace(); + } + + if (value == 0) { + skin.dispalyBrightness(false); + } else { + skin.dispalyBrightness(true); + } + } + + break; + } case SENSOR_DAEMON_START: { - logger.info( "received SENSOR_DAEMON_START from QEMU." ); - synchronized ( this ) { + logger.info("received SENSOR_DAEMON_START from QEMU."); + synchronized (this) { isSensorDaemonStarted = true; } break; } case SHUTDOWN: { - logger.info( "received RESPONSE_SHUTDOWN from QEMU." ); - sendToQEMU( SendCommand.RESPONSE_SHUTDOWN, null ); + logger.info("received RESPONSE_SHUTDOWN from QEMU."); + sendToQEMU(SendCommand.RESPONSE_SHUTDOWN, null); terminate(); break; } default: { - logger.severe( "Unknown command from QEMU. command:" + cmd ); + logger.severe("Unknown command from QEMU. command:" + cmd); break; } } - } catch ( IOException e ) { - logger.log( Level.SEVERE, e.getMessage(), e ); + } catch (IOException e) { + logger.log(Level.SEVERE, e.getMessage(), e); break; } @@ -483,68 +520,66 @@ public class SocketCommunicator implements ICommunicator { } @Override - public void sendToQEMU( SendCommand command, ISendData data ) { - - synchronized ( sendQueue ) { - if ( MAX_SEND_QUEUE_SIZE < sendQueue.size() ) { - logger.warning( "Send queue size exceeded max value, do not push data into send queue." ); + public void sendToQEMU(SendCommand command, ISendData data) { + synchronized(sendQueue) { + if (MAX_SEND_QUEUE_SIZE < sendQueue.size()) { + logger.warning( + "Send queue size exceeded max value, do not push data into send queue."); } else { - sendQueue.add( new SkinSendData( command, data ) ); + sendQueue.add(new SkinSendData(command, data)); sendQueue.notifyAll(); } } - } - private void sendToQEMUInternal( SkinSendData sendData ) { - + private void sendToQEMUInternal(SkinSendData sendData) { try { - if( null == sendData ) { + if (null == sendData) { return; } SendCommand command = sendData.getCommand(); ISendData data = sendData.getSendData(); - - reqId = ( Integer.MAX_VALUE == reqId ) ? 0 : ++reqId; - - ByteArrayOutputStream bao = new ByteArrayOutputStream(); - DataOutputStream dataOutputStream = new DataOutputStream( bao ); - dataOutputStream.writeInt( uId ); - dataOutputStream.writeInt( reqId ); - dataOutputStream.writeShort( command.value() ); + reqId = (Integer.MAX_VALUE == reqId) ? 0 : ++reqId; + + dataOutputStream.writeInt(uId); + dataOutputStream.writeInt(reqId); + dataOutputStream.writeShort(command.value()); short length = 0; - if ( null == data ) { + if (null == data) { length = 0; - dataOutputStream.writeShort( length ); + 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 ); + bao.reset(); + + 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 ) ) { - logger.fine( "[Socket] data - " + data.toString() ); + if (0 < length) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("[Socket] data - " + data.toString()); } } - } catch ( IOException e ) { - logger.log( Level.SEVERE, e.getMessage(), e ); + } catch (IOException e) { + logger.log(Level.SEVERE, e.getMessage(), e); } } @@ -644,6 +679,13 @@ public class SocketCommunicator implements ICommunicator { IOUtil.closeSocket(socket); + try { + bao.close(); + dataOutputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + synchronized (this) { skin.shutdown(); } diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/comm/sock/data/DisplayStateData.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/comm/sock/data/DisplayStateData.java new file mode 100644 index 0000000000..a22ef4d64a --- /dev/null +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/comm/sock/data/DisplayStateData.java @@ -0,0 +1,65 @@ +/** + * + * + * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * YeongKyoon Lee + * HyunJun Son + * + * 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.comm.sock.data; + +import java.io.IOException; + +/** + * + * + */ +public class DisplayStateData extends AbstractSendData { + + int scale; + short rotation; + + public DisplayStateData(int scale, short rotation) { + this.scale = scale; + this.rotation = rotation; + } + + @Override + protected void write() throws IOException { + writeInt(scale); + writeShort(rotation); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("DisplayStateData [scale="); + builder.append(scale); + builder.append(", rotation="); + builder.append(rotation); + builder.append("]"); + return builder.toString(); + } + +} diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/config/EmulatorConfig.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/config/EmulatorConfig.java index 489e4add9c..3048bd4299 100644 --- a/tizen/src/skin/client/src/org/tizen/emulator/skin/config/EmulatorConfig.java +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/config/EmulatorConfig.java @@ -78,6 +78,7 @@ public class EmulatorConfig { } public interface SkinInfoConstants { + public static final String SDK_VERSION_NAME = "sdk.version-name"; public static final String SKIN_NAME = "skin.name"; public static final String RESOLUTION_WIDTH = "resolution.width"; public static final String RESOLUTION_HEIGHT = "resolution.height"; @@ -102,14 +103,16 @@ public class EmulatorConfig { private Properties configProperties; private String skinPropertiesFilePath; - public EmulatorConfig( Map args, EmulatorUI dbiContents, Properties skinProperties, - String skinPropertiesFilePath, Properties configProperties ) { + public EmulatorConfig(Map args, + EmulatorUI dbiContents, Properties skinProperties, + String skinPropertiesFilePath, Properties configProperties) { this.args = args; this.dbiContents = dbiContents; this.skinProperties = skinProperties; this.skinPropertiesFilePath = skinPropertiesFilePath; this.configProperties = configProperties; - if ( null == configProperties ) { + + if (null == configProperties) { this.configProperties = new Properties(); } } diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/custom/ColorTag.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/custom/ColorTag.java new file mode 100644 index 0000000000..1e4654ddfd --- /dev/null +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/custom/ColorTag.java @@ -0,0 +1,66 @@ +/** + * + * + * Copyright (C) 2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * YeongKyoon Lee + * + * 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.custom; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.widgets.Canvas; +import org.eclipse.swt.widgets.Shell; + +public class ColorTag extends Canvas { + private static final int COLORTAG_WIDTH = 8; + private static final int COLORTAG_HEIGHT = 8; + + public ColorTag(final Shell parent, int style, final Color colorOval) { + super(parent, style); + + setSize(COLORTAG_WIDTH, COLORTAG_HEIGHT); + setBackground(parent.getBackground()); + + addPaintListener(new PaintListener() { + @Override + public void paintControl(PaintEvent e) { + e.gc.setBackground(colorOval); + e.gc.setAntialias(SWT.ON); + e.gc.fillOval( + 0, 0, COLORTAG_WIDTH, COLORTAG_HEIGHT); + } + }); + } + + public int getWidth() { + return getSize().x; + } + + public int getHeight() { + return getSize().y; + } +} \ No newline at end of file diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/custom/CustomButton.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/custom/CustomButton.java new file mode 100644 index 0000000000..782e488129 --- /dev/null +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/custom/CustomButton.java @@ -0,0 +1,246 @@ +/** + * Image Button + * + * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * YeongKyoon Lee + * + * 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.custom; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.KeyAdapter; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.MouseAdapter; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseMoveListener; +import org.eclipse.swt.events.MouseTrackAdapter; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Canvas; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; + +public class CustomButton extends Canvas { + /* state */ + private int mouse = 0; + private boolean hit = false; + + /* image - 0 : normal, 1 : hover, 2 : pushed */ + private Image imageButton[]; + + private int width; + private int height; + private String text; + private int textPositionX; + private int textPositionY; + private static Color white; + private static Color gray; + + public CustomButton(Composite parent, int style, + Image imageNormal, Image imageHover, Image imagePushed) { + super(parent, style); + + this.imageButton = new Image[3]; + imageButton[0] = imageNormal; + imageButton[1] = imageHover; + imageButton[2] = imagePushed; + + this.width = imageNormal.getImageData().width; + this.height = imageNormal.getImageData().height; + + this.text = null; + textPositionX = width / 2; + textPositionY = height / 2; + white = Display.getCurrent().getSystemColor(SWT.COLOR_WHITE); + gray = Display.getCurrent().getSystemColor(SWT.COLOR_GRAY); + + this.addPaintListener(new PaintListener() { + @Override + public void paintControl(PaintEvent e) { + switch (mouse) { + case 0: /* default state */ + if (imageButton[0] != null) { + e.gc.drawImage(imageButton[0], 0, 0); + } + + if (text != null) { + e.gc.setForeground(white); + e.gc.drawText(text, + textPositionX, textPositionY, true); + } + + break; + case 1: /* mouse over */ + if (imageButton[1] != null) { + e.gc.drawImage(imageButton[1], 0, 0); + } + + if (text != null) { + e.gc.setForeground(white); + e.gc.drawText(text, + textPositionX, textPositionY, true); + } + + break; + case 2: /* mouse down */ + if (imageButton[2] != null) { + e.gc.drawImage(imageButton[2], 0, 0); + } + + if (text != null) { + e.gc.setForeground(gray); + e.gc.drawText(text, + textPositionX, textPositionY, true); + } + + break; + default: + break; + } + } + }); + + this.addMouseMoveListener(new MouseMoveListener() { + @Override + public void mouseMove(MouseEvent e) { + if (!hit) { + return; + } + + mouse = 2; + + if (e.x < 0 || e.y < 0 || + e.x > getBounds().width || e.y > getBounds().height) { + mouse = 0; + } + + redraw(); + } + }); + + this.addMouseTrackListener(new MouseTrackAdapter() { + @Override + public void mouseEnter(MouseEvent e) { + mouse = 1; + + redraw(); + } + + @Override + public void mouseExit(MouseEvent e) { + mouse = 0; + + redraw(); + } + }); + + this.addMouseListener(new MouseAdapter() { + @Override + public void mouseDown(MouseEvent e) { + hit = true; + mouse = 2; + + redraw(); + } + + @Override + public void mouseUp(MouseEvent e) { + hit = false; + mouse = 1; + + if (e.x < 0 || e.y < 0 || + e.x > getBounds().width || e.y > getBounds().height) { + mouse = 0; + } + + redraw(); + + if (mouse == 1) { + notifyListeners(SWT.Selection, new Event()); + } + } + }); + + this.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + if (e.keyCode == '\r' || e.character == ' ') { + Event event = new Event(); + notifyListeners(SWT.Selection, event); + } + } + }); + } + + public void setText(String textValue) { + /* checking whether the text value is appropriate */ + if (textValue == null || textValue.isEmpty()) { + return; + } + + GC gc = new GC(this); + Point textSize = gc.textExtent(textValue); + Point originalSize = textSize; + + while (textSize.x >= (width - 10)) { + textValue = textValue.substring(0, textValue.length() - 1); + textSize = gc.textExtent(textValue); + } + + if (originalSize.x != textSize.x) { + textValue = textValue.substring(0, textValue.length() - 1); + textValue += ".."; + textSize = gc.textExtent(textValue); + } + + gc.dispose(); + + /* set text */ + text = textValue; + + textPositionX -= textSize.x / 2; + if (textPositionX < 0) { + textPositionX = 0; + } + + textPositionY -= textSize.y / 2; + if (textPositionY < 0) { + textPositionY = 0; + } + } + + public String getText() { + return text; + } + + public Point getImageSize() { + return new Point(imageButton[0].getImageData().width, + imageButton[0].getImageData().height); + } +} \ No newline at end of file diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/custom/CustomProgressBar.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/custom/CustomProgressBar.java new file mode 100644 index 0000000000..a07c3f8e79 --- /dev/null +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/custom/CustomProgressBar.java @@ -0,0 +1,121 @@ +/** + * + * + * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * YeongKyoon Lee + * + * 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.custom; + +import java.util.logging.Logger; + +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Canvas; +import org.eclipse.swt.widgets.Composite; +import org.tizen.emulator.skin.log.SkinLogger; + +public class CustomProgressBar extends Canvas { + public static final RGB PROGRESS_COLOR = new RGB(0, 173, 239); + + private Logger logger = + SkinLogger.getSkinLogger(CustomProgressBar.class).getLogger(); + + private Composite parent; + private int selection; + + public CustomProgressBar(final Composite parent, int style) { + super(parent, style); + + this.parent = parent; + this.selection = 0; + + this.addPaintListener(new PaintListener() { + @Override + public void paintControl(PaintEvent e) { + e.gc.setBackground( + new Color(parent.getDisplay(), PROGRESS_COLOR)); + + Rectangle bounds = getBounds(); + int width = (bounds.width * selection) / 100; + e.gc.fillRectangle(0, 0, width, bounds.height); + + if (selection == -1) { + logger.info("progress : complete!"); + + parent.getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + dispose(); + } + }); + } + } + }); + + /* default is hidden */ + parent.getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + setVisible(false); + } + }); + } + + public void setSelection(int value) { + parent.getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + setVisible(true); + } + }); + + if (value < 0) { + value = 0; + } else if (value > 100) { + value = 100; + } + + selection = value; + logger.info("progress : " + selection); + + parent.getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + redraw(); + + if (selection == 100) { + selection = -1; + } + } + }); + } + + public int getSelection() { + return selection; + } +} diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/custom/CustomScrollBar.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/custom/CustomScrollBar.java new file mode 100644 index 0000000000..876c561843 --- /dev/null +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/custom/CustomScrollBar.java @@ -0,0 +1,226 @@ +/** + * + * + * Copyright (C) 2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * YeongKyoon Lee + * + * 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.custom; + +import java.util.Timer; +import java.util.TimerTask; +import java.util.logging.Logger; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.RowData; +import org.eclipse.swt.layout.RowLayout; +import org.eclipse.swt.widgets.Canvas; +import org.eclipse.swt.widgets.Composite; +import org.tizen.emulator.skin.log.SkinLogger; + + +public class CustomScrollBar { + static final int SCROLL_SHIFT_LENGTH = 10; + + private Logger logger = SkinLogger.getSkinLogger( + CustomScrollBar.class).getLogger(); + + private Composite parent; + private Composite composite; + CustomScrolledComposite compositeScroll; + + private int heightScrollBar; + private int maxShift; + + private Image[] imagesArrowUp; + private Image[] imagesArrowDown; + private Image imageThumb; + private Image imageShaft; + + private CustomButton buttonArrowUp; + private CustomButton buttonArrowDown; + private Canvas canvasShaft; + private CustomButton buttonThumb; + + private int valueSelection; + private Timer timerScroller; + private TimerTask scroller; + + CustomScrollBar(Composite parent, int style, int heightScrollBar, + Image[] imagesArrowUp, Image[] imagesArrowDown, + Image imageThumb, Image imageShaft) { + this.parent = parent; + this.composite = new Composite(parent, SWT.NONE); + this.compositeScroll = ((CustomScrolledComposite) parent.getParent()); + + RowLayout rowLayout = new RowLayout(SWT.VERTICAL); + rowLayout.marginLeft = rowLayout.marginRight = 0; + rowLayout.marginTop = rowLayout.marginBottom = 0; + rowLayout.marginWidth = rowLayout.marginHeight = 0; + rowLayout.spacing = 0; + + composite.setLayout(rowLayout); + + this.heightScrollBar = heightScrollBar; + this.maxShift = SCROLL_SHIFT_LENGTH; + + this.imagesArrowUp = imagesArrowUp; + this.imagesArrowDown = imagesArrowDown; + this.imageThumb = imageThumb; + this.imageShaft = imageShaft; + + //this.timerScroller = new Timer(); + + createContents(); + + addScrollBarListener(); + } + + protected void createContents() { + /* arrow up */ + buttonArrowUp = new CustomButton(composite, SWT.NONE, + imagesArrowUp[0], imagesArrowUp[1], imagesArrowUp[2]); + + int width = buttonArrowUp.getImageSize().x; + int height = buttonArrowUp.getImageSize().y; + + buttonArrowUp.setBackground(parent.getBackground()); + buttonArrowUp.setLayoutData(new RowData(width, height)); + + /* shaft */ + canvasShaft = new Canvas(composite, SWT.NONE); + + final int widthShaft = width; + final int heightShaft = heightScrollBar - (height * 2); + canvasShaft.setLayoutData(new RowData(widthShaft, heightShaft)); + + canvasShaft.addPaintListener(new PaintListener() { + @Override + public void paintControl(PaintEvent e) { + if (imageShaft != null) { + e.gc.drawImage(imageShaft, 0, 0, + imageShaft.getImageData().width, + imageShaft.getImageData().height, + 0, 0, widthShaft, heightShaft); + } + } + }); + + /* arrow down */ + buttonArrowDown = new CustomButton(composite, SWT.NONE, + imagesArrowDown[0], imagesArrowDown[1], imagesArrowDown[2]); + + buttonArrowDown.setBackground(parent.getBackground()); + buttonArrowDown.setLayoutData(new RowData(width, height)); + } + + class ScrollerTask extends TimerTask { + @Override + public void run() { + int vSelection = getSelection(); + if (vSelection <= (173 - heightScrollBar - 1)) { + setSelection(getSelection() + 1); + logger.info("" + getSelection()); + +// Display.getCurrent().asyncExec(new Runnable() { +// @Override +// public void run() { + //compositeScroll.vScroll(); +// } +// }); + } + } + } + + protected void addScrollBarListener() { + buttonArrowUp.addMouseListener(new MouseListener() { + @Override + public void mouseDown(MouseEvent e) { + int shift = getSelection(); + + if (shift > 0) { + setSelection(getSelection() - Math.min(maxShift, shift)); + ((CustomScrolledComposite) parent.getParent()).vScroll(); + } + } + + @Override + public void mouseUp(MouseEvent e) { + /* do nothing */ + } + + @Override + public void mouseDoubleClick(MouseEvent e) { + /* do nothing */ + } + }); + + buttonArrowDown.addMouseListener(new MouseListener() { + @Override + public void mouseDown(MouseEvent e) { + int minHeightContents = + ((CustomScrolledComposite) parent.getParent()).getMinHeight(); + + int shift = (minHeightContents - heightScrollBar) - getSelection(); + + if (shift > 0) { + setSelection(getSelection() + Math.min(maxShift, shift)); + ((CustomScrolledComposite) parent.getParent()).vScroll(); + } + } + + @Override + public void mouseUp(MouseEvent e) { + timerScroller.cancel(); + timerScroller = new Timer(); + } + + @Override + public void mouseDoubleClick(MouseEvent e) { + /* do nothing */ + } + }); + +// buttonArrowDown.addDragDetectListener(new DragDetectListener() { +// @Override +// public void dragDetected( DragDetectEvent e ) { +// logger.info( "dragDetected:" + e.button ); +// timerScroller.schedule(new ScrollerTask(), 1, 100); +// } +// }); + } + + public int getSelection() { + return valueSelection; + } + + public void setSelection(int selection) { + valueSelection = selection; + } +} diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/custom/CustomScrolledComposite.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/custom/CustomScrolledComposite.java new file mode 100644 index 0000000000..9f2c4ab5d9 --- /dev/null +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/custom/CustomScrolledComposite.java @@ -0,0 +1,178 @@ +/** + * + * + * Copyright (C) 2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * YeongKyoon Lee + * + * 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.custom; + +import java.util.logging.Logger; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Listener; +import org.tizen.emulator.skin.log.SkinLogger; + +public class CustomScrolledComposite extends Composite { + + private Logger logger = + SkinLogger.getSkinLogger(CustomScrolledComposite.class).getLogger(); + + Control content; + Listener contentListener; + Listener filter; + Point sizeContent; + + Composite compositeRight; + CustomScrollBar vBar; + + private Image[] imagesArrowUp; + private Image[] imagesArrowDown; + private Image imageThumb; + private Image imageShaft; + + public int minHeight = 0; + public int minWidth = 0; + public boolean expandHorizontal = false; + public boolean expandVertical = false; + + private int value; + + public CustomScrolledComposite(Composite parent, int style, + Image[] imagesArrowUp, Image[] imagesArrowDown, + Image imageThumb, Image imageShaft) { + super(parent, style); + super.setLayout(new ScrolledCompositeLayout()); + + compositeRight = new Composite(this, SWT.NONE); + compositeRight.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_YELLOW)); + + GridLayout compositeGridLayout = new GridLayout(1, false); + compositeGridLayout.marginLeft = compositeGridLayout.marginRight = 0; + compositeGridLayout.marginTop = compositeGridLayout.marginBottom = 0; + compositeGridLayout.marginWidth = compositeGridLayout.marginHeight = 0; + compositeGridLayout.horizontalSpacing = compositeGridLayout.verticalSpacing = 0; + compositeRight.setLayout(compositeGridLayout); + + this.imagesArrowUp = imagesArrowUp; + this.imagesArrowDown = imagesArrowDown; + this.imageThumb = imageThumb; + this.imageShaft = imageShaft; + + value = 0; + } + + public CustomScrollBar getScrollBar() { + return vBar; + } + + public void setContent(Control content, Point sizeContent) { + checkWidget(); + if (this.content != null && !this.content.isDisposed()) { + this.content.removeListener(SWT.Resize, contentListener); + this.content.setBounds(new Rectangle(-200, -200, 0, 0)); + } + + this.content = content; + this.sizeContent = sizeContent; + + if (this.content != null) { + if (vBar == null) { + compositeRight.setBackground(this.content.getBackground()); + vBar = new CustomScrollBar(compositeRight, SWT.NONE, sizeContent.y, + imagesArrowUp, imagesArrowDown, imageThumb, imageShaft); + } + + content.setLocation(0, 0); + + layout(false); + + } + } + + public void setExpandHorizontal(boolean expand) { + checkWidget(); + if (expand == expandHorizontal) return; + expandHorizontal = expand; + layout(false); + } + + public void setExpandVertical(boolean expand) { + checkWidget(); + if (expand == expandVertical) return; + expandVertical = expand; + layout(false); + } + + public void setMinSize(Point size) { + if (size == null) { + setMinSize(0, 0); + } else { + setMinSize(size.x, size.y); + } + } + + public void setMinSize(int width, int height) { + checkWidget(); + if (width == minWidth && height == minHeight) { + return; + } + + minWidth = Math.max(0, width); + minHeight = Math.max(0, height); + + logger.info("composite minWidth : " + minWidth + + ", minHeight : " + minHeight); + + layout(false); + } + + public int getMinWidth() { + checkWidget(); + return minWidth; + } + + public int getMinHeight() { + checkWidget(); + return minHeight; + } + + public void vScroll() { + if (content == null) { + return; + } + + Point location = content.getLocation(); + int vSelection = vBar.getSelection(); + + content.setLocation(location.x, -vSelection); + } +} \ No newline at end of file diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/custom/CustomScrolledCompositeLayout.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/custom/CustomScrolledCompositeLayout.java new file mode 100644 index 0000000000..2b36253b9e --- /dev/null +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/custom/CustomScrolledCompositeLayout.java @@ -0,0 +1,101 @@ +/** + * + * + * Copyright (C) 2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * YeongKyoon Lee + * + * 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.custom; + +import java.util.logging.Logger; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Layout; +import org.tizen.emulator.skin.log.SkinLogger; + +class ScrolledCompositeLayout extends Layout { + static final int DEFAULT_WIDTH = 64; + static final int DEFAULT_HEIGHT = 64; + + private Logger logger = SkinLogger.getSkinLogger( + ScrolledCompositeLayout.class).getLogger(); + + private boolean inLayout = false; + + protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) { + CustomScrolledComposite sc = (CustomScrolledComposite)composite; + Point size = new Point(DEFAULT_WIDTH, DEFAULT_HEIGHT); + + if (sc.content != null) { + Point preferredSize = sc.content.computeSize(wHint, hHint, flushCache); + size.x = preferredSize.x; + size.y = preferredSize.y; + } + size.x = Math.max(size.x, sc.minWidth); + size.y = Math.max(size.y, sc.minHeight); + + if (wHint != SWT.DEFAULT) size.x = wHint; + if (hHint != SWT.DEFAULT) size.y = hHint; + + return size; + } + + protected boolean flushCache(Control control) { + return true; + } + + protected void layout(Composite composite, boolean flushCache) { + if (inLayout) { + return; + } + + CustomScrolledComposite sc = (CustomScrolledComposite)composite; + if (sc.content == null) { + return; + } + + inLayout = true; + Rectangle contentRect = sc.content.getBounds(); + + Rectangle hostRect = sc.getClientArea(); + if (sc.expandHorizontal) { + contentRect.width = Math.max(sc.minWidth, hostRect.width); + } + if (sc.expandVertical) { + contentRect.height = Math.max(sc.minHeight, hostRect.height); + } + + sc.content.setBounds(contentRect); + + Point size = sc.compositeRight.computeSize(SWT.DEFAULT, SWT.DEFAULT); + sc.compositeRight.setBounds( + contentRect.width - size.x, 0, size.x, contentRect.height); + + inLayout = false; + } +} diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/custom/KeyWindow.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/custom/KeyWindow.java new file mode 100644 index 0000000000..0eb30aa8ae --- /dev/null +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/custom/KeyWindow.java @@ -0,0 +1,474 @@ +/** + * + * + * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * YeongKyoon Lee + * + * 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.custom; + +import java.util.List; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.ScrolledComposite; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.events.MouseMoveListener; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.events.ShellEvent; +import org.eclipse.swt.events.ShellListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.ImageData; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.graphics.Region; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.tizen.emulator.skin.EmulatorSkin; +import org.tizen.emulator.skin.comm.ICommunicator.KeyEventType; +import org.tizen.emulator.skin.comm.ICommunicator.SendCommand; +import org.tizen.emulator.skin.comm.sock.SocketCommunicator; +import org.tizen.emulator.skin.comm.sock.data.KeyEventData; +import org.tizen.emulator.skin.dbi.KeyMapType; +import org.tizen.emulator.skin.image.ImageRegistry.KeyWindowImageName; +import org.tizen.emulator.skin.layout.SkinPatches; +import org.tizen.emulator.skin.util.SwtUtil; + +public class KeyWindow extends SkinWindow { + private static final String PATCH_IMAGES_PATH = "images/key-window/"; + private static final int SHELL_MARGIN_BOTTOM = 3; + private static final int PAIRTAG_CIRCLE_SIZE = 8; + private static final int PAIRTAG_MARGIN_BOTTOM = 6; + private static final int BUTTON_DEFAULT_CNT = 4; + private static final int BUTTON_VERTICAL_SPACING = 7; + private static final int SCROLLBAR_HORIZONTAL_SPACING = 4; + private static final int SCROLLBAR_SIZE_WIDTH = 14; + + private EmulatorSkin skin; + private SkinPatches frameMaker; + + private int widthBase; + private int heightBase; + private int widthScrollbar; + private int cntHiddenButton; + + private Image imageNormal; /* ImageButton image */ + private Image imageHover; /* hovered ImageButton image */ + private Image imagePushed; /* pushed ImageButton image */ + private Image imageFrame; /* nine-patch image */ + + private Color colorFrame; + private SocketCommunicator communicator; + private List keyMapList; + + private ShellListener shellListener; + private PaintListener shellPaintListener; + private MouseMoveListener shellMouseMoveListener; + private MouseListener shellMouseListener; + + private boolean isGrabbedShell; + private Point grabPosition; + + public KeyWindow(EmulatorSkin skin, Shell parent, + SocketCommunicator communicator, List keyMapList) { + super(parent, SWT.RIGHT | SWT.CENTER); + + this.skin = skin; + this.shell = new Shell(Display.getDefault(), + SWT.NO_TRIM | SWT.RESIZE | SWT.TOOL); + this.frameMaker = new SkinPatches(PATCH_IMAGES_PATH); + + this.keyMapList = keyMapList; //TODO: null + this.communicator = communicator; + this.grabPosition = new Point(0, 0); + + shell.setText(parent.getText()); + shell.setImage(parent.getImage()); + + /* load image for HW key button */ + imageNormal = skin.getImageRegistry().getKeyWindowImageData( + KeyWindowImageName.KEYBUTTON_NORMAL); + imageHover = skin.getImageRegistry().getKeyWindowImageData( + KeyWindowImageName.KEYBUTTON_HOVER); + imagePushed = skin.getImageRegistry().getKeyWindowImageData( + KeyWindowImageName.KEYBUTTON_PUSHED); + + /* calculate the key window size */ + widthBase = imageNormal.getImageData().width; + heightBase = (imageNormal.getImageData().height * BUTTON_DEFAULT_CNT) + + (BUTTON_VERTICAL_SPACING * (BUTTON_DEFAULT_CNT - 1)); + + widthScrollbar = SCROLLBAR_SIZE_WIDTH + SCROLLBAR_HORIZONTAL_SPACING; + int heightHeaderPart = (PAIRTAG_CIRCLE_SIZE + PAIRTAG_MARGIN_BOTTOM); + int heightTailPart = SHELL_MARGIN_BOTTOM; + + /* make a frame image */ + this.cntHiddenButton = 0; //keyMapList.size() - BUTTON_DEFAULT_CNT; + + this.imageFrame = frameMaker.getPatchedImage( + widthBase + ((cntHiddenButton > 0) ? widthScrollbar : 0), + heightBase + heightHeaderPart + heightTailPart); + this.colorFrame = new Color(shell.getDisplay(), new RGB(38, 38, 38)); + + shell.setBackground(colorFrame); + + createContents(); + trimPatchedShell(shell, imageFrame); + + addKeyWindowListener(); + + shell.setSize(imageFrame.getImageData().width, + imageFrame.getImageData().height); + } + + protected void createContents() { + GridLayout shellGridLayout = new GridLayout(1, false); + shellGridLayout.marginLeft = shellGridLayout.marginRight = frameMaker.getPatchWidth(); + shellGridLayout.marginTop = frameMaker.getPatchHeight(); + shellGridLayout.marginBottom = frameMaker.getPatchHeight() + SHELL_MARGIN_BOTTOM; + shellGridLayout.marginWidth = shellGridLayout.marginHeight = 0; + shellGridLayout.horizontalSpacing = shellGridLayout.verticalSpacing = 0; + + shell.setLayout(shellGridLayout); + + /* make a pair tag circle */ + ColorTag pairTagCanvas = new ColorTag(shell, SWT.NONE, skin.getColorVM()); + pairTagCanvas.setLayoutData(new GridData(PAIRTAG_CIRCLE_SIZE, + PAIRTAG_CIRCLE_SIZE + PAIRTAG_MARGIN_BOTTOM)); + + /* make a region of HW keys */ + if (cntHiddenButton > 0) { + /* added custom scrollbar */ + + Image imagesScrollArrowUp[] = new Image[3]; + Image imagesScrollArrowDown[] = new Image[3]; + + imagesScrollArrowUp[0] = skin.getImageRegistry().getKeyWindowImageData( + KeyWindowImageName.SCROLL_UPBUTTON_NORMAL); + imagesScrollArrowUp[1] = skin.getImageRegistry().getKeyWindowImageData( + KeyWindowImageName.SCROLL_UPBUTTON_HOVER); + imagesScrollArrowUp[2] = skin.getImageRegistry().getKeyWindowImageData( + KeyWindowImageName.SCROLL_UPBUTTON_PUSHED); + + imagesScrollArrowDown[0] = skin.getImageRegistry().getKeyWindowImageData( + KeyWindowImageName.SCROLL_DOWNBUTTON_NORMAL); + imagesScrollArrowDown[1] = skin.getImageRegistry().getKeyWindowImageData( + KeyWindowImageName.SCROLL_DOWNBUTTON_HOVER); + imagesScrollArrowDown[2] = skin.getImageRegistry().getKeyWindowImageData( + KeyWindowImageName.SCROLL_DOWNBUTTON_PUSHED); + + CustomScrolledComposite compositeScroll = + new CustomScrolledComposite(shell, SWT.NONE, + imagesScrollArrowUp, imagesScrollArrowDown, + skin.getImageRegistry().getKeyWindowImageData( + KeyWindowImageName.SCROLL_THUMB), + skin.getImageRegistry().getKeyWindowImageData( + KeyWindowImageName.SCROLL_SHAFT)); + compositeScroll.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, true, true, 1, 1)); + + Composite compositeBase = new Composite(compositeScroll, SWT.NONE); + + createHwKeys(compositeBase); + + Point sizeContent = compositeBase.computeSize( + widthBase + widthScrollbar, heightBase); + compositeScroll.setContent(compositeBase, sizeContent); + compositeScroll.setExpandHorizontal(true); + compositeScroll.setExpandVertical(true); + + sizeContent.y += (imageNormal.getImageData().height * cntHiddenButton) + + (BUTTON_VERTICAL_SPACING * cntHiddenButton); + compositeScroll.setMinSize(sizeContent); + } else { + ScrolledComposite compositeScroll = new ScrolledComposite(shell, SWT.V_SCROLL); + compositeScroll.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, true, true, 1, 1)); + + Composite compositeBase = new Composite(compositeScroll, SWT.NONE); + createHwKeys(compositeBase); + + compositeScroll.setContent(compositeBase); + compositeScroll.setExpandHorizontal(true); + compositeScroll.setExpandVertical(true); + compositeScroll.setMinSize(compositeBase.computeSize(SWT.DEFAULT, SWT.DEFAULT)); + } + } + + protected void createHwKeys(Composite composite) { + composite.setBackground(colorFrame); + + GridLayout compositeGridLayout = new GridLayout(1, false); + compositeGridLayout.marginLeft = compositeGridLayout.marginRight = 0; + compositeGridLayout.marginTop = compositeGridLayout.marginBottom = 0; + compositeGridLayout.marginWidth = compositeGridLayout.marginHeight = 0; + compositeGridLayout.horizontalSpacing = 0; + compositeGridLayout.verticalSpacing = BUTTON_VERTICAL_SPACING; + composite.setLayout(compositeGridLayout); + + /* attach HW keys */ + if (keyMapList != null && keyMapList.isEmpty() == false) { + for (KeyMapType keyEntry : keyMapList) { + CustomButton HWKeyButton = new CustomButton(composite, + SWT.NO_FOCUS, imageNormal, imageHover, imagePushed); + HWKeyButton.setText(keyEntry.getEventInfo().getKeyName()); + HWKeyButton.setToolTipText(keyEntry.getTooltip()); + HWKeyButton.setBackground(colorFrame); + HWKeyButton.setLayoutData(new GridData(imageNormal.getImageData().width, + imageNormal.getImageData().height)); + + final int keycode = keyEntry.getEventInfo().getKeyCode(); + HWKeyButton.addMouseListener(new MouseListener() { + @Override + public void mouseDown(MouseEvent e) { + KeyEventData keyEventData = new KeyEventData( + KeyEventType.PRESSED.value(), keycode, 0, 0); + communicator.sendToQEMU(SendCommand.SEND_HARD_KEY_EVENT, keyEventData); + } + + @Override + public void mouseUp(MouseEvent e) { + KeyEventData keyEventData = new KeyEventData( + KeyEventType.RELEASED.value(), keycode, 0, 0); + communicator.sendToQEMU(SendCommand.SEND_HARD_KEY_EVENT, keyEventData); + } + + @Override + public void mouseDoubleClick(MouseEvent e) { + /* do nothing */ + } + }); + } + } + } + + public static void trimPatchedShell(Shell shell, Image image) { + if (null == image) { + return; + } + ImageData imageData = image.getImageData(); + + int width = imageData.width; + int height = imageData.height; + + Region region = new Region(); + region.add(new Rectangle(0, 0, width, height)); + + int r = shell.getDisplay().getSystemColor(SWT.COLOR_MAGENTA).getRed(); + int g = shell.getDisplay().getSystemColor(SWT.COLOR_MAGENTA).getGreen(); + int b = shell.getDisplay().getSystemColor(SWT.COLOR_MAGENTA).getBlue(); + int colorKey; + + if (SwtUtil.isWindowsPlatform()) { + colorKey = r << 24 | g << 16 | b << 8; + } else { + colorKey = r << 16 | g << 8 | b; + } + + for (int i = 0; i < width; i++) { + for (int j = 0; j < height; j++) { + int colorPixel = imageData.getPixel(i, j); + if (colorPixel == colorKey /* magenta */) { + region.subtract(i, j, 1, 1); + } + } + } + + shell.setRegion(region); + } + + private void addKeyWindowListener() { + shellPaintListener = new PaintListener() { + @Override + public void paintControl(final PaintEvent e) { + if (imageFrame != null) { + e.gc.drawImage(imageFrame, 0, 0); + } + } + }; + + shell.addPaintListener(shellPaintListener); + + shellListener = new ShellListener() { + @Override + public void shellClosed(ShellEvent event) { + logger.info("Key Window is closed"); + + if (skin.pairTag != null) { + skin.pairTag.setVisible(false); + } + skin.keyWindow = null; + + if (null != shellPaintListener) { + shell.removePaintListener(shellPaintListener); + } + + if (null != shellListener) { + shell.removeShellListener(shellListener); + } + + if (null != shellMouseMoveListener) { + shell.removeMouseMoveListener(shellMouseMoveListener); + } + + if (null != shellMouseListener) { + shell.removeMouseListener(shellMouseListener); + } + + colorFrame.dispose(); + + frameMaker.freePatches(); + } + + @Override + public void shellActivated(ShellEvent event) { + logger.info("activate"); + + if (SwtUtil.isMacPlatform() == true) { + parent.moveAbove(shell); + } else { + shell.getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + parent.setActive(); + } + }); + } + } + + @Override + public void shellDeactivated(ShellEvent event) { + logger.info("deactivate"); + + /* do nothing */ + } + + @Override + public void shellIconified(ShellEvent event) { + /* do nothing */ + } + + @Override + public void shellDeiconified(ShellEvent event) { + logger.info("deiconified"); + + shell.getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + if (parent.getMinimized() == true) { + parent.setMinimized(false); + } + } + }); + } + }; + + shell.addShellListener(shellListener); + + shellMouseMoveListener = new MouseMoveListener() { + @Override + public void mouseMove(MouseEvent e) { + if (isGrabbedShell == true && e.button == 0/* left button */) { + if (getDockPosition() != SWT.NONE) { + dock(SWT.NONE, false, false); + shell.moveAbove(parent); + } + + /* move a window */ + Point previousLocation = shell.getLocation(); + int x = previousLocation.x + (e.x - grabPosition.x); + int y = previousLocation.y + (e.y - grabPosition.y); + + shell.setLocation(x, y); + return; + } + } + }; + + shell.addMouseMoveListener(shellMouseMoveListener); + + shellMouseListener = new MouseListener() { + @Override + public void mouseUp(MouseEvent e) { + if (e.button == 1) { /* left button */ + isGrabbedShell = false; + grabPosition.x = grabPosition.y = 0; + + /* Let me check whether the key window was landed + * on docking area. */ + Rectangle parentBounds = parent.getBounds(); + Rectangle childBounds = shell.getBounds(); + + int heightOneThird = parentBounds.height / 3; + + /* right-middle */ + Rectangle attachBounds1 = new Rectangle( + (parentBounds.x + parentBounds.width) - 5, + parentBounds.y + heightOneThird, + 30, heightOneThird); + /* right-top */ + Rectangle attachBounds2 = new Rectangle( + (parentBounds.x + parentBounds.width) - 5, + parentBounds.y, + 30, heightOneThird); + /* right-bottom */ + Rectangle attachBounds3 = new Rectangle( + (parentBounds.x + parentBounds.width) - 5, + parentBounds.y + (heightOneThird * 2), + 30, heightOneThird); + + if (childBounds.intersects(attachBounds1) == true) { + dock(SWT.RIGHT | SWT.CENTER, false, true); + } else if (childBounds.intersects(attachBounds2) == true) { + dock(SWT.RIGHT | SWT.TOP, false, true); + } else if (childBounds.intersects(attachBounds3) == true) { + dock(SWT.RIGHT | SWT.BOTTOM, false, true); + } else { + dock(SWT.NONE, false, true); + } + } + } + + @Override + public void mouseDown(MouseEvent e) { + if (1 == e.button) { /* left button */ + isGrabbedShell = true; + grabPosition.x = e.x; + grabPosition.y = e.y; + } + } + + @Override + public void mouseDoubleClick(MouseEvent e) { + /* do nothing */ + } + }; + + shell.addMouseListener(shellMouseListener); + } +} diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/custom/SkinWindow.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/custom/SkinWindow.java new file mode 100644 index 0000000000..19e08746aa --- /dev/null +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/custom/SkinWindow.java @@ -0,0 +1,130 @@ +/** + * + * + * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * YeongKyoon Lee + * + * 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.custom; + +import java.util.logging.Logger; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.tizen.emulator.skin.log.SkinLogger; + +public class SkinWindow { + protected Logger logger = SkinLogger.getSkinLogger( + SkinWindow.class).getLogger(); + + protected Shell shell; + protected Shell parent; + private int dockPosition; + + public SkinWindow(Shell parent, int dockPosition) { + this.parent = parent; + this.dockPosition = dockPosition; + } + + public Shell getShell() { + return shell; + } + + public void open(int dockValue) { + if (shell.isDisposed()) { + return; + } + + dock(dockValue, true, true); + + shell.open(); + } + + public void dock(int dockValue, + boolean correction, boolean enableLogger) { + int x = 0; + int y = 0; + + Rectangle monitorBounds = Display.getDefault().getBounds(); + Rectangle parentBounds = parent.getBounds(); + Rectangle childBounds = shell.getBounds(); + + if (enableLogger == true) { + logger.info("host monitor display bounds : " + monitorBounds); + logger.info("current parent shell bounds : " + parentBounds); + logger.info("current child shell bounds : " + childBounds); + } + + dockPosition = dockValue; + + if (dockPosition == SWT.NONE){ + logger.info("undock"); + /* do nothing */ + + return; + } else if (dockPosition == (SWT.RIGHT | SWT.TOP)) { + x = parentBounds.x + parentBounds.width; + y = parentBounds.y; + + /* correction of location */ + /*if ((x + childBounds.width) > + (monitorBounds.x + monitorBounds.width)) { + x = parentBounds.x - childBounds.width; + }*/ + } else if (dockPosition == (SWT.RIGHT | SWT.BOTTOM)) { + x = parentBounds.x + parentBounds.width; + y = parentBounds.y + parentBounds.height - childBounds.height; + + /* correction of location */ + /*int shift = (monitorBounds.x + monitorBounds.width) - + (x + childBounds.width); + if (shift < 0) { + x += shift; + parent.setLocation(parentBounds.x + shift, parentBounds.y); + }*/ + } else { /* SWT.RIGHT | SWT.CENTER */ + x = parentBounds.x + parentBounds.width; + y = parentBounds.y + (parentBounds.height / 2) - + (childBounds.height / 2); + } + + /* correction of location */ + if (correction == true) { + int shift = (monitorBounds.x + monitorBounds.width) - + (x + childBounds.width); + if (shift < 0) { + x += shift; + parent.setLocation(parentBounds.x + shift, parentBounds.y); + } + } + + shell.setLocation(x, y); + } + + public int getDockPosition() { + return dockPosition; + } +} diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/dialog/AboutDialog.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/dialog/AboutDialog.java index 0077773942..c95ba2496a 100644 --- a/tizen/src/skin/client/src/org/tizen/emulator/skin/dialog/AboutDialog.java +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/dialog/AboutDialog.java @@ -52,6 +52,7 @@ import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Link; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; +import org.tizen.emulator.skin.config.EmulatorConfig; import org.tizen.emulator.skin.log.SkinLogger; import org.tizen.emulator.skin.util.IOUtil; import org.tizen.emulator.skin.util.StringUtil; @@ -67,12 +68,17 @@ public class AboutDialog extends SkinDialog { public static final String URL_TIZEN_ORG = "https://developer.tizen.org"; + private Logger logger = + SkinLogger.getSkinLogger(AboutDialog.class).getLogger(); + private Image aboutImage; + private EmulatorConfig config; - private Logger logger = SkinLogger.getSkinLogger(AboutDialog.class).getLogger(); - public AboutDialog(Shell parent) { + public AboutDialog(Shell parent, EmulatorConfig config) { super(parent, "About Tizen Emulator", SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL); + + this.config = config; } private GridLayout getNopaddedGridLayout(int numColumns, boolean makeColumnEqualWidth) { @@ -160,10 +166,13 @@ public class AboutDialog extends SkinDialog { /* SDK version */ Text versionText = new Text(compositeRight, SWT.NONE); - String version = getValue(properties, PROP_KEY_VERSION); + /*String version = getValue(properties, PROP_KEY_VERSION); if (version.isEmpty()) { version = "Not identified"; - } + }*/ + String version = config.getSkinProperty( + EmulatorConfig.SkinInfoConstants.SDK_VERSION_NAME); + versionText.setText("Version : " + version); versionText.setEditable(false); versionText.setBackground(white); diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/image/ImageRegistry.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/image/ImageRegistry.java index 7e77c002a9..d7623f82ed 100644 --- a/tizen/src/skin/client/src/org/tizen/emulator/skin/image/ImageRegistry.java +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/image/ImageRegistry.java @@ -63,14 +63,15 @@ public class ImageRegistry { public static final String SKINS_FOLDER = "skins"; public static final String GENERAL_FOLDER = "emul-general"; public static final String ICON_FOLDER = "icons"; - + public static final String IMAGES_FOLDER = "images"; + public static final String KEYWINDOW_FOLDER = "key-window"; + public enum ImageType { IMG_TYPE_MAIN, IMG_TYPE_PRESSED } - + public enum IconName { - DETAIL_INFO("detail_info.png"), ROTATE("rotate.png"), SCALE("scale.png"), @@ -104,12 +105,38 @@ public class ImageRegistry { } } - + + public enum KeyWindowImageName { + KEYBUTTON_NORMAL("keybutton_nml.png"), + KEYBUTTON_HOVER("keybutton_hover.png"), + KEYBUTTON_PUSHED("keybutton_pushed.png"), + + SCROLL_UPBUTTON_NORMAL("scroll_button_up_nml.png"), + SCROLL_UPBUTTON_HOVER("scroll_button_up_hover.png"), + SCROLL_UPBUTTON_PUSHED("scroll_button_up_pushed.png"), + SCROLL_DOWNBUTTON_NORMAL("scroll_button_down_nml.png"), + SCROLL_DOWNBUTTON_HOVER("scroll_button_down_hover.png"), + SCROLL_DOWNBUTTON_PUSHED("scroll_button_down_pushed.png"), + SCROLL_THUMB("scroll_thumb.png"), + SCROLL_SHAFT("scroll_back.png"); + + private String name; + + private KeyWindowImageName(String name) { + this.name = name; + } + + public String getName() { + return this.name; + } + } + private Display display; private EmulatorUI dbiContents; private Map skinImageMap; private Map iconMap; + private Map keyWindowImageMap; private String argSkinPath; @@ -140,6 +167,7 @@ public class ImageRegistry { this.dbiContents = config.getDbiContents(); this.skinImageMap = new HashMap(); this.iconMap = new HashMap(); + this.keyWindowImageMap = new HashMap(); init(this.argSkinPath); @@ -243,13 +271,12 @@ public class ImageRegistry { return id + ":" + imageType.ordinal(); } - public Image getIcon( IconName name ) { + public Image getIcon(IconName name) { - if ( 0 != iconMap.size() ) { + if (0 != iconMap.size()) { + Image image = iconMap.get(name.getName()); - Image image = iconMap.get( name.getName() ); return image; - } else { // load all of the icons at once. @@ -257,7 +284,7 @@ public class ImageRegistry { ClassLoader classLoader = this.getClass().getClassLoader(); IconName[] values = IconName.values(); - for ( IconName iconName : values ) { + for (IconName iconName : values) { String icoNname = iconName.getName(); @@ -265,53 +292,93 @@ public class ImageRegistry { InputStream is = null; try { - is = classLoader.getResourceAsStream( iconPath ); - if ( null != is ) { - logger.fine( "load icon:" + iconPath ); - iconMap.put( icoNname, new Image( display, is ) ); + is = classLoader.getResourceAsStream(iconPath); + if (null != is) { + logger.fine("load icon:" + iconPath); + iconMap.put(icoNname, new Image(display, is)); } else { - logger.severe( "missing icon:" + iconPath ); + logger.severe("missing icon:" + iconPath); } } finally { - IOUtil.close( is ); + IOUtil.close(is); } } - return iconMap.get( name.getName() ); - + return iconMap.get(name.getName()); } - } - public void dispose() { + public Image getKeyWindowImageData(KeyWindowImageName name) { + if (0 != keyWindowImageMap.size()) { + Image image = keyWindowImageMap.get(name.getName()); + + return image; + } else { + ClassLoader classLoader = this.getClass().getClassLoader(); + KeyWindowImageName[] values = KeyWindowImageName.values(); - if ( null != skinImageMap ) { + for (KeyWindowImageName value : values) { + String imageName = value.getName(); + + String imagePath = IMAGES_FOLDER + "/" + + KEYWINDOW_FOLDER + "/" + imageName; + + InputStream is = null; + try { + is = classLoader.getResourceAsStream(imagePath); + if (null != is) { + logger.fine("load keywindow images:" + imagePath); + keyWindowImageMap.put(imageName, new Image(display, is)); + } else { + logger.severe("missing image:" + imagePath); + } + } finally { + IOUtil.close(is); + } + + } + + return keyWindowImageMap.get(name.getName()); + } + } + + public void dispose() { + /* skin image */ + if (null != skinImageMap) { Collection images = skinImageMap.values(); Iterator imageIterator = images.iterator(); - while ( imageIterator.hasNext() ) { + while (imageIterator.hasNext()) { Image image = imageIterator.next(); image.dispose(); } - } - if ( null != iconMap ) { - + /* icon */ + if (null != iconMap) { Collection icons = iconMap.values(); Iterator iconIterator = icons.iterator(); - while ( iconIterator.hasNext() ) { + while (iconIterator.hasNext()) { Image image = iconIterator.next(); image.dispose(); } - } + /* key window image */ + if (null != keyWindowImageMap) { + Collection images = keyWindowImageMap.values(); + + Iterator imagesIterator = images.iterator(); + + while (imagesIterator.hasNext()) { + Image image = imagesIterator.next(); + image.dispose(); + } + } } - } diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/layout/GeneralPurposeSkinComposer.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/layout/GeneralPurposeSkinComposer.java index 2fbb281cd1..fe317dfb56 100644 --- a/tizen/src/skin/client/src/org/tizen/emulator/skin/layout/GeneralPurposeSkinComposer.java +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/layout/GeneralPurposeSkinComposer.java @@ -1,7 +1,7 @@ /** * * - * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: * GiWoong Kim @@ -51,6 +51,7 @@ 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.SkinPropertiesConstants; +import org.tizen.emulator.skin.custom.ColorTag; import org.tizen.emulator.skin.custom.CustomButton; import org.tizen.emulator.skin.custom.CustomProgressBar; import org.tizen.emulator.skin.image.ImageRegistry; @@ -68,8 +69,6 @@ public class GeneralPurposeSkinComposer implements ISkinComposer { private static final int PAIR_TAG_POSITION_X = 26; private static final int PAIR_TAG_POSITION_Y = 13; - private static final int PAIR_TAG_POSITION_WIDTH = 8; - private static final int PAIR_TAG_POSITION_HEIGHT = 8; private Logger logger = SkinLogger.getSkinLogger( GeneralPurposeSkinComposer.class).getLogger(); @@ -109,6 +108,8 @@ public class GeneralPurposeSkinComposer implements ISkinComposer { @Override public Canvas compose(int style) { + shell.setBackground(backgroundColor); + displayCanvas = new Canvas(shell, style); int vmIndex = config.getArgInt(ArgsConstants.NET_BASE_PORT) % 100; @@ -141,7 +142,7 @@ public class GeneralPurposeSkinComposer implements ISkinComposer { shell.setLocation(x, y); String emulatorName = SkinUtil.makeEmulatorName(config); - shell.setText(emulatorName); + shell.setText("Emulator - " + emulatorName); displayCanvas.setBackground( shell.getDisplay().getSystemColor(SWT.COLOR_BLACK)); @@ -189,21 +190,9 @@ public class GeneralPurposeSkinComposer implements ISkinComposer { }); /* make a pair tag circle */ - skin.pairTagCanvas = new Canvas(shell, SWT.NO_FOCUS); - skin.pairTagCanvas.setBackground(backgroundColor); - - skin.pairTagCanvas.addPaintListener(new PaintListener() { - @Override - public void paintControl(PaintEvent e) { - if (skin.colorPairTag != null) { - e.gc.setBackground(skin.colorPairTag); - e.gc.setAntialias(SWT.ON); - e.gc.fillOval( - 0, 0, PAIR_TAG_POSITION_WIDTH, PAIR_TAG_POSITION_HEIGHT); - } - } - }); - skin.pairTagCanvas.setVisible(false); + skin.pairTag = + new ColorTag(shell, SWT.NO_FOCUS, skin.getColorVM()); + skin.pairTag.setVisible(false); /* create a progress bar for booting status */ skin.bootingProgress = new CustomProgressBar(shell, SWT.NONE); @@ -269,11 +258,6 @@ public class GeneralPurposeSkinComposer implements ISkinComposer { displayBounds.y + displayBounds.height + 1, displayBounds.width, 2); } - /* arrange the pair tag */ - skin.pairTagCanvas.setBounds( - PAIR_TAG_POSITION_X, PAIR_TAG_POSITION_Y, - PAIR_TAG_POSITION_WIDTH, PAIR_TAG_POSITION_HEIGHT); - /* set window size */ if (currentState.getCurrentImage() != null) { ImageData imageData = currentState.getCurrentImage().getImageData(); @@ -287,6 +271,29 @@ public class GeneralPurposeSkinComposer implements ISkinComposer { shell.setSize(imageData.width, imageData.height); } + /* arrange the pair tag */ + int rotationType = currentState.getCurrentRotationId(); + if (rotationType == RotationInfo.PORTRAIT.id()) { + skin.pairTag.setBounds( + PAIR_TAG_POSITION_X, PAIR_TAG_POSITION_Y, + skin.pairTag.getWidth(), skin.pairTag.getHeight()); + } else if (rotationType == RotationInfo.LANDSCAPE.id()) { + skin.pairTag.setBounds( + PAIR_TAG_POSITION_Y, + shell.getSize().y - PAIR_TAG_POSITION_X - skin.pairTag.getHeight(), + skin.pairTag.getWidth(), skin.pairTag.getHeight()); + } else if (rotationType == RotationInfo.REVERSE_PORTRAIT.id()) { + skin.pairTag.setBounds( + shell.getSize().x - PAIR_TAG_POSITION_X - skin.pairTag.getWidth(), + shell.getSize().y - PAIR_TAG_POSITION_Y - skin.pairTag.getHeight(), + skin.pairTag.getWidth(), skin.pairTag.getHeight()); + } else if (rotationType == RotationInfo.REVERSE_LANDSCAPE.id()) { + skin.pairTag.setBounds( + shell.getSize().x - PAIR_TAG_POSITION_Y - skin.pairTag.getWidth(), + PAIR_TAG_POSITION_X, + skin.pairTag.getWidth(), skin.pairTag.getHeight()); + } + /* custom window shape */ trimPatchedShell(shell, currentState.getCurrentImage()); @@ -499,8 +506,8 @@ public class GeneralPurposeSkinComposer implements ISkinComposer { toggleButton.dispose(); } - if (skin.pairTagCanvas != null) { - skin.pairTagCanvas.dispose(); + if (skin.pairTag != null) { + skin.pairTag.dispose(); } if (backgroundColor != null) { diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/layout/PhoneShapeSkinComposer.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/layout/PhoneShapeSkinComposer.java index 7fd6b9ec33..21eeeea071 100644 --- a/tizen/src/skin/client/src/org/tizen/emulator/skin/layout/PhoneShapeSkinComposer.java +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/layout/PhoneShapeSkinComposer.java @@ -136,7 +136,7 @@ public class PhoneShapeSkinComposer implements ISkinComposer { shell.setLocation(x, y); String emulatorName = SkinUtil.makeEmulatorName(config); - shell.setText(emulatorName); + shell.setText("Emulator - " + emulatorName); lcdCanvas.setBackground(shell.getDisplay().getSystemColor(SWT.COLOR_BLACK)); diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/util/SkinUtil.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/util/SkinUtil.java index 7d97323069..b4d0a51024 100644 --- a/tizen/src/skin/client/src/org/tizen/emulator/skin/util/SkinUtil.java +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/util/SkinUtil.java @@ -124,6 +124,10 @@ public class SkinUtil { return sdbPath; } + public static String getSdkVersionFilePath() { + return ".." + File.separator + "etc" + File.separator + "version"; + } + public static List getHWKeyMapList(short rotationId) { RotationType rotation = SkinRotation.getRotation(rotationId); if (rotation == null) { diff --git a/tizen/src/skin/maruskin_client.c b/tizen/src/skin/maruskin_client.c index 4dacfe7a71..c79503385e 100644 --- a/tizen/src/skin/maruskin_client.c +++ b/tizen/src/skin/maruskin_client.c @@ -49,7 +49,6 @@ MULTI_DEBUG_CHANNEL(qemu, skin_client); - #define SKIN_SERVER_READY_TIME 3 // second #define SKIN_SERVER_SLEEP_TIME 10 // milli second @@ -64,6 +63,10 @@ extern char tizen_target_path[]; static int skin_argc; static char** skin_argv; +#ifdef CONFIG_WIN32 +static char* JAVA_EXEFILE_PATH = NULL; +#endif + static void* run_skin_client(void* arg) { char cmd[JAVA_MAX_COMMAND_LENGTH] = { 0, }; @@ -90,7 +93,7 @@ static void* run_skin_client(void* arg) char buf_tizen_base_port[16]; sprintf(buf_skin_server_port, "%d", skin_server_port); sprintf(buf_uid, "%d", uid); - sprintf(buf_tizen_base_port, "%d", tizen_base_port); + sprintf(buf_tizen_base_port, "%d", get_emul_vm_base_port()); #ifdef CONFIG_WIN32 // find java path in 64bit windows @@ -114,11 +117,12 @@ static void* run_skin_client(void* arg) char* bin_dir = get_bin_path(); #endif INFO("bin directory : %s\n", bin_dir); + int maxtouchpoint = get_emul_max_touch_point(); int len_maxtouchpoint; - if(maxtouchpoint > 9) { + if (maxtouchpoint > 9) { len_maxtouchpoint = 2; - }else { + } else { len_maxtouchpoint = 1; } @@ -146,16 +150,16 @@ static void* run_skin_client(void* arg) OPT_SVR_PORT, skin_server_port, OPT_UID, uid, OPT_VM_PATH, vm_path, - OPT_NET_BASE_PORT, tizen_base_port, + OPT_NET_BASE_PORT, get_emul_vm_base_port(), OPT_MAX_TOUCHPOINT, maxtouchpoint, - argv ); + argv); INFO("command for swt : %s\n", cmd); #ifdef CONFIG_WIN32 // for 64bit windows free(JAVA_EXEFILE_PATH); - JAVA_EXEFILE_PATH=0; + JAVA_EXEFILE_PATH = NULL; //WinExec( cmd, SW_SHOW ); { @@ -257,10 +261,11 @@ int start_skin_client(int argc, char* argv[]) } else { count++; INFO("sleep for ready. count:%d\n", count); + #ifdef CONFIG_WIN32 - Sleep(SKIN_SERVER_SLEEP_TIME); + Sleep(SKIN_SERVER_SLEEP_TIME); #else - usleep(1000 * SKIN_SERVER_SLEEP_TIME); + usleep(1000 * SKIN_SERVER_SLEEP_TIME); #endif } diff --git a/tizen/src/skin/maruskin_client.h b/tizen/src/skin/maruskin_client.h index 9c3707dc33..4c42cc6d64 100644 --- a/tizen/src/skin/maruskin_client.h +++ b/tizen/src/skin/maruskin_client.h @@ -49,7 +49,6 @@ #define MY_KEY_WOW64_64KEY 0x0100 int is_wow64(void); int get_java_path(char**); -static char* JAVA_EXEFILE_PATH = 0; #else #define JAVA_EXEFILE_PATH "java" #endif diff --git a/tizen/src/skin/maruskin_keymap.h b/tizen/src/skin/maruskin_keymap.h index b722dc9780..37c7520534 100644 --- a/tizen/src/skin/maruskin_keymap.h +++ b/tizen/src/skin/maruskin_keymap.h @@ -88,6 +88,10 @@ enum JAVA_KEYCODE { #define KEY_MAX 0777 #define KEY_F0 0410 + +#ifdef KEY_F +#undef KEY_F +#endif #define KEY_F(n) (KEY_F0 + (n)) #define KEY_DOWN 0402 diff --git a/tizen/src/skin/maruskin_operation.c b/tizen/src/skin/maruskin_operation.c index ce4cf993d1..b6ade33c46 100644 --- a/tizen/src/skin/maruskin_operation.c +++ b/tizen/src/skin/maruskin_operation.c @@ -1,7 +1,7 @@ /* * operation for emulator skin * - * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: * GiWoong Kim @@ -36,6 +36,7 @@ #include "maruskin_operation.h" #include "hw/maru_brightness.h" #include "maru_display.h" +#include "emulator.h" #include "debug_ch.h" #include "sdb.h" #include "nbd.h" @@ -54,12 +55,18 @@ #include "target-i386/hax-i386.h" #endif +#if defined(CONFIG_USE_SHM) && defined(TARGET_I386) +#include +int g_shmid; +#endif + MULTI_DEBUG_CHANNEL(qemu, skin_operation); -#define RESUME_KEY_SEND_INTERVAL 500 // milli-seconds -#define CLOSE_POWER_KEY_INTERVAL 1200 // milli-seconds -#define DATA_DELIMITER "#" // in detail info data -#define TIMEOUT_FOR_SHUTDOWN 10 // seconds + +#define RESUME_KEY_SEND_INTERVAL 500 /* milli-seconds */ +#define CLOSE_POWER_KEY_INTERVAL 1200 /* milli-seconds */ +#define DATA_DELIMITER "#" /* in detail info data */ +#define TIMEOUT_FOR_SHUTDOWN 10 /* seconds */ static int requested_shutdown_qemu_gracefully = 0; @@ -71,10 +78,16 @@ static int pressing_origin_x = -1, pressing_origin_y = -1; extern pthread_mutex_t mutex_screenshot; extern pthread_cond_t cond_screenshot; +extern int tizen_base_port; + static void* run_timed_shutdown_thread(void* args); -static void send_to_emuld(const char* request_type, int request_size, const char* send_buf, int buf_size); +static void send_to_emuld(const char* request_type, + int request_size, const char* send_buf, int buf_size); + -void start_display(uint64 handle_id, int lcd_size_width, int lcd_size_height, double scale_factor, short rotation_type) +void start_display(uint64 handle_id, + int lcd_size_width, int lcd_size_height, + double scale_factor, short rotation_type) { INFO("start_display handle_id:%ld, lcd size:%dx%d, scale_factor:%f, rotation_type:%d\n", (long)handle_id, lcd_size_width, lcd_size_height, scale_factor, rotation_type); @@ -273,7 +286,7 @@ void do_hardkey_event(int event_type, int keycode) } } - mloop_evcmd_hwkey(event_type, keycode); + maru_hwkey_event(event_type, keycode); } void do_scale_event(double scale_factor) @@ -348,14 +361,21 @@ QemuSurfaceInfo* get_screenshot_info(void) info->pixel_data = (unsigned char*) g_malloc0( length ); if ( !info->pixel_data ) { g_free( info ); - ERR( "Fail to malloc for pixel data.\n"); + ERR("Fail to malloc for pixel data.\n"); return NULL; } + /* If the LCD is turned off, return empty buffer. + Because the empty buffer is seen as a black. */ + if (brightness_off) { + info->pixel_data_length = length; + return info; + } + pthread_mutex_lock(&mutex_screenshot); MaruScreenshot* maru_screenshot = get_maru_screenshot(); - if ( !maru_screenshot || maru_screenshot->isReady != 1) { - ERR( "maru screenshot is NULL or not ready.\n" ); + if (!maru_screenshot || maru_screenshot->isReady != 1) { + ERR("maru screenshot is NULL or not ready.\n"); memset(info->pixel_data, 0x00, length); } else { maru_screenshot->pixel_data = info->pixel_data; @@ -419,7 +439,7 @@ DetailInfo* get_detail_info(int qemu_argc, char** qemu_argv) /* collect log path information */ #define LOGPATH_TEXT "log_path=" - char* log_path = get_log_path(); + const char* log_path = get_log_path(); int log_path_len = strlen(LOGPATH_TEXT) + strlen(log_path) + delimiter_len; total_len += (log_path_len + 1); @@ -473,6 +493,7 @@ void free_detail_info(DetailInfo* detail_info) void do_open_shell(void) { INFO("open shell\n"); + /* do nothing */ } @@ -518,48 +539,60 @@ void request_close(void) } -void shutdown_qemu_gracefully( void ) { - +void shutdown_qemu_gracefully(void) +{ requested_shutdown_qemu_gracefully = 1; pthread_t thread_id; - if( 0 > pthread_create( &thread_id, NULL, run_timed_shutdown_thread, NULL ) ) { - ERR( "!!! Fail to create run_timed_shutdown_thread. shutdown qemu right now !!!\n" ); + if (0 > pthread_create( + &thread_id, NULL, run_timed_shutdown_thread, NULL)) { + + ERR("!!! Fail to create run_timed_shutdown_thread. shutdown qemu right now !!!\n"); qemu_system_shutdown_request(); } } -int is_requested_shutdown_qemu_gracefully( void ) { +int is_requested_shutdown_qemu_gracefully(void) +{ return requested_shutdown_qemu_gracefully; } -static void* run_timed_shutdown_thread( void* args ) { - - send_to_emuld( "system\n\n\n\n", 10, "shutdown", 8 ); +static void* run_timed_shutdown_thread(void* args) +{ + send_to_emuld("system\n\n\n\n", 10, "shutdown", 8); - int sleep_interval_time = 1000; // milli-seconds + int sleep_interval_time = 1000; /* milli-seconds */ int i; - for ( i = 0; i < TIMEOUT_FOR_SHUTDOWN; i++ ) { + for (i = 0; i < TIMEOUT_FOR_SHUTDOWN; i++) { #ifdef CONFIG_WIN32 - Sleep( sleep_interval_time ); + Sleep(sleep_interval_time); #else - usleep( sleep_interval_time * 1000 ); + usleep(sleep_interval_time * 1000); #endif - // do not use logger to help user see log in console - fprintf( stdout, "Wait for shutdown qemu...%d\n", ( i + 1 ) ); + /* do not use logger to help user see log in console */ + fprintf(stdout, "Wait for shutdown qemu...%d\n", (i + 1)); + } + + INFO("Shutdown qemu !!!\n"); + +#if defined(CONFIG_USE_SHM) && defined(TARGET_I386) + if (shmctl(g_shmid, IPC_RMID, 0) == -1) { + ERR("shmctl failed\n"); + perror("maruskin_operation.c:g_shmid: "); } +#endif - INFO( "Shutdown qemu !!!\n" ); qemu_system_shutdown_request(); return NULL; } -static void send_to_emuld( const char* request_type, int request_size, const char* send_buf, int buf_size ) { - +static void send_to_emuld(const char* request_type, + int request_size, const char* send_buf, int buf_size) +{ int s = tcp_socket_outgoing( "127.0.0.1", (uint16_t) ( tizen_base_port + SDB_TCP_EMULD_INDEX ) ); if ( s < 0 ) { @@ -568,9 +601,15 @@ static void send_to_emuld( const char* request_type, int request_size, const cha return; } - socket_send( s, (char*)request_type, request_size ); - socket_send( s, &buf_size, 4 ); - socket_send( s, (char*)send_buf, buf_size ); + if(send( s, (char*)request_type, request_size, 0 ) < 0) { + ERR("failed to send to emuld\n"); + } + if(send( s, &buf_size, 4, 0 ) < 0) { + ERR("failed to send to emuld\n"); + } + if(send( s, (char*)send_buf, buf_size, 0 ) < 0) { + ERR("failed to send to emuld\n"); + } INFO( "send to emuld [req_type:%s, send_data:%s, send_size:%d] 127.0.0.1:%d/tcp \n", request_type, send_buf, buf_size, tizen_base_port + SDB_TCP_EMULD_INDEX ); diff --git a/tizen/src/skin/maruskin_server.c b/tizen/src/skin/maruskin_server.c index 66d1ce232f..17458a8ad2 100644 --- a/tizen/src/skin/maruskin_server.c +++ b/tizen/src/skin/maruskin_server.c @@ -123,13 +123,11 @@ enum { SEND_DETAIL_INFO = 3, SEND_RAMDUMP_COMPLETE = 4, SEND_BOOTING_PROGRESS = 5, + SEND_BRIGHTNESS_VALUE = 6, SEND_SENSOR_DAEMON_START = 800, SEND_SHUTDOWN = 999, }; -pthread_mutex_t mutex_screenshot = PTHREAD_MUTEX_INITIALIZER; -pthread_cond_t cond_screenshot = PTHREAD_COND_INITIALIZER; - static int seq_req_id = 0; static uint16_t svr_port = 0; @@ -145,7 +143,11 @@ static int is_started_heartbeat = 0; static int stop_heartbeat = 0; static int recv_heartbeat_count = 0; static pthread_t thread_id_heartbeat; + +static pthread_mutex_t mutex_send_data = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t mutex_recv_heartbeat_count = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t mutex_screenshot = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t cond_screenshot = PTHREAD_COND_INITIALIZER; static int skin_argc = 0; static char** skin_argv = NULL; @@ -267,6 +269,8 @@ void shutdown_skin_server(void) } } + pthread_mutex_destroy(&mutex_send_data); + pthread_mutex_destroy(&mutex_recv_heartbeat_count); } void notify_sensor_daemon_start(void) @@ -336,6 +340,27 @@ void notify_booting_progress(int progress_value) } } +void notify_brightness(bool on) +{ + char brightness_data[2] = { 0, }; + int brightness_value = 1; + + if (on == FALSE) { + brightness_value = 0; + } + + snprintf(brightness_data, 2, "%d", brightness_value); + TRACE("brightness value = %s\n", brightness_data); + + if (client_sock) { + if (0 > send_skin_data(client_sock, + SEND_BRIGHTNESS_VALUE, (unsigned char *)brightness_data, 2, 0)) { + + ERR("fail to send SEND_BRIGHTNESS_VALUE to skin.\n"); + } + } +} + int is_ready_skin_server(void) { return ready_server; @@ -1094,8 +1119,13 @@ static int send_skin_header_only(int sockfd, short send_cmd, int print_log) make_header(sockfd, send_cmd, 0, headerbuf, print_log); + /* send */ + pthread_mutex_lock(&mutex_send_data); + int send_count = send(sockfd, headerbuf, SEND_HEADER_SIZE, 0); + pthread_mutex_unlock(&mutex_send_data); + return send_count; } @@ -1105,21 +1135,28 @@ static int send_skin_data(int sockfd, char headerbuf[SEND_HEADER_SIZE] = { 0, }; + if (data == NULL) { + ERR("send data is NULL.\n"); + return -1; + } + make_header(sockfd, send_cmd, length, headerbuf, 1); - int header_cnt = send(sockfd, headerbuf, SEND_HEADER_SIZE, 0); + /* send */ + pthread_mutex_lock(&mutex_send_data); + int header_cnt = send(sockfd, headerbuf, SEND_HEADER_SIZE, 0); if (0 > header_cnt) { ERR("send header for data is NULL.\n"); - return header_cnt; - } + pthread_mutex_unlock(&mutex_send_data); - if (!data) { - ERR("send data is NULL.\n"); - return -1; + return header_cnt; } int send_cnt = send_n(sockfd, data, length, big_data); + + pthread_mutex_unlock(&mutex_send_data); + TRACE("send_n result:%d\n", send_cnt); return send_cnt; diff --git a/tizen/src/skin/maruskin_server.h b/tizen/src/skin/maruskin_server.h index ee5e13a14f..59207972bb 100644 --- a/tizen/src/skin/maruskin_server.h +++ b/tizen/src/skin/maruskin_server.h @@ -30,12 +30,16 @@ #ifndef MARUSKIN_SERVER_H_ #define MARUSKIN_SERVER_H_ +#include + int start_skin_server(int argc, char** argv, int qemu_argc, char** qemu_argv); void shutdown_skin_server(void); void notify_sensor_daemon_start(void); void notify_ramdump_completed(void); void notify_booting_progress(int progress_value); +void notify_brightness(bool on); + int is_ready_skin_server(void); int get_skin_server_port(void); diff --git a/vl.c b/vl.c old mode 100644 new mode 100755 index 4dce5cc6c6..ea8395f9a7 --- a/vl.c +++ b/vl.c @@ -181,14 +181,12 @@ int qemu_main(int argc, char **argv, char **envp); #include "ui/qemu-spice.h" #ifdef CONFIG_MARU -#include "tizen/src/emulator.h" #include "tizen/src/maru_common.h" -#include "tizen/src/maru_display.h" -#include "tizen/src/option.h" -#include "tizen/src/sdb.h" +#include "tizen/src/emulator.h" +#include "tizen/src/maru_err_table.h" #include "tizen/src/emul_state.h" +#include "tizen/src/maru_display.h" #include "tizen/src/skin/maruskin_operation.h" -#include "tizen/src/maru_err_table.h" #endif //#define DEBUG_NET @@ -199,8 +197,10 @@ int qemu_main(int argc, char **argv, char **envp); #define MAX_VIRTIO_CONSOLES 1 #ifdef CONFIG_MARU -#define MARUCAM_DEV_NAME "maru_camera_pci" int skin_disabled = 0; +//virtio-gl +extern int enable_gl; +extern int enable_yagl; #endif static const char *data_dir; @@ -261,20 +261,6 @@ uint8_t *boot_splash_filedata; int boot_splash_filedata_size; uint8_t qemu_extra_params_fw[2]; -//virtio-gl -#define VIRTIOGL_DEV_NAME "virtio-gl-pci" -#if defined(CONFIG_MARU) -extern int gl_acceleration_capability_check(void); -int enable_gl = 0; -int capability_check_gl = 0; -#endif -#if defined(CONFIG_MARU) -#define WEBCAM_INFO_IGNORE 0x00 -#define WEBCAM_INFO_WRITE 0x04 -extern int marucam_device_check(int log_flag); -int is_webcam_enabled = 0; -#endif - typedef struct FWBootEntry FWBootEntry; @@ -1978,24 +1964,10 @@ static int device_init_func(QemuOpts *opts, void *opaque) { DeviceState *dev; -#ifdef CONFIG_GL_BACKEND -#if defined(CONFIG_MARU) - // virtio-gl pci device - if (!enable_gl) { - // ignore virtio-gl-pci device, even if users set it in option. - const char *driver = qemu_opt_get(opts, "driver"); - if (driver && (strcmp (driver, VIRTIOGL_DEV_NAME) == 0)) { - return 0; - } - } -#endif -#endif -#if defined(CONFIG_MARU) - if (!is_webcam_enabled) { - const char *driver = qemu_opt_get(opts, "driver"); - if (driver && (strcmp (driver, MARUCAM_DEV_NAME) == 0)) { - return 0; - } +#ifdef CONFIG_MARU + if(maru_device_check(opts) == -1) { + return 0; + } #endif @@ -2436,34 +2408,13 @@ static void free_and_trace(gpointer mem) free(mem); } -// virtio-gl pci device lookup -typedef struct { - const char *device_name; - int found; -} device_opt_finding_t; - -static int find_device_opt (QemuOpts *opts, void *opaque) -{ - device_opt_finding_t *devp = (device_opt_finding_t *) opaque; - if (devp->found == 1) { - return 0; - } - - const char *str = qemu_opt_get (opts, "driver"); - if (strcmp (str, devp->device_name) == 0) { - devp->found = 1; - } - return 0; -} - -int use_qemu_display = 0; //0:use tizen qemu sdl, 1:use original qemu sdl - int qemu_init_main_loop(void) { return main_loop_init(); } #ifdef CONFIG_MARU +int use_qemu_display = 0; //0:use tizen qemu sdl, 1:use original qemu sdl // W/A for preserve larger continuous heap for RAM. void *preallocated_ptr = 0; #endif @@ -2475,7 +2426,6 @@ int main(int argc, char **argv, char **envp) const char *icount_option = NULL; const char *initrd_filename; const char *kernel_filename, *kernel_cmdline; - char* tmp_cmdline = NULL; char boot_devices[33] = "cad"; /* default to HD->floppy->CD-ROM */ DisplayState *ds; DisplayChangeListener *dcl; @@ -2505,13 +2455,6 @@ int main(int argc, char **argv, char **envp) const char *trace_events = NULL; const char *trace_file = NULL; -#ifdef CONFIG_MARU - #define MIDBUF 128 - char http_proxy[MIDBUF] ={0},https_proxy[MIDBUF] = {0,}, - ftp_proxy[MIDBUF] = {0,}, socks_proxy[MIDBUF] = {0,}, - dns1[MIDBUF] = {0}, dns2[MIDBUF] = {0}; -#endif - atexit(qemu_run_exit_notifiers); error_set_progname(argv[0]); @@ -2744,28 +2687,7 @@ int main(int argc, char **argv, char **envp) qemu_opts_set(qemu_find_opts("machine"), 0, "initrd", optarg); break; case QEMU_OPTION_append: -#ifdef CONFIG_MARU - gethostproxy(http_proxy, https_proxy, ftp_proxy, socks_proxy); - gethostDNS(dns1, dns2); - - check_shdmem(); - socket_init(); - tizen_base_port = get_sdb_base_port(); - make_shdmem(); - - sdb_setup(); - - tmp_cmdline = g_strdup_printf("%s sdb_port=%d," - " http_proxy=%s https_proxy=%s ftp_proxy=%s socks_proxy=%s" - " dns1=%s dns2=%s", optarg, tizen_base_port, - http_proxy, https_proxy, ftp_proxy, socks_proxy, - dns1, dns2); - qemu_opts_set(qemu_find_opts("machine"), 0, "append", - tmp_cmdline); - fprintf(stdout, "kernel command : %s\n", tmp_cmdline); -#else qemu_opts_set(qemu_find_opts("machine"), 0, "append", optarg); -#endif break; case QEMU_OPTION_dtb: qemu_opts_set(qemu_find_opts("machine"), 0, "dtb", optarg); @@ -3210,10 +3132,8 @@ int main(int argc, char **argv, char **envp) qemu_opts_parse(olist, "accel=kvm", 0); break; case QEMU_OPTION_enable_gl: -#ifdef CONFIG_GL_BACKEND -#if defined(CONFIG_MARU) +#if defined(CONFIG_MARU) && defined(CONFIG_GL_BACKEND) enable_gl = 1; -#endif #else fprintf(stderr, "Virtio GL support is disabled, ignoring -enable-gl\n"); #endif @@ -3512,36 +3432,6 @@ int main(int argc, char **argv, char **envp) exit(0); } -#ifdef CONFIG_GL_BACKEND -#if defined(CONFIG_MARU) - if (enable_gl) { - capability_check_gl = gl_acceleration_capability_check(); - - if (capability_check_gl != 0) { - enable_gl = 0; - fprintf (stderr, "Warn: GL acceleration was disabled due to the fail of GL check!\n"); - } - - if (enable_gl) { - device_opt_finding_t devp = {VIRTIOGL_DEV_NAME, 0}; - qemu_opts_foreach(qemu_find_opts("device"), find_device_opt, &devp, 0); - if (devp.found == 0) { - if (!qemu_opts_parse(qemu_find_opts("device"), VIRTIOGL_DEV_NAME, 1)) { - exit(1); - } - } - } - } - - // To check host gl driver capability and notify to guest. - gchar *tmp = tmp_cmdline; - tmp_cmdline = g_strdup_printf("%s gles=%d", tmp, enable_gl); - qemu_opts_set(qemu_find_opts("machine"), 0, "append", tmp_cmdline); - fprintf(stdout, "kernel command : %s\n", tmp_cmdline); - g_free(tmp); - -#endif -#endif /* Open the logfile at this point, if necessary. We can't open the logfile * when encountering either of the logging options (-d or -D) because the @@ -3694,30 +3584,6 @@ int main(int argc, char **argv, char **envp) kernel_cmdline = ""; } -#if defined(CONFIG_MARU) - is_webcam_enabled = marucam_device_check(WEBCAM_INFO_WRITE); - if (!is_webcam_enabled) { - fprintf (stderr, "[Webcam] Webcam support was disabled " - "due to the fail of webcam capability check!\n"); - } - - gchar const *tmp_cam_kcmd = kernel_cmdline; - kernel_cmdline = g_strdup_printf("%s enable_cam=%d", tmp_cam_kcmd, is_webcam_enabled); -// g_free(tmp_cam_kcmd); - - if (is_webcam_enabled) { - device_opt_finding_t devp = {MARUCAM_DEV_NAME, 0}; - qemu_opts_foreach(qemu_find_opts("device"), find_device_opt, &devp, 0); - if (devp.found == 0) { - if (!qemu_opts_parse(qemu_find_opts("device"), MARUCAM_DEV_NAME, 1)) { - fprintf(stderr, "Failed to initialize the marucam device.\n"); - exit(1); - } - } - fprintf(stdout, "[Webcam] Webcam support was enabled.\n"); - } -#endif - linux_boot = (kernel_filename != NULL); if (!linux_boot && *kernel_cmdline != '\0') { @@ -3865,12 +3731,14 @@ int main(int argc, char **argv, char **envp) qdev_machine_init(); - machine->init(ram_size, boot_devices, - kernel_filename, kernel_cmdline, initrd_filename, cpu_model); #ifdef CONFIG_MARU - g_free((gchar *)tmp_cmdline); + // return variable points different address from input variable. + kernel_cmdline = prepare_maru_devices(kernel_cmdline); #endif + machine->init(ram_size, boot_devices, + kernel_filename, kernel_cmdline, initrd_filename, cpu_model); + cpu_synchronize_all_post_init(); set_numa_modes(); -- 2.34.1