changeset 4635:0c57f87f454d

7124627: Please sync up changes from workspace macosx-port into the jdk7u-osx Reviewed-by: art, anthony, dcherepanov, alexp
author kizune
date Fri, 23 Dec 2011 22:01:01 +0300
parents 12819477ce5a
children dd45e1667b76
files make/com/apple/osx/Makefile make/com/apple/osxui/Makefile make/javax/sound/FILES_c.gmk make/sun/Makefile make/sun/lwawt/FILES_c_macosx.gmk make/sun/lwawt/FILES_export_macosx.gmk make/sun/lwawt/Makefile make/sun/osxapp/Makefile make/sun/splashscreen/Makefile src/macosx/classes/com/apple/laf/AquaFocus.java src/macosx/classes/com/apple/laf/AquaPainter.java src/macosx/classes/com/apple/laf/AquaScrollBarUI.java src/macosx/classes/com/apple/laf/AquaSpinnerUI.java src/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java src/macosx/classes/com/apple/laf/AquaTabbedPaneUI.java src/macosx/classes/sun/awt/CGraphicsConfig.java src/macosx/classes/sun/awt/CGraphicsEnvironment.java src/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java src/macosx/classes/sun/java2d/opengl/CGLLayer.java src/macosx/classes/sun/java2d/opengl/CGLSurfaceData.java src/macosx/classes/sun/lwawt/LWButtonPeer.java src/macosx/classes/sun/lwawt/LWCanvasPeer.java src/macosx/classes/sun/lwawt/LWCheckboxPeer.java src/macosx/classes/sun/lwawt/LWChoicePeer.java src/macosx/classes/sun/lwawt/LWComponentPeer.java src/macosx/classes/sun/lwawt/LWContainerPeer.java src/macosx/classes/sun/lwawt/LWKeyboardFocusManagerPeer.java src/macosx/classes/sun/lwawt/LWLabelPeer.java src/macosx/classes/sun/lwawt/LWListPeer.java src/macosx/classes/sun/lwawt/LWPanelPeer.java src/macosx/classes/sun/lwawt/LWRepaintArea.java src/macosx/classes/sun/lwawt/LWScrollBarPeer.java src/macosx/classes/sun/lwawt/LWScrollPanePeer.java src/macosx/classes/sun/lwawt/LWTextAreaPeer.java src/macosx/classes/sun/lwawt/LWTextComponentPeer.java src/macosx/classes/sun/lwawt/LWTextFieldPeer.java src/macosx/classes/sun/lwawt/LWToolkit.java src/macosx/classes/sun/lwawt/LWWindowPeer.java src/macosx/classes/sun/lwawt/PlatformWindow.java src/macosx/classes/sun/lwawt/macosx/CCursorManager.java src/macosx/classes/sun/lwawt/macosx/CDataTransferer.java src/macosx/classes/sun/lwawt/macosx/CDragSourceContextPeer.java src/macosx/classes/sun/lwawt/macosx/CDropTargetContextPeer.java src/macosx/classes/sun/lwawt/macosx/CInputMethod.java src/macosx/classes/sun/lwawt/macosx/CPlatformComponent.java src/macosx/classes/sun/lwawt/macosx/CPlatformView.java src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java src/macosx/classes/sun/lwawt/macosx/CPrinterJob.java src/macosx/classes/sun/lwawt/macosx/CRobot.java src/macosx/classes/sun/lwawt/macosx/CTrayIcon.java src/macosx/classes/sun/lwawt/macosx/CWrapper.java src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java src/macosx/classes/sun/lwawt/macosx/event/NSEvent.java src/macosx/native/com/sun/media/sound/CARingBuffer.cpp src/macosx/native/com/sun/media/sound/CARingBuffer.h src/macosx/native/com/sun/media/sound/PLATFORM_API_MacOSX_MidiIn.c src/macosx/native/com/sun/media/sound/PLATFORM_API_MacOSX_MidiOut.c src/macosx/native/com/sun/media/sound/PLATFORM_API_MacOSX_MidiUtils.c src/macosx/native/com/sun/media/sound/PLATFORM_API_MacOSX_MidiUtils.h src/macosx/native/com/sun/media/sound/PLATFORM_API_MacOSX_PCM.cpp src/macosx/native/com/sun/media/sound/PLATFORM_API_MacOSX_Ports.cpp src/macosx/native/com/sun/media/sound/PLATFORM_API_MacOSX_Utils.cpp src/macosx/native/com/sun/media/sound/PLATFORM_API_MacOSX_Utils.h src/macosx/native/com/sun/media/sound/PLATFORM_API_MacOS_MidiIn.c src/macosx/native/com/sun/media/sound/PLATFORM_API_MacOS_MidiOut.c src/macosx/native/com/sun/media/sound/PLATFORM_API_MacOS_MidiUtils.c src/macosx/native/com/sun/media/sound/PLATFORM_API_MacOS_MidiUtils.h src/macosx/native/jobjc/src/generator/java/com/apple/internal/jobjc/generator/utils/StructOffsetResolver.java src/macosx/native/sun/awt/AWTView.m src/macosx/native/sun/awt/AWTWindow.h src/macosx/native/sun/awt/AWTWindow.m src/macosx/native/sun/awt/AWT_debug.h src/macosx/native/sun/awt/CDragSource.m src/macosx/native/sun/awt/CDropTarget.m src/macosx/native/sun/awt/CDropTargetContextPeer.m src/macosx/native/sun/awt/CRobot.m src/macosx/native/sun/awt/CTrayIcon.h src/macosx/native/sun/awt/CTrayIcon.m src/macosx/native/sun/awt/CWrapper.m src/macosx/native/sun/awt/NSApplicationAWT.h src/macosx/native/sun/awt/NSApplicationAWT.m src/macosx/native/sun/awt/PropertiesUtilities.h src/macosx/native/sun/awt/PropertiesUtilities.m src/macosx/native/sun/awt/ThreadUtilities.h src/macosx/native/sun/awt/ThreadUtilities.m src/macosx/native/sun/awt/awt.m src/macosx/native/sun/awt/splashscreen/splashscreen_config.h src/macosx/native/sun/awt/splashscreen/splashscreen_sys.m src/macosx/native/sun/java2d/opengl/CGLGraphicsConfig.h src/macosx/native/sun/java2d/opengl/CGLLayer.h src/macosx/native/sun/java2d/opengl/CGLLayer.m src/macosx/native/sun/java2d/opengl/CGLSurfaceData.h src/macosx/native/sun/java2d/opengl/CGLSurfaceData.m src/macosx/native/sun/osxapp/AWT_debug.h src/macosx/native/sun/osxapp/NSApplicationAWT.h src/macosx/native/sun/osxapp/NSApplicationAWT.m src/macosx/native/sun/osxapp/PropertiesUtilities.h src/macosx/native/sun/osxapp/PropertiesUtilities.m src/macosx/native/sun/osxapp/QueuingApplicationDelegate.h src/macosx/native/sun/osxapp/QueuingApplicationDelegate.m src/macosx/native/sun/osxapp/ThreadUtilities.h src/macosx/native/sun/osxapp/ThreadUtilities.m src/share/bin/java.c src/share/classes/java/awt/KeyboardFocusManager.java src/share/classes/javax/swing/plaf/basic/BasicButtonListener.java src/share/classes/javax/swing/plaf/basic/BasicLabelUI.java src/share/classes/javax/swing/plaf/basic/BasicLookAndFeel.java src/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java src/share/classes/javax/swing/plaf/basic/BasicTextUI.java src/share/classes/sun/awt/AWTAccessor.java src/share/classes/sun/awt/SunToolkit.java src/share/classes/sun/java2d/opengl/OGLBlitLoops.java src/share/classes/sun/java2d/opengl/OGLSurfaceData.java src/share/native/com/sun/media/sound/DirectAudioDevice.c src/share/native/com/sun/media/sound/Utilities.h src/share/native/sun/awt/splashscreen/splashscreen_impl.h src/solaris/bin/java_md.c src/solaris/native/java/net/PlainDatagramSocketImpl.c src/solaris/native/java/net/PlainDatagramSocketImpl.c.orig src/solaris/native/sun/awt/awt_LoadLibrary.c
diffstat 120 files changed, 8861 insertions(+), 3963 deletions(-) [+]
line wrap: on
line diff
--- a/make/com/apple/osx/Makefile	Thu Dec 22 11:05:51 2011 -0800
+++ b/make/com/apple/osx/Makefile	Fri Dec 23 22:01:01 2011 +0300
@@ -78,9 +78,11 @@
 CPPFLAGS += \
 	$(call NativeSrcDirList,-I,native/com/apple/laf) \
 	$(call NativeSrcDirList,-I,native/apple/awt) \
-	$(call NativeSrcDirList,-I,native/sun/awt)
+	$(call NativeSrcDirList,-I,native/sun/awt) \
+	$(call NativeSrcDirList,-I,native/sun/osxapp)
 
 OTHER_LDLIBS = \
+    -losxapp \
     -framework Cocoa \
     -framework ApplicationServices \
     -framework JavaNativeFoundation \
--- a/make/com/apple/osxui/Makefile	Thu Dec 22 11:05:51 2011 -0800
+++ b/make/com/apple/osxui/Makefile	Fri Dec 23 22:01:01 2011 +0300
@@ -93,10 +93,11 @@
 	$(call NativeSrcDirList,-I,native/com/apple/laf) \
 	$(call NativeSrcDirList,-I,native/apple/awt) \
 	$(call NativeSrcDirList,-I,native/sun/awt) \
+	$(call NativeSrcDirList,-I,native/sun/osxapp) \
 	-I$(TEMPDIR)/../../sun.awt/awt/CClassHeaders
 
 OTHER_LDLIBS = \
-    -lawt \
+    -lawt -losxapp \
     -llwawt -L$(LIBDIR)/lwawt -Xlinker -rpath -Xlinker @loader_path/lwawt \
     -framework Cocoa \
     -framework Carbon \
--- a/make/javax/sound/FILES_c.gmk	Thu Dec 22 11:05:51 2011 -0800
+++ b/make/javax/sound/FILES_c.gmk	Fri Dec 23 22:01:01 2011 +0300
@@ -37,15 +37,14 @@
 FILES_bsd =
 
 FILES_macosx = \
-    PLATFORM_API_MacOSX_Ports.c \
-    PLATFORM_API_MacOSX_Utils.c \
-    PLATFORM_API_MacOS_MidiIn.c \
-    PLATFORM_API_MacOS_MidiOut.c \
-    PLATFORM_API_MacOS_MidiUtils.c
+    PLATFORM_API_MacOSX_MidiIn.c \
+    PLATFORM_API_MacOSX_MidiOut.c \
+    PLATFORM_API_MacOSX_MidiUtils.c
 
 FILES_cpp_macosx = \
+    PLATFORM_API_MacOSX_Utils.cpp \
     PLATFORM_API_MacOSX_PCM.cpp \
-    CARingBuffer.cpp
+    PLATFORM_API_MacOSX_Ports.cpp
 
 FILES_windows = \
 	PLATFORM_API_WinOS_MidiIn.c \
--- a/make/sun/Makefile	Thu Dec 22 11:05:51 2011 -0800
+++ b/make/sun/Makefile	Fri Dec 23 22:01:01 2011 +0300
@@ -59,6 +59,7 @@
 endif
 
 ifeq ($(PLATFORM), macosx)
+  LWAWT_PRE_SUBDIR = osxapp
   LWAWT_SUBDIR = lwawt
 endif
 
@@ -85,7 +86,7 @@
   DISPLAY_TOOLS = applet
 endif
 SUBDIRS_desktop    = audio $(RENDER_SUBDIR) image \
-                     $(DISPLAY_LIBS) $(DGA_SUBDIR) $(LWAWT_SUBDIR) \
+                     $(LWAWT_PRE_SUBDIR) $(DISPLAY_LIBS) $(DGA_SUBDIR) $(LWAWT_SUBDIR) \
                      jawt font jpeg cmm $(DISPLAY_TOOLS) beans
 SUBDIRS_management = management
 SUBDIRS_misc       = $(ORG_SUBDIR) rmi $(JDBC_SUBDIR) tracing
--- a/make/sun/lwawt/FILES_c_macosx.gmk	Thu Dec 22 11:05:51 2011 -0800
+++ b/make/sun/lwawt/FILES_c_macosx.gmk	Fri Dec 23 22:01:01 2011 +0300
@@ -25,7 +25,6 @@
 
 FILES_objc = \
         awt.m \
-        NSApplicationAWT.m \
         ApplicationDelegate.m \
         CFRetainedResource.m \
         CGLGraphicsConfig.m \
@@ -72,9 +71,7 @@
         JavaComponentAccessibility.m \
         JavaTextAccessibility.m \
         LWCToolkit.m \
-        ThreadUtilities.m \
         GeomUtilities.m \
-        PropertiesUtilities.m \
         CPrinterJob.m \
         PrintModel.m \
         PrinterSurfaceData.m \
--- a/make/sun/lwawt/FILES_export_macosx.gmk	Thu Dec 22 11:05:51 2011 -0800
+++ b/make/sun/lwawt/FILES_export_macosx.gmk	Fri Dec 23 22:01:01 2011 +0300
@@ -101,8 +101,9 @@
         sun/lwawt/LWListPeer.java \
         sun/lwawt/LWMouseInfoPeer.java \
         sun/lwawt/LWPanelPeer.java \
+        sun/lwawt/LWRepaintArea.java \
         sun/lwawt/LWScrollBarPeer.java \
-	sun/lwawt/LWScrollPanePeer.java \
+        sun/lwawt/LWScrollPanePeer.java \
         sun/lwawt/LWTextComponentPeer.java \
         sun/lwawt/LWTextFieldPeer.java \
         sun/lwawt/LWToolkit.java \
--- a/make/sun/lwawt/Makefile	Thu Dec 22 11:05:51 2011 -0800
+++ b/make/sun/lwawt/Makefile	Fri Dec 23 22:01:01 2011 +0300
@@ -71,7 +71,7 @@
 vpath %.m   $(call NativeSrcDirList,,native/sun/java2d/opengl)
 
 OTHER_LDLIBS += \
-	-lawt -lmlib_image $(JVMLIB) $(LIBM) \
+	-lawt -lmlib_image -losxapp $(JVMLIB) $(LIBM) \
 	-framework Accelerate \
 	-framework ApplicationServices \
 	-framework AudioToolbox \
@@ -101,6 +101,7 @@
         -I$(SHARE_SRC)/native/sun/awt/medialib \
         -I$(SHARE_SRC)/native/sun/awt \
         $(call NativeSrcDirList,-I,/native/sun/awt) \
+        $(call NativeSrcDirList,-I,/native/sun/osxapp) \
         $(call NativeSrcDirList,-I,/native/sun/font) \
 	$(call NativeSrcDirList,-I,/native/sun/java2d) \
 	$(call NativeSrcDirList,-I,/native/sun/java2d/opengl)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/sun/osxapp/Makefile	Fri Dec 23 22:01:01 2011 +0300
@@ -0,0 +1,75 @@
+#
+# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code 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
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+BUILDDIR = ../..
+LIBRARY = osxapp
+PRODUCT = sun
+include $(BUILDDIR)/common/Defs.gmk
+
+#
+# Files
+#
+FILES_objc = \
+	NSApplicationAWT.m \
+	QueuingApplicationDelegate.m \
+	PropertiesUtilities.m \
+	ThreadUtilities.m
+
+#
+# Rules.
+#
+include $(BUILDDIR)/common/Library.gmk
+
+#
+# Add to the ambient vpath to pick up files in subdirectories
+#
+vpath %.m   $(call NativeSrcDirList,,native/sun/osxapp)
+
+# TODO: perhaps not all of the below frameworks are required
+OTHER_LDLIBS += \
+	-framework Accelerate \
+	-framework ApplicationServices \
+	-framework AudioToolbox \
+	-framework Carbon \
+	-framework Cocoa \
+	-framework Security \
+	-framework ExceptionHandling \
+	-framework JavaNativeFoundation \
+	-framework JavaRuntimeSupport \
+	-framework OpenGL \
+	-framework IOSurface \
+	-framework QuartzCore
+
+CPPFLAGS += \
+        $(call NativeSrcDirList,-I,/native/sun/osxapp)
+
+
+ifeq ($(MILESTONE), internal)
+  CPPFLAGS += -DINTERNAL_BUILD
+endif
+
+clean clobber::
+
+.PHONY:
--- a/make/sun/splashscreen/Makefile	Thu Dec 22 11:05:51 2011 -0800
+++ b/make/sun/splashscreen/Makefile	Fri Dec 23 22:01:01 2011 +0300
@@ -61,7 +61,27 @@
 
 CFLAGS += -DSPLASHSCREEN
 
-ifneq ($(PLATFORM), windows)
+ifeq ($(PLATFORM), macosx)
+  CFLAGS += -DWITH_MACOSX
+
+  # CFLAGS and CPPFLAGS are added when linking as well, so we use VARIANT
+  # instead to specify that we're actually compiling objective-c code here
+  CFLAGS_$(VARIANT)/java_awt_SplashScreen.o = -x objective-c
+  CFLAGS_$(VARIANT)/splashscreen_gfx_impl.o = -x objective-c
+  CFLAGS_$(VARIANT)/splashscreen_gif.o = -x objective-c
+  CFLAGS_$(VARIANT)/splashscreen_impl.o = -x objective-c
+  CFLAGS_$(VARIANT)/splashscreen_jpeg.o = -x objective-c
+  CFLAGS_$(VARIANT)/splashscreen_png.o = -x objective-c
+  CFLAGS_$(VARIANT)/splashscreen_sys.o = -x objective-c
+
+  OTHER_CFLAGS += -F/System/Library/Frameworks/ApplicationServices.framework/Frameworks
+  CPPFLAGS += -I/System/Library/Frameworks/AppKit.framework/Versions/C/Headers
+  OTHER_LDLIBS += $(LIBM) -lpthread -liconv -losxapp \
+				  -framework ApplicationServices \
+				  -framework Foundation \
+				  -framework Cocoa \
+				  -framework JavaNativeFoundation
+else ifneq ($(PLATFORM), windows)
   CFLAGS += -DWITH_X11
   ifeq ($(PLATFORM), macosx))
     OTHER_LDLIBS += -liconv
@@ -89,9 +109,19 @@
 endif
 vpath %.c   $(SHARE_SRC)/native/$(PKGDIR)/libpng
 vpath %.c   $(SHARE_SRC)/native/$(PKGDIR)/image/jpeg
-vpath %.c   $(PLATFORM_SRC)/native/$(PKGDIR)/splashscreen
+ifneq ($(PLATFORM), macosx)
+  vpath %.c   $(PLATFORM_SRC)/native/$(PKGDIR)/splashscreen
+else
+  vpath %.m   $(call NativeSrcDirList,,native/$(PKGDIR)/splashscreen)
+endif
 
-CPPFLAGS += -I$(PLATFORM_SRC)/native/$(PKGDIR)/splashscreen -I$(SHARE_SRC)/native/$(PKGDIR)/splashscreen
+ifneq ($(PLATFORM), macosx)
+  CPPFLAGS += -I$(PLATFORM_SRC)/native/$(PKGDIR)/splashscreen
+else
+  CPPFLAGS += $(call NativeSrcDirList,-I,native/$(PKGDIR)/splashscreen)
+  CPPFLAGS += $(call NativeSrcDirList,-I,/native/sun/osxapp)
+endif
+CPPFLAGS += -I$(SHARE_SRC)/native/$(PKGDIR)/splashscreen
 CPPFLAGS += -I$(SHARE_SRC)/native/$(PKGDIR)/image/jpeg
 ifneq ($(SYSTEM_ZLIB),true)
   CPPFLAGS += -I$(SHARE_SRC)/native/java/util/zip/zlib-$(ZLIB_VERSION)
--- a/src/macosx/classes/com/apple/laf/AquaFocus.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/com/apple/laf/AquaFocus.java	Fri Dec 23 22:01:01 2011 +0300
@@ -41,7 +41,7 @@
 
 public class AquaFocus {
     interface Drawable {
-        public void draw(final SunGraphics2D sg2d);
+        public void draw(final Graphics2D sg2d);
     }
 
     static boolean paintFocus(final Graphics g, final Drawable drawable) {
--- a/src/macosx/classes/com/apple/laf/AquaPainter.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/com/apple/laf/AquaPainter.java	Fri Dec 23 22:01:01 2011 +0300
@@ -66,7 +66,7 @@
         return new AquaNineSlicingImagePainter<T>(state, metricsProvider);
     }
 
-    abstract void paint(final SunGraphics2D g, final T stateToPaint, final Component c);
+    abstract void paint(final Graphics2D g, final T stateToPaint, final Component c);
 
     final Rectangle boundsRect = new Rectangle();
     final JRSUIControl control;
@@ -85,7 +85,7 @@
         boundsRect.setBounds(x, y, w, h);
 
         final T nextState = (T)state.derive();
-        final SunGraphics2D g2d = getGraphics2D(g);
+        final Graphics2D g2d = getGraphics2D(g);
         if (g2d != null) paint(g2d, nextState, c);
         state = nextState;
     }
@@ -105,7 +105,7 @@
         }
 
         @Override
-        void paint(final SunGraphics2D g, final T stateToPaint, final Component c) {
+        void paint(final Graphics2D g, final T stateToPaint, final Component c) {
             if (metricsProvider == null) {
                 AquaSingleImagePainter.paintFromSingleCachedImage(g, control, stateToPaint, c, boundsRect);
                 return;
@@ -132,11 +132,11 @@
         }
 
         @Override
-        void paint(SunGraphics2D g, T stateToPaint, Component c) {
+        void paint(Graphics2D g, T stateToPaint, Component c) {
             paintFromSingleCachedImage(g, control, stateToPaint, c, boundsRect);
         }
 
-        static void paintFromSingleCachedImage(final SunGraphics2D g, final JRSUIControl control, final JRSUIState controlState, final Component c, final Rectangle boundsRect) {
+        static void paintFromSingleCachedImage(final Graphics2D g, final JRSUIControl control, final JRSUIState controlState, final Component c, final Rectangle boundsRect) {
             Rectangle clipRect = g.getClipBounds();
             Rectangle intersection = boundsRect.intersection(clipRect);
             if (intersection.width <= 0 || intersection.height <= 0) return;
@@ -195,7 +195,7 @@
         }
     }
 
-    protected SunGraphics2D getGraphics2D(final Graphics g) {
+    protected Graphics2D getGraphics2D(final Graphics g) {
         try {
             return (SunGraphics2D)g; // doing a blind try is faster than checking instanceof
         } catch (Exception e) {
@@ -206,6 +206,8 @@
                 final ProxyGraphics2D pg = (ProxyGraphics2D)g;
                 final Graphics2D g2d = pg.getDelegate();
                 if (g2d instanceof SunGraphics2D) { return (SunGraphics2D)g2d; }
+            } else if (g instanceof Graphics2D) {
+                return (Graphics2D) g;
             }
         }
 
--- a/src/macosx/classes/com/apple/laf/AquaScrollBarUI.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/com/apple/laf/AquaScrollBarUI.java	Fri Dec 23 22:01:01 2011 +0300
@@ -303,6 +303,13 @@
                 mouseDraggedInTrack(e);
             } else {
                 // In pageup/down zones
+
+                // check that thumb has not been scrolled under the mouse cursor
+                final Hit previousPart = getPartHit(fCurrentMouseX, fCurrentMouseY);
+                if (!HitUtil.isTrack(previousPart)) {
+                    fStillInTrack = false;
+                }
+
                 fCurrentMouseX = e.getX();
                 fCurrentMouseY = e.getY();
 
--- a/src/macosx/classes/com/apple/laf/AquaSpinnerUI.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/com/apple/laf/AquaSpinnerUI.java	Fri Dec 23 22:01:01 2011 +0300
@@ -149,6 +149,7 @@
         final TransparentButton b = new TransparentButton();
         b.addActionListener(getPreviousButtonHandler());
         b.addMouseListener(getPreviousButtonHandler());
+        b.setInheritsPopupMenu(true);
         return b;
     }
 
@@ -156,6 +157,7 @@
         final TransparentButton b = new TransparentButton();
         b.addActionListener(getNextButtonHandler());
         b.addMouseListener(getNextButtonHandler());
+        b.setInheritsPopupMenu(true);
         return b;
     }
 
@@ -199,6 +201,11 @@
         if (!(editor instanceof DefaultEditor)) return;
 
         editor.setOpaque(false);
+        editor.setInheritsPopupMenu(true);
+
+        if (editor.getFont() instanceof UIResource) {
+            editor.setFont(spinner.getFont());
+        }
 
         final JFormattedTextField editorTextField = ((DefaultEditor)editor).getTextField();
         final InputMap spinnerInputMap = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
@@ -606,6 +613,17 @@
                     ui.updateEnabledState();
                 } else if (JComponent.TOOL_TIP_TEXT_KEY.equals(propertyName)) {
                     ui.updateToolTipTextForChildren(spinner);
+                } else if ("font".equals(propertyName)) {
+                    JComponent editor = spinner.getEditor();
+                    if (editor != null && editor instanceof JSpinner.DefaultEditor) {
+                        JTextField tf =
+                                ((JSpinner.DefaultEditor) editor).getTextField();
+                        if (tf != null) {
+                            if (tf.getFont() instanceof UIResource) {
+                                tf.setFont(spinner.getFont());
+                            }
+                        }
+                    }
                 }
             }
         }
--- a/src/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java	Fri Dec 23 22:01:01 2011 +0300
@@ -3300,22 +3300,8 @@
             } else if (name == "displayedMnemonicIndexAt") {
                 pane.repaint();
             } else if (name == "indexForTitle") {
-                final int index = ((Integer)e.getNewValue()).intValue();
-                final String title = tabPane.getTitleAt(index);
-                if (BasicHTML.isHTMLString(title)) {
-                    if (htmlViews == null) { // Initialize vector
-                        htmlViews = createHTMLVector();
-                    } else { // Vector already exists
-                        final View v = BasicHTML.createHTMLView(tabPane, title);
-                        htmlViews.setElementAt(v, index);
-                    }
-                } else {
-                    if (htmlViews != null && htmlViews.elementAt(index) != null) {
-                        htmlViews.setElementAt(null, index);
-                    }
-                }
                 calculatedBaseline = false;
-                updateMnemonics();
+                updateHtmlViews((Integer) e.getNewValue());
             } else if (name == "tabLayoutPolicy") {
                 AquaTabbedPaneCopyFromBasicUI.this.uninstallUI(pane);
                 AquaTabbedPaneCopyFromBasicUI.this.installUI(pane);
@@ -3351,6 +3337,9 @@
                 tabPane.revalidate();
                 tabPane.repaint();
                 calculatedBaseline = false;
+            } else if (name == "indexForNullComponent") {
+                isRunsDirty = true;
+                updateHtmlViews((Integer) e.getNewValue());
             } else if (name == "font") {
                 calculatedBaseline = false;
             }
@@ -3468,14 +3457,18 @@
             if (child instanceof UIResource) {
                 return;
             }
-            final int index = tp.indexOfComponent(child);
-            final String title = tp.getTitleAt(index);
+            isRunsDirty = true;
+            updateHtmlViews(tp.indexOfComponent(child));
+        }
+
+        private void updateHtmlViews(int index) {
+            final String title = tabPane.getTitleAt(index);
             final boolean isHTML = BasicHTML.isHTMLString(title);
             if (isHTML) {
                 if (htmlViews == null) { // Initialize vector
                     htmlViews = createHTMLVector();
                 } else { // Vector already exists
-                    final View v = BasicHTML.createHTMLView(tp, title);
+                    final View v = BasicHTML.createHTMLView(tabPane, title);
                     htmlViews.insertElementAt(v, index);
                 }
             } else { // Not HTML
@@ -3483,7 +3476,6 @@
                     htmlViews.insertElementAt(null, index);
                 } // else nada!
             }
-            isRunsDirty = true;
             updateMnemonics();
         }
 
--- a/src/macosx/classes/com/apple/laf/AquaTabbedPaneUI.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/com/apple/laf/AquaTabbedPaneUI.java	Fri Dec 23 22:01:01 2011 +0300
@@ -35,7 +35,6 @@
 import javax.swing.plaf.*;
 import javax.swing.text.View;
 
-import sun.java2d.SunGraphics2D;
 import sun.swing.SwingUtilities2;
 import apple.laf.*;
 import apple.laf.JRSUIConstants.*;
@@ -306,11 +305,11 @@
         }
 
         // from super.paintText - its normal text painting is totally wrong for the Mac
-        if (!(g instanceof SunGraphics2D)) {
+        if (!(g instanceof Graphics2D)) {
             g.setClip(temp);
             return;
         }
-        final SunGraphics2D g2d = (SunGraphics2D)g;
+        final Graphics2D g2d = (Graphics2D) g;
 
         AffineTransform savedAT = null;
         if (isVertical) {
--- a/src/macosx/classes/sun/awt/CGraphicsConfig.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/awt/CGraphicsConfig.java	Fri Dec 23 22:01:01 2011 +0300
@@ -30,6 +30,7 @@
 import java.awt.image.*;
 
 import sun.java2d.SurfaceData;
+import sun.java2d.opengl.CGLLayer;
 import sun.lwawt.macosx.CPlatformView;
 
 public class CGraphicsConfig extends GraphicsConfiguration {
@@ -101,6 +102,14 @@
     }
 
     /**
+     * Creates a new SurfaceData that will be associated with the given
+     * CGLLayer.
+     */
+    public SurfaceData createSurfaceData(CGLLayer layer) {
+        throw new UnsupportedOperationException("not implemented");
+    }
+
+    /**
      * Creates a new hidden-acceleration image of the given width and height
      * that is associated with the target Component.
      */
--- a/src/macosx/classes/sun/awt/CGraphicsEnvironment.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/awt/CGraphicsEnvironment.java	Fri Dec 23 22:01:01 2011 +0300
@@ -134,18 +134,40 @@
      * @return
      */
     private synchronized void initDevices() {
+        devices.clear();
+
+        int mainID = getMainDisplayID();
+
+        // initialization of the graphics device may change
+        // list of displays on hybrid systems via an activation
+        // of discrete video.
+        // So, we initialize the main display first, and then
+        // retrieve actual list of displays.
+        CGraphicsDevice mainDevice = new CGraphicsDevice(mainID);
+
         final int[] displayIDs = getDisplayIDs();
 
-        devices.clear();
         for (int displayID : displayIDs) {
-            devices.put(displayID, new CGraphicsDevice(displayID));
+            if (displayID != mainID) {
+                devices.put(displayID, new CGraphicsDevice(displayID));
+            } else {
+                devices.put(mainID, mainDevice);
+            }
         }
     }
 
     @Override
     public synchronized GraphicsDevice getDefaultScreenDevice() throws HeadlessException {
         final int mainDisplayID = getMainDisplayID();
-        return devices.get(mainDisplayID);
+        CGraphicsDevice d = devices.get(mainDisplayID);
+        if (d == null) {
+            // we do not exepct that this may happen, the only responce
+            // is to re-initialize the list of devices
+            initDevices();
+
+            d = devices.get(mainDisplayID);
+        }
+        return d;
     }
 
     @Override
--- a/src/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java	Fri Dec 23 22:01:01 2011 +0300
@@ -289,6 +289,15 @@
     }
 
     /**
+     * Creates a new SurfaceData that will be associated with the given
+     * CGLLayer.
+     */
+    @Override
+    public SurfaceData createSurfaceData(CGLLayer layer) {
+        return CGLSurfaceData.createData(layer);
+    }
+
+    /**
      * Creates a new hidden-acceleration image of the given width and height
      * that is associated with the target Component.
      */
--- a/src/macosx/classes/sun/java2d/opengl/CGLLayer.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/java2d/opengl/CGLLayer.java	Fri Dec 23 22:01:01 2011 +0300
@@ -26,16 +26,113 @@
 package sun.java2d.opengl;
 
 import sun.lwawt.macosx.CFRetainedResource;
+import sun.lwawt.LWWindowPeer;
+
+import sun.java2d.SurfaceData;
+import sun.java2d.NullSurfaceData;
+
+import sun.awt.CGraphicsConfig;
+
+import java.awt.Rectangle;
+import java.awt.GraphicsConfiguration;
+import java.awt.Transparency;
 
 public class CGLLayer extends CFRetainedResource {
 
-    private static native long nativeCreateLayer();
+    private native long nativeCreateLayer();
 
-    public CGLLayer() {
-        super(nativeCreateLayer(), true);
+    private static native void validate(long layerPtr, CGLSurfaceData cglsd);
+    private static native void blitTexture(long layerPtr);
+
+    private LWWindowPeer peer;
+
+    private SurfaceData surfaceData; // represents intermediate buffer (texture)
+
+    public CGLLayer(LWWindowPeer peer) {
+        super(0, true);
+
+        setPtr(nativeCreateLayer());
+        this.peer = peer;
     }
 
     public long getPointer() {
         return ptr;
     }
+
+    public Rectangle getBounds() {
+        return peer.getBounds();
+    }
+
+    public GraphicsConfiguration getGraphicsConfiguration() {
+        return peer.getGraphicsConfiguration();
+    }
+
+    public boolean isOpaque() {
+        return peer.isOpaque();
+    }
+
+    public int getTransparency() {
+        return (peer.isOpaque() ? Transparency.OPAQUE : Transparency.TRANSLUCENT);
+    }
+
+    public Object getDestination() {
+        return peer;
+    }
+
+    public SurfaceData replaceSurfaceData() {
+        if (peer.getBounds().isEmpty()) {
+            surfaceData = NullSurfaceData.theInstance;
+            return surfaceData;
+        }
+
+        // the layer redirects all painting to the buffer's graphics
+        // and blits the buffer to the layer surface (in drawInCGLContext callback)
+        CGraphicsConfig gc = (CGraphicsConfig)peer.getGraphicsConfiguration();
+        surfaceData = gc.createSurfaceData(this);
+
+        // the layer holds a reference to the buffer, which in
+        // turn has a reference back to this layer
+        if (surfaceData instanceof CGLSurfaceData) {
+            validate((CGLSurfaceData)surfaceData);
+        }
+
+        return surfaceData;
+    }
+
+    public SurfaceData getSurfaceData() {
+        return surfaceData;
+    }
+
+    public void validate(final CGLSurfaceData cglsd) {
+        OGLRenderQueue rq = OGLRenderQueue.getInstance();
+        rq.lock();
+        try {
+            validate(getPointer(), cglsd);
+        } finally {
+            rq.unlock();
+        }
+    }
+
+    @Override
+    public void dispose() {
+        // break the connection between the layer and the buffer
+        validate(null);
+        super.dispose();
+    }
+
+    // ----------------------------------------------------------------------
+    // NATIVE CALLBACKS
+    // ----------------------------------------------------------------------
+
+    private void drawInCGLContext() {
+        // tell the flusher thread not to update the intermediate buffer
+        // until we are done blitting from it
+        OGLRenderQueue rq = OGLRenderQueue.getInstance();
+        rq.lock();
+        try {
+            blitTexture(getPointer());
+        } finally {
+            rq.unlock();
+        }
+    }
 }
--- a/src/macosx/classes/sun/java2d/opengl/CGLSurfaceData.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/java2d/opengl/CGLSurfaceData.java	Fri Dec 23 22:01:01 2011 +0300
@@ -44,16 +44,16 @@
     protected CPlatformView pView;
     private CGLGraphicsConfig graphicsConfig;
 
-    // Mac OS X specific - we never recreate surfaces, just resize them
-    native void resize(int xoff, int yoff, int width, int height);
+    native void validate(int xoff, int yoff, int width, int height, boolean isOpaque);
 
-    private native void initOps(long pConfigInfo, long pPeerData, int xoff, int yoff);
+    private native void initOps(long pConfigInfo, long pPeerData, long layerPtr,
+                                int xoff, int yoff, boolean isOpaque);
 
     protected native boolean initPbuffer(long pData, long pConfigInfo,
             boolean isOpaque, int width, int height);
 
     protected CGLSurfaceData(CPlatformView pView, CGLGraphicsConfig gc,
-            ColorModel cm, int type)
+                             ColorModel cm, int type)
     {
         super(gc, cm, type);
         this.pView = pView;
@@ -61,10 +61,28 @@
 
         long pConfigInfo = gc.getNativeConfigInfo();
         long pPeerData = 0L;
+        boolean isOpaque = true;
         if (pView != null) {
             pPeerData = pView.getAWTView();
+            isOpaque = pView.isOpaque();
         }
-        initOps(pConfigInfo, pPeerData, 0, 0);
+        initOps(pConfigInfo, pPeerData, 0, 0, 0, isOpaque);
+    }
+
+    protected CGLSurfaceData(CGLLayer layer, CGLGraphicsConfig gc,
+                             ColorModel cm, int type)
+    {
+        super(gc, cm, type);
+        this.graphicsConfig = gc;
+
+        long pConfigInfo = gc.getNativeConfigInfo();
+        long layerPtr = 0L;
+        boolean isOpaque = true;
+        if (layer != null) {
+            layerPtr = layer.getPointer();
+            isOpaque = layer.isOpaque();
+        }
+        initOps(pConfigInfo, 0, layerPtr, 0, 0, isOpaque);
     }
 
     @Override //SurfaceData
@@ -82,6 +100,16 @@
     }
 
     /**
+     * Creates a SurfaceData object representing the intermediate buffer
+     * between the Java2D flusher thread and the AppKit thread.
+     */
+    public static CGLLayerSurfaceData createData(CGLLayer layer) {
+        CGLGraphicsConfig gc = getGC(layer);
+        Rectangle r = layer.getBounds();
+        return new CGLLayerSurfaceData(layer, gc, r.width, r.height);
+    }
+
+    /**
      * Creates a SurfaceData object representing the back buffer of a
      * double-buffered on-screen Window.
      */
@@ -115,13 +143,17 @@
             // REMIND: this should rarely (never?) happen, but what if
             // default config is not CGL?
             GraphicsEnvironment env = GraphicsEnvironment
-                    .getLocalGraphicsEnvironment();
+                .getLocalGraphicsEnvironment();
             GraphicsDevice gd = env.getDefaultScreenDevice();
             return (CGLGraphicsConfig) gd.getDefaultConfiguration();
         }
     }
 
-    public void setBounds() {
+    public static CGLGraphicsConfig getGC(CGLLayer layer) {
+        return (CGLGraphicsConfig)layer.getGraphicsConfiguration();
+    }
+
+    public void validate() {
         // Overridden in CGLWindowSurfaceData below
     }
 
@@ -153,16 +185,14 @@
             return pView.getDestination();
         }
 
-        // Mac OS X specific - we never recreate surfaces, just resize them
-        public void setBounds() {
+        public void validate() {
             OGLRenderQueue rq = OGLRenderQueue.getInstance();
             rq.lock();
             try {
                 rq.flushAndInvokeNow(new Runnable() {
                     public void run() {
-                        // Component c = peer.getTarget();
                         Rectangle peerBounds = pView.getBounds();
-                        resize(0, 0, peerBounds.width, peerBounds.height);
+                        validate(0, 0, peerBounds.width, peerBounds.height, pView.isOpaque());
                     }
                 });
             } finally {
@@ -178,6 +208,61 @@
     }
 
     /**
+     * A surface which implements an intermediate buffer between
+     * the Java2D flusher thread and the AppKit thread.
+     *
+     * This surface serves as a buffer attached to a CGLLayer and
+     * the layer redirects all painting to the buffer's graphics.
+     */
+    public static class CGLLayerSurfaceData extends CGLSurfaceData {
+
+        private CGLLayer layer;
+        private int width, height;
+
+        public CGLLayerSurfaceData(CGLLayer layer, CGLGraphicsConfig gc,
+                                   int width, int height) {
+            super(layer, gc, gc.getColorModel(), FBOBJECT);
+
+            this.width = width;
+            this.height = height;
+            this.layer = layer;
+
+            initSurface(width, height);
+        }
+
+        @Override
+        public SurfaceData getReplacement() {
+            return layer.getSurfaceData();
+        }
+
+        @Override
+        boolean isOnScreen() {
+            return true;
+        }
+
+        @Override
+        public Rectangle getBounds() {
+            return new Rectangle(width, height);
+        }
+
+        @Override
+        public Object getDestination() {
+            return layer.getDestination();
+        }
+
+        @Override
+        public int getTransparency() {
+            return layer.getTransparency();
+        }
+
+        @Override
+        public void invalidate() {
+            super.invalidate();
+            clearWindow();
+        }
+    }
+
+    /**
      * A surface which implements a v-synced flip back-buffer with COPIED
      * FlipContents.
      *
@@ -214,8 +299,8 @@
         private int width, height;
 
         public CGLOffScreenSurfaceData(CPlatformView pView,
-                CGLGraphicsConfig gc, int width, int height, Image image,
-                ColorModel cm, int type) {
+                                       CGLGraphicsConfig gc, int width, int height, Image image,
+                                       ColorModel cm, int type) {
             super(pView, gc, cm, type);
 
             this.width = width;
--- a/src/macosx/classes/sun/lwawt/LWButtonPeer.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/lwawt/LWButtonPeer.java	Fri Dec 23 22:01:01 2011 +0300
@@ -27,7 +27,6 @@
 package sun.lwawt;
 
 import java.awt.Button;
-import java.awt.Color;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.peer.ButtonPeer;
@@ -37,10 +36,6 @@
 final class LWButtonPeer extends LWComponentPeer<Button, JButton>
         implements ButtonPeer, ActionListener {
 
-    // We don't support background and foreground colors for button
-    // since AquaButtonUI doesn't do it
-    private Color background, foreground;
-
     LWButtonPeer(final Button target,
                  final PlatformComponent platformComponent) {
         super(target, platformComponent);
@@ -60,22 +55,6 @@
         }
     }
 
-    public Color getBackground() {
-        return background;
-    }
-
-    public void setBackground(Color background) {
-        this.background = background;
-    }
-
-    public Color getForeground() {
-        return foreground;
-    }
-
-    public void setForeground(Color foreground) {
-        this.foreground = foreground;
-    }
-
     @Override
     public void actionPerformed(final ActionEvent e) {
         postEvent(new ActionEvent(getTarget(), ActionEvent.ACTION_PERFORMED,
--- a/src/macosx/classes/sun/lwawt/LWCanvasPeer.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/lwawt/LWCanvasPeer.java	Fri Dec 23 22:01:01 2011 +0300
@@ -97,11 +97,6 @@
         }
 
         @Override
-        public boolean isOpaque() {
-            return true;
-        }
-
-        @Override
         protected void paintComponent(final Graphics g) {
             if (isOpaque()) {
                 g.setColor(getBackground());
--- a/src/macosx/classes/sun/lwawt/LWCheckboxPeer.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/lwawt/LWCheckboxPeer.java	Fri Dec 23 22:01:01 2011 +0300
@@ -23,21 +23,30 @@
  * questions.
  */
 
+
 package sun.lwawt;
 
-import java.awt.*;
+import java.awt.Checkbox;
+import java.awt.CheckboxGroup;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.event.ItemEvent;
 import java.awt.event.ItemListener;
-import java.awt.event.ItemEvent;
-import java.awt.event.AWTEventListener;
 import java.awt.peer.CheckboxPeer;
 import java.beans.Transient;
 
-import javax.swing.*;
+import javax.swing.JCheckBox;
+import javax.swing.JComponent;
+import javax.swing.JRadioButton;
+import javax.swing.JToggleButton;
+import javax.swing.SwingUtilities;
 
-class LWCheckboxPeer
+final class LWCheckboxPeer
         extends LWComponentPeer<Checkbox, LWCheckboxPeer.CheckboxDelegate>
         implements CheckboxPeer, ItemListener {
-    LWCheckboxPeer(Checkbox target, PlatformComponent platformComponent) {
+
+    LWCheckboxPeer(final Checkbox target,
+                   final PlatformComponent platformComponent) {
         super(target, platformComponent);
     }
 
@@ -51,23 +60,24 @@
         return getDelegate().getCurrentButton();
     }
 
+    @Override
     public void initialize() {
         super.initialize();
-        getDelegate().setRadioButton(getTarget().getCheckboxGroup() != null);
-        getDelegate().getCurrentButton().setText(getTarget().getLabel());
-        getDelegate().getCurrentButton().setSelected(getTarget().getState());
-        getDelegate().getCurrentButton().addItemListener(this);
+        setLabel(getTarget().getLabel());
+        setState(getTarget().getState());
+        setCheckboxGroup(getTarget().getCheckboxGroup());
     }
 
-
+    @Override
     public void itemStateChanged(final ItemEvent e) {
         // group.setSelectedCheckbox() will repaint the component
         // to let LWCheckboxPeer correctly handle it we should call it
         // after the current event is processed
         SwingUtilities.invokeLater(new Runnable() {
+            @Override
             public void run() {
                 boolean postEvent = true;
-                CheckboxGroup group = getTarget().getCheckboxGroup();
+                final CheckboxGroup group = getTarget().getCheckboxGroup();
                 if (group != null) {
                     if (e.getStateChange() == ItemEvent.SELECTED) {
                         if (group.getSelectedCheckbox() != getTarget()) {
@@ -78,38 +88,46 @@
                     } else {
                         postEvent = false;
                         if (group.getSelectedCheckbox() == getTarget()) {
-                            // don't want to leave the group with no selected checkbox
+                            // Don't want to leave the group with no selected
+                            // checkbox.
                             getTarget().setState(true);
                         }
                     }
                 } else {
-                    getTarget().setState(e.getStateChange() == ItemEvent.SELECTED);
+                    getTarget().setState(e.getStateChange()
+                                         == ItemEvent.SELECTED);
                 }
-                if(postEvent) {
-                    postEvent(new ItemEvent(getTarget(), ItemEvent.ITEM_STATE_CHANGED,
-                            getTarget().getLabel(), e.getStateChange()));
+                if (postEvent) {
+                    postEvent(new ItemEvent(getTarget(),
+                                            ItemEvent.ITEM_STATE_CHANGED,
+                                            getTarget().getLabel(),
+                                            e.getStateChange()));
                 }
             }
         });
     }
 
-    public void setCheckboxGroup(CheckboxGroup g) {
+    @Override
+    public void setCheckboxGroup(final CheckboxGroup g) {
         synchronized (getDelegateLock()) {
-            initialize();
+            getDelegate().getCurrentButton().removeItemListener(this);
+            getDelegate().setRadioButton(g != null);
+            getDelegate().getCurrentButton().addItemListener(this);
         }
         repaintPeer();
     }
 
-    public void setLabel(String label) {
+    @Override
+    public void setLabel(final String label) {
         synchronized (getDelegateLock()) {
-            getDelegate().getCurrentButton().setText(label);
+            getDelegate().setText(label);
         }
-        repaintPeer();
     }
 
-    public void setState(boolean state) {
+    @Override
+    public void setState(final boolean state) {
         synchronized (getDelegateLock()) {
-            getDelegate().getCurrentButton().setSelected(state);
+            getDelegate().setSelected(state);
         }
         repaintPeer();
     }
@@ -120,61 +138,77 @@
     }
 
     final class CheckboxDelegate extends JComponent {
-        private JCheckBox cb;
-        private JRadioButton rb;
+
+        private final JCheckBox cb;
+        private final JRadioButton rb;
 
         CheckboxDelegate() {
+            super();
             cb = new JCheckBox() {
+                @Override
                 public boolean hasFocus() {
                     return getTarget().hasFocus();
                 }
             };
-            cb.setOpaque(false);
             rb = new JRadioButton() {
+                @Override
                 public boolean hasFocus() {
                     return getTarget().hasFocus();
                 }
             };
-            rb.setOpaque(false);
+            setLayout(null);
+            setRadioButton(false);
+            add(rb);
             add(cb);
         }
 
-        public boolean isRadioButton() {
-            return getCurrentButton() == rb;
-        }
-
-        public void setRadioButton(boolean b) {
-            AWTEventListener toolkitListener = getToolkitAWTEventListener();
-            synchronized (Toolkit.getDefaultToolkit()) {
-                try {
-                    remove(getCurrentButton());
-                    add(b ? rb : cb);
-                } finally {
-                    setToolkitAWTEventListener(toolkitListener);
-                }
-            }
-        }
-
-        private JToggleButton getCurrentButton() {
-            return (JToggleButton) getComponent(0);
-        }
-
         @Override
         public void setEnabled(final boolean enabled) {
+            super.setEnabled(enabled);
             rb.setEnabled(enabled);
             cb.setEnabled(enabled);
         }
 
-        @Deprecated
-        public void reshape(int x, int y, int w, int h) {
-            super.reshape(x, y, w, h);
-            getCurrentButton().setBounds(0, 0, w, h);
+        @Override
+        public void setOpaque(final boolean isOpaque) {
+            super.setOpaque(isOpaque);
+            rb.setOpaque(isOpaque);
+            cb.setOpaque(isOpaque);
         }
 
+        @Override
+        @Deprecated
+        public void reshape(final int x, final int y, final int w,
+                            final int h) {
+            super.reshape(x, y, w, h);
+            cb.setBounds(0, 0, w, h);
+            rb.setBounds(0, 0, w, h);
+        }
+
+        @Override
         @Transient
         public Dimension getMinimumSize() {
             return getCurrentButton().getMinimumSize();
         }
+
+        void setRadioButton(final boolean showRadioButton) {
+            rb.setVisible(showRadioButton);
+            cb.setVisible(!showRadioButton);
+        }
+
+        @Transient
+        JToggleButton getCurrentButton() {
+            return cb.isVisible() ? cb : rb;
+        }
+
+        void setText(final String label) {
+            cb.setText(label);
+            rb.setText(label);
+        }
+
+        void setSelected(final boolean state) {
+            cb.setSelected(state);
+            rb.setSelected(state);
+        }
     }
 }
-
--- a/src/macosx/classes/sun/lwawt/LWChoicePeer.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/lwawt/LWChoicePeer.java	Fri Dec 23 22:01:01 2011 +0300
@@ -37,7 +37,15 @@
 final class LWChoicePeer extends LWComponentPeer<Choice, JComboBox<String>>
         implements ChoicePeer, ItemListener {
 
-    LWChoicePeer(final Choice target, PlatformComponent platformComponent) {
+    /**
+     * According to Choice specification item events are sent in response to
+     * user input, but not in response to calls to select(). But JComboBox are
+     * sent item events in both cases. Should be used under delegateLock.
+     */
+    private boolean skipPostMessage;
+
+    LWChoicePeer(final Choice target,
+                 final PlatformComponent platformComponent) {
         super(target, platformComponent);
     }
 
@@ -65,15 +73,18 @@
     }
 
     @Override
-    public void itemStateChanged(final ItemEvent event) {
+    public void itemStateChanged(final ItemEvent e) {
         // AWT Choice sends SELECTED event only whereas JComboBox
         // sends both SELECTED and DESELECTED.
-        if (event.getStateChange() == ItemEvent.SELECTED) {
+        if (e.getStateChange() == ItemEvent.SELECTED) {
             synchronized (getDelegateLock()) {
+                if (skipPostMessage) {
+                    return;
+                }
                 getTarget().select(getDelegate().getSelectedIndex());
             }
             postEvent(new ItemEvent(getTarget(), ItemEvent.ITEM_STATE_CHANGED,
-                                    event.getItem(), ItemEvent.SELECTED));
+                                    e.getItem(), ItemEvent.SELECTED));
         }
     }
 
@@ -87,7 +98,10 @@
     @Override
     public void remove(final int index) {
         synchronized (getDelegateLock()) {
+            // We shouldn't post event, if selected item was removed.
+            skipPostMessage = true;
             getDelegate().removeItemAt(index);
+            skipPostMessage = false;
         }
     }
 
@@ -101,7 +115,11 @@
     @Override
     public void select(final int index) {
         synchronized (getDelegateLock()) {
-            getDelegate().setSelectedIndex(index);
+            if (index != getDelegate().getSelectedIndex()) {
+                skipPostMessage = true;
+                getDelegate().setSelectedIndex(index);
+                skipPostMessage = false;
+            }
         }
     }
 
@@ -128,5 +146,18 @@
         public Point getLocationOnScreen() {
             return LWChoicePeer.this.getLocationOnScreen();
         }
+
+        /**
+         * We should post ITEM_STATE_CHANGED event when the same element is
+         * reselected.
+         */
+        @Override
+        public void setSelectedItem(final Object anObject) {
+            final Object oldSelection = selectedItemReminder;
+            if (oldSelection != null && oldSelection.equals(anObject)) {
+                selectedItemChanged();
+            }
+            super.setSelectedItem(anObject);
+        }
     }
 }
--- a/src/macosx/classes/sun/lwawt/LWComponentPeer.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/lwawt/LWComponentPeer.java	Fri Dec 23 22:01:01 2011 +0300
@@ -23,6 +23,7 @@
  * questions.
  */
 
+
 package sun.lwawt;
 
 import java.awt.*;
@@ -31,7 +32,6 @@
 import java.awt.dnd.peer.DropTargetPeer;
 import java.awt.event.*;
 
-import java.awt.geom.Area;
 import java.awt.image.ColorModel;
 import java.awt.image.ImageObserver;
 import java.awt.image.ImageProducer;
@@ -54,13 +54,13 @@
 import sun.awt.image.ToolkitImage;
 
 import sun.java2d.SunGraphics2D;
+import sun.java2d.opengl.OGLRenderQueue;
 import sun.java2d.pipe.Region;
 
 import javax.swing.JComponent;
 import javax.swing.SwingUtilities;
 import javax.swing.RepaintManager;
 
-import sun.java2d.pipe.SpanIterator;
 import sun.lwawt.macosx.CDropTarget;
 
 import com.sun.java.swing.SwingUtilities3;
@@ -108,8 +108,7 @@
 
     // Bounds are relative to parent peer
     private Rectangle bounds = new Rectangle();
-    private Region shape;
-    private Shape clip;
+    private Region region;
 
     // Component state. Should be accessed under the state lock
     private boolean visible = false;
@@ -131,47 +130,57 @@
 
     private PlatformComponent platformComponent;
 
-    private class DelegateContainer extends Container {
+    private final class DelegateContainer extends Container {
         {
             enableEvents(0xFFFFFFFF);
         }
 
+        DelegateContainer() {
+            super();
+        }
+
         @Override
         public boolean isLightweight() {
             return false;
         }
 
+        @Override
         public Point getLocation() {
             return getLocationOnScreen();
         }
 
+        @Override
         public Point getLocationOnScreen() {
             return LWComponentPeer.this.getLocationOnScreen();
         }
 
+        @Override
         public int getX() {
             return getLocation().x;
         }
 
+        @Override
         public int getY() {
             return getLocation().y;
         }
 
+        @Override
         @Transient
         public Color getBackground() {
             return getTarget().getBackground();
         }
 
+        @Override
         @Transient
         public Color getForeground() {
             return getTarget().getForeground();
         }
 
+        @Override
         @Transient
         public Font getFont() {
             return getTarget().getFont();
         }
-
     }
 
     public LWComponentPeer(T target, PlatformComponent platformComponent) {
@@ -222,16 +231,9 @@
                     // to extract the painting call from the event's processing routine
                     //TODO: so why exactly do we have to emulate this in lwawt? We use a back-buffer anyway,
                     //why not paint the components synchronously into the buffer?
-                    SwingUtilities.invokeLater(new Runnable() {
-                        public void run() {
-                            if (isShowing()) {
-                                Rectangle res = SwingUtilities.convertRectangle(
-                                        c, new Rectangle(x, y, w, h), getDelegate());
-                                LWComponentPeer.this.repaintPeer(
-                                        res.x, res.y, res.width, res.height);
-                            }
-                        }
-                    });
+                    Rectangle res = SwingUtilities.convertRectangle(
+                            c, new Rectangle(x, y, w, h), getDelegate());
+                    repaintPeer(res);
                 }
             });
         }
@@ -298,7 +300,16 @@
      */
     public void initialize() {
         platformComponent.initialize(target, this, getPlatformWindow());
-        targetPaintArea = new RepaintArea();
+        targetPaintArea = new LWRepaintArea();
+        synchronized (getDelegateLock()) {
+            if (getDelegate() != null) {
+                getDelegate().setOpaque(true);
+                resetColorsAndFont(delegate);
+                // we must explicitly set the font here
+                // see Component.getFont_NoClientCode() for details
+                delegateContainer.setFont(target.getFont());
+            }
+        }
         if (target.isBackgroundSet()) {
             setBackground(target.getBackground());
         }
@@ -311,17 +322,9 @@
         setBounds(target.getBounds());
         setEnabled(target.isEnabled());
         setVisible(target.isVisible());
-        synchronized (getDelegateLock()) {
-            if (getDelegate() != null) {
-                resetColorsAndFont(delegate);
-                // we must explicitly set the font here
-                // see Component.getFont_NoClientCode() for details
-                delegateContainer.setFont(target.getFont());
-            }
-        }
     }
 
-    private void resetColorsAndFont(Container c) {
+    private static void resetColorsAndFont(final Container c) {
         c.setBackground(null);
         c.setForeground(null);
         c.setFont(null);
@@ -367,7 +370,7 @@
     }
 
     // Just a helper method
-    // Overriden in LWWindowPeer to skip containerPeer initialization
+    // Overridden in LWWindowPeer to skip containerPeer initialization
     protected void initializeContainerPeer() {
         Container parent = LWToolkit.getNativeContainer(target);
         if (parent != null) {
@@ -380,6 +383,10 @@
         return windowPeer.getPlatformWindow();
     }
 
+    protected AppContext getAppContext() {
+        return SunToolkit.targetToAppContext(getTarget());
+    }
+
     // ---- PEER METHODS ---- //
 
     @Override
@@ -437,68 +444,85 @@
         return false;
     }
 
+    @Override
+    public final synchronized Graphics getGraphics() {
+        Graphics g = getWindowPeerOrSelf().isOpaque() ? getOnscreenGraphics()
+                                                      : getOffscreenGraphics();
+        if (g != null) {
+            synchronized (getPeerTreeLock()){
+                applyConstrain(g);
+            }
+        }
+        return g;
+    }
+
     /*
      * Peer Graphics is borrowed from the parent peer, while
      * foreground and background colors and font are specific to
      * this peer.
      */
-    @Override
-    public Graphics getGraphics() {
-        // getGraphics() is executed outside of the synchronized block
-        // as the state lock should be the last one in the chain
-        return getGraphics(getForeground(), getBackground(), getFont());
+    public final Graphics getOnscreenGraphics() {
+        final LWWindowPeer wp = getWindowPeerOrSelf();
+        return wp.getOnscreenGraphics(getForeground(), getBackground(),
+                                      getFont());
     }
 
-    /*
-     * To be overridden in LWWindowPeer to get a Graphics from
-     * the delegate.
-     */
-    protected Graphics getGraphics(Color fg, Color bg, Font f) {
-        LWContainerPeer cp = getContainerPeer();
-        // Don't check containerPeer for null as it can only happen
-        // for windows, but this method is overridden in
-        // LWWindowPeer and doesn't call super()
-        SunGraphics2D g = (SunGraphics2D) cp.getGraphics(fg, bg, f);
-        if (g != null) {
-            final Rectangle r = getBounds();
-            final Rectangle constr = r.intersection(cp.getContentSize());
-            g.constrain(constr.x, constr.y, constr.width, constr.height);
-            g.translate(r.x - constr.x, r.y - constr.y);
-            if (clip != null) {
-                g.clip(clip);
+    public final Graphics getOffscreenGraphics() {
+        final LWWindowPeer wp = getWindowPeerOrSelf();
+
+        return wp.getOffscreenGraphics(getForeground(), getBackground(),
+                                       getFont());
+    }
+
+    private void applyConstrain(final Graphics g) {
+        final SunGraphics2D sg2d = (SunGraphics2D) g;
+        final Rectangle constr = localToWindow(getSize());
+        // translate and set rectangle constrain.
+        sg2d.constrain(constr.x, constr.y, constr.width, constr.height);
+        // set region constrain.
+        //sg2d.constrain(getVisibleRegion());
+        SG2DConstraint(sg2d, getVisibleRegion());
+    }
+
+    //TODO Move this method to SG2D?
+    private void SG2DConstraint(final SunGraphics2D sg2d, Region r) {
+        sg2d.constrainX = sg2d.transX;
+        sg2d.constrainY = sg2d.transY;
+
+        Region c = sg2d.constrainClip;
+        if ((sg2d.constrainX | sg2d.constrainY) != 0) {
+            r = r.getTranslatedRegion(sg2d.constrainX, sg2d.constrainY);
+        }
+        if (c == null) {
+            c = r;
+        } else {
+            c = c.getIntersection(r);
+            if (c == sg2d.constrainClip) {
+                // Common case to ignore
+                return;
             }
         }
-        return g;
+        sg2d.constrainClip = c;
+        //validateCompClip() forced call.
+        sg2d.setDevClip(r.getLoX(), r.getLoY(), r.getWidth(), r.getHeight());
     }
 
-    public Graphics getOffscreenGraphics() {
-        return getOffscreenGraphics(getForeground(), getBackground(),
-                getFont());
+    public Region getVisibleRegion() {
+        return computeVisibleRect(this, getRegion());
     }
 
-    /**
-     * This method returns a back buffer Graphics to render all the peers to.
-     * After the peer is painted, the back buffer contents should be flushed to
-     * the screen. All the target painting (Component.paint() method) should be
-     * done directly to the screen.
-     */
-    protected Graphics getOffscreenGraphics(final Color fg, final Color bg,
-                                            final Font f) {
-        final LWContainerPeer cp = getContainerPeer();
-        // Don't check containerPeer for null as it can only happen
-        // for windows, but this method is overridden in
-        // LWWindowPeer and doesn't call super()
-        SunGraphics2D g = (SunGraphics2D) cp.getOffscreenGraphics(fg, bg, f);
-        if (g != null) {
-            final Rectangle r = getBounds();
-            final Rectangle constr = r.intersection(cp.getContentSize());
-            g.constrain(constr.x, constr.y, constr.width, constr.height);
-            g.translate(r.x - constr.x, r.y - constr.y);
-            if (clip != null) {
-                g.clip(clip);
-            }
+    static final Region computeVisibleRect(LWComponentPeer c, Region region) {
+        final LWContainerPeer p = c.getContainerPeer();
+        if (p != null) {
+            final Rectangle r = c.getBounds();
+            region = region.getTranslatedRegion(r.x, r.y);
+            region = region.getIntersection(p.getRegion());
+            region = region.getIntersection(p.getContentSize());
+            region = p.cutChildren(region, c);
+            region = computeVisibleRect(p, region);
+            region = region.getTranslatedRegion(-r.x, -r.y);
         }
-        return g;
+        return region;
     }
 
     @Override
@@ -539,15 +563,16 @@
         setBounds(r.x, r.y, r.width, r.height, SET_BOUNDS);
     }
 
-    /*
-    * This method could be called on the toolkit thread.
-    */
+    /**
+     * This method could be called on the toolkit thread.
+     */
     @Override
     public void setBounds(int x, int y, int w, int h, int op) {
-        setBounds(x, y, w, h, op, true);
+        setBounds(x, y, w, h, op, true, false);
     }
 
-    protected void setBounds(int x, int y, int w, int h, int op, boolean notify) {
+    protected void setBounds(int x, int y, int w, int h, int op, boolean notify,
+                             final boolean updateTarget) {
         Rectangle oldBounds;
         synchronized (getStateLock()) {
             oldBounds = new Rectangle(bounds);
@@ -560,26 +585,46 @@
                 bounds.height = h;
             }
         }
-        if (notify) {
-            boolean moved = (oldBounds.x != x) || (oldBounds.y != y);
-            boolean resized = (oldBounds.width != w) || (oldBounds.height != h);
-//            paintPending = !resized;
-            if (moved) {
-                handleMove(oldBounds.x, oldBounds.y, x, y);
-            }
-            if (resized) {
-                handleResize(oldBounds.width, oldBounds.height, w, h);
+        boolean moved = (oldBounds.x != x) || (oldBounds.y != y);
+        boolean resized = (oldBounds.width != w) || (oldBounds.height != h);
+        if (!moved && !resized) {
+            return;
+        }
+        final D delegate = getDelegate();
+        if (delegate != null) {
+            synchronized (getDelegateLock()) {
+                delegateContainer.setBounds(0, 0, w, h);
+                delegate.setBounds(delegateContainer.getBounds());
+                // TODO: the following means that the delegateContainer NEVER gets validated. That's WRONG!
+                delegate.validate();
             }
         }
-        Point locationInWindow = localToWindow(0, 0);
-        platformComponent.setBounds(locationInWindow.x, locationInWindow.y,
-                bounds.width, bounds.height);
+
+        final Point locationInWindow = localToWindow(0, 0);
+        platformComponent.setBounds(locationInWindow.x, locationInWindow.y, w,
+                                    h);
+        if (notify) {
+            repaintOldNewBounds(oldBounds);
+            if (resized) {
+                handleResize(w, h, updateTarget);
+            }
+            if (moved) {
+                handleMove(x, y, updateTarget);
+            }
+        }
     }
 
-    public Rectangle getBounds() {
+    public final Rectangle getBounds() {
         synchronized (getStateLock()) {
             // Return a copy to prevent subsequent modifications
-            return new Rectangle(bounds);
+            return bounds.getBounds();
+        }
+    }
+
+    public final Rectangle getSize() {
+        synchronized (getStateLock()) {
+            // Return a copy to prevent subsequent modifications
+            return new Rectangle(bounds.width, bounds.height);
         }
     }
 
@@ -730,13 +775,11 @@
                 delegate.setVisible(v);
             }
         }
-
-        LWContainerPeer cp = getContainerPeer();
-        if (cp != null) {
-            Rectangle r = getBounds();
-            cp.repaintPeer(r.x, r.y, r.width, r.height);
+        if (visible) {
+            repaintPeer();
+        } else {
+            repaintParent(getBounds());
         }
-        repaintPeer();
     }
 
     // Helper method
@@ -747,9 +790,7 @@
     }
 
     @Override
-    public void paint(Graphics g) {
-        // For some unknown reasons, all the platforms just call
-        // to target.paint() here and don't paint the peer itself
+    public void paint(final Graphics g) {
         getTarget().paint(g);
     }
 
@@ -809,8 +850,8 @@
         return false;
     }
 
-    /*
-     * Should be overriden in subclasses to forward the request
+    /**
+     * Should be overridden in subclasses to forward the request
      * to the Swing helper component, if required.
      */
     @Override
@@ -852,13 +893,13 @@
     public boolean requestFocus(Component lightweightChild, boolean temporary,
                                 boolean focusedWindowChangeAllowed, long time,
                                 CausedFocusEvent.Cause cause) {
-        if (getLWToolkit().getKeyboardFocusManagerPeer().
+        if (LWKeyboardFocusManagerPeer.getInstance(getAppContext()).
                 processSynchronousLightweightTransfer(getTarget(), lightweightChild, temporary,
                         focusedWindowChangeAllowed, time)) {
             return true;
         }
 
-        int result = getLWToolkit().getKeyboardFocusManagerPeer().
+        int result = LWKeyboardFocusManagerPeer.getInstance(getAppContext()).
                 shouldNativelyFocusHeavyweight(getTarget(), lightweightChild, temporary,
                         focusedWindowChangeAllowed, time, cause);
         switch (result) {
@@ -885,7 +926,8 @@
                 }
 
                 LWComponentPeer focusOwnerPeer =
-                        getLWToolkit().getKeyboardFocusManagerPeer().getFocusOwner();
+                    LWKeyboardFocusManagerPeer.getInstance(getAppContext()).
+                        getFocusOwner();
                 Component focusOwner = (focusOwnerPeer != null) ? focusOwnerPeer.getTarget() : null;
                 return LWKeyboardFocusManagerPeer.deliverFocus(lightweightChild,
                         getTarget(), temporary,
@@ -934,38 +976,16 @@
     }
 
     @Override
-    public void applyShape(final Region shape) {
-        Area area = null;
-        if (shape != null) {
-            area = new Area();
-            final int[] span = new int[4];
-            final SpanIterator si = shape.getSpanIterator();
-            while (si.nextSpan(span)) {
-                area.add(new Area(new Rectangle(span[0], span[1], span[2],
-                        span[3])));
-            }
+    public final void applyShape(final Region shape) {
+        synchronized (getStateLock()) {
+            region = shape;
         }
-        synchronized (getStateLock()) {
-            clip = area;
-            this.shape = shape;
-        }
-        LWContainerPeer cp = getContainerPeer();
-        if (cp != null) {
-            Rectangle r = getBounds();
-            cp.repaintPeer(r.x, r.y, r.width, r.height);
-        }
-        repaintPeer();
+        repaintParent(getBounds());
     }
 
-    private Region getShape() {
+    protected final Region getRegion() {
         synchronized (getStateLock()) {
-            return shape;
-        }
-    }
-
-    protected Shape getClip() {
-        synchronized (getStateLock()) {
-            return clip;
+            return region == null ? Region.getInstance(getSize()) : region;
         }
     }
 
@@ -1000,7 +1020,7 @@
 
     // ---- PEER NOTIFICATIONS ---- //
 
-    /*
+    /**
      * Called when this peer's location has been changed either as a result
      * of target.setLocation() or as a result of user actions (window is
      * dragged with mouse).
@@ -1009,19 +1029,16 @@
      *
      * This method could be called on the toolkit thread.
      */
-
-    protected void handleMove(int oldX, int oldY, int newX, int newY) {
-        postEvent(new ComponentEvent(getTarget(), ComponentEvent.COMPONENT_MOVED));
-        LWContainerPeer cp = getContainerPeer();
-        if (cp != null) {
-            // Repaint unobscured part of the parent
-            Rectangle r = getBounds();
-            cp.repaintPeer(oldX, oldY, r.width, r.height);
-            cp.repaintPeer(newX, newY, r.width, r.height);
+    protected final void handleMove(final int x, final int y,
+                                    final boolean updateTarget) {
+        if (updateTarget) {
+            AWTAccessor.getComponentAccessor().setLocation(getTarget(), x, y);
         }
+        postEvent(new ComponentEvent(getTarget(),
+                                     ComponentEvent.COMPONENT_MOVED));
     }
 
-    /*
+    /**
      * Called when this peer's size has been changed either as a result of
      * target.setSize() or as a result of user actions (window is resized).
      *
@@ -1030,52 +1047,35 @@
      *
      * This method could be called on the toolkit thread.
      */
-    protected void handleResize(int oldW, int oldH, int newW, int newH) {
-        postEvent(new ComponentEvent(getTarget(), ComponentEvent.COMPONENT_RESIZED));
-        LWContainerPeer cp = getContainerPeer();
+    protected final void handleResize(final int w, final int h,
+                                      final boolean updateTarget) {
+        if (updateTarget) {
+            AWTAccessor.getComponentAccessor().setSize(getTarget(), w, h);
+        }
+        postEvent(new ComponentEvent(getTarget(),
+                                     ComponentEvent.COMPONENT_RESIZED));
+    }
+
+    protected final void repaintOldNewBounds(final Rectangle oldB) {
+        repaintParent(oldB);
+        repaintPeer(getSize());
+    }
+
+    protected final void repaintParent(final Rectangle oldB) {
+        final LWContainerPeer cp = getContainerPeer();
         if (cp != null) {
             // Repaint unobscured part of the parent
-            Rectangle r = getBounds();
-            cp.repaintPeer(r.x, r.y, oldW, oldH);
-            cp.repaintPeer(r.x, r.y, newW, newH);
+            cp.repaintPeer(cp.getContentSize().intersection(oldB));
         }
-        repaintPeer(0, 0, newW, newH);
-
-        D delegate = getDelegate();
-        if (delegate != null) {
-            synchronized (getDelegateLock()) {
-                delegateContainer.setBounds(0, 0, newW, newH);
-                delegate.setBounds(delegateContainer.getBounds());
-                // TODO: the following means that the delegateContainer NEVER gets validated. That's WRONG!
-                delegate.validate();
-            }
-        }
-    }
-
-    /*
-     * Called by the container when any part of this peer or child
-     * peers should be repainted.
-     *
-     * This method is called on the toolkit thread.
-     */
-    public void handleExpose(int x, int y, int w, int h) {
-        postPaintEvent(x, y, w, h);
     }
 
     // ---- EVENTS ---- //
 
-    /*
+    /**
      * Post an event to the proper Java EDT.
      */
-
     public void postEvent(AWTEvent event) {
-        SunToolkit.postEvent(SunToolkit.targetToAppContext(getTarget()), event);
-    }
-
-    // Just a helper method
-    protected void postPaintEvent() {
-        Rectangle r = getBounds();
-        postPaintEvent(0, 0, r.width, r.height);
+        SunToolkit.postEvent(getAppContext(), event);
     }
 
     protected void postPaintEvent(int x, int y, int w, int h) {
@@ -1109,7 +1109,7 @@
 //                paintPending = false;
                 // fall through to the next statement
             case PaintEvent.UPDATE:
-                handleJavaPaintEvent((PaintEvent) e);
+                handleJavaPaintEvent();
                 break;
             case MouseEvent.MOUSE_PRESSED:
                 Component target = getTarget();
@@ -1186,25 +1186,37 @@
         return delegateEvent;
     }
 
-    /*
-    * Handler for FocusEvents.
-    */
+    /**
+     * Handler for FocusEvents.
+     */
     protected void handleJavaFocusEvent(FocusEvent e) {
         // Note that the peer receives all the FocusEvents from
         // its lightweight children as well
-        getLWToolkit().getKeyboardFocusManagerPeer().
+        LWKeyboardFocusManagerPeer.getInstance(getAppContext()).
                 setFocusOwner(e.getID() == FocusEvent.FOCUS_GAINED ? this : null);
     }
 
-    /*
+    /**
+     * Peers with null delegates should clear background before paint.
+     *
+     * @return false on components that DO NOT require a clearRect() before
+     *         painting.
+     */
+    protected final boolean shouldClearRectBeforePaint() {
+        // By default, just fill the entire bounds with a bg color
+        // TODO: sun.awt.noerasebackground
+        return getDelegate() == null;
+    }
+
+    /**
      * Handler for PAINT and UPDATE PaintEvents.
      */
-    protected void handleJavaPaintEvent(PaintEvent e) {
+    private void handleJavaPaintEvent() {
         // Skip all painting while layouting and all UPDATEs
         // while waiting for native paint
 //        if (!isLayouting && !paintPending) {
-        if (!isLayouting) {
-            targetPaintArea.paint(getTarget(), false);
+        if (!isLayouting()) {
+            targetPaintArea.paint(getTarget(), shouldClearRectBeforePaint());
         }
     }
 
@@ -1216,10 +1228,8 @@
      */
     public LWComponentPeer findPeerAt(final int x, final int y) {
         final Rectangle r = getBounds();
-        final Region sh = getShape();
-        final boolean found = isVisible() && ((sh == null)
-                ? r.contains(x, y)
-                : sh.contains(x - r.x, y - r.y));
+        final Region sh = getRegion();
+        final boolean found = isVisible() && sh.contains(x - r.x, y - r.y);
         return found ? this : null;
     }
 
@@ -1271,65 +1281,17 @@
         return new Rectangle(p, r.getSize());
     }
 
-    // Just a helper method, thus final
-    protected final void paintPeerDirtyRect() {
-        Rectangle r = getBounds();
-        paintPeerDirtyRect(new Rectangle(0, 0, r.width, r.height));
+    public final void repaintPeer() {
+        repaintPeer(getSize());
     }
 
-    /*
-     * Repaints the given rectangle of the back buffer and flushes it
-     * to the screen. This method should only be called on EDT.
-     */
-    protected void paintPeerDirtyRect(final Rectangle r) {
-        if ((r == null) || r.isEmpty() || !isShowing()) {
+    public void repaintPeer(final Rectangle r) {
+        final Rectangle toPaint = getSize().intersection(r);
+        if (!isShowing() || toPaint.isEmpty()) {
             return;
         }
 
-        final Graphics g = getOffscreenGraphics();
-        if (g != null) {
-            try {
-                peerPaint(g, r);
-            } finally {
-                g.dispose();
-            }
-            flushOffscreenGraphics(r);
-        }
-    }
-
-
-    // TODO: rename to repaintPeer()?
-    protected void paintPeerDirtyRectOnEDT(final Rectangle dirty) {
-        if (LWToolkit.isDispatchThreadForAppContext(getTarget())) {
-            paintPeerDirtyRect(dirty);
-        } else {
-            Runnable r = new Runnable() {
-                public void run() {
-                    paintPeerDirtyRect(dirty);
-                }
-            };
-            // TODO: high-priority invocation event
-            LWToolkit.executeOnEventHandlerThread(getTarget(), r);
-        }
-    }
-
-    // todo swing: think about making both methods private
-    // and leaving repaintPeer() only
-    public void repaintPeer() {
-        repaintPeer(0, 0, getBounds().width, getBounds().height);
-    }
-
-    public void repaintPeer(final int x, final int y, final int width,
-                            final int height) {
-        paintPeerDirtyRectOnEDT(new Rectangle(x, y, width, height));
-        postPaintEvent(x, y, width, height);
-    }
-
-    public void restorePeer() {
-        if (isShowing() && !getBounds().isEmpty()) {
-            flushOffscreenGraphics();
-            postPaintEvent();
-        }
+        postPaintEvent(toPaint.x, toPaint.y, toPaint.width, toPaint.height);
     }
 
     /**
@@ -1349,56 +1311,36 @@
         return false;
     }
 
-    /*
-    * Paints the peer into the given graphics, mostly originated
-    * from the window's back buffer.
-    *
-    * Overridden in LWContainerPeer to paint all the children.
-    */
-    protected void peerPaint(Graphics g, Rectangle r) {
-        Rectangle b = getBounds();
-        if (!isShowing() || r.isEmpty() ||
-                !r.intersects(new Rectangle(0, 0, b.width, b.height))) {
-            return;
-        }
-        g.clipRect(r.x, r.y, r.width, r.height);
-        peerPaintSelf(g, r);
-    }
-
-    /*
-     * Paints the peer. Overriden in subclasses to delegate the actual
-     * painting to Swing components.
+    /**
+     * Paints the peer. Overridden in subclasses to delegate the actual painting
+     * to Swing components.
      */
-    protected void peerPaintSelf(Graphics g, Rectangle r) {
-        D delegate = getDelegate();
-
-        // By default, just fill the entire bounds with a bg color
-        // TODO: sun.awt.noerasebackground
-        if (delegate == null) {
-            g.clearRect(r.x, r.y, r.width, r.height);
-        } else {
+    protected void paintPeer(final Graphics g) {
+        final D delegate = getDelegate();
+        if (delegate != null) {
             if (!SwingUtilities.isEventDispatchThread()) {
                 throw new InternalError("Painting must be done on EDT");
             }
-            //LW delegates does not fill whole bounds.
-            LWComponentPeer cp = getContainerPeer();
-            if (cp != null) {
-                Color c = g.getColor();
-                g.setColor(cp.getBackground());
-                g.fillRect(r.x, r.y, r.width, r.height);
-                g.setColor(c);
-            }
             synchronized (getDelegateLock()) {
                 // JComponent.print() is guaranteed to not affect the double buffer
-                delegate.print(g);
+                getDelegate().print(g);
             }
         }
     }
 
     // Just a helper method, thus final
     protected final void flushOffscreenGraphics() {
-        Rectangle r = getBounds();
-        flushOffscreenGraphics(new Rectangle(0, 0, r.width, r.height));
+        flushOffscreenGraphics(getSize());
+    }
+
+    protected static final void flushOnscreenGraphics(){
+        final OGLRenderQueue rq = OGLRenderQueue.getInstance();
+        rq.lock();
+        try {
+            rq.flushNow();
+        } finally {
+            rq.unlock();
+        }
     }
 
     /*
@@ -1412,13 +1354,18 @@
         Image bb = getWindowPeerOrSelf().getBackBuffer();
         if (bb != null) {
             // g is a screen Graphics from the delegate
-            final Graphics g = getGraphics();
-            if (g != null) {
+            final Graphics g = getOnscreenGraphics();
+
+            if (g != null && g instanceof Graphics2D) {
                 try {
+                    Graphics2D g2d = (Graphics2D)g;
                     Point p = localToWindow(new Point(0, 0));
+                    Composite composite = g2d.getComposite();
+                    g2d.setComposite(AlphaComposite.Src);
                     g.drawImage(bb, x, y, x + width, y + height, p.x + x,
                             p.y + y, p.x + x + width, p.y + y + height,
                             null);
+                    g2d.setComposite(composite);
                 } finally {
                     g.dispose();
                 }
@@ -1426,11 +1373,22 @@
         }
     }
 
+    /**
+     * Used by ContainerPeer to skip all the paint events during layout.
+     *
+     * @param isLayouting layouting state.
+     */
+    protected final void setLayouting(final boolean isLayouting) {
+        this.isLayouting = isLayouting;
+    }
 
-    /*
-    * Used by ContainerPeer to skip all the paint events during layout.
-    */
-    protected void setLayouting(boolean l) {
-        isLayouting = l;
+    /**
+     * Returns layouting state. Used by ComponentPeer to skip all the paint
+     * events during layout.
+     *
+     * @return true during layout, false otherwise.
+     */
+    private final boolean isLayouting() {
+        return isLayouting;
     }
 }
--- a/src/macosx/classes/sun/lwawt/LWContainerPeer.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/lwawt/LWContainerPeer.java	Fri Dec 23 22:01:01 2011 +0300
@@ -26,12 +26,12 @@
 package sun.lwawt;
 
 import sun.awt.SunGraphicsCallback;
+import sun.java2d.pipe.Region;
 
 import java.awt.Container;
 import java.awt.Graphics;
 import java.awt.Insets;
 import java.awt.Rectangle;
-import java.awt.event.PaintEvent;
 import java.awt.peer.ContainerPeer;
 import java.util.LinkedList;
 import java.util.List;
@@ -133,39 +133,32 @@
         }
     }
 
-    /*
-     * Called by the container when any part of this peer or child
-     * peers should be repainted
-     */
     @Override
-    public void handleExpose(int x, int y, int w, int h) {
-        // First, post the PaintEvent for this peer
-        super.handleExpose(x, y, w, h);
-
-        // Second, handle all the children
-        // Use the straight order of children, so the bottom
-        // ones are painted first
-        for (LWComponentPeer child : getChildren()) {
-            Rectangle r = child.getBounds();
-            int paintX = Math.max(0, x - r.x);
-            int paintY = Math.max(0, y - r.y);
-            int paintW = Math.min(w, r.width - paintX);
-            int paintH = Math.min(h, r.height - paintY);
-            child.handleExpose(paintX, paintY, paintW, paintH);
-        }
+    public final Region getVisibleRegion() {
+        return cutChildren(super.getVisibleRegion(), null);
     }
 
-    /*
-     * Handler for PAINT and UPDATE PaintEvents.
+    /**
+     * Removes bounds of children above specific child from the region. If above
+     * is null removes all bounds of children.
      */
-    protected void handleJavaPaintEvent(PaintEvent e) {
-        super.handleJavaPaintEvent(e);
-        // Now this peer and its target are painted. However, when
-        // the target painting may have corrupted some children, so
-        // we should restore them from the window back buffer.
-        for (LWComponentPeer child : getChildren()) {
-            child.restorePeer();
+    protected final Region cutChildren(Region r, final LWComponentPeer above) {
+        boolean aboveFound = above == null;
+        for (final LWComponentPeer child : getChildren()) {
+            if (!aboveFound && child == above) {
+                aboveFound = true;
+                continue;
+            }
+            if (aboveFound) {
+                if(child.isVisible()){
+                    final Rectangle cb = child.getBounds();
+                    final Region cr = child.getRegion();
+                    final Region tr = cr.getTranslatedRegion(cb.x, cb.y);
+                    r = r.getDifference(tr.getIntersection(getContentSize()));
+                }
+            }
         }
+        return r;
     }
 
     // ---- UTILITY METHODS ---- //
@@ -196,44 +189,40 @@
     }
 
     /*
-     * Overrides peerPaint() to paint all the children.
-     */
+    * Called by the container when any part of this peer or child
+    * peers should be repainted
+    */
     @Override
-    protected void peerPaint(Graphics g, Rectangle r) {
-        Rectangle b = getBounds();
-        if (!isShowing() || r.isEmpty() ||
-                !r.intersects(new Rectangle(0, 0, b.width, b.height))) {
+    public final void repaintPeer(final Rectangle r) {
+        final Rectangle toPaint = getSize().intersection(r);
+        if (!isShowing() || toPaint.isEmpty()) {
             return;
         }
-        // First, paint myself
-        super.peerPaint(g, r);
-        // Second, paint all the children
-        peerPaintChildren(r);
+        // First, post the PaintEvent for this peer
+        super.repaintPeer(toPaint);
+        // Second, handle all the children
+        // Use the straight order of children, so the bottom
+        // ones are painted first
+        repaintChildren(toPaint);
     }
 
     /*
-     * Paints all the child peers in the straight z-order, so the
-     * bottom-most ones are painted first.
-     */
-    protected void peerPaintChildren(Rectangle r) {
-        for (LWComponentPeer child : getChildren()) {
-            Graphics cg = child.getOffscreenGraphics();
-            try {
-                Rectangle toPaint = new Rectangle(r);
-                Rectangle childBounds = child.getBounds();
-                toPaint = toPaint.intersection(childBounds);
-                toPaint = toPaint.intersection(getContentSize());
-                toPaint.translate(-childBounds.x, -childBounds.y);
-                child.peerPaint(cg, toPaint);
-            } finally {
-                cg.dispose();
-            }
+    * Paints all the child peers in the straight z-order, so the
+    * bottom-most ones are painted first.
+    */
+    private void repaintChildren(final Rectangle r) {
+        final Rectangle content = getContentSize();
+        for (final LWComponentPeer child : getChildren()) {
+            final Rectangle childBounds = child.getBounds();
+            Rectangle toPaint = r.intersection(childBounds);
+            toPaint = toPaint.intersection(content);
+            toPaint.translate(-childBounds.x, -childBounds.y);
+            child.repaintPeer(toPaint);
         }
     }
 
     protected Rectangle getContentSize() {
-        Rectangle r = getBounds();
-        return new Rectangle(r.width, r.height);
+        return getSize();
     }
 
     @Override
@@ -245,7 +234,7 @@
     }
 
     @Override
-    public void paint(final Graphics g) {
+    public final void paint(final Graphics g) {
         super.paint(g);
         SunGraphicsCallback.PaintHeavyweightComponentsCallback.getInstance().
             runComponents(getTarget().getComponents(), g,
@@ -254,7 +243,7 @@
     }
 
     @Override
-    public void print(final Graphics g) {
+    public final void print(final Graphics g) {
         super.print(g);
         SunGraphicsCallback.PrintHeavyweightComponentsCallback.getInstance().
             runComponents(getTarget().getComponents(), g,
--- a/src/macosx/classes/sun/lwawt/LWKeyboardFocusManagerPeer.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/lwawt/LWKeyboardFocusManagerPeer.java	Fri Dec 23 22:01:01 2011 +0300
@@ -32,6 +32,8 @@
 import java.util.Map;
 import java.util.HashMap;
 
+import sun.awt.AWTAccessor;
+import sun.awt.AppContext;
 import sun.awt.KeyboardFocusManagerPeerImpl;
 
 public class LWKeyboardFocusManagerPeer extends KeyboardFocusManagerPeerImpl {
@@ -43,6 +45,11 @@
     private static Map<KeyboardFocusManager, LWKeyboardFocusManagerPeer> instances =
         new HashMap<KeyboardFocusManager, LWKeyboardFocusManagerPeer>();
 
+    public static synchronized LWKeyboardFocusManagerPeer getInstance(AppContext ctx) {
+        return getInstance(AWTAccessor.getKeyboardFocusManagerAccessor().
+                           getCurrentKeyboardFocusManager(ctx));
+    }
+
     public static synchronized LWKeyboardFocusManagerPeer getInstance(KeyboardFocusManager manager) {
         LWKeyboardFocusManagerPeer instance = instances.get(manager);
         if (instance == null) {
--- a/src/macosx/classes/sun/lwawt/LWLabelPeer.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/lwawt/LWLabelPeer.java	Fri Dec 23 22:01:01 2011 +0300
@@ -46,7 +46,6 @@
     @Override
     protected JLabel createDelegate() {
         final JLabel label = new JLabel();
-        label.setOpaque(true);
         label.setVerticalAlignment(SwingConstants.TOP);
         return label;
     }
--- a/src/macosx/classes/sun/lwawt/LWListPeer.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/lwawt/LWListPeer.java	Fri Dec 23 22:01:01 2011 +0300
@@ -25,75 +25,96 @@
 
 package sun.lwawt;
 
+import javax.swing.*;
+import javax.swing.event.*;
 import java.awt.*;
+import java.awt.event.*;
 import java.awt.peer.ListPeer;
-
-import javax.swing.*;
+import java.util.Arrays;
 
 final class LWListPeer
         extends LWComponentPeer<List, LWListPeer.ScrollableJList>
         implements ListPeer {
 
-    LWListPeer(List target, PlatformComponent platformComponent) {
+    LWListPeer(final List target, final PlatformComponent platformComponent) {
         super(target, platformComponent);
     }
 
+    @Override
     protected ScrollableJList createDelegate() {
         return new ScrollableJList();
     }
 
+    public void initialize() {
+        super.initialize();
+        setMultipleMode(getTarget().isMultipleMode());
+        final int[] selectedIndices = getTarget().getSelectedIndexes();
+        synchronized (getDelegateLock()) {
+            getDelegate().getView().setSelectedIndices(selectedIndices);
+        }
+    }
+
     public boolean isFocusable() {
         return true;
     }
 
+    @Override
     protected Component getDelegateFocusOwner() {
         return getDelegate().getView();
     }
 
+    @Override
     public int[] getSelectedIndexes() {
         synchronized (getDelegateLock()) {
             return getDelegate().getView().getSelectedIndices();
         }
     }
 
-    public void add(String item, int index) {
+    @Override
+    public void add(final String item, final int index) {
         synchronized (getDelegateLock()) {
-            getDelegate().getModel().addElement(item);
+            getDelegate().getModel().add(index, item);
         }
     }
 
-    public void delItems(int start, int end) {
+    @Override
+    public void delItems(final int start, final int end) {
         synchronized (getDelegateLock()) {
             getDelegate().getModel().removeRange(start, end);
         }
     }
 
+    @Override
     public void removeAll() {
         synchronized (getDelegateLock()) {
             getDelegate().getModel().removeAllElements();
         }
     }
 
-    public void select(int index) {
+    @Override
+    public void select(final int index) {
         synchronized (getDelegateLock()) {
             getDelegate().getView().setSelectedIndex(index);
         }
     }
 
-    public void deselect(int index) {
+    @Override
+    public void deselect(final int index) {
         synchronized (getDelegateLock()) {
             getDelegate().getView().getSelectionModel().
                     removeSelectionInterval(index, index);
         }
     }
 
-    public void makeVisible(int index) {
+    @Override
+    public void makeVisible(final int index) {
         synchronized (getDelegateLock()) {
             getDelegate().getView().ensureIndexIsVisible(index);
         }
     }
 
-    public void setMultipleMode(boolean m) {
+    @Override
+    public void setMultipleMode(final boolean m) {
         synchronized (getDelegateLock()) {
             getDelegate().getView().setSelectionMode(m ?
                     ListSelectionModel.MULTIPLE_INTERVAL_SELECTION
@@ -101,29 +122,33 @@
         }
     }
 
-    public Dimension getPreferredSize(int rows) {
+    @Override
+    public Dimension getPreferredSize(final int rows) {
         return getMinimumSize(rows);
     }
 
-    public Dimension getMinimumSize(int rows) {
+    @Override
+    public Dimension getMinimumSize(final int rows) {
         synchronized (getDelegateLock()) {
             final int margin = 2;
             final int space = 1;
 
             // TODO: count ScrollPane's scrolling elements if any.
-            FontMetrics fm = getFontMetrics(getFont());
-            int itemHeight = (fm.getHeight() - fm.getLeading()) + (2 * space);
+            final FontMetrics fm = getFontMetrics(getFont());
+            final int itemHeight = (fm.getHeight() - fm.getLeading()) + (2 * space);
 
-            return new Dimension(20 + (fm == null ? 10*15 : fm.stringWidth("0123456789abcde")),
+            return new Dimension(20 + (fm == null ? 10 * 15 : fm.stringWidth("0123456789abcde")),
                     (fm == null ? 10 : itemHeight) * rows + (2 * margin));
         }
     }
 
-    final class ScrollableJList extends JScrollPane {
+
+    final class ScrollableJList extends JScrollPane implements ListSelectionListener {
 
         private DefaultListModel<Object> model =
                 new DefaultListModel<Object>() {
-                    public void add(int index, Object element) {
+                    @Override
+                    public void add(final int index, final Object element) {
                         if (index == -1) {
                             addElement(element);
                         } else {
@@ -132,22 +157,44 @@
                     }
                 };
 
+        private int[] oldSelectedIndices = new int[0];
+
         ScrollableJList() {
             getViewport().setScrollMode(JViewport.SIMPLE_SCROLL_MODE);
-            JList<Object> list = new JList<Object>(model) {
-                public boolean hasFocus() {
-                    return getTarget().hasFocus();
-                }
-            };
+            final JList<Object> list = new JListDelegate();
+            list.addListSelectionListener(this);
+
             getViewport().setView(list);
 
             // Pull the items from the target.
-            String[] items = getTarget().getItems();
+            final String[] items = getTarget().getItems();
             for (int i = 0; i < items.length; i++) {
                 model.add(i, items[i]);
             }
         }
 
+        @Override
+        public void valueChanged(final ListSelectionEvent e) {
+            if (!e.getValueIsAdjusting()) {
+                final JList source = (JList) e.getSource();
+                for(int i = 0 ; i < source.getModel().getSize(); i++) {
+
+                    final boolean wasSelected = Arrays.binarySearch(oldSelectedIndices, i) >= 0;
+                    final boolean isSelected = source.isSelectedIndex(i);
+
+                    if (wasSelected == isSelected) {
+                        continue;
+                    }
+
+                    final int state = !wasSelected && isSelected ? ItemEvent.SELECTED: ItemEvent.DESELECTED;
+
+                    LWListPeer.this.postEvent(new ItemEvent(getTarget(), ItemEvent.ITEM_STATE_CHANGED,
+                            i, state));
+                }
+                oldSelectedIndices = source.getSelectedIndices();
+            }
+        }
+
         public JList getView() {
             return (JList) getViewport().getView();
         }
@@ -158,29 +205,78 @@
 
         @Override
         public void setEnabled(final boolean enabled) {
-            getViewport().getView().setEnabled(enabled);
+            getView().setEnabled(enabled);
             super.setEnabled(enabled);
         }
 
-        public void setBackground(Color bg) {
+        @Override
+        public void setBackground(final Color bg) {
             super.setBackground(bg);
             if (getView() != null) {
                 getView().setBackground(bg);
             }
         }
 
-        public void setForeground(Color fg) {
+        @Override
+        public void setForeground(final Color fg) {
             super.setForeground(fg);
             if (getView() != null) {
                 getView().setForeground(fg);
             }
         }
 
-        public void setFont(Font font) {
+        @Override
+        public void setFont(final Font font) {
             super.setFont(font);
             if (getView() != null) {
                 getView().setFont(font);
             }
         }
+
+        @Override
+        public void setOpaque(final boolean isOpaque) {
+            super.setOpaque(isOpaque);
+            if (getView() != null) {
+                getView().setOpaque(isOpaque);
+            }
+        }
+
+        private final class JListDelegate extends JList<Object> {
+
+            JListDelegate() {
+                super(ScrollableJList.this.model);
+            }
+
+            @Override
+            public boolean hasFocus() {
+                return getTarget().hasFocus();
+            }
+
+            @Override
+            protected void processMouseEvent(final MouseEvent e) {
+                super.processMouseEvent(e);
+                if (e.getID() == MouseEvent.MOUSE_CLICKED && e.getClickCount() == 2) {
+                    final int index = locationToIndex(e.getPoint());
+                    LWListPeer.this.postEvent(new ActionEvent(getTarget(), ActionEvent.ACTION_PERFORMED,
+                            getModel().getElementAt(index).toString(), e.getWhen(), e.getModifiers()));
+                }
+            }
+
+            @Override
+            protected void processKeyEvent(final KeyEvent e) {
+                super.processKeyEvent(e);
+                if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_ENTER) {
+                    final int index = getSelectedIndex();
+                    LWListPeer.this.postEvent(new ActionEvent(getTarget(), ActionEvent.ACTION_PERFORMED,
+                            getModel().getElementAt(index).toString(), e.getWhen(), e.getModifiers()));
+                }
+            }
+
+            //Needed for Autoscroller.
+            @Override
+            public Point getLocationOnScreen() {
+                return LWListPeer.this.getLocationOnScreen();
+            }
+        }
     }
 }
--- a/src/macosx/classes/sun/lwawt/LWPanelPeer.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/lwawt/LWPanelPeer.java	Fri Dec 23 22:01:01 2011 +0300
@@ -26,7 +26,8 @@
 
 package sun.lwawt;
 
-import java.awt.*;
+import java.awt.Dimension;
+import java.awt.Panel;
 import java.awt.peer.PanelPeer;
 
 import javax.swing.JPanel;
@@ -34,7 +35,7 @@
 final class LWPanelPeer extends LWContainerPeer<Panel, JPanel>
         implements PanelPeer {
 
-    LWPanelPeer(final Panel target, PlatformComponent platformComponent) {
+    LWPanelPeer(final Panel target, final PlatformComponent platformComponent) {
         super(target, platformComponent);
     }
 
@@ -43,6 +44,7 @@
         return new JPanel();
     }
 
+    @Override
     public Dimension getMinimumSize() {
         return getTarget().getSize();
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/macosx/classes/sun/lwawt/LWRepaintArea.java	Fri Dec 23 22:01:01 2011 +0300
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package sun.lwawt;
+
+import sun.awt.RepaintArea;
+
+import java.awt.Component;
+import java.awt.Graphics;
+
+/**
+ * @author Sergey Bylokhov
+ */
+final class LWRepaintArea extends RepaintArea {
+
+    @Override
+    protected void updateComponent(final Component comp, final Graphics g) {
+        if (comp != null) {
+            final LWComponentPeer peer = (LWComponentPeer) comp.getPeer();
+            if (peer != null) {
+                peer.paintPeer(g);
+            }
+            super.updateComponent(comp, g);
+            flushBuffers(peer);
+        }
+    }
+
+    @Override
+    protected void paintComponent(final Component comp, final Graphics g) {
+        if (comp != null) {
+            final LWComponentPeer peer = (LWComponentPeer) comp.getPeer();
+            if (peer != null) {
+                peer.paintPeer(g);
+            }
+            super.paintComponent(comp, g);
+            flushBuffers(peer);
+        }
+    }
+
+    private static void flushBuffers(final LWComponentPeer peer) {
+        if (peer != null) {
+            if (!peer.getWindowPeerOrSelf().isOpaque()) {
+                peer.flushOffscreenGraphics();
+            }
+            peer.flushOnscreenGraphics();
+        }
+    }
+}
--- a/src/macosx/classes/sun/lwawt/LWScrollBarPeer.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/lwawt/LWScrollBarPeer.java	Fri Dec 23 22:01:01 2011 +0300
@@ -23,9 +23,11 @@
  * questions.
  */
 
+
 package sun.lwawt;
 
-import java.awt.AWTEvent;
+import java.awt.Adjustable;
+import java.awt.Dimension;
 import java.awt.Scrollbar;
 import java.awt.event.AdjustmentEvent;
 import java.awt.event.AdjustmentListener;
@@ -33,42 +35,46 @@
 
 import javax.swing.JScrollBar;
 
-public class LWScrollBarPeer
-    extends LWComponentPeer<Scrollbar, JScrollBar>
-    implements ScrollbarPeer, AdjustmentListener
-{
+final class LWScrollBarPeer extends LWComponentPeer<Scrollbar, JScrollBar>
+        implements ScrollbarPeer, AdjustmentListener {
+
     //JScrollBar fires two changes with firePropertyChange (one for old value
     // and one for new one.
     // We save the last value and don't fire event if not changed.
     private int currentValue;
 
-    public LWScrollBarPeer(Scrollbar target, PlatformComponent platformComponent) {
+    LWScrollBarPeer(final Scrollbar target,
+                    final PlatformComponent platformComponent) {
         super(target, platformComponent);
-        this.currentValue = target.getValue();
+    }
 
+    @Override
+    protected JScrollBar createDelegate() {
+        return new JScrollBar();
+    }
+
+    @Override
+    public void initialize() {
+        super.initialize();
+        final Scrollbar target = getTarget();
+        setValues(target.getValue(), target.getVisibleAmount(),
+                  target.getMinimum(), target.getMaximum());
+
+        final int orientation = target.getOrientation();
+        final JScrollBar delegate = getDelegate();
         synchronized (getDelegateLock()) {
-            getDelegate().setOrientation(
-                            target.getOrientation() == Scrollbar.HORIZONTAL ? JScrollBar.HORIZONTAL
-                                    : JScrollBar.VERTICAL);
-            getDelegate().setValue(target.getValue());
-            getDelegate().setMinimum(target.getMinimum());
-            getDelegate().setMaximum(target.getMaximum());
-            getDelegate().setVisibleAmount(target.getVisibleAmount());
-            getDelegate().addAdjustmentListener(this);
+            delegate.setOrientation(orientation == Scrollbar.HORIZONTAL
+                                    ? Adjustable.HORIZONTAL
+                                    : Adjustable.VERTICAL);
+            delegate.addAdjustmentListener(this);
         }
     }
 
     @Override
-    protected JScrollBar createDelegate() {
-        JScrollBar delegate = new JScrollBar();
-        delegate.setBackground(getTarget().getBackground());
-        delegate.setForeground(getTarget().getForeground());
-        return delegate;
-    }
-
-    public void setValues(int value, int visible, int minimum, int maximum) {
+    public void setValues(final int value, final int visible, final int minimum,
+                          final int maximum) {
         synchronized (getDelegateLock()) {
-            this.currentValue = value;
+            currentValue = value;
             getDelegate().setValue(value);
             getDelegate().setVisibleAmount(visible);
             getDelegate().setMinimum(minimum);
@@ -76,25 +82,36 @@
         }
     }
 
-    public void setLineIncrement(int l) {
+    @Override
+    public void setLineIncrement(final int l) {
         synchronized (getDelegateLock()) {
             getDelegate().setUnitIncrement(l);
         }
     }
 
-    public void setPageIncrement(int l) {
+    @Override
+    public void setPageIncrement(final int l) {
         synchronized (getDelegateLock()) {
             getDelegate().setBlockIncrement(l);
         }
     }
 
+    @Override
+    public Dimension getPreferredSize() {
+        synchronized (getDelegateLock()) {
+            return getDelegate().getPreferredSize();
+        }
+    }
+
     // Peer also registered as a listener for ComponentDelegate component
     @Override
-    public void adjustmentValueChanged(AdjustmentEvent e) {
-        if (this.currentValue == e.getValue()) {
-            return;
+    public void adjustmentValueChanged(final AdjustmentEvent e) {
+        synchronized (getDelegateLock()) {
+            if (currentValue == e.getValue()) {
+                return;
+            }
+            currentValue = e.getValue();
         }
-        this.currentValue = e.getValue();
 
         // TODO: we always get event with the TRACK adj. type.
         // Could we check if we are over the ArrowButton and send event there?
@@ -102,5 +119,4 @@
                                       e.getAdjustmentType(), e.getValue(),
                                       e.getValueIsAdjusting()));
     }
-
 }
--- a/src/macosx/classes/sun/lwawt/LWScrollPanePeer.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/lwawt/LWScrollPanePeer.java	Fri Dec 23 22:01:01 2011 +0300
@@ -42,8 +42,9 @@
 
     protected JScrollPane createDelegate() {
         final JScrollPane sp = new JScrollPane();
-        JPanel panel = new JPanel();
+        final JPanel panel = new JPanel();
         panel.setOpaque(false);
+        panel.setVisible(false);
         sp.getViewport().setView(panel);
         sp.setBorder(BorderFactory.createEmptyBorder());
         sp.getViewport().addChangeListener(this);
@@ -51,14 +52,18 @@
     }
 
     @Override
-    public void stateChanged(ChangeEvent e) {
+    public void stateChanged(final ChangeEvent e) {
         SwingUtilities.invokeLater(new Runnable() {
+            @Override
             public void run() {
-                synchronized (getDelegateLock()) {
-                    LWComponentPeer viewPeer = getViewPeer();
-                    if (viewPeer != null) {
-                        viewPeer.setBounds(getDelegate().getViewport().getView().getBounds());
+                final LWComponentPeer viewPeer = getViewPeer();
+                if (viewPeer != null) {
+                    final Rectangle r;
+                    synchronized (getDelegateLock()) {
+                        r = getDelegate().getViewport().getView().getBounds();
                     }
+                    viewPeer.setBounds(r.x, r.y, r.width, r.height, SET_BOUNDS,
+                                       true, true);
                 }
             }
         });
--- a/src/macosx/classes/sun/lwawt/LWTextAreaPeer.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/lwawt/LWTextAreaPeer.java	Fri Dec 23 22:01:01 2011 +0300
@@ -101,15 +101,17 @@
 
     @Override
     public void insert(final String text, final int pos) {
+        final ScrollableJTextArea pane = getDelegate();
         synchronized (getDelegateLock()) {
-            final JTextArea area = getDelegate().getView();
+            final JTextArea area = pane.getView();
             final boolean doScroll = pos >= area.getDocument().getLength()
                                      && area.getDocument().getLength() != 0;
             area.insert(text, pos);
+            pane.validate();
             if (doScroll) {
-                final JScrollBar bar = getDelegate().getVerticalScrollBar();
-                if (bar != null) {
-                    bar.setValue(bar.getMaximum() - bar.getVisibleAmount());
+                final JScrollBar vbar = pane.getVerticalScrollBar();
+                if (vbar != null) {
+                    vbar.setValue(vbar.getMaximum() - vbar.getVisibleAmount());
                 }
             }
         }
--- a/src/macosx/classes/sun/lwawt/LWTextComponentPeer.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/lwawt/LWTextComponentPeer.java	Fri Dec 23 22:01:01 2011 +0300
@@ -49,7 +49,6 @@
      * Character with reasonable value between the minimum width and maximum.
      */
     protected static final char WIDE_CHAR = 'w';
-
     private volatile boolean firstChangeSkipped;
 
     LWTextComponentPeer(final T target,
@@ -57,13 +56,6 @@
         super(target, platformComponent);
     }
 
-    /**
-     * Returns height of the line in textarea or textfield.
-     */
-    protected static int getItemHeight(final FontMetrics metrics) {
-        return metrics.getHeight();
-    }
-
     @Override
     public void initialize() {
         super.initialize();
@@ -96,7 +88,7 @@
         final int borderWidth = insets.left + insets.right;
         final FontMetrics fm = getFontMetrics(getFont());
         final int charWidth = (fm != null) ? fm.charWidth(WIDE_CHAR) : 10;
-        final int itemHeight = (fm != null) ? getItemHeight(fm) : 10;
+        final int itemHeight = (fm != null) ? fm.getHeight() : 10;
         return new Dimension(columns * charWidth + borderWidth,
                              rows * itemHeight + borderHeight);
     }
--- a/src/macosx/classes/sun/lwawt/LWTextFieldPeer.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/lwawt/LWTextFieldPeer.java	Fri Dec 23 22:01:01 2011 +0300
@@ -49,9 +49,7 @@
 
     @Override
     protected JPasswordField createDelegate() {
-        final JPasswordField delegate = new JTextAreaDelegate();
-        delegate.setOpaque(true);
-        return delegate;
+        return new JTextAreaDelegate();
     }
 
     @Override
--- a/src/macosx/classes/sun/lwawt/LWToolkit.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/lwawt/LWToolkit.java	Fri Dec 23 22:01:01 2011 +0300
@@ -396,13 +396,6 @@
         return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration().getColorModel();
     }
 
-    //Used by a delegate to check if it ought to bring the
-    //content out of the backbuffer to the screen or not.
-    //false by default. Known to be true on MacOSX.
-    public boolean isNativeDoubleBufferingEnabled() {
-        return false;
-    }
-
     @Override
     public boolean isDesktopSupported() {
         return true;
@@ -422,7 +415,7 @@
 
     @Override
     public KeyboardFocusManagerPeer createKeyboardFocusManagerPeer(KeyboardFocusManager manager) {
-        return getKeyboardFocusManagerPeer(manager);
+        return LWKeyboardFocusManagerPeer.getInstance(manager);
     }
 
     @Override
@@ -532,22 +525,13 @@
      */
     public abstract LWCursorManager getCursorManager();
 
-    //TODO: We've got these getXXX, and there's also createXXX above. Why so many variants?
-    /*
-     * Returns the current keyboard focus manager.
-     */
-    public LWKeyboardFocusManagerPeer getKeyboardFocusManagerPeer() {
-        return getKeyboardFocusManagerPeer(KeyboardFocusManager.getCurrentKeyboardFocusManager());
-    }
-
-    /*
-     * Returns the keyboard focus manager.
-     */
-    public LWKeyboardFocusManagerPeer getKeyboardFocusManagerPeer(KeyboardFocusManager manager) {
-        return LWKeyboardFocusManagerPeer.getInstance(manager);
-    }
-
     public static void postEvent(AWTEvent event) {
         postEvent(targetToAppContext(event.getSource()), event);
     }
+
+    // use peer's back buffer to implement non-opaque windows.
+    @Override
+    public boolean needUpdateWindow() {
+        return true;
+    }
 }
--- a/src/macosx/classes/sun/lwawt/LWWindowPeer.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/lwawt/LWWindowPeer.java	Fri Dec 23 22:01:01 2011 +0300
@@ -35,6 +35,8 @@
 
 import sun.awt.*;
 import sun.java2d.*;
+import sun.java2d.loops.Blit;
+import sun.java2d.loops.CompositeType;
 
 public class LWWindowPeer
     extends LWContainerPeer<Window, JComponent>
@@ -58,6 +60,9 @@
     private int sysW;
     private int sysH;
 
+    private static final int MINIMUM_WIDTH = 1;
+    private static final int MINIMUM_HEIGHT = 1;
+
     private Insets insets = new Insets(0, 0, 0, 0);
 
     private int screenOn = -1;
@@ -99,12 +104,14 @@
 
     private volatile boolean cachedFocusableWindow;
 
-    private final static Font DEFAULT_FONT = new Font(Font.DIALOG, Font.PLAIN, 12);
+    private static final Font DEFAULT_FONT = new Font(Font.DIALOG, Font.PLAIN, 12);
 
     private Color background;
     private Color foreground;
     private Font font;
 
+    private volatile boolean isOpaque = true;
+
     /**
      * Current modal blocker or null.
      *
@@ -152,6 +159,7 @@
         cachedFocusableWindow = getTarget().isFocusableWindow();
 
         setOpacity(getTarget().getOpacity());
+        setOpaque(getTarget().isOpaque());
 
         // Create surface data and back buffer
         replaceSurfaceData(1, null);
@@ -230,7 +238,7 @@
 
     @Override
     protected void disposeImpl() {
-        SurfaceData oldData = surfaceData;
+        SurfaceData oldData = getSurfaceData();
         surfaceData = null;
         if (oldData != null) {
             oldData.invalidate();
@@ -240,27 +248,32 @@
     }
 
     @Override
-    public void setVisible(final boolean visible) {
-        if (isVisible() == visible) {
+    public void setVisible(final boolean v) {
+        if (getSurfaceData() == null) {
+            replaceSurfaceData();
+        }
+
+        if (isVisible() == v) {
             return;
         }
-        super.setVisible(visible);
+        super.setVisible(v);
+
         // TODO: update graphicsConfig, see 4868278
         // TODO: don't notify the delegate if our visibility is unchanged
 
         // it is important to call this method on EDT
-        // to prevent the deadlocks duruing the painting of the lightweight delegates
+        // to prevent the deadlocks during the painting of the lightweight delegates
         //TODO: WHY? This is a native-system related call. Perhaps NOT calling
-        // the painiting procedure right from the setVisible(), but rather relying
-        // on the native Expose event (or, scheduling the repainiting asynchronously)
+        // the painting procedure right from the setVisible(), but rather relying
+        // on the native Expose event (or, scheduling the repainting asynchronously)
         // is better?
         SwingUtilities.invokeLater(new Runnable() {
             @Override
             public void run() {
-                platformWindow.setVisible(visible);
+                platformWindow.setVisible(v);
                 if (isSimpleWindow()) {
                     updateFocusableWindowState();
-                    changeFocusedWindow(visible, visible);
+                    changeFocusedWindow(v, v);
                 }
             }
         });
@@ -277,8 +290,10 @@
         return false;
     }
 
-    @Override
-    protected Graphics getGraphics(Color fg, Color bg, Font f) {
+    protected final synchronized Graphics getOnscreenGraphics(Color fg, Color bg, Font f) {
+        if (getSurfaceData() == null) {
+            return null;
+        }
         if (fg == null) {
             fg = SystemColor.windowText;
         }
@@ -288,11 +303,7 @@
         if (f == null) {
             f = DEFAULT_FONT;
         }
-        if (surfaceData == null) {
-            replaceSurfaceData();
-        }
-
-        return platformWindow.transformGraphics(new SunGraphics2D(surfaceData, fg, bg, f));
+        return platformWindow.transformGraphics(new SunGraphics2D(getSurfaceData(), fg, bg, f));
     }
 
     @Override
@@ -339,20 +350,19 @@
             op |= SET_SIZE;
         }
 
-        Rectangle oldBounds = getBounds();
+        if (w < MINIMUM_WIDTH) {
+            w = MINIMUM_WIDTH;
+        }
+        if (h < MINIMUM_HEIGHT) {
+            h = MINIMUM_HEIGHT;
+        }
 
         // Don't post ComponentMoved/Resized and Paint events
         // until we've got a notification from the delegate
-        setBounds(x, y, w, h, op, false);
+        setBounds(x, y, w, h, op, false, false);
         // Get updated bounds, so we don't have to handle 'op' here manually
         Rectangle r = getBounds();
         platformWindow.setBounds(r.x, r.y, r.width, r.height);
-
-        // TODO: this replaceSurfaceData should be called upon
-        // the notification about the top-level size from the underlying system
-        if (oldBounds.height != r.height || oldBounds.width != r.width) {
-               replaceSurfaceData();
-        }
     }
 
     @Override
@@ -360,7 +370,7 @@
         return platformWindow.getLocationOnScreen();
     }
 
-    /*
+    /**
      * Overridden from LWContainerPeer to return the correct insets.
      * Insets are queried from the delegate and are kept up to date by
      * requiering when needed (i.e. when the window geometry is changed).
@@ -418,9 +428,9 @@
             d = getTarget().getMinimumSize();
         }
         if (d == null) {
-            d = new Dimension(1, 1);
+            d = new Dimension(MINIMUM_WIDTH, MINIMUM_HEIGHT);
         }
-        platformWindow.setMinimumSize(d.height, d.width);
+        platformWindow.setMinimumSize(d.width, d.height);
     }
 
     @Override
@@ -435,13 +445,20 @@
 
     @Override
     public void setOpaque(boolean isOpaque) {
-        // TODO: not implemented
-//        throw new RuntimeException("not implemented");
+        if (this.isOpaque != isOpaque) {
+            this.isOpaque = isOpaque;
+            getPlatformWindow().setOpaque(isOpaque);
+            replaceSurfaceData();
+        }
+    }
+
+    public boolean isOpaque() {
+        return isOpaque;
     }
 
     @Override
     public void updateWindow() {
-        throw new RuntimeException("not implemented");
+        flushOffscreenGraphics();
     }
 
     @Override
@@ -535,7 +552,7 @@
         postWindowStateChangedEvent(newWindowState);
     }
 
-    /*
+    /**
      * Called by the delegate when any part of the window should be repainted.
      */
     public void notifyExpose(final int x, final int y, final int w, final int h) {
@@ -547,28 +564,16 @@
         // and override that part which is only called after if
         // createPaintEvent() returned non-null value and flush the buffer
         // from the overridden method
-
-        // First, restore the window contents from the back buffer, just
-        // like SwingPaintEventDispatcher does
-        //flushOffscreenGraphics(new Rectangle(x, y, w, h));
-
-        // Second, refresh the back buffer contents and flush it onto
-        // the screen - on EDT
-        //paintPeerDirtyRectOnEDT(new Rectangle(x, y, w, h));
-
-        // Last, post the paint events for all the subcomponents. As paint
-        // events are of lower priority, the runnable above will be executed
-        // before any of them are handled
-        //handleExpose(x, y, w, h);
-        repaintPeer(x, y, w, h);
+        flushOnscreenGraphics();
+        repaintPeer(new Rectangle(x, y, w, h));
     }
 
-    /*
+    /**
      * Called by the delegate when this window is moved/resized by user.
      * There's no notifyReshape() in LWComponentPeer as the only
      * components which could be resized by user are top-level windows.
      */
-    public void notifyReshape(int x, int y, int w, int h) {
+    public final void notifyReshape(int x, int y, int w, int h) {
         boolean moved = false;
         boolean resized = false;
         synchronized (getStateLock()) {
@@ -585,26 +590,33 @@
             return;
         }
         // First, update peer's bounds
-        setBounds(x, y, w, h, SET_BOUNDS, false);
+        setBounds(x, y, w, h, SET_BOUNDS, false, false);
 
         // Second, update the graphics config and surface data
         checkIfOnNewScreen();
         if (resized) {
             replaceSurfaceData();
-            flushOffscreenGraphics(new Rectangle(0, 0, w, h));
+            flushOnscreenGraphics();
         }
 
-        // Third, update target's bounds
-        AWTAccessor.getComponentAccessor().setLocation(getTarget(), x, y);
-        AWTAccessor.getComponentAccessor().setSize(getTarget(), w, h);
-
-        // Fourth, post COMPONENT_MOVED/COMPONENT_RESIZED events
-        // TODO: is it worth reusing handleMove/handleResize methods here?
+        // Third, COMPONENT_MOVED/COMPONENT_RESIZED events
         if (moved) {
-            postEvent(new ComponentEvent(getTarget(), ComponentEvent.COMPONENT_MOVED));
+            handleMove(x, y, true);
         }
         if (resized) {
-            postEvent(new ComponentEvent(getTarget(), ComponentEvent.COMPONENT_RESIZED));
+            handleResize(w, h,true);
+        }
+    }
+
+    private void clearBackground(final int w, final int h) {
+        final Graphics g = getOnscreenGraphics(getForeground(), getBackground(),
+                                               getFont());
+        if (g != null) {
+            try {
+                g.clearRect(0, 0, w, h);
+            } finally {
+                g.dispose();
+            }
         }
     }
 
@@ -804,7 +816,8 @@
                                  int keyCode, char keyChar, int keyLocation)
     {
         LWComponentPeer focusOwner =
-            getLWToolkit().getKeyboardFocusManagerPeer().getFocusOwner();
+            LWKeyboardFocusManagerPeer.getInstance(getAppContext()).
+                getFocusOwner();
 
         // Null focus owner may receive key event when
         // application hides the focused window upon ESC press
@@ -826,7 +839,7 @@
             AWTAccessor.getFrameAccessor().setExtendedState(
                     (Frame)getTarget(), newWindowState);
         }
-        WindowEvent stateChangedEvent = new WindowEvent((Window)getTarget(),
+        WindowEvent stateChangedEvent = new WindowEvent(getTarget(),
                 WindowEvent.WINDOW_STATE_CHANGED,
                 windowState, newWindowState);
         postEvent(stateChangedEvent);
@@ -901,13 +914,13 @@
         });
     }
 
-    /*
+    /**
      * This method returns a back buffer Graphics to render all the
      * peers to. After the peer is painted, the back buffer contents
      * should be flushed to the screen. All the target painting
      * (Component.paint() method) should be done directly to the screen.
      */
-    protected Graphics getOffscreenGraphics(Color fg, Color bg, Font f) {
+    protected final Graphics getOffscreenGraphics(Color fg, Color bg, Font f) {
         final Image bb = getBackBuffer();
         if (bb == null) {
             return null;
@@ -931,16 +944,9 @@
     }
 
     /*
-    private boolean checkBackBufferingEnabled() {
-        LWToolkit tk = (LWToolkit)Toolkit.getDefaultToolkit();
-        return tk.isNativeDoubleBufferingEnabled();
-    }
-    */
-
-    /*
      * May be called by delegate to provide SD to Java2D code.
      */
-    public SurfaceData getSurfaceData() {
+    public synchronized SurfaceData getSurfaceData() {
         //TODO: synchronize access to the surfaceData.
         return surfaceData;
     }
@@ -949,25 +955,31 @@
         replaceSurfaceData(backBufferCount, backBufferCaps);
     }
 
-    private void replaceSurfaceData(int newBackBufferCount,
-                                    BufferCapabilities newBackBufferCaps)
-    {
+    private synchronized void replaceSurfaceData(int newBackBufferCount,
+                                                 BufferCapabilities newBackBufferCaps) {
         // TODO: need some kind of synchronization here?
-        SurfaceData oldData = surfaceData;
+        final SurfaceData oldData = getSurfaceData();
         surfaceData = platformWindow.replaceSurfaceData();
         // TODO: volatile image
 //        VolatileImage oldBB = backBuffer;
         BufferedImage oldBB = backBuffer;
         backBufferCount = newBackBufferCount;
         backBufferCaps = newBackBufferCaps;
-        if ((oldData != null) && (oldData != surfaceData)) {
+        final Rectangle size = getSize();
+        if (getSurfaceData() != null && oldData != getSurfaceData()) {
+            clearBackground(size.width, size.height);
+        }
+        blitSurfaceData(oldData, getSurfaceData());
+
+        if (oldData != null && oldData != getSurfaceData()) {
             // TODO: drop oldData for D3D/WGL pipelines
             // This can only happen when this peer is being created
             oldData.flush();
         }
+
         // TODO: volatile image
 //        backBuffer = (VolatileImage)delegate.createBackBuffer();
-        backBuffer = (BufferedImage)platformWindow.createBackBuffer();
+        backBuffer = (BufferedImage) platformWindow.createBackBuffer();
         if (backBuffer != null) {
             Graphics g = backBuffer.getGraphics();
             try {
@@ -985,6 +997,23 @@
         }
     }
 
+    private void blitSurfaceData(final SurfaceData src, final SurfaceData dst) {
+        //TODO blit. proof-of-concept
+        if (src != dst && src != null && dst != null
+            && !(dst instanceof NullSurfaceData)
+            && !(src instanceof NullSurfaceData)
+            && src.getSurfaceType().equals(dst.getSurfaceType())) {
+            final Rectangle size = getSize();
+            final Blit blit = Blit.locate(src.getSurfaceType(),
+                                          CompositeType.Src,
+                                          dst.getSurfaceType());
+            if (blit != null) {
+                blit.Blit(src, dst, ((Graphics2D) getGraphics()).getComposite(),
+                          getRegion(), 0, 0, 0, 0, size.width, size.height);
+            }
+        }
+    }
+
     public int getBackBufferCount() {
         return backBufferCount;
     }
@@ -1056,7 +1085,8 @@
             }
         }
 
-        LWKeyboardFocusManagerPeer manager = getLWToolkit().getKeyboardFocusManagerPeer();
+        LWKeyboardFocusManagerPeer manager = LWKeyboardFocusManagerPeer.
+            getInstance(getAppContext());
 
         Window oppositeWindow = becomesFocused ? manager.getCurrentFocusedWindow() : null;
         // TODO: ungrab
--- a/src/macosx/classes/sun/lwawt/PlatformWindow.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/lwawt/PlatformWindow.java	Fri Dec 23 22:01:01 2011 +0300
@@ -136,6 +136,8 @@
 
     public void setOpacity(float opacity);
 
+    public void setOpaque(boolean isOpaque);
+
     public void enterFullScreenMode();
 
     public void exitFullScreenMode();
--- a/src/macosx/classes/sun/lwawt/macosx/CCursorManager.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/lwawt/macosx/CCursorManager.java	Fri Dec 23 22:01:01 2011 +0300
@@ -48,6 +48,15 @@
 
     @Override
     protected Point getCursorPosition() {
+        synchronized(this) {
+            if (isDragging) {
+                // during the drag operation, the appkit thread is blocked,
+                // so nativeGetCursorPosition invocation may cause a deadlock.
+                // In order to avoid this, we returns last know cursor position.
+                return new Point(dragPos);
+            }
+        }
+
         final Point2D nativePosition = nativeGetCursorPosition();
         return new Point((int)nativePosition.getX(), (int)nativePosition.getY());
     }
@@ -91,4 +100,33 @@
         if (platformWindow == null) return 0;
         return platformWindow.getNSWindowPtr();
     }
+
+    // package private methods to handle cursor change during drag-and-drop
+    private boolean isDragging = false;
+    private Point dragPos = null;
+
+    synchronized void startDrag(int x, int y) {
+        if (isDragging) {
+            throw new RuntimeException("Invalid Drag state in CCursorManager!");
+        }
+
+        isDragging = true;
+
+        dragPos = new Point(x, y);
+    }
+
+    synchronized void updateDragPosition(int x, int y) {
+        if (!isDragging) {
+            throw new RuntimeException("Invalid Drag state in CCursorManager!");
+        }
+        dragPos.move(x, y);
+    }
+
+    synchronized void stopDrag() {
+        if (!isDragging) {
+            throw new RuntimeException("Invalid Drag state in CCursorManager!");
+        }
+        isDragging = false;
+        dragPos = null;
+    }
 }
--- a/src/macosx/classes/sun/lwawt/macosx/CDataTransferer.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/lwawt/macosx/CDataTransferer.java	Fri Dec 23 22:01:01 2011 +0300
@@ -74,6 +74,8 @@
     public static final int CF_HTML        = 5;
     public static final int CF_PDF         = 6;
     public static final int CF_URL         = 7;
+    public static final int CF_PNG         = 10;
+    public static final int CF_JPEG        = 11;
 
     public static final Long L_CF_TIFF = predefinedClipboardNameMap.get(predefinedClipboardNames[CF_TIFF]);
 
@@ -108,7 +110,16 @@
     }
 
     public boolean isImageFormat(long format) {
-        return format == CF_TIFF || format == CF_PDF;
+        int ifmt = (int)format;
+        switch(ifmt) {
+            case CF_TIFF:
+            case CF_PDF:
+            case CF_PNG:
+            case CF_JPEG:
+                return true;
+            default:
+                return false;
+        }
     }
 
     protected Long[] getImageFormatsAsLongArray() {
--- a/src/macosx/classes/sun/lwawt/macosx/CDragSourceContextPeer.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/lwawt/macosx/CDragSourceContextPeer.java	Fri Dec 23 22:01:01 2011 +0300
@@ -50,6 +50,8 @@
     private CImage fDragCImage;
     private Point  fDragImageOffset;
 
+    private static Component hoveringComponent = null;
+
     private static double fMaxImageSize = 128.0;
 
     static {
@@ -174,6 +176,10 @@
                 throw new InvalidDnDOperationException("");
 
             setNativeContext(nativeDragSource);
+
+            CCursorManager.getInstance().startDrag(
+                    (int) (dragOrigin.getX() + componentOffset.x),
+                    (int) (dragOrigin.getY() + componentOffset.y));
         }
 
         catch (Exception e) {
@@ -195,6 +201,8 @@
                     } catch (Exception e) {
                         e.printStackTrace();
                     } finally {
+                        CCursorManager.getInstance().stopDrag();
+
                         releaseNativeDragSource(nativeDragSource);
                         fDragImage = null;
                         if (fDragCImage != null) {
@@ -209,6 +217,8 @@
         }
 
         catch (Exception e) {
+            CCursorManager.getInstance().stopDrag();
+
             final long nativeDragSource = getNativeContext();
             setNativeContext(0);
             releaseNativeDragSource(nativeDragSource);
@@ -427,6 +437,52 @@
         fDragImageOffset = dragImageOffset;
     }
 
+    /**
+     * upcall from native code
+     */
+    private void dragMouseMoved(final int targetActions,
+                                final int modifiers,
+                                final int x, final int y) {
+
+        CCursorManager.getInstance().updateDragPosition(x, y);
+
+        Component rootComponent = SwingUtilities.getRoot(getComponent());
+        if(rootComponent != null) {
+            Point componentPoint = new Point(x, y);
+            SwingUtilities.convertPointFromScreen(componentPoint, rootComponent);
+            Component componentAt = SwingUtilities.getDeepestComponentAt(rootComponent, componentPoint.x, componentPoint.y);
+            if(componentAt != hoveringComponent) {
+                if(hoveringComponent != null) {
+                    dragExit(x, y);
+                }
+                if(componentAt != null) {
+                    dragEnter(targetActions, modifiers, x, y);
+                }
+                hoveringComponent = componentAt;
+            }
+        }
+        postDragSourceDragEvent(targetActions, modifiers, x, y,
+                                DISPATCH_MOUSE_MOVED);
+    }
+
+    /**
+     * upcall from native code
+     */
+    private void dragEnter(final int targetActions,
+                           final int modifiers,
+                           final int x, final int y) {
+        CCursorManager.getInstance().updateDragPosition(x, y);
+
+        postDragSourceDragEvent(targetActions, modifiers, x, y, DISPATCH_ENTER);
+    }
+
+    /**
+     * upcall from native code - reset hovering component
+     */
+    private void resetHovering() {
+        hoveringComponent = null;
+    }
+
     public void setCursor(Cursor c) throws InvalidDnDOperationException {
         // TODO : BG
         //AWTLockAccess.awtLock();
--- a/src/macosx/classes/sun/lwawt/macosx/CDropTargetContextPeer.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/lwawt/macosx/CDropTargetContextPeer.java	Fri Dec 23 22:01:01 2011 +0300
@@ -25,9 +25,12 @@
 
 package sun.lwawt.macosx;
 
-import java.awt.Component;
+import java.awt.*;
 
 import sun.awt.dnd.SunDropTargetContextPeer;
+import sun.awt.dnd.SunDropTargetEvent;
+
+import javax.swing.*;
 
 
 final class CDropTargetContextPeer extends SunDropTargetContextPeer {
@@ -35,6 +38,7 @@
     private long    fNativeDropTransfer = 0;
     private long    fNativeDataAvailable = 0;
     private Object  fNativeData    = null;
+    private boolean insideTarget = false;
 
     Object awtLockAccess = new Object();
 
@@ -84,6 +88,42 @@
         return fNativeData;
     }
 
+    // We need to take care of dragExit message because for some reason it is not being
+    // generated for lightweight components
+    @Override
+    protected void processMotionMessage(SunDropTargetEvent event, boolean operationChanged) {
+        Component eventSource = (Component)event.getComponent();
+        Component rootComponent = SwingUtilities.getRoot(eventSource);
+        Point screenPoint = event.getPoint();
+        SwingUtilities.convertPointToScreen(screenPoint, rootComponent);
+        Rectangle screenBounds = new Rectangle(eventSource.getLocationOnScreen().x,
+                eventSource.getLocationOnScreen().y,
+                eventSource.getWidth(), eventSource.getHeight());
+        if(insideTarget) {
+            if(!screenBounds.contains(screenPoint)) {
+                processExitMessage(event);
+                insideTarget = false;
+                return;
+            }
+            super.processMotionMessage(event, operationChanged);
+        }
+        insideTarget = screenBounds.contains(screenPoint);
+    }
+
+    @Override
+    protected void processDropMessage(SunDropTargetEvent event) {
+        Component eventSource = (Component)event.getComponent();
+        Component rootComponent = SwingUtilities.getRoot(eventSource);
+        Point screenPoint = event.getPoint();
+        SwingUtilities.convertPointToScreen(screenPoint, rootComponent);
+        Rectangle screenBounds = new Rectangle(eventSource.getLocationOnScreen().x,
+                eventSource.getLocationOnScreen().y,
+                eventSource.getWidth(), eventSource.getHeight());
+        if(!screenBounds.contains(screenPoint)) {
+            super.processDropMessage(event);
+        }
+    }
+
     // Signal drop complete:
     protected void doDropDone(boolean success, int dropAction, boolean isLocal) {
         long nativeDropTarget = this.getNativeDragContext();
--- a/src/macosx/classes/sun/lwawt/macosx/CInputMethod.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/lwawt/macosx/CInputMethod.java	Fri Dec 23 22:01:01 2011 +0300
@@ -118,7 +118,7 @@
      *     returns a non-null value.
      * </ul>
      *
-     * @param locale locale to input
+     * @param lang locale to input
      * @return whether the specified locale is supported
      * @exception NullPointerException if <code>locale</code> is null
      */
@@ -196,7 +196,7 @@
     }
 
     /**
-        * Dispatches the event to the input method. If input method support is
+     * Dispatches the event to the input method. If input method support is
      * enabled for the focussed component, incoming events of certain types
      * are dispatched to the current input method for this component before
      * they are dispatched to the component's methods or event listeners.
@@ -214,7 +214,7 @@
      * @param event the event being dispatched to the input method
      * @exception NullPointerException if <code>event</code> is null
      */
-    public void dispatchEvent(AWTEvent e) {
+    public void dispatchEvent(final AWTEvent event) {
         // No-op for Mac OS X.
     }
 
--- a/src/macosx/classes/sun/lwawt/macosx/CPlatformComponent.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformComponent.java	Fri Dec 23 22:01:01 2011 +0300
@@ -56,8 +56,8 @@
         this.peer = peer;
         this.platformWindow = (CPlatformWindow)platformWindow;
 
-        long windowLayer = this.platformWindow.getContentView().getWindowLayer();
-        setPtr(nativeCreateComponent(windowLayer));
+        long windowLayerPtr = this.platformWindow.getContentView().getWindowLayerPtr();
+        setPtr(nativeCreateComponent(windowLayerPtr));
     }
 
     // TODO: visibility, z-order
--- a/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java	Fri Dec 23 22:01:01 2011 +0300
@@ -35,6 +35,7 @@
 
 import sun.java2d.SurfaceData;
 import sun.java2d.opengl.CGLLayer;
+import sun.java2d.opengl.CGLSurfaceData;
 
 public class CPlatformView extends CFRetainedResource {
     private native long nativeCreateView(int x, int y, int width, int height, long windowLayerPtr);
@@ -49,14 +50,21 @@
 
     public void initialize(LWWindowPeer peer) {
         this.peer = peer;
-        this.windowLayer = new CGLLayer();
-        setPtr(nativeCreateView(0, 0, 0, 0, windowLayer.getPointer()));
+
+        if (!LWCToolkit.getSunAwtDisableCALayers()) {
+            this.windowLayer = new CGLLayer(peer);
+        }
+        setPtr(nativeCreateView(0, 0, 0, 0, getWindowLayerPtr()));
     }
 
     public long getAWTView() {
         return ptr;
     }
 
+    public boolean isOpaque() {
+        return peer.isOpaque();
+    }
+
     /*
      * All coordinates passed to the method should be based on the origin being in the bottom-left corner (standard
      * Cocoa coordinates).
@@ -120,28 +128,29 @@
         Rectangle r = peer.getBounds();
         Image im = null;
         if (!r.isEmpty()) {
-            im = peer.getGraphicsConfiguration().createCompatibleImage(r.width, r.height);
+            int transparency = (isOpaque() ? Transparency.OPAQUE : Transparency.TRANSLUCENT);
+            im = peer.getGraphicsConfiguration().createCompatibleImage(r.width, r.height, transparency);
         }
         return im;
     }
 
     public SurfaceData replaceSurfaceData() {
-        if (surfaceData == null) {
-            CGraphicsConfig graphicsConfig = (CGraphicsConfig)peer.getGraphicsConfiguration();
-            surfaceData = graphicsConfig.createSurfaceData(this);
+        if (!LWCToolkit.getSunAwtDisableCALayers()) {
+            surfaceData = windowLayer.replaceSurfaceData();
         } else {
-            validateSurface();
+            if (surfaceData == null) {
+                CGraphicsConfig graphicsConfig = (CGraphicsConfig)peer.getGraphicsConfiguration();
+                surfaceData = graphicsConfig.createSurfaceData(this);
+            } else {
+                validateSurface();
+            }
         }
         return surfaceData;
     }
 
     private void validateSurface() {
-        // on other platforms we create a new SurfaceData for every
-        // live resize step, but on Mac OS X we just resize the onscreen
-        // surface directly
-        // TODO: by the time we come here first time we don't have surface yet
         if (surfaceData != null) {
-            ((sun.java2d.opengl.CGLSurfaceData)surfaceData).setBounds();
+            ((CGLSurfaceData)surfaceData).validate();
         }
     }
 
@@ -155,12 +164,18 @@
 
     @Override
     public void dispose() {
-        windowLayer.dispose();
+        if (!LWCToolkit.getSunAwtDisableCALayers()) {
+            windowLayer.dispose();
+        }
         super.dispose();
     }
 
-    public long getWindowLayer() {
-        return windowLayer.getPointer();
+    public long getWindowLayerPtr() {
+        if (!LWCToolkit.getSunAwtDisableCALayers()) {
+            return windowLayer.getPointer();
+        } else {
+            return 0;
+        }
     }
 
     // ----------------------------------------------------------------------
@@ -176,7 +191,7 @@
         int jY = getBounds().height - event.getY();
         int jAbsX = event.getAbsX();
         int jAbsY = event.getAbsY();
-        int jButton = NSEvent.nsButtonToJavaButton(event.getButton());
+        int jButton = NSEvent.nsButtonToJavaButton(event);
         int jClickCount = event.getClickCount();
         double wheelDeltaY = event.getScrollDeltaY();
         double wheelDeltaX = event.getScrollDeltaX();
--- a/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java	Fri Dec 23 22:01:01 2011 +0300
@@ -36,6 +36,7 @@
 
 import sun.awt.*;
 import sun.java2d.SurfaceData;
+import sun.java2d.opengl.CGLSurfaceData;
 import sun.lwawt.*;
 import sun.lwawt.LWWindowPeer.PeerType;
 import sun.util.logging.PlatformLogger;
@@ -62,8 +63,11 @@
 
     private static native int nativeGetScreenNSWindowIsOn_AppKitThread(long nsWindowPtr);
 
+    private static native boolean nativeIsApplicationActive();
+
     // Loger to report issues happened during execution but that do not affect functionality
     private static final PlatformLogger logger = PlatformLogger.getLogger("sun.lwawt.macosx.CPlatformWindow");
+    private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.lwawt.macosx.focus.CPlatformWindow");
 
     // for client properties
     public static final String WINDOW_BRUSH_METAL_LOOK = "apple.awt.brushMetalLook";
@@ -168,6 +172,9 @@
         new Property<CPlatformWindow>(WINDOW_ZOOMABLE) { public void applyProperty(final CPlatformWindow c, final Object value) {
             c.setStyleBits(ZOOMABLE, Boolean.parseBoolean(value.toString()));
         }},
+        new Property<CPlatformWindow>(WINDOW_FULLSCREENABLE) { public void applyProperty(final CPlatformWindow c, final Object value) {
+            c.setStyleBits(FULLSCREENABLE, Boolean.parseBoolean(value.toString()));
+        }},
         new Property<CPlatformWindow>(WINDOW_SHADOW_REVALIDATE_NOW) { public void applyProperty(final CPlatformWindow c, final Object value) {
             nativeRevalidateNSWindowShadow(c.getNSWindowPtr());
         }},
@@ -570,6 +577,7 @@
 
     @Override
     public void setMinimumSize(int width, int height) {
+        //TODO width, height should be used
         final long nsWindowPtr = getNSWindowPtr();
         final Dimension min = target.getMinimumSize();
         final Dimension max = target.getMaximumSize();
@@ -578,7 +586,16 @@
 
     @Override
     public boolean requestWindowFocus(boolean isMouseEventCause) {
-        // TODO: ask if the native system is to assign focus on the NSWindow.
+        if (!isMouseEventCause && !nativeIsApplicationActive()) {
+            focusLog.fine("the app is inactive, so the window activation is rejected");
+            // Cross-app activation requests are not allowed.
+            return false;
+        }
+        long ptr = getNSWindowPtr();
+        if (CWrapper.NSWindow.canBecomeMainWindow(ptr)) {
+            CWrapper.NSWindow.makeMainWindow(ptr);
+        }
+        CWrapper.NSWindow.makeKeyAndOrderFront(ptr);
         return true;
     }
 
@@ -605,6 +622,15 @@
     }
 
     @Override
+    public void setOpaque(boolean isOpaque) {
+        CWrapper.NSWindow.setOpaque(getNSWindowPtr(), isOpaque);
+        if (!isOpaque) {
+            long clearColor = CWrapper.NSColor.clearColor();
+            CWrapper.NSWindow.setBackgroundColor(getNSWindowPtr(), clearColor);
+        }
+    }
+
+    @Override
     public void enterFullScreenMode() {
         isFullScreenMode = true;
         contentView.enterFullScreenMode(getNSWindowPtr());
@@ -720,13 +746,9 @@
     }
 
     private void validateSurface() {
-        // on other platforms we create a new SurfaceData for every
-        // live resize step, but on Mac OS X we just resize the onscreen
-        // surface directly
-        //TODO: by the time we come here first time we don't have surface yet
         SurfaceData surfaceData = getSurfaceData();
-        if (surfaceData != null) {
-            ((sun.java2d.opengl.CGLSurfaceData)surfaceData).setBounds();
+        if (surfaceData instanceof CGLSurfaceData) {
+            ((CGLSurfaceData)surfaceData).validate();
         }
     }
 
@@ -746,6 +768,7 @@
 
         nativeBounds = new Rectangle(x, y, width, height);
         peer.notifyReshape(x, y, width, height);
+        //TODO validateSurface already called from notifyReshape
         validateSurface();
     }
 
--- a/src/macosx/classes/sun/lwawt/macosx/CPrinterJob.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/lwawt/macosx/CPrinterJob.java	Fri Dec 23 22:01:01 2011 +0300
@@ -178,14 +178,17 @@
     public void print(PrintRequestAttributeSet attributes) throws PrinterException {
         // NOTE: Some of this code is copied from RasterPrinterJob.
 
-/*
+
         // this code uses javax.print APIs
         // this will make it print directly to the printer
         // this will not work if the user clicks on the "Preview" button
+        // However if the printer is a StreamPrintService, its the right path.
         PrintService psvc = getPrintService();
-        spoolToService(psvc, attributes);
-        return;
-*/
+        if (psvc instanceof StreamPrintService) {
+            spoolToService(psvc, attributes);
+            return;
+        }
+
 
         setAttributes(attributes);
 
--- a/src/macosx/classes/sun/lwawt/macosx/CRobot.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/lwawt/macosx/CRobot.java	Fri Dec 23 22:01:01 2011 +0300
@@ -165,10 +165,10 @@
      * peer implementations will throw an exception for other bogus
      * values e.g. -1, 999999
      *
-     * @param keyCode the key to press (e.g. <code>KeyEvent.VK_A</code>)
+     * @param keycode the key to press (e.g. <code>KeyEvent.VK_A</code>)
      */
     @Override
-    public void keyPress(int keycode) {
+    public void keyPress(final int keycode) {
         keyEvent(keycode, true);
     }
 
@@ -183,10 +183,10 @@
      * peer implementations will throw an exception for other bogus
      * values e.g. -1, 999999
      *
-     * @param keyCode the key to release (e.g. <code>KeyEvent.VK_A</code>)
+     * @param keycode the key to release (e.g. <code>KeyEvent.VK_A</code>)
      */
     @Override
-    public void keyRelease(int keycode) {
+    public void keyRelease(final int keycode) {
         keyEvent(keycode, false);
     }
 
@@ -205,11 +205,11 @@
 
     /**
      * Creates an image containing pixels read from the screen.
-     * @param screenRect the rect to capture in screen coordinates
+     * @param bounds the rect to capture in screen coordinates
      * @return the array of pixels
      */
     @Override
-    public int [] getRGBPixels(Rectangle bounds) {
+    public int [] getRGBPixels(final Rectangle bounds) {
         Rectangle screenBounds = fDevice.getDefaultConfiguration().getBounds();
         // screenBounds is in the coordinates of the primary device
         // but bounds is in the coordinates of fDevice
--- a/src/macosx/classes/sun/lwawt/macosx/CTrayIcon.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/lwawt/macosx/CTrayIcon.java	Fri Dec 23 22:01:01 2011 +0300
@@ -25,18 +25,28 @@
 
 package sun.lwawt.macosx;
 
+import sun.awt.SunToolkit;
+
+import javax.swing.*;
 import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
+import java.awt.event.*;
+import java.awt.geom.Point2D;
+import java.awt.image.BufferedImage;
 import java.awt.peer.TrayIconPeer;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
 
 public class CTrayIcon extends CFRetainedResource implements TrayIconPeer {
     private TrayIcon target;
     private PopupMenu popup;
+    private JDialog messageDialog;
+    private DialogEventHandler handler;
 
     CTrayIcon(TrayIcon target) {
         super(0, true);
 
+        this.messageDialog = null;
+        this.handler = null;
         this.target = target;
         this.popup = target.getPopupMenu();
         setPtr(createModel());
@@ -62,7 +72,6 @@
     }
 
     private long createModel() {
-//        final NSStatusBarClass statusBarClass = JObjC.getInstance().AppKit().NSStatusBar();
         return nativeCreate();
     }
 
@@ -80,13 +89,36 @@
         return checkAndCreatePopupPeer().getModel();
     }
 
-    @Override
-    public void displayMessage(String caption, String text, String messageType) {
-        throw new UnsupportedOperationException("MacOS TODO. TrayIcon.displayMessage()");
+    /**
+     * We display tray icon message as a small dialog with OK button.
+     * This is lame, but JDK 1.6 does basically the same. There is a new
+     * kind of window in Lion, NSPopover, so perhaps it could be used it
+     * to implement better looking notifications.
+     */
+    public void displayMessage(final String caption, final String text,
+                               final String messageType) {
+
+        if (SwingUtilities.isEventDispatchThread()) {
+            displayMessageOnEDT(caption, text, messageType);
+        } else {
+            try {
+                SwingUtilities.invokeAndWait(new Runnable() {
+                    public void run() {
+                        displayMessageOnEDT(caption, text, messageType);
+                    }
+                });
+            } catch (Exception e) {
+                throw new AssertionError(e);
+            }
+        }
     }
 
     @Override
     public void dispose() {
+        if (messageDialog != null) {
+            disposeMessageDialog();
+        }
+
         LWCToolkit.targetDisposedPeer(target, this);
         target = null;
 
@@ -131,9 +163,255 @@
 
     //invocation from the AWTTrayIcon.m
     public void performAction() {
-        ActionEvent evt = new ActionEvent(target, 0, "ACTION_TRIGGERED_BY_PEER");
-        for(ActionListener listener:target.getActionListeners()) {
-            listener.actionPerformed(evt);
+        SunToolkit.executeOnEventHandlerThread(target, new Runnable() {
+            public void run() {
+                final String cmd = target.getActionCommand();
+                final ActionEvent event = new ActionEvent(target, ActionEvent.ACTION_PERFORMED, cmd);
+                SunToolkit.postEvent(SunToolkit.targetToAppContext(target), event);
+            }
+        });
+    }
+
+    private native Point2D nativeGetIconLocation(long trayIconModel);
+
+    public void displayMessageOnEDT(String caption, String text,
+                                    String messageType) {
+        if (messageDialog != null) {
+            disposeMessageDialog();
+        }
+
+        // obtain icon to show along the message
+        Icon icon = getIconForMessageType(messageType);
+        if (icon != null) {
+            icon = new ImageIcon(scaleIcon(icon, 0.75));
+        }
+
+        // We want the message dialog text area to be about 1/8 of the screen
+        // size. There is nothing special about this value, it's just makes the
+        // message dialog to look nice
+        Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
+        int textWidth = screenSize.width / 8;
+
+        // create dialog to show
+        messageDialog = createMessageDialog(caption, text, textWidth, icon);
+
+        // finally, show the dialog to user
+        showMessageDialog();
+    }
+
+    /**
+     * Creates dialog window used to display the message
+     */
+    private JDialog createMessageDialog(String caption, String text,
+                                     int textWidth, Icon icon) {
+        JDialog dialog;
+        handler = new DialogEventHandler();
+
+        JTextArea captionArea = null;
+        if (caption != null) {
+            captionArea = createTextArea(caption, textWidth, false, true);
+        }
+
+        JTextArea textArea = null;
+        if (text != null){
+            textArea = createTextArea(text, textWidth, true, false);
+        }
+
+        Object[] panels = null;
+        if (captionArea != null) {
+            if (textArea != null) {
+                panels = new Object[] {captionArea, new JLabel(), textArea};
+            } else {
+                panels = new Object[] {captionArea};
+            }
+        } else {
+           if (textArea != null) {
+                panels = new Object[] {textArea};
+            }
+        }
+
+        // We want message dialog with small title bar. There is a client
+        // property property that does it, however, it must be set before
+        // dialog's native window is created. This is why we create option
+        // pane and dialog separately
+        final JOptionPane op = new JOptionPane(panels);
+        op.setIcon(icon);
+        op.addPropertyChangeListener(handler);
+
+        // Make Ok button small. Most likely won't work for L&F other then Aqua
+        try {
+            JPanel buttonPanel = (JPanel)op.getComponent(1);
+            JButton ok = (JButton)buttonPanel.getComponent(0);
+            ok.putClientProperty("JComponent.sizeVariant", "small");
+        } catch (Throwable t) {
+            // do nothing, we tried and failed, no big deal
+        }
+
+        dialog = new JDialog((Dialog) null);
+        JRootPane rp = dialog.getRootPane();
+
+        // gives us dialog window with small title bar and not zoomable
+        rp.putClientProperty(CPlatformWindow.WINDOW_STYLE, "small");
+        rp.putClientProperty(CPlatformWindow.WINDOW_ZOOMABLE, "false");
+
+        dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
+        dialog.setModal(false);
+        dialog.setResizable(false);
+        dialog.setContentPane(op);
+
+        dialog.addWindowListener(handler);
+
+        dialog.pack();
+
+        return dialog;
+    }
+
+    private void showMessageDialog() {
+
+        Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
+        Point2D iconLoc = nativeGetIconLocation(getModel());
+
+        int dialogY = (int)iconLoc.getY();
+        int dialogX = (int)iconLoc.getX();
+        if (dialogX + messageDialog.getWidth() > screenSize.width) {
+            dialogX = screenSize.width - messageDialog.getWidth();
+        }
+
+        messageDialog.setLocation(dialogX, dialogY);
+        messageDialog.setVisible(true);
+    }
+
+   private void disposeMessageDialog() {
+        if (SwingUtilities.isEventDispatchThread()) {
+            disposeMessageDialogOnEDT();
+        } else {
+            try {
+                SwingUtilities.invokeAndWait(new Runnable() {
+                    public void run() {
+                        disposeMessageDialogOnEDT();
+                    }
+                });
+            } catch (Exception e) {
+                throw new AssertionError(e);
+            }
+        }
+   }
+
+    private void disposeMessageDialogOnEDT() {
+        if (messageDialog != null) {
+            messageDialog.removeWindowListener(handler);
+            messageDialog.removePropertyChangeListener(handler);
+            messageDialog.dispose();
+
+            messageDialog = null;
+            handler = null;
+        }
+    }
+
+    /**
+     * Scales an icon using specified scale factor
+     *
+     * @param icon        icon to scale
+     * @param scaleFactor scale factor to use
+     * @return scaled icon as BuffedredImage
+     */
+    private static BufferedImage scaleIcon(Icon icon, double scaleFactor) {
+        if (icon == null) {
+            return null;
+        }
+
+        int w = icon.getIconWidth();
+        int h = icon.getIconHeight();
+
+        GraphicsEnvironment ge =
+                GraphicsEnvironment.getLocalGraphicsEnvironment();
+        GraphicsDevice gd = ge.getDefaultScreenDevice();
+        GraphicsConfiguration gc = gd.getDefaultConfiguration();
+
+        // convert icon into image
+        BufferedImage iconImage = gc.createCompatibleImage(w, h,
+                Transparency.TRANSLUCENT);
+        Graphics2D g = iconImage.createGraphics();
+        icon.paintIcon(null, g, 0, 0);
+        g.dispose();
+
+        // and scale it nicely
+        int scaledW = (int) (w * scaleFactor);
+        int scaledH = (int) (h * scaleFactor);
+        BufferedImage scaledImage = gc.createCompatibleImage(scaledW, scaledH,
+                Transparency.TRANSLUCENT);
+        g = scaledImage.createGraphics();
+        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
+                RenderingHints.VALUE_INTERPOLATION_BILINEAR);
+        g.drawImage(iconImage, 0, 0, scaledW, scaledH, null);
+        g.dispose();
+
+        return scaledImage;
+    }
+
+
+    /**
+     * Gets Aqua icon used in message dialog.
+     */
+    private static Icon getIconForMessageType(String messageType) {
+        if (messageType.equals("ERROR")) {
+            return UIManager.getIcon("OptionPane.errorIcon");
+        } else if (messageType.equals("WARNING")) {
+            return UIManager.getIcon("OptionPane.warningIcon");
+        } else {
+            // this is just an application icon
+            return UIManager.getIcon("OptionPane.informationIcon");
+        }
+    }
+
+    private static JTextArea createTextArea(String text, int width,
+                                            boolean isSmall, boolean isBold) {
+        JTextArea textArea = new JTextArea(text);
+
+        textArea.setLineWrap(true);
+        textArea.setWrapStyleWord(true);
+        textArea.setEditable(false);
+        textArea.setFocusable(false);
+        textArea.setBorder(null);
+        textArea.setBackground(new JLabel().getBackground());
+
+        if (isSmall) {
+            textArea.putClientProperty("JComponent.sizeVariant", "small");
+        }
+
+        if (isBold) {
+            Font font = textArea.getFont();
+            Font boldFont = new Font(font.getName(), Font.BOLD, font.getSize());
+            textArea.setFont(boldFont);
+        }
+
+        textArea.setSize(width, 1);
+
+        return textArea;
+    }
+
+    /**
+     * Implements all the Listeners needed by message dialog
+     */
+    private final class DialogEventHandler extends WindowAdapter
+            implements PropertyChangeListener {
+
+        public void windowClosing(WindowEvent we) {
+                disposeMessageDialog();
+        }
+
+        public void propertyChange(PropertyChangeEvent e) {
+            if (messageDialog == null) {
+                return;
+            }
+
+            String prop = e.getPropertyName();
+            Container cp = messageDialog.getContentPane();
+
+            if (messageDialog.isVisible() && e.getSource() == cp &&
+                    (prop.equals(JOptionPane.VALUE_PROPERTY))) {
+                disposeMessageDialog();
+            }
         }
     }
 }
--- a/src/macosx/classes/sun/lwawt/macosx/CWrapper.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/lwawt/macosx/CWrapper.java	Fri Dec 23 22:01:01 2011 +0300
@@ -38,6 +38,7 @@
 
         public static native void makeKeyAndOrderFront(long window);
         public static native void makeMainWindow(long window);
+        public static native boolean canBecomeMainWindow(long window);
         public static native boolean isKeyWindow(long window);
 
         public static native void orderFront(long window);
@@ -51,6 +52,8 @@
         public static native void setFrame(long window, int x, int y, int w, int h, boolean display);
 
         public static native void setAlphaValue(long window, float alpha);
+        public static native void setOpaque(long window, boolean opaque);
+        public static native void setBackgroundColor(long window, long color);
 
         public static native void miniaturize(long window);
         public static native void deminiaturize(long window);
@@ -82,4 +85,8 @@
         public static native Rectangle2D visibleFrame(long screen);
         public static native long screenByDisplayId(int displayID);
     }
+
+    public static final class NSColor {
+        public static native long clearColor();
+    }
 }
--- a/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java	Fri Dec 23 22:01:01 2011 +0300
@@ -29,6 +29,7 @@
 import java.awt.datatransfer.Clipboard;
 import java.awt.dnd.*;
 import java.awt.dnd.peer.DragSourceContextPeer;
+import java.awt.event.InputEvent;
 import java.awt.event.InvocationEvent;
 import java.awt.im.InputMethodHighlight;
 import java.awt.peer.*;
@@ -388,11 +389,6 @@
     }
 
     @Override
-    public boolean isNativeDoubleBufferingEnabled() {
-        return true;
-    }
-
-    @Override
     public boolean isTraySupported() {
         return true;
     }
@@ -618,6 +614,13 @@
         return CInputMethod.mapInputMethodHighlight(highlight);
     }
 
+    /**
+     * Returns key modifiers used by Swing to set up a focus accelerator key stroke.
+     */
+    @Override
+    public int getFocusAcceleratorKeyMask() {
+        return InputEvent.CTRL_MASK | InputEvent.ALT_MASK;
+    }
 
     // Extends PeerEvent because we want to pass long an ObjC mediator object and because we want these events to be posted early
     // Typically, rather than relying on the notifier to call notifyAll(), we use the mediator to stop the runloop
@@ -644,6 +647,20 @@
     public static void doAWTRunLoop(long mediator, boolean awtMode) { doAWTRunLoop(mediator, awtMode, true); }
     public static void doAWTRunLoop(long mediator) { doAWTRunLoop(mediator, true); }
 
+    private static Boolean sunAwtDisableCALayers = null;
+
+    /**
+     * Returns the value of "sun.awt.disableCALayers" property. Default
+     * value is {@code false}.
+     */
+    public synchronized static boolean getSunAwtDisableCALayers() {
+        if (sunAwtDisableCALayers == null) {
+            sunAwtDisableCALayers =
+            getBooleanSystemProperty("sun.awt.disableCALayers");
+        }
+        return sunAwtDisableCALayers.booleanValue();
+    }
+
     /************************
      * Native methods section
      ************************/
@@ -681,4 +698,13 @@
             (modalityType == Dialog.ModalityType.TOOLKIT_MODAL);
     }
 
+    @Override
+    public boolean isWindowTranslucencySupported() {
+        return true;
+    }
+
+    @Override
+    public boolean isTranslucencyCapable(GraphicsConfiguration gc) {
+        return true;
+    }
 }
--- a/src/macosx/classes/sun/lwawt/macosx/event/NSEvent.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/classes/sun/lwawt/macosx/event/NSEvent.java	Fri Dec 23 22:01:01 2011 +0300
@@ -25,6 +25,8 @@
 
 package sun.lwawt.macosx.event;
 
+import sun.lwawt.macosx.CocoaConstants;
+
 import java.awt.event.*;
 
 /*
@@ -114,15 +116,18 @@
     /*
      * Converts an NSEvent button number to a MouseEvent constant.
      */
-    public static int nsButtonToJavaButton(int nsButtonNumber) {
+    public static int nsButtonToJavaButton(NSEvent event) {
+        int nsButtonNumber = event.getButton();
         int jbutton = MouseEvent.NOBUTTON;
 
-        if (nsButtonNumber == 0) { // left
-            jbutton = MouseEvent.BUTTON1;
-        } else if (nsButtonNumber == 1) { // right
-            jbutton = MouseEvent.BUTTON3;
-        } else if (nsButtonNumber == 2) { // middle
-            jbutton = MouseEvent.BUTTON2;
+        if (event.getType() != CocoaConstants.NSMouseMoved) {
+            if (nsButtonNumber == 0) { // left
+                jbutton = MouseEvent.BUTTON1;
+            } else if (nsButtonNumber == 1) { // right
+                jbutton = MouseEvent.BUTTON3;
+            } else if (nsButtonNumber == 2) { // middle
+                jbutton = MouseEvent.BUTTON2;
+            }
         }
 
         return jbutton;
--- a/src/macosx/native/com/sun/media/sound/CARingBuffer.cpp	Thu Dec 22 11:05:51 2011 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,306 +0,0 @@
-/*      Copyright � 2007 Apple Inc. All Rights Reserved.
-
-        Disclaimer: IMPORTANT:  This Apple software is supplied to you by
-                        Apple Inc. ("Apple") in consideration of your agreement to the
-                        following terms, and your use, installation, modification or
-                        redistribution of this Apple software constitutes acceptance of these
-                        terms.  If you do not agree with these terms, please do not use,
-                        install, modify or redistribute this Apple software.
-
-                        In consideration of your agreement to abide by the following terms, and
-                        subject to these terms, Apple grants you a personal, non-exclusive
-                        license, under Apple's copyrights in this original Apple software (the
-                        "Apple Software"), to use, reproduce, modify and redistribute the Apple
-                        Software, with or without modifications, in source and/or binary forms;
-                        provided that if you redistribute the Apple Software in its entirety and
-                        without modifications, you must retain this notice and the following
-                        text and disclaimers in all such redistributions of the Apple Software.
-                        Neither the name, trademarks, service marks or logos of Apple Inc.
-                        may be used to endorse or promote products derived from the Apple
-                        Software without specific prior written permission from Apple.  Except
-                        as expressly stated in this notice, no other rights or licenses, express
-                        or implied, are granted by Apple herein, including but not limited to
-                        any patent rights that may be infringed by your derivative works or by
-                        other works in which the Apple Software may be incorporated.
-
-                        The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
-                        MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
-                        THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
-                        FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
-                        OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
-
-                        IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
-                        OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-                        SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-                        INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
-                        MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
-                        AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
-                        STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
-                        POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/*
- This is an imported copy of /Developer/Extras/Public/Utility/CARingBuffer.cpp,
- as found in Mac OS X 10.7.
- */
-
-
-#include "CARingBuffer.h"
-#include "CABitOperations.h"
-#include "CAAutoDisposer.h"
-#include "CAAtomic.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <algorithm>
-#include <libkern/OSAtomic.h>
-
-CARingBuffer::CARingBuffer() :
-        mBuffers(NULL), mNumberChannels(0), mCapacityFrames(0), mCapacityBytes(0)
-{
-
-}
-
-CARingBuffer::~CARingBuffer()
-{
-        Deallocate();
-}
-
-
-void    CARingBuffer::Allocate(int nChannels, UInt32 bytesPerFrame, UInt32 capacityFrames)
-{
-        Deallocate();
-
-        capacityFrames = NextPowerOfTwo(capacityFrames);
-
-        mNumberChannels = nChannels;
-        mBytesPerFrame = bytesPerFrame;
-        mCapacityFrames = capacityFrames;
-        mCapacityFramesMask = capacityFrames - 1;
-        mCapacityBytes = bytesPerFrame * capacityFrames;
-
-        // put everything in one memory allocation, first the pointers, then the deinterleaved channels
-        UInt32 allocSize = (mCapacityBytes + sizeof(Byte *)) * nChannels;
-        Byte *p = (Byte *)CA_malloc(allocSize);
-        memset(p, 0, allocSize);
-        mBuffers = (Byte **)p;
-        p += nChannels * sizeof(Byte *);
-        for (int i = 0; i < nChannels; ++i) {
-                mBuffers[i] = p;
-                p += mCapacityBytes;
-        }
-
-        for (UInt32 i = 0; i<kGeneralRingTimeBoundsQueueSize; ++i)
-        {
-                mTimeBoundsQueue[i].mStartTime = 0;
-                mTimeBoundsQueue[i].mEndTime = 0;
-                mTimeBoundsQueue[i].mUpdateCounter = 0;
-        }
-        mTimeBoundsQueuePtr = 0;
-}
-
-void    CARingBuffer::Deallocate()
-{
-        if (mBuffers) {
-                free(mBuffers);
-                mBuffers = NULL;
-        }
-        mNumberChannels = 0;
-        mCapacityBytes = 0;
-        mCapacityFrames = 0;
-}
-
-inline void ZeroRange(Byte **buffers, int nchannels, int offset, int nbytes)
-{
-        while (--nchannels >= 0) {
-                memset(*buffers + offset, 0, nbytes);
-                ++buffers;
-        }
-}
-
-inline void StoreABL(Byte **buffers, int destOffset, const AudioBufferList *abl, int srcOffset, int nbytes)
-{
-        int nchannels = abl->mNumberBuffers;
-        const AudioBuffer *src = abl->mBuffers;
-        while (--nchannels >= 0) {
-                memcpy(*buffers + destOffset, (Byte *)src->mData + srcOffset, nbytes);
-                ++buffers;
-                ++src;
-        }
-}
-
-inline void FetchABL(AudioBufferList *abl, int destOffset, Byte **buffers, int srcOffset, int nbytes)
-{
-        int nchannels = abl->mNumberBuffers;
-        AudioBuffer *dest = abl->mBuffers;
-        while (--nchannels >= 0) {
-                memcpy((Byte *)dest->mData + destOffset, *buffers + srcOffset, nbytes);
-                ++buffers;
-                ++dest;
-        }
-}
-
-inline void ZeroABL(AudioBufferList *abl, int destOffset, int nbytes)
-{
-        int nBuffers = abl->mNumberBuffers;
-        AudioBuffer *dest = abl->mBuffers;
-        while (--nBuffers >= 0) {
-                memset((Byte *)dest->mData + destOffset, 0, nbytes);
-                ++dest;
-        }
-}
-
-
-CARingBufferError       CARingBuffer::Store(const AudioBufferList *abl, UInt32 framesToWrite, SampleTime startWrite)
-{
-        if (framesToWrite > mCapacityFrames)
-                return kCARingBufferError_TooMuch;              // too big!
-
-        SampleTime endWrite = startWrite + framesToWrite;
-
-        if (startWrite < EndTime()) {
-                // going backwards, throw everything out
-                SetTimeBounds(startWrite, startWrite);
-        } else if (endWrite - StartTime() <= mCapacityFrames) {
-                // the buffer has not yet wrapped and will not need to
-        } else {
-                // advance the start time past the region we are about to overwrite
-                SampleTime newStart = endWrite - mCapacityFrames;       // one buffer of time behind where we're writing
-                SampleTime newEnd = std::max(newStart, EndTime());
-                SetTimeBounds(newStart, newEnd);
-        }
-
-        // write the new frames
-        Byte **buffers = mBuffers;
-        int nchannels = mNumberChannels;
-        int offset0, offset1, nbytes;
-        SampleTime curEnd = EndTime();
-
-        if (startWrite > curEnd) {
-                // we are skipping some samples, so zero the range we are skipping
-                offset0 = FrameOffset(curEnd);
-                offset1 = FrameOffset(startWrite);
-                if (offset0 < offset1)
-                        ZeroRange(buffers, nchannels, offset0, offset1 - offset0);
-                else {
-                        ZeroRange(buffers, nchannels, offset0, mCapacityBytes - offset0);
-                        ZeroRange(buffers, nchannels, 0, offset1);
-                }
-                offset0 = offset1;
-        } else {
-                offset0 = FrameOffset(startWrite);
-        }
-
-        offset1 = FrameOffset(endWrite);
-        if (offset0 == offset1) {
-        // do nothing
-        } else if (offset0 < offset1) {
-                StoreABL(buffers, offset0, abl, 0, offset1 - offset0);
-        } else {
-                nbytes = mCapacityBytes - offset0;
-                StoreABL(buffers, offset0, abl, 0, nbytes);
-                StoreABL(buffers, 0, abl, nbytes, offset1);
-        }
-
-        // now update the end time
-        SetTimeBounds(StartTime(), endWrite);
-
-        return kCARingBufferError_OK;   // success
-}
-
-void    CARingBuffer::SetTimeBounds(SampleTime startTime, SampleTime endTime)
-{
-        UInt32 nextPtr = mTimeBoundsQueuePtr + 1;
-        UInt32 index = nextPtr & kGeneralRingTimeBoundsQueueMask;
-
-        mTimeBoundsQueue[index].mStartTime = startTime;
-        mTimeBoundsQueue[index].mEndTime = endTime;
-        mTimeBoundsQueue[index].mUpdateCounter = nextPtr;
-        CAAtomicCompareAndSwap32Barrier(mTimeBoundsQueuePtr, mTimeBoundsQueuePtr + 1, (SInt32*)&mTimeBoundsQueuePtr);
-}
-
-CARingBufferError       CARingBuffer::GetTimeBounds(SampleTime &startTime, SampleTime &endTime)
-{
-        for (int i=0; i<8; ++i) // fail after a few tries.
-        {
-                UInt32 curPtr = mTimeBoundsQueuePtr;
-                UInt32 index = curPtr & kGeneralRingTimeBoundsQueueMask;
-                CARingBuffer::TimeBounds* bounds = mTimeBoundsQueue + index;
-
-                startTime = bounds->mStartTime;
-                endTime = bounds->mEndTime;
-                UInt32 newPtr = bounds->mUpdateCounter;
-
-                if (newPtr == curPtr)
-                        return kCARingBufferError_OK;
-        }
-        return kCARingBufferError_CPUOverload;
-}
-
-CARingBufferError       CARingBuffer::ClipTimeBounds(SampleTime& startRead, SampleTime& endRead)
-{
-        SampleTime startTime, endTime;
-
-        CARingBufferError err = GetTimeBounds(startTime, endTime);
-        if (err) return err;
-
-        startRead = std::max(startRead, startTime);
-        endRead = std::min(endRead, endTime);
-        endRead = std::max(endRead, startRead);
-
-        return kCARingBufferError_OK;   // success
-}
-
-CARingBufferError       CARingBuffer::Fetch(AudioBufferList *abl, UInt32 nFrames, SampleTime startRead)
-{
-        SampleTime endRead = startRead + nFrames;
-
-        SampleTime startRead0 = startRead;
-        SampleTime endRead0 = endRead;
-        SampleTime size;
-
-        CARingBufferError err = ClipTimeBounds(startRead, endRead);
-        if (err) return err;
-        size = endRead - startRead;
-
-        SInt32 destStartOffset = startRead - startRead0;
-        if (destStartOffset > 0) {
-        SInt32 zeroedFrames = std::min((UInt32)destStartOffset, nFrames);
-                ZeroABL(abl, 0, zeroedFrames * mBytesPerFrame);
-        }
-
-        SInt32 destEndSize = endRead0 - endRead;
-        if (destEndSize > 0) {
-        SInt32 startFrames = destStartOffset + size;
-        SInt32 endFrames   = startFrames + destEndSize;
-
-        startFrames = std::max(startFrames, (SInt32)0);
-        endFrames   = std::min((UInt32)endFrames, nFrames);
-
-                ZeroABL(abl, startFrames * mBytesPerFrame, (endFrames - startFrames) * mBytesPerFrame);
-        }
-
-        Byte **buffers = mBuffers;
-        int offset0 = FrameOffset(startRead);
-        int offset1 = FrameOffset(endRead);
-        int nbytes;
-
-        if (offset0 <= offset1) {
-                FetchABL(abl, destStartOffset, buffers, offset0, nbytes = offset1 - offset0);
-        } else {
-                nbytes = mCapacityBytes - offset0;
-                FetchABL(abl, destStartOffset, buffers, offset0, nbytes);
-                FetchABL(abl, destStartOffset + nbytes, buffers, 0, offset1);
-                nbytes += offset1;
-        }
-
-        int nchannels = abl->mNumberBuffers;
-        AudioBuffer *dest = abl->mBuffers;
-        while (--nchannels >= 0)
-        {
-                dest->mDataByteSize = nbytes;
-                dest++;
-        }
-
-        return noErr;
-}
--- a/src/macosx/native/com/sun/media/sound/CARingBuffer.h	Thu Dec 22 11:05:51 2011 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,126 +0,0 @@
-/*      Copyright � 2007 Apple Inc. All Rights Reserved.
-
-        Disclaimer: IMPORTANT:  This Apple software is supplied to you by
-                        Apple Inc. ("Apple") in consideration of your agreement to the
-                        following terms, and your use, installation, modification or
-                        redistribution of this Apple software constitutes acceptance of these
-                        terms.  If you do not agree with these terms, please do not use,
-                        install, modify or redistribute this Apple software.
-
-                        In consideration of your agreement to abide by the following terms, and
-                        subject to these terms, Apple grants you a personal, non-exclusive
-                        license, under Apple's copyrights in this original Apple software (the
-                        "Apple Software"), to use, reproduce, modify and redistribute the Apple
-                        Software, with or without modifications, in source and/or binary forms;
-                        provided that if you redistribute the Apple Software in its entirety and
-                        without modifications, you must retain this notice and the following
-                        text and disclaimers in all such redistributions of the Apple Software.
-                        Neither the name, trademarks, service marks or logos of Apple Inc.
-                        may be used to endorse or promote products derived from the Apple
-                        Software without specific prior written permission from Apple.  Except
-                        as expressly stated in this notice, no other rights or licenses, express
-                        or implied, are granted by Apple herein, including but not limited to
-                        any patent rights that may be infringed by your derivative works or by
-                        other works in which the Apple Software may be incorporated.
-
-                        The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
-                        MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
-                        THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
-                        FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
-                        OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
-
-                        IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
-                        OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-                        SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-                        INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
-                        MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
-                        AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
-                        STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
-                        POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/*
- This is an imported copy of /Developer/Extras/Public/Utility/CARingBuffer.cpp,
- as found in Mac OS X 10.7.
- */
-
-#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
-        #include <CoreAudio/CoreAudioTypes.h>
-#else
-        #include <CoreAudioTypes.h>
-#endif
-
-
-#ifndef CARingBuffer_Header
-#define CARingBuffer_Header
-
-enum {
-        kCARingBufferError_OK = 0,
-        kCARingBufferError_TooMuch = 3, // fetch start time is earlier than buffer start time and fetch end time is later than buffer end time
-        kCARingBufferError_CPUOverload = 4 // the reader is unable to get enough CPU cycles to capture a consistent snapshot of the time bounds
-};
-
-typedef SInt32 CARingBufferError;
-
-const UInt32 kGeneralRingTimeBoundsQueueSize = 32;
-const UInt32 kGeneralRingTimeBoundsQueueMask = kGeneralRingTimeBoundsQueueSize - 1;
-
-class CARingBuffer {
-public:
-        typedef SInt64 SampleTime;
-
-        CARingBuffer();
-        ~CARingBuffer();
-
-        void                                    Allocate(int nChannels, UInt32 bytesPerFrame, UInt32 capacityFrames);
-                                                                // capacityFrames will be rounded up to a power of 2
-        void                                    Deallocate();
-
-        CARingBufferError       Store(const AudioBufferList *abl, UInt32 nFrames, SampleTime frameNumber);
-                                                        // Copy nFrames of data into the ring buffer at the specified sample time.
-                                                        // The sample time should normally increase sequentially, though gaps
-                                                        // are filled with zeroes. A sufficiently large gap effectively empties
-                                                        // the buffer before storing the new data.
-
-                                                        // If frameNumber is less than the previous frame number, the behavior is undefined.
-
-                                                        // Return false for failure (buffer not large enough).
-
-        CARingBufferError       Fetch(AudioBufferList *abl, UInt32 nFrames, SampleTime frameNumber);
-                                                                // will alter mNumDataBytes of the buffers
-
-        CARingBufferError       GetTimeBounds(SampleTime &startTime, SampleTime &endTime);
-
-protected:
-
-        int                                             FrameOffset(SampleTime frameNumber) { return (frameNumber & mCapacityFramesMask) * mBytesPerFrame; }
-
-        CARingBufferError               ClipTimeBounds(SampleTime& startRead, SampleTime& endRead);
-
-        // these should only be called from Store.
-        SampleTime                              StartTime() const { return mTimeBoundsQueue[mTimeBoundsQueuePtr & kGeneralRingTimeBoundsQueueMask].mStartTime; }
-        SampleTime                              EndTime()   const { return mTimeBoundsQueue[mTimeBoundsQueuePtr & kGeneralRingTimeBoundsQueueMask].mEndTime; }
-        void                                    SetTimeBounds(SampleTime startTime, SampleTime endTime);
-
-protected:
-        Byte **                                 mBuffers;                               // allocated in one chunk of memory
-        int                                             mNumberChannels;
-        UInt32                                  mBytesPerFrame;                 // within one deinterleaved channel
-        UInt32                                  mCapacityFrames;                // per channel, must be a power of 2
-        UInt32                                  mCapacityFramesMask;
-        UInt32                                  mCapacityBytes;                 // per channel
-
-        // range of valid sample time in the buffer
-        typedef struct {
-                volatile SampleTime             mStartTime;
-                volatile SampleTime             mEndTime;
-                volatile UInt32                 mUpdateCounter;
-        } TimeBounds;
-
-        CARingBuffer::TimeBounds mTimeBoundsQueue[kGeneralRingTimeBoundsQueueSize];
-        UInt32 mTimeBoundsQueuePtr;
-};
-
-
-
-#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/macosx/native/com/sun/media/sound/PLATFORM_API_MacOSX_MidiIn.c	Fri Dec 23 22:01:01 2011 +0300
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+//#define USE_ERROR
+//#define USE_TRACE
+
+#if USE_PLATFORM_MIDI_IN == TRUE
+
+#include "PLATFORM_API_MacOSX_MidiUtils.h"
+
+char* MIDI_IN_GetErrorStr(INT32 err) {
+    return (char *) MIDI_Utils_GetErrorMsg((int) err);
+}
+
+
+INT32 MIDI_IN_GetNumDevices() {
+    return MIDI_Utils_GetNumDevices(MIDI_IN);
+}
+
+
+INT32 MIDI_IN_GetDeviceName(INT32 deviceID, char *name, UINT32 nameLength) {
+    return MIDI_Utils_GetDeviceName(MIDI_IN, deviceID, name, nameLength);
+}
+
+
+INT32 MIDI_IN_GetDeviceVendor(INT32 deviceID, char *name, UINT32 nameLength) {
+    return MIDI_Utils_GetDeviceVendor(MIDI_IN, deviceID, name, nameLength);
+}
+
+
+INT32 MIDI_IN_GetDeviceDescription(INT32 deviceID, char *name, UINT32 nameLength) {
+    return MIDI_Utils_GetDeviceDescription(MIDI_IN, deviceID, name, nameLength);
+}
+
+
+INT32 MIDI_IN_GetDeviceVersion(INT32 deviceID, char *name, UINT32 nameLength) {
+    return MIDI_Utils_GetDeviceVersion(MIDI_IN, deviceID, name, nameLength);
+}
+
+
+INT32 MIDI_IN_OpenDevice(INT32 deviceID, MidiDeviceHandle** handle) {
+    TRACE0("MIDI_IN_OpenDevice\n");
+    return
+        MIDI_Utils_OpenDevice(MIDI_IN, deviceID, (MacMidiDeviceHandle**) handle,
+                              MIDI_IN_MESSAGE_QUEUE_SIZE,
+                              MIDI_IN_LONG_QUEUE_SIZE,
+                              MIDI_IN_LONG_MESSAGE_SIZE);
+}
+
+
+INT32 MIDI_IN_CloseDevice(MidiDeviceHandle* handle) {
+    TRACE0("MIDI_IN_CloseDevice\n");
+    return MIDI_Utils_CloseDevice((MacMidiDeviceHandle*) handle);
+}
+
+
+INT32 MIDI_IN_StartDevice(MidiDeviceHandle* handle) {
+    TRACE0("MIDI_IN_StartDevice\n");
+    return MIDI_Utils_StartDevice((MacMidiDeviceHandle*) handle);
+}
+
+
+INT32 MIDI_IN_StopDevice(MidiDeviceHandle* handle) {
+    TRACE0("MIDI_IN_StopDevice\n");
+    return MIDI_Utils_StopDevice((MacMidiDeviceHandle*) handle);
+}
+
+INT64 MIDI_IN_GetTimeStamp(MidiDeviceHandle* handle) {
+    return MIDI_Utils_GetTimeStamp((MacMidiDeviceHandle*) handle);
+}
+
+
+/* read the next message from the queue */
+MidiMessage* MIDI_IN_GetMessage(MidiDeviceHandle* handle) {
+    if (handle == NULL) {
+        return NULL;
+    }
+    while (handle->queue != NULL && handle->platformData != NULL) {
+        MidiMessage* msg = MIDI_QueueRead(handle->queue);
+        if (msg != NULL) {
+            //fprintf(stdout, "GetMessage returns index %d\n", msg->data.l.index); fflush(stdout);
+            return msg;
+        }
+        TRACE0("MIDI_IN_GetMessage: before waiting\n");
+        handle->isWaiting = TRUE;
+        MIDI_WaitOnConditionVariable(handle->platformData, handle->queue->lock);
+        handle->isWaiting = FALSE;
+        TRACE0("MIDI_IN_GetMessage: waiting finished\n");
+    }
+    return NULL;
+}
+
+
+void MIDI_IN_ReleaseMessage(MidiDeviceHandle* handle, MidiMessage* msg) {
+    if (handle == NULL || handle->queue == NULL) {
+        return;
+    }
+    MIDI_QueueRemove(handle->queue, TRUE /*onlyLocked*/);
+}
+
+#endif /* USE_PLATFORM_MIDI_IN */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/macosx/native/com/sun/media/sound/PLATFORM_API_MacOSX_MidiOut.c	Fri Dec 23 22:01:01 2011 +0300
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+//#define USE_ERROR
+//#define USE_TRACE
+
+#if USE_PLATFORM_MIDI_OUT == TRUE
+
+#include "PLATFORM_API_MacOSX_MidiUtils.h"
+
+char* MIDI_OUT_GetErrorStr(INT32 err) {
+    return (char *) MIDI_Utils_GetErrorMsg((int) err);
+}
+
+
+INT32 MIDI_OUT_GetNumDevices() {
+    return MIDI_Utils_GetNumDevices(MIDI_OUT);
+}
+
+
+INT32 MIDI_OUT_GetDeviceName(INT32 deviceID, char *name, UINT32 nameLength) {
+    return MIDI_Utils_GetDeviceName(MIDI_OUT, deviceID, name, nameLength);
+}
+
+
+INT32 MIDI_OUT_GetDeviceVendor(INT32 deviceID, char *name, UINT32 nameLength) {
+    return MIDI_Utils_GetDeviceVendor(MIDI_OUT, deviceID, name, nameLength);
+}
+
+
+INT32 MIDI_OUT_GetDeviceDescription(INT32 deviceID, char *name, UINT32 nameLength) {
+    return MIDI_Utils_GetDeviceDescription(MIDI_OUT, deviceID, name, nameLength);
+}
+
+
+INT32 MIDI_OUT_GetDeviceVersion(INT32 deviceID, char *name, UINT32 nameLength) {
+    return MIDI_Utils_GetDeviceVersion(MIDI_OUT, deviceID, name, nameLength);
+}
+
+
+/* *************************** MidiOutDevice implementation ***************************************** */
+
+INT32 MIDI_OUT_OpenDevice(INT32 deviceID, MidiDeviceHandle** handle) {
+    TRACE1("MIDI_OUT_OpenDevice: deviceID: %d\n", (int) deviceID);
+    /* queue sizes are ignored for MIDI_OUT only (uses STREAMS) */
+    return MIDI_Utils_OpenDevice(MIDI_OUT, deviceID, (MacMidiDeviceHandle**) handle, 0, 0, 0);
+}
+
+INT32 MIDI_OUT_CloseDevice(MidiDeviceHandle* handle) {
+    TRACE0("MIDI_OUT_CloseDevice\n");
+
+    // issue a "SUSTAIN OFF" message to each MIDI channel, 0 to 15.
+    // "CONTROL CHANGE" is 176, "SUSTAIN CONTROLLER" is 64, and the value is 0.
+    // $$fb 2002-04-04: It is responsability of the application developer to
+    // leave the device in a consistent state. So I put this in comments
+    /*
+      for (channel = 0; channel < 16; channel++)
+      MIDI_OUT_SendShortMessage(deviceHandle, (unsigned char)(176 + channel),
+      (unsigned char)64, (unsigned char)0, (UINT32)-1);
+    */
+    return MIDI_Utils_CloseDevice((MacMidiDeviceHandle*) handle);
+}
+
+
+INT64 MIDI_OUT_GetTimeStamp(MidiDeviceHandle* handle) {
+    return MIDI_Utils_GetTimeStamp((MacMidiDeviceHandle*) handle);
+}
+
+
+INT32 MIDI_OUT_SendShortMessage(MidiDeviceHandle* handle, UINT32 packedMsg, UINT32 timestamp) {
+    OSStatus err = noErr;
+
+    TRACE2("> MIDI_OUT_SendShortMessage %x, time: %d\n", (uint) packedMsg, (int) timestamp);
+    if (!handle) {
+        ERROR0("< ERROR: MIDI_OUT_SendShortMessage: handle is NULL\n");
+        return MIDI_INVALID_HANDLE;
+    }
+
+    MacMidiDeviceHandle* macHandle = (MacMidiDeviceHandle*) handle;
+    UInt8 mBuffers[100];
+    MIDIPacketList* packetList = (MIDIPacketList*) mBuffers;
+    MIDIPacket* packet;
+    UINT32 nData;
+    Byte data[3] = {packedMsg & 0xFF, (packedMsg >> 8) & 0xFF, (packedMsg >> 16) & 0xFF};
+    bool byteIsInvalid = FALSE;
+
+    packet = MIDIPacketListInit(packetList);
+    switch (data[0] & 0xF0) {
+        case 0x80:    // Note off
+        case 0x90:    // Note on
+        case 0xA0:    // Aftertouch
+        case 0xB0:    // Controller
+        case 0xE0:    // Pitch wheel
+            nData = 3;
+            break;
+
+        case 0xC0:    // Program change
+        case 0xD0:    // Channel pressure
+            nData = 2;
+            break;
+
+        case 0xF0: {
+            // System common message
+            switch (data[0]) {
+                case 0xF0:
+                case 0xF7:
+                    // System exclusive
+                    fprintf(stderr, "%s: %d->internal error: sysex message status=0x%X while sending short message\n",
+                            __FILE__, __LINE__, data[0]);
+                    byteIsInvalid = TRUE;
+                    break;
+
+                case 0xF1:    // MTC quarter frame message
+                    //fprintf(stderr, ">>>MIDI_OUT_SendShortMessage: MTC quarter frame message....\n");
+                    nData = 2;
+                    break;
+                case 0xF3:    // Song select
+                    //fprintf(stderr, ">>>MIDI_OUT_SendShortMessage: Song select....\n");
+                    nData = 2;
+                    break;
+
+                case 0xF2:    // Song position pointer
+                    //fprintf(stderr, ">>>MIDI_OUT_SendShortMessage: Song position pointer....\n");
+                    nData = 3;
+                    break;
+
+                case 0xF6:    // Tune request
+                    //fprintf(stderr, ">>>MIDI_OUT_SendShortMessage: Tune request....\n");
+                    nData = 1;
+                    break;
+
+                default:
+                    // Invalid message
+                    fprintf(stderr, "%s: %d->Invalid message: message status=0x%X while sending short message\n",
+                            __FILE__, __LINE__, data[0]);
+                    byteIsInvalid = TRUE;
+                    break;
+            }
+            break;
+        }
+
+        default:
+            // This can't happen, but handle it anyway.
+            fprintf(stderr, "%s: %d->Invalid message: message status=0x%X while sending short message\n",
+                    __FILE__, __LINE__, data[0]);
+            byteIsInvalid = TRUE;
+            break;
+    }
+
+    if (byteIsInvalid) return -1;
+
+    MIDIPacketListAdd(packetList, sizeof(mBuffers), packet, 0, nData, data);
+    err = MIDISend(macHandle->port, (MIDIEndpointRef) (intptr_t) handle->deviceHandle, packetList);
+
+    MIDI_CHECK_ERROR;
+    TRACE0("< MIDI_OUT_SendShortMessage\n");
+    return (err == noErr ? MIDI_SUCCESS : -1);
+}
+
+
+INT32 MIDI_OUT_SendLongMessage(MidiDeviceHandle* handle, UBYTE* data, UINT32 size, UINT32 timestamp) {
+    OSStatus err = noErr;
+
+    TRACE2("> MIDI_OUT_SendLongMessage size %d, time: %d\n", (int) size, (int) timestamp);
+    if (!handle || !data) {
+        ERROR0("< ERROR: MIDI_OUT_SendLongMessage: handle, or data is NULL\n");
+        return MIDI_INVALID_HANDLE;
+    }
+    if (size == 0) {
+        return MIDI_SUCCESS;
+    }
+
+    MacMidiDeviceHandle* macHandle = (MacMidiDeviceHandle*) handle;
+    UInt8 mBuffers[8196];
+    MIDIPacketList* packetList = (MIDIPacketList*) mBuffers;
+    MIDIPacket* packet = NULL;
+    UINT32 remaining = size;
+    UINT32 increment = 512;
+    UINT32 nData;
+
+    handle->isWaiting = TRUE;
+
+    while (remaining > 0) {
+
+        if (packet == NULL) {
+            packet = MIDIPacketListInit(packetList);
+        }
+
+        if (remaining > increment) {
+            nData = increment;
+        } else {
+            nData = remaining;
+        }
+
+        // Copies the bytes to our current packet.
+        if ((packet = MIDIPacketListAdd(packetList, sizeof(mBuffers), packet, 0, nData, (const Byte*) data)) == NULL) {
+            // Packet list is full, send it.
+            err = MIDISend(macHandle->port, (MIDIEndpointRef) (intptr_t) handle->deviceHandle, packetList);
+            if (err != noErr) {
+                break;
+            }
+        } else {
+            // Moves the data pointer to the next segment.
+            data += nData;
+            remaining -= nData;
+            packet = MIDIPacketNext(packet);
+        }
+    }
+
+    MIDI_CHECK_ERROR;
+    handle->isWaiting = FALSE;
+    TRACE0("< MIDI_OUT_SendLongMessage\n");
+    return (err == noErr ? MIDI_SUCCESS : -1);
+}
+
+#endif /* USE_PLATFORM_MIDI_OUT */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/macosx/native/com/sun/media/sound/PLATFORM_API_MacOSX_MidiUtils.c	Fri Dec 23 22:01:01 2011 +0300
@@ -0,0 +1,702 @@
+/*
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+**
+**    Overview:
+**      Implementation of the functions used for both MIDI in and MIDI out.
+**
+**      Java package com.sun.media.sound defines the AbstractMidiDevice class
+**      which encapsulates functionalities shared by both MidiInDevice and
+**      MidiOutDevice classes in the same package.
+**
+**      The Java layer classes MidiInDevice and MidiOutDevice in turn map to
+**      the MIDIEndpointRef data type in the CoreMIDI framework, which
+**      represents a source or destination for a standard 16-channel MIDI data
+**      stream.
+*/
+/*****************************************************************************/
+
+//#define USE_ERROR
+//#define USE_TRACE
+
+#if (USE_PLATFORM_MIDI_IN == TRUE) || (USE_PLATFORM_MIDI_OUT == TRUE)
+
+#include "PLATFORM_API_MacOSX_MidiUtils.h"
+#include <pthread.h>
+#include <assert.h>
+
+// Constant character string definitions of CoreMIDI's corresponding error codes.
+
+static const char* strMIDIInvalidClient =
+                        "An invalid MIDIClientRef was passed.";
+static const char* strMIDIInvalidPort =
+                        "An invalid MIDIPortRef was passed.";
+static const char* strMIDIWrongEndpointType =
+                        "A source endpoint was passed to a function expecting a destination, or vice versa.";
+static const char* strMIDINoConnection =
+                        "Attempt to close a non-existant connection.";
+static const char* strMIDIUnknownEndpoint =
+                        "An invalid MIDIEndpointRef was passed.";
+static const char* strMIDIUnknownProperty =
+                        "Attempt to query a property not set on the object.";
+static const char* strMIDIWrongPropertyType =
+                        "Attempt to set a property with a value not of the correct type.";
+static const char* strMIDINoCurrentSetup =
+                        "Internal error; there is no current MIDI setup object.";
+static const char* strMIDIMessageSendErr =
+                        "Communication with MIDIServer failed.";
+static const char* strMIDIServerStartErr =
+                        "Unable to start MIDIServer.";
+static const char* strMIDISetupFormatErr =
+                        "Unable to read the saved state.";
+static const char* strMIDIWrongThread =
+                        "A driver is calling a non-I/O function in the server from a thread other than"
+                        "the server's main thread.";
+static const char* strMIDIObjectNotFound =
+                        "The requested object does not exist.";
+static const char* strMIDIIDNotUnique =
+                        "Attempt to set a non-unique kMIDIPropertyUniqueID on an object.";
+
+static const char* midi_strerror(int err) {
+/*
+    @enum           Error Constants
+    @abstract       The error constants unique to Core MIDI.
+    @discussion     These are the error constants that are unique to Core MIDI. Note that Core MIDI
+                    functions may return other codes that are not listed here.
+*/
+    const char* strerr;
+
+    switch (err) {
+    case kMIDIInvalidClient:
+        strerr = strMIDIInvalidClient;
+        break;
+    case kMIDIInvalidPort:
+        strerr = strMIDIInvalidPort;
+        break;
+    case kMIDIWrongEndpointType:
+        strerr = strMIDIWrongEndpointType;
+        break;
+    case kMIDINoConnection:
+        strerr = strMIDINoConnection;
+        break;
+    case kMIDIUnknownEndpoint:
+        strerr = strMIDIUnknownEndpoint;
+        break;
+    case kMIDIUnknownProperty:
+        strerr = strMIDIUnknownProperty;
+        break;
+    case kMIDIWrongPropertyType:
+        strerr = strMIDIWrongPropertyType;
+        break;
+    case kMIDINoCurrentSetup:
+        strerr = strMIDINoCurrentSetup;
+        break;
+    case kMIDIMessageSendErr:
+        strerr = strMIDIMessageSendErr;
+        break;
+    case kMIDIServerStartErr:
+        strerr = strMIDIServerStartErr;
+        break;
+    case kMIDISetupFormatErr:
+        strerr = strMIDISetupFormatErr;
+        break;
+    case kMIDIWrongThread:
+        strerr = strMIDIWrongThread;
+        break;
+    case kMIDIObjectNotFound:
+        strerr = strMIDIObjectNotFound;
+        break;
+    case kMIDIIDNotUnique:
+        strerr = strMIDIIDNotUnique;
+        break;
+    default:
+        strerr = "Unknown error.";
+        break;
+    }
+    return strerr;
+}
+
+const char* MIDI_Utils_GetErrorMsg(int err) {
+    return midi_strerror(err);
+}
+
+
+void MIDI_Utils_PrintError(int err) {
+#ifdef USE_ERROR
+    const char* s = MIDI_Utils_GetErrorMsg(err);
+    if (s != NULL) {
+        fprintf(stderr, "%s\n", s);
+    }
+#endif
+}
+
+
+// Note direction is either MIDI_IN or MIDI_OUT.
+INT32 MIDI_Utils_GetNumDevices(int direction) {
+    int num_endpoints;
+    if (direction == MIDI_IN) {
+        num_endpoints = MIDIGetNumberOfSources();
+    //fprintf(stdout, "MIDIGetNumberOfSources() returns %d\n", num_endpoints);
+    } else if (direction == MIDI_OUT) {
+        num_endpoints = MIDIGetNumberOfDestinations();
+        //printf(stdout, "MIDIGetNumberOfDestinations() returns %d\n", num_endpoints);
+    } else {
+        assert((direction == MIDI_IN || direction == MIDI_OUT));
+        num_endpoints = 0;
+    }
+    return (INT32) num_endpoints;
+}
+
+// Wraps calls to CFStringGetCStringPtr and CFStringGetCString to make sure
+// we extract the c characters into the buffer and null-terminate it.
+static void CFStringExtractCString(CFStringRef cfs, char* buffer, UINT32 bufferSize, CFStringEncoding encoding) {
+    const char* ptr = CFStringGetCStringPtr(cfs, encoding);
+    if (ptr) {
+        strlcpy(buffer, ptr, bufferSize);
+    } else {
+        if (! CFStringGetCString(cfs, buffer, bufferSize, encoding)) {
+            // There's an error in conversion, make sure we null-terminate the buffer.
+            buffer[bufferSize - 1] = '\0';
+        }
+    }
+}
+
+//
+// @see com.sun.media.sound.AbstractMidiDeviceProvider.getDeviceInfo().
+static int getEndpointProperty(int direction, INT32 deviceID, char *buffer, int bufferLength, CFStringRef propertyID) {
+
+    if (deviceID < 0) {
+        return MIDI_INVALID_DEVICEID;
+    }
+
+    MIDIEndpointRef endpoint;
+
+    if (direction == MIDI_IN) {
+        endpoint = MIDIGetSource(deviceID);
+    } else if (direction == MIDI_OUT) {
+        endpoint = MIDIGetDestination(deviceID);
+    } else {
+        return MIDI_INVALID_ARGUMENT;
+    }
+
+    if (!endpoint) {
+        return MIDI_INVALID_DEVICEID;
+    }
+
+    int status = MIDI_SUCCESS;
+    if (propertyID == kMIDIPropertyDriverVersion) {
+        SInt32 driverVersion;
+        status = MIDIObjectGetIntegerProperty(endpoint, kMIDIPropertyDriverVersion, &driverVersion);
+        if (status != MIDI_SUCCESS) return status;
+        snprintf(buffer,
+                 bufferLength,
+                 "%d",
+                 (int) driverVersion);
+    }
+    else {
+        CFStringRef pname;
+        status = MIDIObjectGetStringProperty(endpoint, propertyID, &pname);
+        if (status != MIDI_SUCCESS) return status;
+        CFStringExtractCString(pname, buffer, bufferLength, 0);
+    }
+    return MIDI_ERROR_NONE;
+}
+
+// A simple utility which encapsulates CoreAudio's HostTime APIs.
+// It returns the current host time in nanoseconds which when subtracted from
+// a previous getCurrentTimeInNanos() result produces the delta in nanos.
+static UInt64 getCurrentTimeInNanos() {
+    UInt64 hostTime = AudioGetCurrentHostTime();
+    UInt64 nanos = AudioConvertHostTimeToNanos(hostTime);
+    return nanos;
+}
+
+
+INT32 MIDI_Utils_GetDeviceName(int direction, INT32 deviceID, char *name, UINT32 bufferLength) {
+    return getEndpointProperty(direction, deviceID, name, bufferLength, kMIDIPropertyName);
+}
+
+
+INT32 MIDI_Utils_GetDeviceVendor(int direction, INT32 deviceID, char *name, UINT32 bufferLength) {
+    return getEndpointProperty(direction, deviceID, name, bufferLength, kMIDIPropertyManufacturer);
+}
+
+
+INT32 MIDI_Utils_GetDeviceDescription(int direction, INT32 deviceID, char *name, UINT32 bufferLength) {
+    return getEndpointProperty(direction, deviceID, name, bufferLength, kMIDIPropertyDisplayName);
+}
+
+
+INT32 MIDI_Utils_GetDeviceVersion(int direction, INT32 deviceID, char *name, UINT32 bufferLength) {
+    return getEndpointProperty(direction, deviceID, name, bufferLength, kMIDIPropertyDriverVersion);
+}
+
+
+static MIDIClientRef client = (MIDIClientRef) NULL;
+static MIDIPortRef inPort = (MIDIPortRef) NULL;
+static MIDIPortRef outPort = (MIDIPortRef) NULL;
+
+// Each MIDIPacket can contain more than one midi messages.
+// This function processes the packet and adds the messages to the specified message queue.
+// @see also src/share/native/com/sun/media/sound/PlatformMidi.h.
+static void processMessagesForPacket(const MIDIPacket* packet, MacMidiDeviceHandle* handle) {
+    const UInt8* data;
+    UInt16 length;
+    UInt8 byte;
+    UInt8 pendingMessageStatus;
+    UInt8 pendingData[2];
+    UInt16 pendingDataIndex, pendingDataLength;
+    UINT32 packedMsg;
+    MIDITimeStamp ts = packet->timeStamp;
+
+    pendingMessageStatus = 0;
+    pendingDataIndex = pendingDataLength = 0;
+
+    data = packet->data;
+    length = packet->length;
+    while (length--) {
+        bool byteIsInvalid = FALSE;
+
+        byte = *data++;
+        packedMsg = byte;
+
+        if (byte >= 0xF8) {
+            // Each RealTime Category message (ie, Status of 0xF8 to 0xFF) consists of only 1 byte, the Status.
+            // Except that 0xFD is an invalid status code.
+            //
+            // 0xF8 -> Midi clock
+            // 0xF9 -> Midi tick
+            // 0xFA -> Midi start
+            // 0xFB -> Midi continue
+            // 0xFC -> Midi stop
+            // 0xFE -> Active sense
+            // 0xFF -> Reset
+            if (byte == 0xFD) {
+                byteIsInvalid = TRUE;
+            } else {
+                pendingDataLength = 0;
+            }
+        } else {
+            if (byte < 0x80) {
+                // Not a status byte -- check our history.
+                if (handle->readingSysExData) {
+                    CFDataAppendBytes(handle->readingSysExData, &byte, 1);
+
+                } else if (pendingDataIndex < pendingDataLength) {
+                    pendingData[pendingDataIndex] = byte;
+                    pendingDataIndex++;
+
+                    if (pendingDataIndex == pendingDataLength) {
+                        // This message is now done -- do the final processing.
+                        if (pendingDataLength == 2) {
+                            packedMsg = pendingMessageStatus | pendingData[0] << 8 | pendingData[1] << 16;
+                        } else if (pendingDataLength == 1) {
+                            packedMsg = pendingMessageStatus | pendingData[0] << 8;
+                        } else {
+                            fprintf(stderr, "%s: %d->internal error: pendingMessageStatus=0x%X, pendingDataLength=%d\n",
+                                    __FILE__, __LINE__, pendingMessageStatus, pendingDataLength);
+                            byteIsInvalid = TRUE;
+                        }
+                        pendingDataLength = 0;
+                    }
+                } else {
+                    // Skip this byte -- it is invalid.
+                    byteIsInvalid = TRUE;
+                }
+            } else {
+                if (handle->readingSysExData /* && (byte == 0xF7) */) {
+                    // We have reached the end of system exclusive message -- send it finally.
+                    const UInt8* bytes = CFDataGetBytePtr(handle->readingSysExData);
+                    CFIndex size = CFDataGetLength(handle->readingSysExData);
+                    MIDI_QueueAddLong(handle->h.queue,
+                                      (UBYTE*) bytes,
+                                      (UINT32) size,
+                                      0, // Don't care, windowish porting only.
+                                      (INT64) (AudioConvertHostTimeToNanos(ts) + 500) / 1000,
+                                      TRUE);
+                    CFRelease(handle->readingSysExData);
+                    handle->readingSysExData = NULL;
+                }
+
+                pendingMessageStatus = byte;
+                pendingDataLength = 0;
+                pendingDataIndex = 0;
+
+                switch (byte & 0xF0) {
+                    case 0x80:    // Note off
+                    case 0x90:    // Note on
+                    case 0xA0:    // Aftertouch
+                    case 0xB0:    // Controller
+                    case 0xE0:    // Pitch wheel
+                        pendingDataLength = 2;
+                        break;
+
+                    case 0xC0:    // Program change
+                    case 0xD0:    // Channel pressure
+                        pendingDataLength = 1;
+                        break;
+
+                    case 0xF0: {
+                        // System common message
+                        switch (byte) {
+                        case 0xF0:
+                            // System exclusive
+                            // Allocates a CFMutableData reference to accumulate the SysEx data until EOX (0xF7) is reached.
+                            handle->readingSysExData = CFDataCreateMutable(NULL, 0);
+                            break;
+
+                        case 0xF7:
+                            // System exclusive ends--already handled above.
+                            // But if this is showing up outside of sysex, it's invalid.
+                            byteIsInvalid = TRUE;
+                            break;
+
+                        case 0xF1:    // MTC quarter frame message
+                        case 0xF3:    // Song select
+                            pendingDataLength = 1;
+                            break;
+
+                        case 0xF2:    // Song position pointer
+                            pendingDataLength = 2;
+                            break;
+
+                        case 0xF6:    // Tune request
+                            pendingDataLength = 0;
+                            break;
+
+                        default:
+                            // Invalid message
+                            byteIsInvalid = TRUE;
+                            break;
+                        }
+                        break;
+                    }
+
+                    default:
+                        // This can't happen, but handle it anyway.
+                        byteIsInvalid = TRUE;
+                        break;
+                }
+            }
+        }
+        if (byteIsInvalid) continue;
+
+        // If the byte is valid and pendingDataLength is 0, we are ready to send the message.
+        if (pendingDataLength == 0) {
+            MIDI_QueueAddShort(handle->h.queue, packedMsg, (INT64) (AudioConvertHostTimeToNanos(ts) + 500) / 1000, TRUE);
+        }
+    }
+}
+
+static void midiReadProc(const MIDIPacketList* packetList, void* refCon, void* connRefCon) {
+    unsigned int i;
+    const MIDIPacket* packet;
+    MacMidiDeviceHandle* handle = (MacMidiDeviceHandle*) connRefCon;
+
+    packet = packetList->packet;
+    for (i = 0; i < packetList->numPackets; ++i) {
+        processMessagesForPacket(packet, handle);
+        packet = MIDIPacketNext(packet);
+    }
+
+    // Notify the waiting thread that there's data available.
+    if (handle) {
+        MIDI_SignalConditionVariable(handle->h.platformData);
+    }
+}
+
+static void midiInit() {
+    if (client) {
+        return;
+    }
+
+    OSStatus err = noErr;
+
+    err = MIDIClientCreate(CFSTR("MIDI Client"), NULL, NULL, &client);
+    if (err != noErr) { goto Exit; }
+
+    // This just creates an input port through which the client may receive
+    // incoming MIDI messages from any MIDI source.
+    err = MIDIInputPortCreate(client, CFSTR("MIDI Input Port"), midiReadProc, NULL, &inPort);
+    if (err != noErr) { goto Exit; }
+
+    err = MIDIOutputPortCreate(client, CFSTR("MIDI Output Port"), &outPort);
+    if (err != noErr) { goto Exit; }
+
+Exit:
+    if (err != noErr) {
+        const char* s = MIDI_Utils_GetErrorMsg(err);
+        if (s != NULL) {
+            printf("%s\n", s);
+        }
+    }
+}
+
+
+INT32 MIDI_Utils_OpenDevice(int direction, INT32 deviceID, MacMidiDeviceHandle** handle,
+                            int num_msgs, int num_long_msgs,
+                            size_t lm_size)
+{
+    midiInit();
+
+    int err = MIDI_ERROR_NONE;
+    MIDIEndpointRef endpoint = (MIDIEndpointRef) NULL;
+
+    TRACE0("MIDI_Utils_OpenDevice\n");
+
+    (*handle) = (MacMidiDeviceHandle*) malloc(sizeof(MacMidiDeviceHandle));
+    if (!(*handle)) {
+        ERROR0("ERROR: MIDI_Utils_OpenDevice: out of memory\n");
+        return MIDI_OUT_OF_MEMORY;
+    }
+    memset(*handle, 0, sizeof(MacMidiDeviceHandle));
+
+    // Create the infrastructure for MIDI in/out, and after that,
+    // get the device's endpoint.
+    if (direction == MIDI_IN) {
+        // Create queue and the pthread condition variable.
+        (*handle)->h.queue = MIDI_CreateQueue(num_msgs);
+        (*handle)->h.platformData = MIDI_CreateConditionVariable();
+        if (!(*handle)->h.queue || !(*handle)->h.platformData) {
+            ERROR0("< ERROR: MIDI_IN_OpenDevice: could not create queue or condition variable\n");
+            free(*handle);
+            (*handle) = NULL;
+            return MIDI_OUT_OF_MEMORY;
+        }
+        endpoint = MIDIGetSource(deviceID);
+        (*handle)->port = inPort;
+    } else if (direction == MIDI_OUT) {
+        endpoint = MIDIGetDestination(deviceID);
+        (*handle)->port = outPort;
+    }
+
+    if (!endpoint) {
+        // An error occurred.
+        free(*handle);
+        return MIDI_INVALID_DEVICEID;
+    }
+    (*handle)->h.deviceHandle = (void*) (intptr_t) endpoint;
+    (*handle)->h.startTime = getCurrentTimeInNanos();
+    (*handle)->direction = direction;
+    (*handle)->deviceID = deviceID;
+
+    TRACE0("MIDI_Utils_OpenDevice: succeeded\n");
+    return err;
+}
+
+
+INT32 MIDI_Utils_CloseDevice(MacMidiDeviceHandle* handle) {
+    int err = MIDI_ERROR_NONE;
+    bool midiIn = (handle->direction == MIDI_IN);
+
+    TRACE0("> MIDI_Utils_CloseDevice\n");
+    if (!handle) {
+        ERROR0("< ERROR: MIDI_Utils_CloseDevice: handle is NULL\n");
+        return MIDI_INVALID_HANDLE;
+    }
+    if (!handle->h.deviceHandle) {
+        ERROR0("< ERROR: MIDI_Utils_CloseDevice: native handle is NULL\n");
+        return MIDI_INVALID_HANDLE;
+    }
+    handle->isStarted = FALSE;
+    handle->h.deviceHandle = NULL;
+
+    if (midiIn) {
+        if (handle->h.queue != NULL) {
+            MidiMessageQueue* queue = handle->h.queue;
+            handle->h.queue = NULL;
+            MIDI_DestroyQueue(queue);
+        }
+        if (handle->h.platformData) {
+            MIDI_DestroyConditionVariable(handle->h.platformData);
+        }
+    }
+    free(handle);
+
+    TRACE0("< MIDI_Utils_CloseDevice: succeeded\n");
+    return err;
+}
+
+
+INT32 MIDI_Utils_StartDevice(MacMidiDeviceHandle* handle) {
+    OSStatus err = noErr;
+
+    if (!handle || !handle->h.deviceHandle) {
+        ERROR0("ERROR: MIDI_Utils_StartDevice: handle or native is NULL\n");
+        return MIDI_INVALID_HANDLE;
+    }
+
+    // Clears all the events from the queue.
+    MIDI_QueueClear(handle->h.queue);
+
+    if (!handle->isStarted) {
+        /* set the flag that we can now receive messages */
+        handle->isStarted = TRUE;
+
+        if (handle->direction == MIDI_IN) {
+            // The handle->h.platformData field contains the (pthread_cond_t*)
+            // associated with the source of the MIDI input stream, and is
+            // used in the CoreMIDI's callback to signal the arrival of new
+            // data.
+            //
+            // Similarly, handle->h.queue is used in the CoreMDID's callback
+            // to dispatch the incoming messages to the appropriate queue.
+            //
+            err = MIDIPortConnectSource(inPort, (MIDIEndpointRef) (intptr_t) (handle->h.deviceHandle), (void*) handle);
+        } else if (handle->direction == MIDI_OUT) {
+            // Unschedules previous-sent packets.
+            err = MIDIFlushOutput((MIDIEndpointRef) (intptr_t) handle->h.deviceHandle);
+        }
+
+        MIDI_CHECK_ERROR;
+    }
+    return MIDI_SUCCESS; /* don't fail */
+}
+
+
+INT32 MIDI_Utils_StopDevice(MacMidiDeviceHandle* handle) {
+    OSStatus err = noErr;
+
+    if (!handle || !handle->h.deviceHandle) {
+        ERROR0("ERROR: MIDI_Utils_StopDevice: handle or native handle is NULL\n");
+        return MIDI_INVALID_HANDLE;
+    }
+
+    if (handle->isStarted) {
+        /* set the flag that we don't want to receive messages anymore */
+        handle->isStarted = FALSE;
+
+        if (handle->direction == MIDI_IN) {
+            err = MIDIPortDisconnectSource(inPort, (MIDIEndpointRef) (intptr_t) (handle->h.deviceHandle));
+        } else if (handle->direction == MIDI_OUT) {
+            // Unschedules previously-sent packets.
+            err = MIDIFlushOutput((MIDIEndpointRef) (intptr_t) handle->h.deviceHandle);
+        }
+
+        MIDI_CHECK_ERROR;
+    }
+    return MIDI_SUCCESS;
+}
+
+
+INT64 MIDI_Utils_GetTimeStamp(MacMidiDeviceHandle* handle) {
+
+    if (!handle || !handle->h.deviceHandle) {
+        ERROR0("ERROR: MIDI_Utils_GetTimeStamp: handle or native handle is NULL\n");
+        return (INT64) -1; /* failure */
+    }
+
+    UInt64 delta = getCurrentTimeInNanos() - handle->h.startTime;
+    return (INT64) ((delta + 500) / 1000);
+}
+
+
+/***************************************************************************/
+/*            Condition Variable Support for Mac OS X Port                 */
+/*                                                                         */
+/* This works with the Native Locking Support defined below.  We are using */
+/* POSIX pthread_cond_t/pthread_mutex_t to do locking and synchronization. */
+/*                                                                         */
+/* For MidiDeviceHandle* handle, the mutex reference is stored as handle-> */
+/* queue->lock while the condition variabale reference is stored as handle */
+/* ->platformData.                                                         */
+/***************************************************************************/
+
+// Called from Midi_Utils_Opendevice(...) to create a condition variable
+// used to synchronize between the receive thread created by the CoreMIDI
+// and the Java-initiated MidiInDevice run loop.
+void* MIDI_CreateConditionVariable() {
+    pthread_cond_t* cond = (pthread_cond_t*) malloc(sizeof(pthread_cond_t));
+    pthread_cond_init(cond, NULL);
+    return (void*) cond;
+}
+
+void MIDI_DestroyConditionVariable(void* cond) {
+    while (pthread_cond_destroy((pthread_cond_t*) cond) == EBUSY) {
+        pthread_cond_broadcast((pthread_cond_t*) cond);
+        sched_yield();
+    }
+    return;
+}
+
+// Called from MIDI_IN_GetMessage(...) to wait for MIDI messages to become
+// available via delivery from the CoreMIDI receive thread
+void MIDI_WaitOnConditionVariable(void* cond, void* lock) {
+    if (cond && lock) {
+        pthread_mutex_lock(lock);
+        pthread_cond_wait((pthread_cond_t*) cond, (pthread_mutex_t*) lock);
+        pthread_mutex_unlock(lock);
+    }
+    return;
+}
+
+// Called from midiReadProc(...) to notify the waiting thread to unblock on
+// the condition variable.
+void MIDI_SignalConditionVariable(void* cond) {
+    if (cond) {
+        pthread_cond_signal((pthread_cond_t*) cond);
+    }
+    return;
+}
+
+
+/**************************************************************************/
+/*                     Native Locking Support                             */
+/*                                                                        */
+/* @see src/share/natve/com/sun/media/sound/PlatformMidi.c which contains */
+/* utility functions for platform midi support where the section of code  */
+/* for MessageQueue implementation calls out to these functions.          */
+/**************************************************************************/
+
+void* MIDI_CreateLock() {
+    pthread_mutex_t* lock = (pthread_mutex_t*) malloc(sizeof(pthread_mutex_t));
+    pthread_mutex_init(lock, NULL);
+    TRACE0("MIDI_CreateLock\n");
+    return (void *)lock;
+}
+
+void MIDI_DestroyLock(void* lock) {
+    if (lock) {
+        pthread_mutex_destroy((pthread_mutex_t*) lock);
+        free(lock);
+        TRACE0("MIDI_DestroyLock\n");
+    }
+}
+
+void MIDI_Lock(void* lock) {
+    if (lock) {
+        pthread_mutex_lock((pthread_mutex_t*) lock);
+    }
+}
+
+void MIDI_Unlock(void* lock) {
+    if (lock) {
+        pthread_mutex_unlock((pthread_mutex_t*) lock);
+    }
+}
+
+
+#endif // USE_PLATFORM_MIDI_IN || USE_PLATFORM_MIDI_OUT
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/macosx/native/com/sun/media/sound/PLATFORM_API_MacOSX_MidiUtils.h	Fri Dec 23 22:01:01 2011 +0300
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#if (USE_PLATFORM_MIDI_IN == TRUE) || (USE_PLATFORM_MIDI_OUT == TRUE)
+
+#include "PlatformMidi.h"                  // JavaSound header for platform midi support.
+#include <CoreMIDI/CoreMIDI.h>             // Umbrella header for the CoreMIDI framework.
+#include <CoreAudio/CoreAudio.h>           // This provides access to the host's time base and translations to nanoseconds.
+#include <CoreFoundation/CoreFoundation.h> // CFDataRef.
+
+/* for memcpy */
+#include <string.h>
+/* for malloc */
+#include <stdlib.h>
+/* for usleep */
+#include <unistd.h>
+
+#ifdef USE_ERROR
+#include <stdio.h>
+#endif
+
+#define MIDI_ERROR_NONE MIDI_SUCCESS
+
+#ifdef USE_ERROR
+#define MIDI_CHECK_ERROR  { if (err != MIDI_ERROR_NONE) MIDI_Utils_PrintError(err); }
+#else
+#define MIDI_CHECK_ERROR
+#endif
+
+typedef struct {
+    MidiDeviceHandle h;                  /* the real handle (must be the first field!) */
+    int direction;                       /* direction of the endpoint */
+    int deviceID;                        /* logical index (0 .. numEndpoints-1) */
+    int isStarted;                       /* whether device is "started" */
+    MIDIPortRef port;                    /* input or output port associated with the endpoint */
+    CFMutableDataRef readingSysExData;   /* Non-Null: in the middle of reading SysEx data; Null: otherwise */
+} MacMidiDeviceHandle;
+
+extern const char* MIDI_Utils_GetErrorMsg(int err);
+extern void MIDI_Utils_PrintError(int err);
+
+// A MIDI endpoint represents a source or a destination for a standard 16-channel MIDI data stream.
+enum {
+    MIDI_IN = 0, // source
+    MIDI_OUT = 1 // destination
+};
+
+// The parameter "direction" is either MIDI_IN or MIDI_OUT.
+// Declarations of functions required by the JavaSound MIDI Porting layer.
+
+extern INT32 MIDI_Utils_GetNumDevices(int direction);
+extern INT32 MIDI_Utils_GetDeviceName(int direction, INT32 deviceID, char *name, UINT32 nameLength);
+extern INT32 MIDI_Utils_GetDeviceVendor(int direction, INT32 deviceID, char *name, UINT32 nameLength);
+extern INT32 MIDI_Utils_GetDeviceDescription(int direction, INT32 deviceID, char *name, UINT32 nameLength);
+extern INT32 MIDI_Utils_GetDeviceVersion(int direction, INT32 deviceID, char *name, UINT32 nameLength);
+extern INT32 MIDI_Utils_OpenDevice(int direction, INT32 deviceID, MacMidiDeviceHandle** handle,
+                   int num_msgs, int num_long_msgs,
+                   size_t lm_size);
+extern INT32 MIDI_Utils_CloseDevice(MacMidiDeviceHandle* handle);
+extern INT32 MIDI_Utils_StartDevice(MacMidiDeviceHandle* handle);
+extern INT32 MIDI_Utils_StopDevice(MacMidiDeviceHandle* handle);
+extern INT64 MIDI_Utils_GetTimeStamp(MacMidiDeviceHandle* handle);
+
+// Mac OS X port for locking and synchronization.
+
+extern void* MIDI_CreateConditionVariable();
+extern void  MIDI_DestroyConditionVariable(void* cond);
+extern void  MIDI_WaitOnConditionVariable(void* cond, void* lock);
+extern void  MIDI_SignalConditionVariable(void* cond);
+
+#endif // USE_PLATFORM_MIDI_IN || USE_PLATFORM_MIDI_OUT
--- a/src/macosx/native/com/sun/media/sound/PLATFORM_API_MacOSX_PCM.cpp	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/native/com/sun/media/sound/PLATFORM_API_MacOSX_PCM.cpp	Fri Dec 23 22:01:01 2011 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,147 +25,404 @@
 
 //#define USE_ERROR
 //#define USE_TRACE
+//#define USE_VERBOSE_TRACE
 
 #include <AudioUnit/AudioUnit.h>
 #include <CoreServices/CoreServices.h>
-#include <CoreAudio/CoreAudio.h>
-#include <libkern/OSAtomic.h>
-#include <algorithm>
+#include <pthread.h>
+/*
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+#include <CoreAudio/CoreAudioTypes.h>
+#else
+#include <CoreAudioTypes.h>
+#endif
+*/
 
-#include <CABitOperations.h>
-#include "CARingBuffer.h"
+#include "PLATFORM_API_MacOSX_Utils.h"
 
 extern "C" {
+#include "Utilities.h"
 #include "DirectAudio.h"
-#include "PLATFORM_API_MacOSX_Utils.h"
 }
 
 #if USE_DAUDIO == TRUE
 
-typedef struct OSXDirectAudioDevice {
-    AudioUnit    unit;
-    CARingBuffer buffer;
-    AudioStreamBasicDescription asbd;
-    SInt64       lastReadSampleTime;
-    int          bufferSizeInFrames;
 
-    int        inputBufferSize;
-    pthread_mutex_t inputMutex;
-    pthread_cond_t  inputCond;
-    int             isDraining;
+#ifdef USE_TRACE
+static void PrintStreamDesc(AudioStreamBasicDescription *inDesc) {
+    TRACE4("ID='%c%c%c%c'", (char)(inDesc->mFormatID >> 24), (char)(inDesc->mFormatID >> 16), (char)(inDesc->mFormatID >> 8), (char)(inDesc->mFormatID));
+    TRACE2(", %f Hz, flags=0x%lX", (float)inDesc->mSampleRate, (long unsigned)inDesc->mFormatFlags);
+    TRACE2(", %ld channels, %ld bits", (long)inDesc->mChannelsPerFrame, (long)inDesc->mBitsPerChannel);
+    TRACE1(", %ld bytes per frame\n", (long)inDesc->mBytesPerFrame);
+}
+#else
+static inline void PrintStreamDesc(AudioStreamBasicDescription *inDesc) { }
+#endif
 
-    OSXDirectAudioDevice() : unit(NULL), asbd(), lastReadSampleTime(0), bufferSizeInFrames(0),
-                             inputMutex((pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER), inputCond((pthread_cond_t)PTHREAD_COND_INITIALIZER),
-                             isDraining(0) {}
 
-    ~OSXDirectAudioDevice() {
-        pthread_cond_destroy(&inputCond);
-        pthread_mutex_destroy(&inputMutex);
-        buffer.Deallocate();
-        CloseComponent(unit);
-    }
-} OSXDirectAudioDevice;
+#define MAX(x, y)   ((x) >= (y) ? (x) : (y))
+#define MIN(x, y)   ((x) <= (y) ? (x) : (y))
+
+
+// =======================================
+// MixerProvider functions implementation
+
+static DeviceList deviceCache;
 
 INT32 DAUDIO_GetDirectAudioDeviceCount() {
-    int count = 1 + GetAudioDeviceCount();
-    TRACE1("< DAUDIO_GetDirectAudioDeviceCount = %d\n", count);
-
+    deviceCache.Refresh();
+    int count = deviceCache.GetCount();
+    if (count > 0) {
+        // add "default" device
+        count++;
+        TRACE1("DAUDIO_GetDirectAudioDeviceCount: returns %d devices\n", count);
+    } else {
+        TRACE0("DAUDIO_GetDirectAudioDeviceCount: no devices found\n");
+    }
     return count;
 }
 
-INT32 DAUDIO_GetDirectAudioDeviceDescription(INT32 mixerIndex, DirectAudioDeviceDescription* daudioDescription) {
-    AudioDeviceDescription description;
-
-    description.strLen = DAUDIO_STRING_LENGTH;
-    description.name   = daudioDescription->name;
-    description.vendor = daudioDescription->vendor;
-    description.description = daudioDescription->description;
-
-    /*
-     We can't fill out the version field.
-     */
-
-    int err = GetAudioDeviceDescription(mixerIndex - 1, &description);
-
-    daudioDescription->deviceID = description.deviceID;
-    daudioDescription->maxSimulLines = description.numInputStreams + description.numOutputStreams;
-
-    TRACE1("< DAUDIO_GetDirectAudioDeviceDescription = %d lines\n", (int)daudioDescription->maxSimulLines);
-
-    return err == noErr;
+INT32 DAUDIO_GetDirectAudioDeviceDescription(INT32 mixerIndex, DirectAudioDeviceDescription *desc) {
+    bool result = true;
+    desc->deviceID = 0;
+    if (mixerIndex == 0) {
+        // default device
+        strncpy(desc->name, "Default Audio Device", DAUDIO_STRING_LENGTH);
+        strncpy(desc->description, "Default Audio Device", DAUDIO_STRING_LENGTH);
+        desc->maxSimulLines = -1;
+    } else {
+        AudioDeviceID deviceID;
+        result = deviceCache.GetDeviceInfo(mixerIndex-1, &deviceID, DAUDIO_STRING_LENGTH,
+            desc->name, desc->vendor, desc->description, desc->version);
+        if (result) {
+            desc->deviceID = (INT32)deviceID;
+            desc->maxSimulLines = -1;
+        }
+    }
+    return result ? TRUE : FALSE;
 }
 
-/*
- Philosophical differences here -
-
- Sample rate -
- Audio Output Unit has a current sample rate, but will accept any sample rate for output.
- For input, the sample rate of the unit must be the current hardware sample rate.
- It is possible for the user to change this, but there is no way to notify Java of it
- happening, so this is not handled.
-
- Integer format -
- Core Audio uses floats. Audio Output Unit will accept anything.
- The best Direct Audio can do is 16-bit signed.
- */
 
 void DAUDIO_GetFormats(INT32 mixerIndex, INT32 deviceID, int isSource, void* creator) {
-        TRACE3("> DAUDIO_GetFormats mixer=%d deviceID=%#x isSource=%d\n", (int)mixerIndex, (int)deviceID, isSource);
-    AudioDeviceDescription description = {0};
-    OSStatus err = noErr;
-    Float64 sampleRate;
-    int numStreams, numChannels;
-    UInt32 size;
+    TRACE3(">>DAUDIO_GetFormats mixerIndex=%d deviceID=0x%x isSource=%d\n", (int)mixerIndex, (int)deviceID, isSource);
 
-    GetAudioDeviceDescription(mixerIndex - 1, &description);
+    AudioDeviceID audioDeviceID = deviceID == 0 ? GetDefaultDevice(isSource) : (AudioDeviceID)deviceID;
 
-    numChannels = isSource ? description.numOutputChannels : description.numInputChannels;
-
-    int channels[] = {1, 2, numChannels};
-    int i;
-
-    numStreams = isSource ? description.numOutputStreams : description.numInputStreams;
-
-    if (numStreams == 0) {
-        goto exit;
+    if (audioDeviceID == 0) {
+        return;
     }
 
-    /*
-     For output, register 16-bit for any sample rate with either 1ch/2ch.
-     For input, we must use the real sample rate.
-     */
+    int totalChannels = GetChannelCount(audioDeviceID, isSource);
 
-    int maxChannelIndex;
-
-    if (!isSource && numChannels == 1)
-        maxChannelIndex = 0;
-    else if (numChannels <= 2)
-        maxChannelIndex = 1;
-    else
-        maxChannelIndex = 2;
-
-    sampleRate = isSource ? -1 : description.inputSampleRate;
-
-    for (i = 0; i <= maxChannelIndex; i++) {
-        DAUDIO_AddAudioFormat(creator,
-                              16,           /* 16-bit */
-                              -1,           /* frame size (auto) */
-                              channels[i],  /* channels */
-                              sampleRate,   /* sample rate (any for output) */
-                              DAUDIO_PCM,   /* only accept PCM */
-                              1,            /* signed (for 16-bit) */
-                              BYTE_ORDER == BIG_ENDIAN);
+    if (totalChannels == 0) {
+        TRACE0("<<DAUDIO_GetFormats, no streams!\n");
+        return;
     }
 
-exit:
-    if (err) {
-        ERROR1("DAUDIO_GetFormats err %.4s\n", &err);
+    if (isSource && totalChannels < 2) {
+        // report 2 channels even if only mono is supported
+        totalChannels = 2;
     }
+
+    int channels[] = {1, 2, totalChannels};
+    int channelsCount = MIN(totalChannels, 3);
+
+    float hardwareSampleRate = GetSampleRate(audioDeviceID, isSource);
+    TRACE2("  DAUDIO_GetFormats: got %d channels, sampleRate == %f\n", totalChannels, hardwareSampleRate);
+
+    // target lines support only current sample rate!
+    float sampleRate = isSource ? -1 : hardwareSampleRate;
+
+    static int sampleBits[] = {8, 16, 24};
+    static int sampleBitsCount = sizeof(sampleBits)/sizeof(sampleBits[0]);
+
+    // the last audio format is the default one (used by DataLine.open() if format is not specified)
+    // consider as default 16bit PCM stereo (mono is stereo is not supported) with the current sample rate
+    int defBits = 16;
+    int defChannels = MIN(2, channelsCount);
+    float defSampleRate = hardwareSampleRate;
+    // don't add default format is sample rate is not specified
+    bool addDefault = defSampleRate > 0;
+
+    // TODO: CoreAudio can handle signed/unsigned, little-endian/big-endian
+    // TODO: register the formats (to prevent DirectAudio software conversion) - need to fix DirectAudioDevice.createDataLineInfo
+    // to avoid software conversions if both signed/unsigned or big-/little-endian are supported
+    for (int channelIndex = 0; channelIndex < channelsCount; channelIndex++) {
+        for (int bitIndex = 0; bitIndex < sampleBitsCount; bitIndex++) {
+            int bits = sampleBits[bitIndex];
+            if (addDefault && bits == defBits && channels[channelIndex] != defChannels && sampleRate == defSampleRate) {
+                // the format is the default one, don't add it now
+                continue;
+            }
+            DAUDIO_AddAudioFormat(creator,
+                bits,                       // sample size in bits
+                -1,                         // frame size (auto)
+                channels[channelIndex],     // channels
+                sampleRate,                 // sample rate
+                DAUDIO_PCM,                 // only accept PCM
+                bits == 8 ? FALSE : TRUE,   // signed
+                bits == 8 ? FALSE           // little-endian for 8bit
+                    : UTIL_IsBigEndianPlatform());
+        }
+    }
+    // add default format
+    if (addDefault) {
+        DAUDIO_AddAudioFormat(creator,
+            defBits,                        // 16 bits
+            -1,                             // automatically calculate frame size
+            defChannels,                    // channels
+            defSampleRate,                  // sample rate
+            DAUDIO_PCM,                     // PCM
+            TRUE,                           // signed
+            UTIL_IsBigEndianPlatform());    // native endianess
+    }
+
+    TRACE0("<<DAUDIO_GetFormats\n");
 }
 
+
+// =======================================
+// Source/Target DataLine functions implementation
+
+// ====
+/* 1writer-1reader ring buffer class with flush() support */
+class RingBuffer {
+public:
+    RingBuffer() : pBuffer(NULL), nBufferSize(0) {
+        pthread_mutex_init(&lockMutex, NULL);
+    }
+    ~RingBuffer() {
+        Deallocate();
+        pthread_mutex_destroy(&lockMutex);
+    }
+
+    // extraBytes: number of additionally allocated bytes to prevent data
+    // overlapping when almost whole buffer is filled
+    // (required only if Write() can override the buffer)
+    bool Allocate(int requestedBufferSize, int extraBytes) {
+        int fullBufferSize = requestedBufferSize + extraBytes;
+        int powerOfTwo = 1;
+        while (powerOfTwo < fullBufferSize) {
+            powerOfTwo <<= 1;
+        }
+        pBuffer = (Byte*)malloc(powerOfTwo);
+        if (pBuffer == NULL) {
+            ERROR0("RingBuffer::Allocate: OUT OF MEMORY\n");
+            return false;
+        }
+
+        nBufferSize = requestedBufferSize;
+        nAllocatedBytes = powerOfTwo;
+        nPosMask = powerOfTwo - 1;
+        nWritePos = 0;
+        nReadPos = 0;
+        nFlushPos = -1;
+
+        TRACE2("RingBuffer::Allocate: OK, bufferSize=%d, allocated:%d\n", nBufferSize, nAllocatedBytes);
+        return true;
+    }
+
+    void Deallocate() {
+        if (pBuffer) {
+            free(pBuffer);
+            pBuffer = NULL;
+            nBufferSize = 0;
+        }
+    }
+
+    inline int GetBufferSize() {
+        return nBufferSize;
+    }
+
+    inline int GetAllocatedSize() {
+        return nAllocatedBytes;
+    }
+
+    // gets number of bytes available for reading
+    int GetValidByteCount() {
+        lock();
+        INT64 result = nWritePos - (nFlushPos >= 0 ? nFlushPos : nReadPos);
+        unlock();
+        return result > (INT64)nBufferSize ? nBufferSize : (int)result;
+    }
+
+    int Write(void *srcBuffer, int len, bool preventOverflow) {
+        lock();
+        TRACE2("RingBuffer::Write (%d bytes, preventOverflow=%d)\n", len, preventOverflow ? 1 : 0);
+        TRACE2("  writePos = %lld (%d)", (long long)nWritePos, Pos2Offset(nWritePos));
+        TRACE2("  readPos=%lld (%d)", (long long)nReadPos, Pos2Offset(nReadPos));
+        TRACE2("  flushPos=%lld (%d)\n", (long long)nFlushPos, Pos2Offset(nFlushPos));
+
+        INT64 writePos = nWritePos;
+        if (preventOverflow) {
+            INT64 avail_read = writePos - (nFlushPos >= 0 ? nFlushPos : nReadPos);
+            if (avail_read >= (INT64)nBufferSize) {
+                // no space
+                TRACE0("  preventOverlow: OVERFLOW => len = 0;\n");
+                len = 0;
+            } else {
+                int avail_write = nBufferSize - (int)avail_read;
+                if (len > avail_write) {
+                    TRACE2("  preventOverlow: desrease len: %d => %d\n", len, avail_write);
+                    len = avail_write;
+                }
+            }
+        }
+        unlock();
+
+        if (len > 0) {
+
+            write((Byte *)srcBuffer, Pos2Offset(writePos), len);
+
+            lock();
+            TRACE4("--RingBuffer::Write writePos: %lld (%d) => %lld, (%d)\n",
+                (long long)nWritePos, Pos2Offset(nWritePos), (long long)nWritePos + len, Pos2Offset(nWritePos + len));
+            nWritePos += len;
+            unlock();
+        }
+        return len;
+    }
+
+    int Read(void *dstBuffer, int len) {
+        lock();
+        TRACE1("RingBuffer::Read (%d bytes)\n", len);
+        TRACE2("  writePos = %lld (%d)", (long long)nWritePos, Pos2Offset(nWritePos));
+        TRACE2("  readPos=%lld (%d)", (long long)nReadPos, Pos2Offset(nReadPos));
+        TRACE2("  flushPos=%lld (%d)\n", (long long)nFlushPos, Pos2Offset(nFlushPos));
+
+        applyFlush();
+        INT64 avail_read = nWritePos - nReadPos;
+        // check for overflow
+        if (avail_read > (INT64)nBufferSize) {
+            nReadPos = nWritePos - nBufferSize;
+            avail_read = nBufferSize;
+            TRACE0("  OVERFLOW\n");
+        }
+        INT64 readPos = nReadPos;
+        unlock();
+
+        if (len > (int)avail_read) {
+            TRACE2("  RingBuffer::Read - don't have enough data, len: %d => %d\n", len, (int)avail_read);
+            len = (int)avail_read;
+        }
+
+        if (len > 0) {
+
+            read((Byte *)dstBuffer, Pos2Offset(readPos), len);
+
+            lock();
+            if (applyFlush()) {
+                // just got flush(), results became obsolete
+                TRACE0("--RingBuffer::Read, got Flush, return 0\n");
+                len = 0;
+            } else {
+                TRACE4("--RingBuffer::Read readPos: %lld (%d) => %lld (%d)\n",
+                    (long long)nReadPos, Pos2Offset(nReadPos), (long long)nReadPos + len, Pos2Offset(nReadPos + len));
+                nReadPos += len;
+            }
+            unlock();
+        } else {
+            // underrun!
+        }
+        return len;
+    }
+
+    // returns number of the flushed bytes
+    int Flush() {
+        lock();
+        INT64 flushedBytes = nWritePos - (nFlushPos >= 0 ? nFlushPos : nReadPos);
+        nFlushPos = nWritePos;
+        unlock();
+        return flushedBytes > (INT64)nBufferSize ? nBufferSize : (int)flushedBytes;
+    }
+
+private:
+    Byte *pBuffer;
+    int nBufferSize;
+    int nAllocatedBytes;
+    INT64 nPosMask;
+
+    pthread_mutex_t lockMutex;
+
+    volatile INT64 nWritePos;
+    volatile INT64 nReadPos;
+    // Flush() sets nFlushPos value to nWritePos;
+    // next Read() sets nReadPos to nFlushPos and resests nFlushPos to -1
+    volatile INT64 nFlushPos;
+
+    inline void lock() {
+        pthread_mutex_lock(&lockMutex);
+    }
+    inline void unlock() {
+        pthread_mutex_unlock(&lockMutex);
+    }
+
+    inline bool applyFlush() {
+        if (nFlushPos >= 0) {
+            nReadPos = nFlushPos;
+            nFlushPos = -1;
+            return true;
+        }
+        return false;
+    }
+
+    inline int Pos2Offset(INT64 pos) {
+        return (int)(pos & nPosMask);
+    }
+
+    void write(Byte *srcBuffer, int dstOffset, int len) {
+        int dstEndOffset = dstOffset + len;
+
+        int lenAfterWrap = dstEndOffset - nAllocatedBytes;
+        if (lenAfterWrap > 0) {
+            // dest.buffer does wrap
+            len = nAllocatedBytes - dstOffset;
+            memcpy(pBuffer+dstOffset, srcBuffer, len);
+            memcpy(pBuffer, srcBuffer+len, lenAfterWrap);
+        } else {
+            // dest.buffer does not wrap
+            memcpy(pBuffer+dstOffset, srcBuffer, len);
+        }
+    }
+
+    void read(Byte *dstBuffer, int srcOffset, int len) {
+        int srcEndOffset = srcOffset + len;
+
+        int lenAfterWrap = srcEndOffset - nAllocatedBytes;
+        if (lenAfterWrap > 0) {
+            // need to unwrap data
+            len = nAllocatedBytes - srcOffset;
+            memcpy(dstBuffer, pBuffer+srcOffset, len);
+            memcpy(dstBuffer+len, pBuffer, lenAfterWrap);
+        } else {
+            // source buffer is not wrapped
+            memcpy(dstBuffer, pBuffer+srcOffset, len);
+        }
+    }
+};
+
+
+struct OSX_DirectAudioDevice {
+    AudioUnit   audioUnit;
+    RingBuffer  ringBuffer;
+    AudioStreamBasicDescription asbd;
+
+    // only for target lines
+    UInt32      inputBufferSizeInBytes;
+
+    OSX_DirectAudioDevice() : audioUnit(NULL), asbd() {
+    }
+
+    ~OSX_DirectAudioDevice() {
+        if (audioUnit) {
+            CloseComponent(audioUnit);
+        }
+    }
+};
+
 static AudioUnit CreateOutputUnit(AudioDeviceID deviceID, int isSource)
 {
-    OSStatus err = noErr;
+    OSStatus err;
     AudioUnit unit;
     UInt32 size;
 
@@ -180,133 +437,117 @@
         err = OpenAComponent(comp, &unit);
 
     if (err) {
-        ERROR1("OpenComponent err %d\n", err);
-        goto exit;
+        OS_ERROR0(err, "CreateOutputUnit:OpenAComponent");
+        return NULL;
     }
 
     if (!isSource) {
         int enableIO = 0;
         err = AudioUnitSetProperty(unit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output,
-                             0, &enableIO, sizeof(enableIO));
-        if (err) ERROR1("SetProperty 1 err %d\n", err);
+                                    0, &enableIO, sizeof(enableIO));
+        if (err) {
+            OS_ERROR0(err, "SetProperty (output EnableIO)");
+        }
         enableIO = 1;
         err = AudioUnitSetProperty(unit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input,
-                             1, &enableIO, sizeof(enableIO));
-        if (err) ERROR1("SetProperty 2 err %d\n", err);
+                                    1, &enableIO, sizeof(enableIO));
+        if (err) {
+            OS_ERROR0(err, "SetProperty (input EnableIO)");
+        }
+
+        if (!deviceID) {
+            // get real AudioDeviceID for default input device (macosx current input device)
+            deviceID = GetDefaultDevice(isSource);
+            if (!deviceID) {
+                CloseComponent(unit);
+                return NULL;
+            }
+        }
     }
 
-    if (deviceID || !isSource) {
-        UInt32 inputDeviceID;
-
-        /* There is no "default input unit", so get the current input device. */
-        GetAudioObjectProperty(kAudioObjectSystemObject, kAudioObjectPropertyScopeGlobal, kAudioHardwarePropertyDefaultInputDevice,
-                               sizeof(inputDeviceID), &inputDeviceID, 1);
-
+    if (deviceID) {
         err = AudioUnitSetProperty(unit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global,
-                                   0, deviceID ? &deviceID : &inputDeviceID, sizeof(deviceID));
+                                    0, &deviceID, sizeof(deviceID));
         if (err) {
-            ERROR1("SetProperty 3 err %d\n", err);
-            goto exit;
+            OS_ERROR0(err, "SetProperty (CurrentDevice)");
+            CloseComponent(unit);
+            return NULL;
         }
     }
 
     return unit;
-
-exit:
-
-    if (unit)
-        CloseComponent(unit);
-
-    return NULL;
 }
 
-static void ClearAudioBufferList(AudioBufferList *list, int start, int end, int sampleSize)
+static OSStatus OutputCallback(void                         *inRefCon,
+                               AudioUnitRenderActionFlags   *ioActionFlags,
+                               const AudioTimeStamp         *inTimeStamp,
+                               UInt32                       inBusNumber,
+                               UInt32                       inNumberFrames,
+                               AudioBufferList              *ioData)
 {
-    for (int channel = 0; channel < list->mNumberBuffers; channel++)
-        memset((char*)list->mBuffers[channel].mData + start*sampleSize, 0, (end - start)*sampleSize);
-}
+    OSX_DirectAudioDevice *device = (OSX_DirectAudioDevice*)inRefCon;
 
-static OSStatus AudioOutputCallback(void                    *inRefCon,
-                             AudioUnitRenderActionFlags         *ioActionFlags,
-                             const AudioTimeStamp           *inTimeStamp,
-                             UInt32                                             inBusNumber,
-                             UInt32                                             inNumberFrames,
-                             AudioBufferList                *ioData)
-{
-    OSXDirectAudioDevice *device = (OSXDirectAudioDevice*)inRefCon;
-    CARingBufferError err;
+    int nchannels = ioData->mNumberBuffers; // should be always == 1 (interleaved channels)
+    AudioBuffer *audioBuffer = ioData->mBuffers;
 
-    SInt64 readTime = device->lastReadSampleTime;
-    SInt64 startTime, endTime;
-    int underran = 0;
-    err = device->buffer.GetTimeBounds(startTime, endTime);
+    TRACE3(">>OutputCallback: busNum=%d, requested %d frames (%d bytes)\n",
+        (int)inBusNumber, (int)inNumberFrames, (int)(inNumberFrames * device->asbd.mBytesPerFrame));
+    TRACE3("  abl: %d buffers, buffer[0].channels=%d, buffer.size=%d\n",
+        nchannels, (int)audioBuffer->mNumberChannels, (int)audioBuffer->mDataByteSize);
 
-    if (err) goto exit;
-    if (endTime < readTime) goto exit; // endTime can go backwards upon DAUDIO_Flush
-    if (readTime + inNumberFrames >= endTime) {
-        ClearAudioBufferList(ioData, endTime - readTime, inNumberFrames, device->asbd.mBytesPerFrame);
-        inNumberFrames = endTime - readTime;
-        underran = 1;
+    int bytesToRead = inNumberFrames * device->asbd.mBytesPerFrame;
+    if (bytesToRead > (int)audioBuffer->mDataByteSize) {
+        TRACE0("--OutputCallback: !!! audioBuffer IS TOO SMALL!!!\n");
+        bytesToRead = audioBuffer->mDataByteSize / device->asbd.mBytesPerFrame * device->asbd.mBytesPerFrame;
+    }
+    int bytesRead = device->ringBuffer.Read(audioBuffer->mData, bytesToRead);
+    if (bytesRead < bytesToRead) {
+        // no enough data (underrun)
+        TRACE2("--OutputCallback: !!! UNDERRUN (read %d bytes of %d)!!!\n", bytesRead, bytesToRead);
+        // silence the rest
+        memset((Byte*)audioBuffer->mData + bytesRead, 0, bytesToRead-bytesRead);
+        bytesRead = bytesToRead;
     }
 
-    err = device->buffer.Fetch(ioData, inNumberFrames, readTime);
+    audioBuffer->mDataByteSize = (UInt32)bytesRead;
+    // SAFETY: set mDataByteSize for all other AudioBuffer in the AudioBufferList to zero
+    while (--nchannels > 0) {
+        audioBuffer++;
+        audioBuffer->mDataByteSize = 0;
+    }
+    TRACE1("<<OutputCallback (returns %d)\n", bytesRead);
 
-    if (err) goto exit;
-
-    if (underran) {
-        TRACE4("< Underrun, only fetched %d frames (%lld %lld %lld)\n", inNumberFrames, startTime, readTime, endTime);
-    }
-
-    OSAtomicCompareAndSwap64Barrier(readTime, readTime + inNumberFrames, &device->lastReadSampleTime);
-
-    return noErr;
-
-exit:
-    ClearAudioBufferList(ioData, 0, inNumberFrames, device->asbd.mBytesPerFrame);
     return noErr;
 }
 
-static OSStatus AudioInputCallback(void                    *inRefCon,
-                            AudioUnitRenderActionFlags     *ioActionFlags,
-                            const AudioTimeStamp           *inTimeStamp,
-                            UInt32                         inBusNumber,
-                            UInt32                         inNumberFrames,
-                            AudioBufferList                *ioData)
+static OSStatus InputCallback(void                          *inRefCon,
+                              AudioUnitRenderActionFlags    *ioActionFlags,
+                              const AudioTimeStamp          *inTimeStamp,
+                              UInt32                        inBusNumber,
+                              UInt32                        inNumberFrames,
+                              AudioBufferList               *ioData)
 {
-    OSXDirectAudioDevice *device = (OSXDirectAudioDevice*)inRefCon;
-    AudioBufferList abl;
-    SInt64 sampleTime = inTimeStamp->mSampleTime;
-    SInt64 startTime, endTime;
-    CARingBufferError err;
+    OSX_DirectAudioDevice *device = (OSX_DirectAudioDevice*)inRefCon;
 
-    if (device->isDraining) goto exit;
+    TRACE4(">>InputCallback: busNum=%d, timeStamp=%lld, %d frames (%d bytes)\n",
+        (int)inBusNumber, (long long)inTimeStamp->mSampleTime, (int)inNumberFrames, (int)(inNumberFrames * device->asbd.mBytesPerFrame));
 
-    err = device->buffer.GetTimeBounds(startTime, endTime);
-    if (err) goto exit;
-
+    AudioBufferList abl;    // by default it contains 1 AudioBuffer
     abl.mNumberBuffers = 1;
     abl.mBuffers[0].mNumberChannels = device->asbd.mChannelsPerFrame;
-    abl.mBuffers[0].mDataByteSize   = device->inputBufferSize * device->asbd.mBytesPerFrame;
-    abl.mBuffers[0].mData           = NULL;
+    abl.mBuffers[0].mDataByteSize   = device->inputBufferSizeInBytes;   // assume this is == (inNumberFrames * device->asbd.mBytesPerFrame)
+    abl.mBuffers[0].mData           = NULL;     // request for the audioUnit's buffer
 
-    err = AudioUnitRender(device->unit, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, &abl);
+    // TODO: is it possible device->inputBufferSizeInBytes != inNumberFrames * device->asbd.mBytesPerFrame??
+
+    OSStatus err = AudioUnitRender(device->audioUnit, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, &abl);
     if (err) {
-        ERROR1("AudioUnitRender err %d\n", err);
-        goto exit;
+        OS_ERROR0(err, "<<InputCallback: AudioUnitRender");
+    } else {
+        int bytesWritten = device->ringBuffer.Write(abl.mBuffers[0].mData, (int)abl.mBuffers[0].mDataByteSize, false);
+        TRACE2("<<InputCallback (saved %d bytes of %d)\n", bytesWritten, (int)abl.mBuffers[0].mDataByteSize);
     }
 
-    err = device->buffer.Store(&abl, inNumberFrames, sampleTime);
-    if (err) goto exit;
-
-    pthread_cond_broadcast(&device->inputCond);
-
-    return noErr;
-
-exit:
-    device->isDraining = 1;
-
-    pthread_cond_broadcast(&device->inputCond);
-
     return noErr;
 }
 
@@ -315,254 +556,213 @@
                   int frameSize, int channels,
                   int isSigned, int isBigEndian, int bufferSizeInBytes)
 {
-        TRACE2("> DAUDIO_Open mixerIndex=%d deviceID=%#x\n", mixerIndex, deviceID);
+    TRACE3(">>DAUDIO_Open: mixerIndex=%d deviceID=0x%x isSource=%d\n", (int)mixerIndex, (unsigned int)deviceID, isSource);
+    TRACE3("  sampleRate=%d sampleSizeInBits=%d channels=%d\n", (int)sampleRate, sampleSizeInBits, channels);
+#ifdef USE_TRACE
+    {
+        AudioDeviceID audioDeviceID = deviceID;
+        if (audioDeviceID == 0) {
+            // default device
+            audioDeviceID = GetDefaultDevice(isSource);
+        }
+        char name[256];
+        OSStatus err = GetAudioObjectProperty(audioDeviceID, kAudioUnitScope_Global, kAudioDevicePropertyDeviceName, 256, &name, 0);
+        if (err != noErr) {
+            OS_ERROR1(err, "  audioDeviceID=0x%x, name is N/A:", (int)audioDeviceID);
+        } else {
+            TRACE2("  audioDeviceID=0x%x, name=%s\n", (int)audioDeviceID, name);
+        }
+    }
+#endif
+
+    if (encoding != DAUDIO_PCM) {
+        ERROR1("<<DAUDIO_Open: ERROR: unsupported encoding (%d)\n", encoding);
+        return NULL;
+    }
+
+    // TODO: for target lines we should ensure that sampleRate == current device sample rate
+    // (othewise we get error -10863 (kAudioUnitErr_CannotDoInCurrentContext in AUComponent.h) from AudioUnitRender(in InputCallback))
+
+    OSX_DirectAudioDevice *device = new OSX_DirectAudioDevice();
 
     AudioUnitScope scope = isSource ? kAudioUnitScope_Input : kAudioUnitScope_Output;
     int element = isSource ? 0 : 1;
-    OSXDirectAudioDevice *device = new OSXDirectAudioDevice;
-    int bufferSizeInFrames = bufferSizeInBytes / frameSize;
     OSStatus err = noErr;
+    int extraBufferBytes = 0;
 
-#ifdef USE_TRACE
-    if (deviceID) AudioObjectShow(deviceID);
-#endif
+    device->audioUnit = CreateOutputUnit(deviceID, isSource);
 
-    device->unit = CreateOutputUnit(deviceID, isSource);
-
-    if (!device->unit)
-        goto exit;
+    if (!device->audioUnit) {
+        delete device;
+        return NULL;
+    }
 
     FillOutASBDForLPCM(device->asbd, sampleRate, channels, sampleSizeInBits, sampleSizeInBits, 0, isBigEndian);
+    // Workaround for FillOutASBDForLPCM - it always set kAudioFormatFlagIsSignedInteger for non-float formats
+    if (!isSigned) {
+        device->asbd.mFormatFlags &= ~(UInt32)kAudioFormatFlagIsSignedInteger;
+    }
 
-    err = AudioUnitSetProperty(device->unit, kAudioUnitProperty_StreamFormat, scope, element, &device->asbd, sizeof(device->asbd));
+    err = AudioUnitSetProperty(device->audioUnit, kAudioUnitProperty_StreamFormat, scope, element, &device->asbd, sizeof(device->asbd));
     if (err) {
-        ERROR1("Setting stream format err %d\n", err);
-        goto exit;
+        OS_ERROR0(err, "<<DAUDIO_Open set StreamFormat");
+        delete device;
+        return NULL;
     }
 
     AURenderCallbackStruct output;
-    output.inputProc       = isSource ? AudioOutputCallback : AudioInputCallback;
+    output.inputProc       = isSource ? OutputCallback : InputCallback;
     output.inputProcRefCon = device;
 
-    err = AudioUnitSetProperty(device->unit, isSource ? kAudioUnitProperty_SetRenderCallback : kAudioOutputUnitProperty_SetInputCallback,
-                               kAudioUnitScope_Global, 0, &output, sizeof(output));
-    if (err) goto exit;
+    err = AudioUnitSetProperty(device->audioUnit,
+                                isSource
+                                    ? (AudioUnitPropertyID)kAudioUnitProperty_SetRenderCallback
+                                    : (AudioUnitPropertyID)kAudioOutputUnitProperty_SetInputCallback,
+                                kAudioUnitScope_Global, 0, &output, sizeof(output));
+    if (err) {
+        OS_ERROR0(err, "<<DAUDIO_Open set RenderCallback");
+        delete device;
+        return NULL;
+    }
 
-    err = AudioUnitInitialize(device->unit);
-    if (err) goto exit;
+    err = AudioUnitInitialize(device->audioUnit);
+    if (err) {
+        OS_ERROR0(err, "<<DAUDIO_Open UnitInitialize");
+        delete device;
+        return NULL;
+    }
 
     if (!isSource) {
+        // for target lines we need extra bytes in the buffer
+        // to prevent collisions when InputCallback overrides data on overflow
         UInt32 size;
         OSStatus err;
 
-        size = sizeof(device->inputBufferSize);
-        err  = AudioUnitGetProperty(device->unit, kAudioDevicePropertyBufferFrameSize, kAudioUnitScope_Global, 0, &device->inputBufferSize, &size);
+        size = sizeof(device->inputBufferSizeInBytes);
+        err  = AudioUnitGetProperty(device->audioUnit, kAudioDevicePropertyBufferFrameSize, kAudioUnitScope_Global,
+                                    0, &device->inputBufferSizeInBytes, &size);
+        if (err) {
+            OS_ERROR0(err, "<<DAUDIO_Open (TargetDataLine)GetBufferSize\n");
+            delete device;
+            return NULL;
+        }
+        device->inputBufferSizeInBytes *= device->asbd.mBytesPerFrame;  // convert frames by bytes
+        extraBufferBytes = (int)device->inputBufferSizeInBytes;
     }
 
-    device->buffer.Allocate(channels, frameSize, bufferSizeInFrames);
-    device->bufferSizeInFrames = NextPowerOfTwo(bufferSizeInFrames);
-
-    return device;
-
-exit:
-    if (err) {
-        ERROR1("DAUDIO_Open err %d\n", err);
+    if (!device->ringBuffer.Allocate(bufferSizeInBytes, extraBufferBytes)) {
+        ERROR0("<<DAUDIO_Open: Ring buffer allocation error\n");
+        delete device;
+        return NULL;
     }
 
-    delete device;
-    return NULL;
+    TRACE0("<<DAUDIO_Open: OK\n");
+    return device;
 }
 
 int DAUDIO_Start(void* id, int isSource) {
-    TRACE0("> DAUDIO_Start\n");
-    OSXDirectAudioDevice *device = (OSXDirectAudioDevice*)id;
-    OSStatus err;
+    OSX_DirectAudioDevice *device = (OSX_DirectAudioDevice*)id;
+    TRACE0("DAUDIO_Start\n");
 
-    device->isDraining = 0;
-    err = AudioOutputUnitStart(device->unit);
+    OSStatus err = AudioOutputUnitStart(device->audioUnit);
+
+    if (err != noErr) {
+        OS_ERROR0(err, "DAUDIO_Start");
+    }
 
     return err == noErr ? TRUE : FALSE;
 }
 
 int DAUDIO_Stop(void* id, int isSource) {
-    TRACE0("> DAUDIO_Stop\n");
-    OSXDirectAudioDevice *device = (OSXDirectAudioDevice*)id;
-    OSStatus err;
+    OSX_DirectAudioDevice *device = (OSX_DirectAudioDevice*)id;
+    TRACE0("DAUDIO_Stop\n");
 
-    device->isDraining = 1;
-    err = AudioOutputUnitStop(device->unit);
+    OSStatus err = AudioOutputUnitStop(device->audioUnit);
 
     return err == noErr ? TRUE : FALSE;
 }
 
 void DAUDIO_Close(void* id, int isSource) {
-    TRACE0("> DAUDIO_Close\n");
-    OSXDirectAudioDevice *device = (OSXDirectAudioDevice*)id;
+    OSX_DirectAudioDevice *device = (OSX_DirectAudioDevice*)id;
+    TRACE0("DAUDIO_Close\n");
 
     delete device;
 }
 
-static SInt64 GetLastSampleTime(CARingBuffer *buffer)
-{
-    SInt64 startTime, endTime;
-    OSStatus err = buffer->GetTimeBounds(startTime, endTime);
+int DAUDIO_Write(void* id, char* data, int byteSize) {
+    OSX_DirectAudioDevice *device = (OSX_DirectAudioDevice*)id;
+    TRACE1(">>DAUDIO_Write: %d bytes to write\n", byteSize);
 
-    return endTime;
-}
+    int result = device->ringBuffer.Write(data, byteSize, true);
 
-int DAUDIO_Write(void* id, char* data, int byteSize) {
-    OSXDirectAudioDevice *device = (OSXDirectAudioDevice*)id;
-    AudioBufferList bufferList;
-
-    bufferList.mNumberBuffers = 1;
-    bufferList.mBuffers[0].mNumberChannels= device->asbd.mChannelsPerFrame;
-    bufferList.mBuffers[0].mDataByteSize  = byteSize;
-    bufferList.mBuffers[0].mData          = data;
-
-    SInt64 firstAvailableSampleTime, lastWrittenSampleTime, lastReadSampleTime, newLastSampleTime;
-    device->buffer.GetTimeBounds(firstAvailableSampleTime, lastWrittenSampleTime);
-    lastReadSampleTime = device->lastReadSampleTime;
-
-    int numAvailableFrames = byteSize / device->asbd.mBytesPerFrame;
-    int numUsedFrames      = lastWrittenSampleTime - firstAvailableSampleTime;
-    int numFreeFrames      = (lastReadSampleTime - firstAvailableSampleTime) /* already-written samples */
-                           + (device->bufferSizeInFrames - numUsedFrames);   /* space at the end of the buffer */
-    int numFrames          = std::min(numAvailableFrames, numFreeFrames);
-
-    if (numFrames == 0)
-        return 0;
-
-    TRACE4("> DAUDIO_Write %d frames (%d %d %d)\n", numFrames,
-                                                    numFreeFrames,
-                                                    numAvailableFrames,
-                                                    lastWrittenSampleTime - lastReadSampleTime);
-
-    int err = device->buffer.Store(&bufferList, numFrames, lastWrittenSampleTime);
-
-    if (err) {
-        TRACE1("Store err %d\n", err);
-    }
-
-    return err == kCARingBufferError_OK ? numFrames * device->asbd.mBytesPerFrame /* bytes written */
-                                        : -1;                                     /* error */
+    TRACE1("<<DAUDIO_Write: %d bytes written\n", result);
+    return result;
 }
 
 int DAUDIO_Read(void* id, char* data, int byteSize) {
-    OSXDirectAudioDevice *device = (OSXDirectAudioDevice*)id;
+    OSX_DirectAudioDevice *device = (OSX_DirectAudioDevice*)id;
+    TRACE1(">>DAUDIO_Read: %d bytes to read\n", byteSize);
 
-    SInt64 firstAvailableSampleTime, lastWrittenSampleTime, lastReadSampleTime = device->lastReadSampleTime;
-    int numRequestedFrames = byteSize / device->asbd.mBytesPerFrame, numAvailableFrames = 0;
-    int waits = 0;
+    int result = device->ringBuffer.Read(data, byteSize);
 
-    while (1) {
-        device->buffer.GetTimeBounds(firstAvailableSampleTime, lastWrittenSampleTime);
-
-        numAvailableFrames = lastWrittenSampleTime - lastReadSampleTime;
-
-        if (numRequestedFrames <= numAvailableFrames || device->isDraining) {
-            break;
-        }
-
-        pthread_mutex_lock(&device->inputMutex);
-        pthread_cond_wait(&device->inputCond, &device->inputMutex);
-        pthread_mutex_unlock(&device->inputMutex);
-        waits++;
-    }
-
-    AudioBufferList bufferList;
-
-    bufferList.mNumberBuffers = 1;
-    bufferList.mBuffers[0].mNumberChannels = device->asbd.mChannelsPerFrame;
-    bufferList.mBuffers[0].mDataByteSize   = byteSize;
-    bufferList.mBuffers[0].mData           = data;
-
-    SInt64 timeToRead = std::max(lastReadSampleTime, firstAvailableSampleTime);
-    int numFrames = device->isDraining ? numAvailableFrames : numRequestedFrames;
-
-    CARingBufferError err = device->buffer.Fetch(&bufferList, numRequestedFrames, timeToRead);
-    device->lastReadSampleTime = timeToRead + numRequestedFrames;
-
-    TRACE4("> DAUDIO_Read read %d frames (%lld-%lld), waited %d times\n", numRequestedFrames, lastReadSampleTime, device->lastReadSampleTime, waits);
-
-    return err == kCARingBufferError_OK ? numRequestedFrames * device->asbd.mBytesPerFrame : -1;
+    TRACE1("<<DAUDIO_Read: %d bytes has been read\n", result);
+    return result;
 }
 
 int DAUDIO_GetBufferSize(void* id, int isSource) {
-    OSXDirectAudioDevice *device = (OSXDirectAudioDevice*)id;
-    int bufferSizeInBytes = device->bufferSizeInFrames * device->asbd.mBytesPerFrame;
+    OSX_DirectAudioDevice *device = (OSX_DirectAudioDevice*)id;
 
-    TRACE1("< DAUDIO_GetBufferSize %d\n", bufferSizeInBytes);
+    int bufferSizeInBytes = device->ringBuffer.GetBufferSize();
+
+    TRACE1("DAUDIO_GetBufferSize returns %d\n", bufferSizeInBytes);
     return bufferSizeInBytes;
 }
 
 int DAUDIO_StillDraining(void* id, int isSource) {
-    OSXDirectAudioDevice *device = (OSXDirectAudioDevice*)id;
-    SInt64 startTime, endTime;
-    int draining;
+    OSX_DirectAudioDevice *device = (OSX_DirectAudioDevice*)id;
 
-    device->buffer.GetTimeBounds(startTime, endTime);
+    int draining = device->ringBuffer.GetValidByteCount() > 0 ? TRUE : FALSE;
 
-    draining = device->lastReadSampleTime < endTime;
-
-    TRACE1("< DAUDIO_StillDraining %d\n", draining);
+    TRACE1("DAUDIO_StillDraining returns %d\n", draining);
     return draining;
 }
 
 int DAUDIO_Flush(void* id, int isSource) {
-    TRACE0("> DAUDIO_Flush\n");
-    OSXDirectAudioDevice *device = (OSXDirectAudioDevice*)id;
-    SInt64 startTime, endTime;
-    CARingBufferError err;
+    OSX_DirectAudioDevice *device = (OSX_DirectAudioDevice*)id;
+    TRACE0("DAUDIO_Flush\n");
 
-    err = device->buffer.GetTimeBounds(startTime, endTime);
-    if (err)
-        return FALSE;
+    device->ringBuffer.Flush();
 
-    device->buffer.Store(NULL, 0, startTime);
-
-    return 0;
+    return TRUE;
 }
 
 int DAUDIO_GetAvailable(void* id, int isSource) {
-    OSXDirectAudioDevice *device = (OSXDirectAudioDevice*)id;
-    SInt64 firstAvailableSampleTime, lastWrittenSampleTime, lastReadSampleTime = device->lastReadSampleTime;
-    CARingBufferError err;
+    OSX_DirectAudioDevice *device = (OSX_DirectAudioDevice*)id;
 
-    err = device->buffer.GetTimeBounds(firstAvailableSampleTime, lastWrittenSampleTime);
-    if (err)
-        return FALSE;
-
-    int numUsedFrames = lastWrittenSampleTime - firstAvailableSampleTime;
-    int numFreeFrames = (lastReadSampleTime - firstAvailableSampleTime) + (device->bufferSizeInFrames - numUsedFrames);
-
+    int bytesInBuffer = device->ringBuffer.GetValidByteCount();
     if (isSource) {
-        // free bytes in the output buffer
-        return numFreeFrames * device->asbd.mBytesPerFrame;
+        return device->ringBuffer.GetBufferSize() - bytesInBuffer;
     } else {
-        // used bytes in the input buffer
-        return numUsedFrames * device->asbd.mBytesPerFrame;
+        return bytesInBuffer;
     }
 }
 
 INT64 DAUDIO_GetBytePosition(void* id, int isSource, INT64 javaBytePos) {
-    //TRACE0("> DAUDIO_GetBytePosition\n");
-    OSXDirectAudioDevice *device = (OSXDirectAudioDevice*)id;
+    OSX_DirectAudioDevice *device = (OSX_DirectAudioDevice*)id;
     INT64 position;
 
-    if (isSource) { // output
-        position = javaBytePos - (device->lastReadSampleTime * device->asbd.mBytesPerFrame);
-    } else { // input
-        SInt64 startTime, endTime;
-        CARingBufferError err = device->buffer.GetTimeBounds(startTime, endTime);
-        if (err) return FALSE;
-        position = (endTime * device->asbd.mBytesPerFrame) - javaBytePos;
+    if (isSource) {
+        position = javaBytePos - device->ringBuffer.GetValidByteCount();
+    } else {
+        position = javaBytePos + device->ringBuffer.GetValidByteCount();
     }
 
-    TRACE1("< DAUDIO_GetBytePosition %lld\n", position);
+    TRACE2("DAUDIO_GetBytePosition returns %lld (javaBytePos = %lld)\n", (long long)position, (long long)javaBytePos);
     return position;
 }
 
 void DAUDIO_SetBytePosition(void* id, int isSource, INT64 javaBytePos) {
+    // no need javaBytePos (it's available in DAUDIO_GetBytePosition)
 }
 
 int DAUDIO_RequiresServicing(void* id, int isSource) {
@@ -570,6 +770,7 @@
 }
 
 void DAUDIO_Service(void* id, int isSource) {
+    // unreachable
 }
 
-#endif
+#endif  // USE_DAUDIO == TRUE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/macosx/native/com/sun/media/sound/PLATFORM_API_MacOSX_Ports.cpp	Fri Dec 23 22:01:01 2011 +0300
@@ -0,0 +1,528 @@
+/*
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+//#define USE_ERROR
+//#define USE_TRACE
+
+#include <CoreAudio/CoreAudio.h>
+#include <IOKit/audio/IOAudioTypes.h>
+
+#include "PLATFORM_API_MacOSX_Utils.h"
+
+extern "C" {
+#include "Ports.h"
+}
+
+#if USE_PORTS == TRUE
+
+/*
+ TODO
+
+ Test devices with >2 channels.
+ Compare control names and tree structure to other platforms.
+ Implement virtual controls (balance, pan, master volume).
+ */
+
+static DeviceList deviceCache;
+
+struct PortMixer;
+
+struct PortControl {
+    PortMixer *mixer;
+
+    AudioObjectID control;
+    AudioClassID classID; // kAudioVolumeControlClassID etc.
+    UInt32 scope; // input, output
+
+    void *jcontrol;
+    char *jcontrolType; // CONTROL_TYPE_VOLUME etc.
+
+    int channel; // master = 0, channels = 1 2 ...
+
+    AudioValueRange range;
+};
+
+struct PortMixer {
+    AudioDeviceID deviceID;
+
+    // = # of ports on the mixer
+    // cached here in case the values can change
+    int numInputStreams;
+    int numOutputStreams;
+    // streams[0..numInputStreams-1] contains inputs,
+    // streams[numInputStreams..numInputStreams+numOutputStreams-1] contains outputs
+    AudioStreamID *streams;
+
+    int numDeviceControls;
+    PortControl *deviceControls;
+
+    int *numStreamControls;
+    PortControl **streamControls;
+};
+
+INT32 PORT_GetPortMixerCount() {
+    deviceCache.Refresh();
+    int count = deviceCache.GetCount();
+    TRACE1("< PORT_GetPortMixerCount = %d\n", count);
+
+    return count;
+}
+
+INT32 PORT_GetPortMixerDescription(INT32 mixerIndex, PortMixerDescription* mixerDescription) {
+    bool result = deviceCache.GetDeviceInfo(mixerIndex, NULL, PORT_STRING_LENGTH,
+            mixerDescription->name, mixerDescription->vendor, mixerDescription->description, mixerDescription->version);
+
+    return result ? TRUE : FALSE;
+}
+
+void* PORT_Open(INT32 mixerIndex) {
+    OSStatus err;
+    PortMixer *mixer = (PortMixer *)calloc(1, sizeof(PortMixer));
+    memset(mixer, 0, sizeof(mixer));
+
+    mixer->deviceID = deviceCache.GetDeviceID(mixerIndex);
+    if (mixer->deviceID != 0) {
+        UInt32 sizeIn = 0, sizeOut = 0;
+        GetAudioObjectPropertySize(mixer->deviceID, kAudioDevicePropertyScopeInput, kAudioDevicePropertyStreams, &sizeIn);
+        GetAudioObjectPropertySize(mixer->deviceID, kAudioDevicePropertyScopeOutput, kAudioDevicePropertyStreams, &sizeOut);
+
+        if (sizeIn > 0 || sizeOut > 0) {
+            mixer->numInputStreams  = sizeIn / sizeof(AudioStreamID);
+            mixer->numOutputStreams = sizeOut / sizeof(AudioStreamID);
+
+            mixer->streams = (AudioStreamID *)calloc(mixer->numInputStreams + mixer->numOutputStreams, sizeof(AudioStreamID));
+
+            GetAudioObjectProperty(mixer->deviceID, kAudioDevicePropertyScopeInput, kAudioDevicePropertyStreams,
+                                mixer->numInputStreams * sizeof(AudioStreamID), mixer->streams, 0);
+            GetAudioObjectProperty(mixer->deviceID, kAudioDevicePropertyScopeOutput, kAudioDevicePropertyStreams,
+                                mixer->numOutputStreams * sizeof(AudioStreamID),
+                                mixer->streams + mixer->numInputStreams, 0);
+        }
+    }
+
+    TRACE1("< PORT_Open %p\n", mixer);
+    return mixer;
+}
+
+void PORT_Close(void* id) {
+    PortMixer *mixer = (PortMixer *)id;
+    TRACE1("> PORT_Close %p\n", id);
+
+    if (mixer) {
+        free(mixer->streams);
+        free(mixer);
+    }
+}
+
+INT32 PORT_GetPortCount(void* id) {
+    PortMixer *mixer = (PortMixer *)id;
+    int numStreams = mixer->numInputStreams + mixer->numOutputStreams;
+
+    TRACE1("< PORT_GetPortCount = %d\n", numStreams);
+    return numStreams;
+}
+
+INT32 PORT_GetPortType(void* id, INT32 portIndex) {
+    PortMixer *mixer = (PortMixer *)id;
+
+    AudioStreamID streamID = mixer->streams[portIndex];
+    UInt32 direction;
+    UInt32 terminalType;
+    UInt32 size;
+    INT32 ret = 0;
+    OSStatus err;
+
+    err = GetAudioObjectProperty(streamID, kAudioObjectPropertyScopeGlobal, kAudioStreamPropertyTerminalType,
+                                 sizeof(terminalType), &terminalType, 1);
+    if (err) {
+        OS_ERROR1(err, "PORT_GetPortType(kAudioStreamPropertyTerminalType), portIndex=%d", portIndex);
+        return 0;
+    }
+    err = GetAudioObjectProperty(streamID, kAudioObjectPropertyScopeGlobal, kAudioStreamPropertyDirection,
+                                 sizeof(direction), &direction, 1);
+    if (err) {
+        OS_ERROR1(err, "PORT_GetPortType(kAudioStreamPropertyDirection), portIndex=%d", portIndex);
+        return 0;
+    }
+
+    // Note that kAudioStreamPropertyTerminalType actually returns values from
+    // IOAudioTypes.h, not the defined kAudioStreamTerminalType*.
+
+    if (direction) {
+        // input
+        switch (terminalType) {
+        case EXTERNAL_LINE_CONNECTOR:
+            ret = PORT_SRC_LINE_IN;
+            break;
+        case INPUT_MICROPHONE:
+            ret = PORT_SRC_MICROPHONE;
+            break;
+        case EXTERNAL_SPDIF_INTERFACE:
+            ret = PORT_SRC_UNKNOWN;
+            break;
+        default:
+            TRACE1("unknown input terminal type %#x\n", terminalType);
+#ifdef USE_TRACE
+            AudioObjectShow(mixer->deviceID);
+            AudioObjectShow(streamID);
+#endif
+            ret = PORT_SRC_UNKNOWN;
+        }
+    } else {
+        // output
+        switch (terminalType) {
+        case EXTERNAL_LINE_CONNECTOR:
+            ret = PORT_DST_LINE_OUT;
+            break;
+        case OUTPUT_SPEAKER:
+            ret = PORT_DST_SPEAKER;
+            break;
+        case OUTPUT_HEADPHONES:
+            ret = PORT_DST_HEADPHONE;
+            break;
+        case EXTERNAL_SPDIF_INTERFACE:
+            ret = PORT_DST_UNKNOWN;
+            break;
+        default:
+            TRACE1("unknown output terminal type %#x\n", terminalType);
+#ifdef USE_TRACE
+            AudioObjectShow(mixer->deviceID);
+            AudioObjectShow(streamID);
+#endif
+            ret = PORT_DST_UNKNOWN;
+        }
+    }
+
+    TRACE2("< PORT_GetPortType (portIndex=%d) = %d\n", portIndex, ret);
+    return ret;
+}
+
+INT32 PORT_GetPortName(void* id, INT32 portIndex, char* name, INT32 len) {
+    PortMixer *mixer = (PortMixer *)id;
+    AudioStreamID streamID = mixer->streams[portIndex];
+
+    CFStringRef cfname = NULL;
+    OSStatus err = noErr;
+
+    err = GetAudioObjectProperty(streamID, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyName,
+                                 sizeof(cfname), &cfname, 1);
+    if (err && err != kAudioHardwareUnknownPropertyError) {
+        OS_ERROR1(err, "PORT_GetPortName(stream name), portIndex=%d", portIndex);
+        return FALSE;
+    }
+
+    if (!cfname) {
+        // use the device's name if the stream has no name (usually the case)
+        err = GetAudioObjectProperty(mixer->deviceID, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyName,
+                                     sizeof(cfname), &cfname, 1);
+        if (err) {
+            OS_ERROR1(err, "PORT_GetPortName(device name), portIndex=%d", portIndex);
+            return FALSE;
+        }
+    }
+
+    if (cfname) {
+        CFStringGetCString(cfname, name, len, kCFStringEncodingUTF8);
+        CFRelease(cfname);
+    }
+
+    TRACE2("< PORT_GetPortName (portIndex = %d) = %s\n", portIndex, name);
+    return TRUE;
+}
+
+static void CreateVolumeControl(PortControlCreator *creator, PortControl *control)
+{
+    Float32 min = 0, max = 1, precision;
+    AudioValueRange *range = &control->range;
+    UInt32 size;
+
+    control->jcontrolType = CONTROL_TYPE_VOLUME;
+
+    GetAudioObjectProperty(control->control, kAudioObjectPropertyScopeGlobal, kAudioLevelControlPropertyDecibelRange,
+                           sizeof(control->range), &control->range, 1);
+    precision = 1. / (range->mMaximum - range->mMinimum);
+
+    control->jcontrol = creator->newFloatControl(creator, control, CONTROL_TYPE_VOLUME, min, max, precision, "");
+}
+
+static void CreateMuteControl(PortControlCreator *creator, PortControl *control)
+{
+    control->jcontrolType = CONTROL_TYPE_MUTE;
+    control->jcontrol = creator->newBooleanControl(creator, control, CONTROL_TYPE_MUTE);
+}
+
+void PORT_GetControls(void* id, INT32 portIndex, PortControlCreator* creator) {
+    PortMixer *mixer = (PortMixer *)id;
+    AudioStreamID streamID = mixer->streams[portIndex];
+
+    UInt32 size;
+    OSStatus err;
+    int i;
+
+    int numVolumeControls = 0, numMuteControls = 0; // not counting the master
+    int hasChannelVolume  = 0, hasChannelMute  = 0;
+    PortControl *masterVolume = NULL, *masterMute = NULL;
+
+    UInt32 wantedScope = portIndex < mixer->numInputStreams ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput;
+
+    // initialize the device controls if this is the first stream
+    if (!mixer->numDeviceControls) {
+        // numDeviceControls / numStreamControls are overestimated
+        // because we don't actually filter by if the owned objects are controls
+        err = GetAudioObjectPropertySize(mixer->deviceID, kAudioObjectPropertyScopeGlobal,
+                                         kAudioObjectPropertyOwnedObjects, &size);
+        mixer->numDeviceControls = size / sizeof(AudioObjectID);
+
+        if (err == noErr && mixer->numDeviceControls) {
+            AudioObjectID controlIDs[mixer->numDeviceControls];
+            mixer->deviceControls = (PortControl *)calloc(mixer->numDeviceControls, sizeof(PortControl));
+
+            err = GetAudioObjectProperty(mixer->deviceID, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyOwnedObjects,
+                                         sizeof(controlIDs), &controlIDs, 1);
+
+            if (err == noErr) {
+                for (i = 0; i < mixer->numDeviceControls; i++) {
+                    PortControl *control = &mixer->deviceControls[i];
+
+                    control->control = controlIDs[i];
+                    control->mixer = mixer;
+
+                    GetAudioObjectProperty(control->control, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyClass,
+                                           sizeof(control->classID), &control->classID, 1);
+                    err = GetAudioObjectProperty(control->control, kAudioObjectPropertyScopeGlobal, kAudioControlPropertyElement,
+                                           sizeof(control->channel), &control->channel, 1);
+
+                    if (err) { // not a control
+                        control->classID = 0;
+                        continue;
+                    }
+
+                    GetAudioObjectProperty(control->control, kAudioObjectPropertyScopeGlobal, kAudioControlPropertyScope,
+                                           sizeof(control->scope), &control->scope, 1);
+
+                    TRACE3("%.4s control, channel %d scope %.4s\n", &control->classID, control->channel, &control->scope);
+                }
+            }
+        }
+        if (err) {
+            mixer->numDeviceControls = 0;
+            if (mixer->deviceControls) {
+                free(mixer->deviceControls);
+                mixer->deviceControls = NULL;
+            }
+        }
+    }
+
+    // count the number of device controls with the appropriate scope
+    if (mixer->numDeviceControls) {
+        for (i = 0; i < mixer->numDeviceControls; i++) {
+            PortControl *control = &mixer->deviceControls[i];
+
+            if (control->scope != wantedScope)
+                continue;
+
+            switch (control->classID) {
+            case kAudioVolumeControlClassID:
+                if (control->channel == 0)
+                    masterVolume = control;
+                else {
+                    numVolumeControls++;
+                    hasChannelVolume = 1;
+                }
+                break;
+            case kAudioMuteControlClassID:
+                if (control->channel == 0)
+                    masterMute = control;
+                else {
+                    numMuteControls++;
+                    hasChannelMute = 1;
+                }
+                break;
+            }
+        }
+    }
+
+    TRACE4("volume: channel %d master %d, mute: channel %d master %d\n", numVolumeControls, masterVolume != NULL, numMuteControls, masterMute != NULL);
+
+    if (masterVolume) {
+        if (!masterVolume->jcontrol)
+            CreateVolumeControl(creator, masterVolume);
+        creator->addControl(creator, masterVolume->jcontrol);
+    }
+
+    if (masterMute) {
+        if (!masterMute->jcontrol)
+            CreateMuteControl(creator, masterMute);
+        creator->addControl(creator, masterMute->jcontrol);
+    }
+
+    if (numVolumeControls) {
+        void **jControls = (void **)calloc(numVolumeControls, sizeof(void*));
+        int j = 0;
+        for (i = 0; i < mixer->numDeviceControls && j < numVolumeControls; i++) {
+            PortControl *control = &mixer->deviceControls[i];
+
+            if (control->classID != kAudioVolumeControlClassID || control->channel == 0 || control->scope != wantedScope)
+                continue;
+
+            if (!control->jcontrol)
+                CreateVolumeControl(creator, control);
+            jControls[j++] = control->jcontrol;
+        }
+
+        void *compoundControl = creator->newCompoundControl(creator, "Volume", jControls, numVolumeControls);
+        creator->addControl(creator, compoundControl);
+        free(jControls);
+    }
+
+    if (numMuteControls) {
+        void **jControls = (void **)calloc(numMuteControls, sizeof(void*));
+        int j = 0;
+        for (i = 0; i < mixer->numDeviceControls && j < numMuteControls; i++) {
+            PortControl *control = &mixer->deviceControls[i];
+
+            if (control->classID != kAudioMuteControlClassID || control->channel == 0 || control->scope != wantedScope)
+                continue;
+
+            if (!control->jcontrol)
+                CreateMuteControl(creator, control);
+            jControls[j++] = control->jcontrol;
+        }
+
+        void *compoundControl = creator->newCompoundControl(creator, "Mute", jControls, numMuteControls);
+        creator->addControl(creator, compoundControl);
+        free(jControls);
+    }
+
+    if (!mixer->numStreamControls)
+        mixer->numStreamControls = (int *)calloc(mixer->numInputStreams + mixer->numOutputStreams, sizeof(int));
+
+    err = GetAudioObjectPropertySize(streamID, kAudioObjectPropertyScopeGlobal,
+                                     kAudioObjectPropertyOwnedObjects, &size);
+    if (err != noErr) {
+        mixer->numStreamControls[portIndex] = size / sizeof(AudioObjectID);
+    }
+
+    TRACE2("< PORT_GetControls, %d controls on device, %d on stream\n", mixer->numDeviceControls, mixer->numStreamControls[portIndex]);
+}
+
+INT32 PORT_GetIntValue(void* controlIDV) {
+    PortControl *control = (PortControl *)controlIDV;
+    UInt32 value = 0;
+    OSStatus err = 0;
+    UInt32 size;
+
+    switch (control->classID) {
+    case kAudioMuteControlClassID:
+        err = GetAudioObjectProperty(control->control, kAudioObjectPropertyScopeGlobal,
+                                     kAudioBooleanControlPropertyValue, sizeof(value), &value, 1);
+        break;
+    default:
+        ERROR0("PORT_GetIntValue requested for non-Int control\n");
+        return 0;
+    }
+
+    if (err) {
+        OS_ERROR0(err, "PORT_GetIntValue");
+        return 0;
+    }
+
+    TRACE1("< PORT_GetIntValue = %d\n", value);
+    return value;
+}
+
+void PORT_SetIntValue(void* controlIDV, INT32 value) {
+    TRACE1("> PORT_SetIntValue = %d\n", value);
+    PortControl *control = (PortControl *)controlIDV;
+    OSStatus err = noErr;
+
+    switch (control->classID) {
+    case kAudioMuteControlClassID:
+        err = SetAudioObjectProperty(control->control, kAudioObjectPropertyScopeGlobal,
+                                     kAudioBooleanControlPropertyValue, sizeof(value), &value);
+        break;
+    default:
+        ERROR0("PORT_SetIntValue requested for non-Int control\n");
+        return;
+    }
+
+    if (err) {
+        OS_ERROR0(err, "PORT_SetIntValue");
+        return;
+    }
+}
+
+float PORT_GetFloatValue(void* controlIDV) {
+    PortControl *control = (PortControl *)controlIDV;
+    Float32 value = 0;
+    OSStatus err = 0;
+    UInt32 size;
+
+    switch (control->classID) {
+    case kAudioVolumeControlClassID:
+        err = GetAudioObjectProperty(control->control, kAudioObjectPropertyScopeGlobal,
+                                     kAudioLevelControlPropertyDecibelValue, sizeof(value), &value, 1);
+        if (err == noErr) {
+            // convert decibel to 0-1 logarithmic
+            value = (value - control->range.mMinimum) / (control->range.mMaximum - control->range.mMinimum);
+        }
+        break;
+    default:
+        ERROR0("GetFloatValue requested for non-Float control\n");
+        break;
+    }
+
+    if (err) {
+        OS_ERROR0(err, "PORT_GetFloatValue");
+        return 0;
+    }
+
+    TRACE1("< PORT_GetFloatValue = %f\n", value);
+    return value;
+}
+
+void PORT_SetFloatValue(void* controlIDV, float value) {
+    TRACE1("> PORT_SetFloatValue = %f\n", value);
+    PortControl *control = (PortControl *)controlIDV;
+    OSStatus err = 0;
+
+    switch (control->classID) {
+    case kAudioVolumeControlClassID:
+        value = (value * (control->range.mMaximum - control->range.mMinimum)) + control->range.mMinimum;
+        err = SetAudioObjectProperty(control->control, kAudioObjectPropertyScopeGlobal,
+                                     kAudioLevelControlPropertyDecibelValue, sizeof(value), &value);
+        break;
+    default:
+        ERROR0("PORT_SetFloatValue requested for non-Float control\n");
+        break;
+    }
+
+    if (err) {
+        OS_ERROR0(err, "PORT_SetFloatValue");
+        return;
+    }
+}
+
+#endif // USE_PORTS
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/macosx/native/com/sun/media/sound/PLATFORM_API_MacOSX_Utils.cpp	Fri Dec 23 22:01:01 2011 +0300
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+//#define USE_TRACE
+//#define USE_ERROR
+
+#include "PLATFORM_API_MacOSX_Utils.h"
+
+int MACOSX_DAUDIO_Init() {
+    static int initialized = 0;
+    if (!initialized) {
+        CFRunLoopRef runLoop = NULL;
+
+        OSStatus err = SetAudioObjectProperty(kAudioObjectSystemObject, kAudioObjectPropertyScopeGlobal,
+            kAudioHardwarePropertyRunLoop, sizeof(CFRunLoopRef), &runLoop);
+
+        if (err) {
+            OS_ERROR0(err, "MACOSX_DAUDIO_Init(kAudioHardwarePropertyRunLoop)");
+        } else {
+            TRACE0("MACOSX_DAUDIO_Init(kAudioHardwarePropertyRunLoop): OK\n");
+            initialized = 1;
+        }
+    }
+    return initialized;
+}
+
+DeviceList::DeviceList(): count(0), devices(NULL) {
+    MACOSX_DAUDIO_Init();
+
+    AudioObjectPropertyAddress address = {kAudioHardwarePropertyDevices,
+        kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster};
+    OSStatus err = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &address, NotificationCallback, this);
+    if (err) {
+        OS_ERROR0(err, "AudioObjectAddPropertyListener(kAudioHardwarePropertyDevices)");
+    } else {
+        TRACE0("AudioObjectAddPropertyListener(kAudioHardwarePropertyDevices): OK\n");
+    }
+}
+
+DeviceList::~DeviceList() {
+    Free();
+
+    AudioObjectPropertyAddress address = {kAudioHardwarePropertyDevices,
+        kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster};
+    AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &address, NotificationCallback, this);
+}
+
+OSStatus DeviceList::Refresh() {
+    MutexLock::Locker locker(lock);
+    Free();
+
+    OSStatus err;
+    UInt32 size;
+    err = GetAudioObjectPropertySize(kAudioObjectSystemObject, kAudioObjectPropertyScopeGlobal, kAudioHardwarePropertyDevices, &size);
+    if (err == noErr) {
+        devices = (AudioDeviceID *)malloc(size);
+        err = GetAudioObjectProperty(kAudioObjectSystemObject, kAudioObjectPropertyScopeGlobal, kAudioHardwarePropertyDevices, &size, devices);
+        if (err == noErr) {
+            count = size/sizeof(AudioDeviceID);
+        }
+    }
+    if (err) {
+        OS_ERROR0(err, "DeviceList::Refresh");
+        Free();
+    }
+#ifdef USE_TRACE
+    TRACE1("<<DeviceList::Refresh, %d devices {", count);
+    for (int i=0; i<count; i++) {
+        if (i > 0)
+            TRACE0(", ");
+        TRACE1("0x%x", (int)devices[i]);
+    }
+    TRACE0("}\n");
+#endif
+
+    return err;
+}
+
+int DeviceList::GetCount() {
+    MutexLock::Locker locker(lock);
+    return count;
+}
+
+AudioDeviceID DeviceList::GetDeviceID(int index) {
+    MutexLock::Locker locker(lock);
+    return index < 0 ? 0 : index >= count ? 0 : devices[index];
+}
+
+bool DeviceList::GetDeviceInfo(int index, AudioDeviceID *pDeviceID, int stringLength, char *name, char *vendor, char *description, char *version) {
+    MutexLock::Locker locker(lock);
+    if (index < 0 || index >= count) {
+        return false;
+    }
+
+    AudioDeviceID deviceID = devices[index];
+    if (pDeviceID != NULL)
+        *pDeviceID = deviceID;
+
+    OSStatus err = noErr;
+
+    if (name != NULL || description != NULL) {
+        CFStringRef cfName = NULL;
+        err = GetAudioObjectProperty(deviceID, kAudioObjectPropertyScopeGlobal,
+            kAudioObjectPropertyName, sizeof(cfName), &cfName, 1);
+        if (err == noErr) {
+            if (name != NULL)
+                CFStringGetCString(cfName, name, stringLength, kCFStringEncodingUTF8);
+            if (description)
+                CFStringGetCString(cfName, description, stringLength, kCFStringEncodingUTF8);
+            CFRelease(cfName);
+        }
+    }
+
+    if (vendor != NULL) {
+        CFStringRef cfManufacturer = NULL;
+        err = GetAudioObjectProperty(deviceID, kAudioObjectPropertyScopeGlobal,
+            kAudioObjectPropertyManufacturer, sizeof(cfManufacturer), &cfManufacturer, 1);
+        if (err == noErr) {
+            CFStringGetCString(cfManufacturer, vendor, stringLength, kCFStringEncodingUTF8);
+            CFRelease(cfManufacturer);
+        }
+    }
+
+    return true;
+}
+
+void DeviceList::Free() {
+    if (devices != NULL) {
+        free(devices);
+        devices = NULL;
+        count = 0;
+    }
+}
+
+/*static*/
+OSStatus DeviceList::NotificationCallback(AudioObjectID inObjectID,
+    UInt32 inNumberAddresses, const AudioObjectPropertyAddress inAddresses[], void *inClientData)
+{
+    DeviceList *pThis = (DeviceList *)inClientData;
+
+    for (UInt32 i=0; i<inNumberAddresses; i++) {
+        switch (inAddresses[i].mSelector) {
+        case kAudioHardwarePropertyDevices:
+            TRACE0("NOTIFICATION: kAudioHardwarePropertyDevices\n");
+            break;
+        }
+    }
+
+    return noErr;
+}
+
+
+
+AudioDeviceID GetDefaultDevice(int isSource) {
+    AudioDeviceID deviceID;
+    OSStatus err = GetAudioObjectProperty(kAudioObjectSystemObject, kAudioObjectPropertyScopeGlobal,
+        isSource ? kAudioHardwarePropertyDefaultOutputDevice : kAudioHardwarePropertyDefaultInputDevice,
+        sizeof(deviceID), &deviceID, 1);
+    if (err) {
+        OS_ERROR1(err, "GetDefaultDevice(isSource=%d)", isSource);
+        return 0;
+    }
+    return deviceID;
+}
+
+int GetChannelCount(AudioDeviceID deviceID, int isSource) {
+    int result = 0;
+    OSStatus err;
+    UInt32 size, i;
+    AudioObjectPropertyScope scope = isSource ? kAudioDevicePropertyScopeOutput : kAudioDevicePropertyScopeInput;
+
+    err = GetAudioObjectPropertySize(deviceID, scope, kAudioDevicePropertyStreamConfiguration, &size);
+    if (err) {
+        OS_ERROR2(err, "GetChannelCount(getSize), deviceID=0x%x, isSource=%d", (int)deviceID, isSource);
+    } else {
+        AudioBufferList *pBufferList = (AudioBufferList *)malloc(size);
+        memset(pBufferList, 0, size);
+        err = GetAudioObjectProperty(deviceID, scope, kAudioDevicePropertyStreamConfiguration, &size, pBufferList);
+        if (err == noErr) {
+            for (i=0; i<pBufferList->mNumberBuffers; i++) {
+                result += pBufferList->mBuffers[i].mNumberChannels;
+            }
+        } else {
+            OS_ERROR2(err, "GetChannelCount(getData), deviceID=0x%x, isSource=%d", (int)deviceID, isSource);
+        }
+        free(pBufferList);
+    }
+    TRACE2("GetChannelCount (deviceID=0x%x): total %d channels\n", (int)deviceID, result);
+    return result;
+}
+
+float GetSampleRate(AudioDeviceID deviceID, int isSource) {
+    Float64 result;
+    AudioObjectPropertyScope scope = isSource ? kAudioDevicePropertyScopeOutput : kAudioDevicePropertyScopeInput;
+    OSStatus err = GetAudioObjectProperty(deviceID, scope, kAudioDevicePropertyActualSampleRate, sizeof(result), &result, 1);
+    if (err) {
+        OS_ERROR2(err, "GetSampleRate(ActualSampleRate), deviceID=0x%x, isSource=%d", (int)deviceID, isSource);
+        // try to get NominalSampleRate
+        err = GetAudioObjectProperty(deviceID, scope, kAudioDevicePropertyNominalSampleRate, sizeof(result), &result, 1);
+        if (err) {
+            OS_ERROR2(err, "GetSampleRate(NominalSampleRate), deviceID=0x%x, isSource=%d", (int)deviceID, isSource);
+            return 0;
+        }
+    }
+    return (float)result;
+}
+
+
+OSStatus GetAudioObjectPropertySize(AudioObjectID object, AudioObjectPropertyScope scope, AudioObjectPropertySelector prop, UInt32 *size)
+{
+    const AudioObjectPropertyAddress address = {prop, scope, kAudioObjectPropertyElementMaster};
+    OSStatus err;
+
+    err = AudioObjectGetPropertyDataSize(object, &address, 0, NULL, size);
+
+    return err;
+}
+
+OSStatus GetAudioObjectProperty(AudioObjectID object, AudioObjectPropertyScope scope, AudioObjectPropertySelector prop, UInt32 *size, void *data)
+{
+    const AudioObjectPropertyAddress address = {prop, scope, kAudioObjectPropertyElementMaster};
+    OSStatus err;
+
+    err = AudioObjectGetPropertyData(object, &address, 0, NULL, size, data);
+
+    return err;
+}
+
+OSStatus GetAudioObjectProperty(AudioObjectID object, AudioObjectPropertyScope scope, AudioObjectPropertySelector prop, UInt32 size, void *data, int checkSize)
+{
+    const AudioObjectPropertyAddress address = {prop, scope, kAudioObjectPropertyElementMaster};
+    UInt32 oldSize = size;
+    OSStatus err;
+
+    err = AudioObjectGetPropertyData(object, &address, 0, NULL, &size, data);
+
+    if (!err && checkSize && size != oldSize)
+        return kAudioHardwareBadPropertySizeError;
+    return err;
+}
+
+// wrapper for AudioObjectSetPropertyData (kAudioObjectPropertyElementMaster)
+OSStatus SetAudioObjectProperty(AudioObjectID object, AudioObjectPropertyScope scope, AudioObjectPropertySelector prop, UInt32 size, void *data)
+{
+    AudioObjectPropertyAddress address = {prop, scope, kAudioObjectPropertyElementMaster};
+
+    OSStatus err = AudioObjectSetPropertyData(object, &address, 0, NULL, size, data);
+
+    return err;
+}
--- a/src/macosx/native/com/sun/media/sound/PLATFORM_API_MacOSX_Utils.h	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/native/com/sun/media/sound/PLATFORM_API_MacOSX_Utils.h	Fri Dec 23 22:01:01 2011 +0300
@@ -24,24 +24,90 @@
  */
 
 #include <CoreAudio/CoreAudio.h>
-#include "SoundDefs.h"
+#include <pthread.h>
 
-typedef struct AudioDeviceDescription {
-    int strLen;
-    char *name;
-    char *vendor;
-    char *description;
+extern "C" {
+#include "Utilities.h"
+}
 
-    AudioDeviceID deviceID;
-    int numInputStreams;
-    int numOutputStreams;
-    int numInputChannels;
-    int numOutputChannels;
-    Float64 inputSampleRate;
-} AudioDeviceDescription;
 
-int GetAudioDeviceCount();
-int GetAudioDeviceDescription(int index, AudioDeviceDescription *description);
-AudioDeviceID GetAudioDeviceIDByIndex(int index);
-OSStatus GetAudioObjectProperty(AudioObjectID object, AudioObjectPropertyScope scope, AudioObjectPropertySelector property, UInt32 size, void *data, int checkSize);
-OSStatus GetAudioObjectPropertySize(AudioObjectID object, AudioObjectPropertyScope scope, AudioObjectPropertySelector property, UInt32 *size);
+#ifdef USE_ERROR
+#define OS_ERROR_END(err) {                     \
+    char errStr[32];                            \
+    snprintf(errStr, 32, "%d('%c%c%c%c')>", (int)err, (char)(err >> 24), (char)(err >> 16), (char)(err >> 8), (char)err); \
+    ERROR1(" ERROR %s\n", errStr);              \
+}
+#define OS_ERROR0(err, string)                  { ERROR0(string); OS_ERROR_END(err); }
+#define OS_ERROR1(err, string, p1)              { ERROR1(string, p1); OS_ERROR_END(err); }
+#define OS_ERROR2(err, string, p1, p2)          { ERROR2(string, p1, p2); OS_ERROR_END(err); }
+#define OS_ERROR3(err, string, p1, p2, p3)      { ERROR3(string, p1, p2, p3); OS_ERROR_END(err); }
+#define OS_ERROR4(err, string, p1, p2, p3, p4)  { ERROR4(string, p1, p2, p3, p4); OS_ERROR_END(err); }
+#else
+#define OS_ERROR0(err, string)
+#define OS_ERROR1(err, string, p1)
+#define OS_ERROR2(err, string, p1, p2)
+#define OS_ERROR3(err, string, p1, p2, p3)
+#define OS_ERROR4(err, string, p1, p2, p3, p4)
+#endif
+
+
+// Simple mutex wrapper class
+class MutexLock {
+private:
+    pthread_mutex_t lockMutex;
+public:
+    MutexLock() { pthread_mutex_init(&lockMutex, NULL); }
+    ~MutexLock() { pthread_mutex_destroy(&lockMutex); }
+
+    void Lock() { pthread_mutex_lock(&lockMutex); }
+    void Unlock() { pthread_mutex_unlock(&lockMutex); }
+
+    class Locker {
+    public:
+        Locker(MutexLock &lock) : pLock(&lock) { pLock->Lock(); }
+        ~Locker() { pLock->Unlock(); }
+    private:
+        MutexLock *pLock;
+    };
+};
+
+
+// DirectAudio and Ports need own caches of the device list
+class DeviceList {
+public:
+    DeviceList();
+    ~DeviceList();
+
+    OSStatus Refresh();
+
+    int GetCount();
+    AudioDeviceID GetDeviceID(int index);
+    // stringLength specified length of name, vendor, description & version strings
+    bool GetDeviceInfo(int index, AudioDeviceID *deviceID, int stringLength, char *name, char *vendor, char *description, char *version);
+
+private:
+    int count;
+    AudioDeviceID *devices;
+    MutexLock lock;
+    void Free();
+
+    static OSStatus NotificationCallback(AudioObjectID inObjectID,
+        UInt32 inNumberAddresses, const AudioObjectPropertyAddress inAddresses[], void *inClientData);
+
+};
+
+int MACOSX_DAUDIO_Init();
+
+AudioDeviceID GetDefaultDevice(int isSource);
+int GetChannelCount(AudioDeviceID deviceID, int isSource);
+float GetSampleRate(AudioDeviceID deviceID, int isSource);
+
+
+// wrappers for AudioObjectGetPropertyDataSize/AudioObjectGetPropertyData (master element)
+OSStatus GetAudioObjectPropertySize(AudioObjectID object, AudioObjectPropertyScope scope, AudioObjectPropertySelector prop, UInt32 *size);
+OSStatus GetAudioObjectProperty(AudioObjectID object, AudioObjectPropertyScope scope, AudioObjectPropertySelector prop, UInt32 *size, void *data);
+OSStatus GetAudioObjectProperty(AudioObjectID object, AudioObjectPropertyScope scope, AudioObjectPropertySelector prop, UInt32 size, void *data, int checkSize);
+
+// wrapper for AudioObjectSetPropertyData (kAudioObjectPropertyElementMaster)
+OSStatus SetAudioObjectProperty(AudioObjectID object, AudioObjectPropertyScope scope, AudioObjectPropertySelector prop, UInt32 size, void *data);
+
--- a/src/macosx/native/com/sun/media/sound/PLATFORM_API_MacOS_MidiIn.c	Thu Dec 22 11:05:51 2011 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,123 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code 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
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-//#define USE_ERROR
-//#define USE_TRACE
-
-#if USE_PLATFORM_MIDI_IN == TRUE
-
-#include "PLATFORM_API_MacOS_MidiUtils.h"
-
-char* MIDI_IN_GetErrorStr(INT32 err) {
-    return (char *) MIDI_Utils_GetErrorMsg((int) err);
-}
-
-
-INT32 MIDI_IN_GetNumDevices() {
-    return MIDI_Utils_GetNumDevices(MIDI_IN);
-}
-
-
-INT32 MIDI_IN_GetDeviceName(INT32 deviceID, char *name, UINT32 nameLength) {
-    return MIDI_Utils_GetDeviceName(MIDI_IN, deviceID, name, nameLength);
-}
-
-
-INT32 MIDI_IN_GetDeviceVendor(INT32 deviceID, char *name, UINT32 nameLength) {
-    return MIDI_Utils_GetDeviceVendor(MIDI_IN, deviceID, name, nameLength);
-}
-
-
-INT32 MIDI_IN_GetDeviceDescription(INT32 deviceID, char *name, UINT32 nameLength) {
-    return MIDI_Utils_GetDeviceDescription(MIDI_IN, deviceID, name, nameLength);
-}
-
-
-INT32 MIDI_IN_GetDeviceVersion(INT32 deviceID, char *name, UINT32 nameLength) {
-    return MIDI_Utils_GetDeviceVersion(MIDI_IN, deviceID, name, nameLength);
-}
-
-
-INT32 MIDI_IN_OpenDevice(INT32 deviceID, MidiDeviceHandle** handle) {
-    TRACE0("MIDI_IN_OpenDevice\n");
-    return
-        MIDI_Utils_OpenDevice(MIDI_IN, deviceID, (MacMidiDeviceHandle**) handle,
-                              MIDI_IN_MESSAGE_QUEUE_SIZE,
-                              MIDI_IN_LONG_QUEUE_SIZE,
-                              MIDI_IN_LONG_MESSAGE_SIZE);
-}
-
-
-INT32 MIDI_IN_CloseDevice(MidiDeviceHandle* handle) {
-    TRACE0("MIDI_IN_CloseDevice\n");
-    return MIDI_Utils_CloseDevice((MacMidiDeviceHandle*) handle);
-}
-
-
-INT32 MIDI_IN_StartDevice(MidiDeviceHandle* handle) {
-    TRACE0("MIDI_IN_StartDevice\n");
-    return MIDI_Utils_StartDevice((MacMidiDeviceHandle*) handle);
-}
-
-
-INT32 MIDI_IN_StopDevice(MidiDeviceHandle* handle) {
-    TRACE0("MIDI_IN_StopDevice\n");
-    return MIDI_Utils_StopDevice((MacMidiDeviceHandle*) handle);
-}
-
-INT64 MIDI_IN_GetTimeStamp(MidiDeviceHandle* handle) {
-    return MIDI_Utils_GetTimeStamp((MacMidiDeviceHandle*) handle);
-}
-
-
-/* read the next message from the queue */
-MidiMessage* MIDI_IN_GetMessage(MidiDeviceHandle* handle) {
-    if (handle == NULL) {
-        return NULL;
-    }
-    while (handle->queue != NULL && handle->platformData != NULL) {
-        MidiMessage* msg = MIDI_QueueRead(handle->queue);
-        if (msg != NULL) {
-            //fprintf(stdout, "GetMessage returns index %d\n", msg->data.l.index); fflush(stdout);
-            return msg;
-        }
-        TRACE0("MIDI_IN_GetMessage: before waiting\n");
-        handle->isWaiting = TRUE;
-        MIDI_WaitOnConditionVariable(handle->platformData, handle->queue->lock);
-        handle->isWaiting = FALSE;
-        TRACE0("MIDI_IN_GetMessage: waiting finished\n");
-    }
-    return NULL;
-}
-
-
-void MIDI_IN_ReleaseMessage(MidiDeviceHandle* handle, MidiMessage* msg) {
-    if (handle == NULL || handle->queue == NULL) {
-        return;
-    }
-    MIDI_QueueRemove(handle->queue, TRUE /*onlyLocked*/);
-}
-
-#endif /* USE_PLATFORM_MIDI_IN */
--- a/src/macosx/native/com/sun/media/sound/PLATFORM_API_MacOS_MidiOut.c	Thu Dec 22 11:05:51 2011 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,238 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code 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
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-//#define USE_ERROR
-//#define USE_TRACE
-
-#if USE_PLATFORM_MIDI_OUT == TRUE
-
-#include "PLATFORM_API_MacOS_MidiUtils.h"
-
-char* MIDI_OUT_GetErrorStr(INT32 err) {
-    return (char *) MIDI_Utils_GetErrorMsg((int) err);
-}
-
-
-INT32 MIDI_OUT_GetNumDevices() {
-    return MIDI_Utils_GetNumDevices(MIDI_OUT);
-}
-
-
-INT32 MIDI_OUT_GetDeviceName(INT32 deviceID, char *name, UINT32 nameLength) {
-    return MIDI_Utils_GetDeviceName(MIDI_OUT, deviceID, name, nameLength);
-}
-
-
-INT32 MIDI_OUT_GetDeviceVendor(INT32 deviceID, char *name, UINT32 nameLength) {
-    return MIDI_Utils_GetDeviceVendor(MIDI_OUT, deviceID, name, nameLength);
-}
-
-
-INT32 MIDI_OUT_GetDeviceDescription(INT32 deviceID, char *name, UINT32 nameLength) {
-    return MIDI_Utils_GetDeviceDescription(MIDI_OUT, deviceID, name, nameLength);
-}
-
-
-INT32 MIDI_OUT_GetDeviceVersion(INT32 deviceID, char *name, UINT32 nameLength) {
-    return MIDI_Utils_GetDeviceVersion(MIDI_OUT, deviceID, name, nameLength);
-}
-
-
-/* *************************** MidiOutDevice implementation ***************************************** */
-
-INT32 MIDI_OUT_OpenDevice(INT32 deviceID, MidiDeviceHandle** handle) {
-    TRACE1("MIDI_OUT_OpenDevice: deviceID: %d\n", (int) deviceID);
-    /* queue sizes are ignored for MIDI_OUT only (uses STREAMS) */
-    return MIDI_Utils_OpenDevice(MIDI_OUT, deviceID, (MacMidiDeviceHandle**) handle, 0, 0, 0);
-}
-
-INT32 MIDI_OUT_CloseDevice(MidiDeviceHandle* handle) {
-    TRACE0("MIDI_OUT_CloseDevice\n");
-
-    // issue a "SUSTAIN OFF" message to each MIDI channel, 0 to 15.
-    // "CONTROL CHANGE" is 176, "SUSTAIN CONTROLLER" is 64, and the value is 0.
-    // $$fb 2002-04-04: It is responsability of the application developer to
-    // leave the device in a consistent state. So I put this in comments
-    /*
-      for (channel = 0; channel < 16; channel++)
-      MIDI_OUT_SendShortMessage(deviceHandle, (unsigned char)(176 + channel),
-      (unsigned char)64, (unsigned char)0, (UINT32)-1);
-    */
-    return MIDI_Utils_CloseDevice((MacMidiDeviceHandle*) handle);
-}
-
-
-INT64 MIDI_OUT_GetTimeStamp(MidiDeviceHandle* handle) {
-    return MIDI_Utils_GetTimeStamp((MacMidiDeviceHandle*) handle);
-}
-
-
-INT32 MIDI_OUT_SendShortMessage(MidiDeviceHandle* handle, UINT32 packedMsg, UINT32 timestamp) {
-    OSStatus err = noErr;
-
-    TRACE2("> MIDI_OUT_SendShortMessage %x, time: %d\n", (uint) packedMsg, (int) timestamp);
-    if (!handle) {
-        ERROR0("< ERROR: MIDI_OUT_SendShortMessage: handle is NULL\n");
-        return MIDI_INVALID_HANDLE;
-    }
-
-    MacMidiDeviceHandle* macHandle = (MacMidiDeviceHandle*) handle;
-    UInt8 mBuffers[100];
-    MIDIPacketList* packetList = (MIDIPacketList*) mBuffers;
-    MIDIPacket* packet;
-    UINT32 nData;
-    Byte data[3] = {packedMsg & 0xFF, (packedMsg >> 8) & 0xFF, (packedMsg >> 16) & 0xFF};
-    bool byteIsInvalid = FALSE;
-
-    packet = MIDIPacketListInit(packetList);
-    switch (data[0] & 0xF0) {
-        case 0x80:    // Note off
-        case 0x90:    // Note on
-        case 0xA0:    // Aftertouch
-        case 0xB0:    // Controller
-        case 0xE0:    // Pitch wheel
-            nData = 3;
-            break;
-
-        case 0xC0:    // Program change
-        case 0xD0:    // Channel pressure
-            nData = 2;
-            break;
-
-        case 0xF0: {
-            // System common message
-            switch (data[0]) {
-                case 0xF0:
-                case 0xF7:
-                    // System exclusive
-                    fprintf(stderr, "%s: %d->internal error: sysex message status=0x%X while sending short message\n",
-                            __FILE__, __LINE__, data[0]);
-                    byteIsInvalid = TRUE;
-                    break;
-
-                case 0xF1:    // MTC quarter frame message
-                    //fprintf(stderr, ">>>MIDI_OUT_SendShortMessage: MTC quarter frame message....\n");
-                    nData = 2;
-                    break;
-                case 0xF3:    // Song select
-                    //fprintf(stderr, ">>>MIDI_OUT_SendShortMessage: Song select....\n");
-                    nData = 2;
-                    break;
-
-                case 0xF2:    // Song position pointer
-                    //fprintf(stderr, ">>>MIDI_OUT_SendShortMessage: Song position pointer....\n");
-                    nData = 3;
-                    break;
-
-                case 0xF6:    // Tune request
-                    //fprintf(stderr, ">>>MIDI_OUT_SendShortMessage: Tune request....\n");
-                    nData = 1;
-                    break;
-
-                default:
-                    // Invalid message
-                    fprintf(stderr, "%s: %d->Invalid message: message status=0x%X while sending short message\n",
-                            __FILE__, __LINE__, data[0]);
-                    byteIsInvalid = TRUE;
-                    break;
-            }
-            break;
-        }
-
-        default:
-            // This can't happen, but handle it anyway.
-            fprintf(stderr, "%s: %d->Invalid message: message status=0x%X while sending short message\n",
-                    __FILE__, __LINE__, data[0]);
-            byteIsInvalid = TRUE;
-            break;
-    }
-
-    if (byteIsInvalid) return -1;
-
-    MIDIPacketListAdd(packetList, sizeof(mBuffers), packet, 0, nData, data);
-    err = MIDISend(macHandle->port, (MIDIEndpointRef) (intptr_t) handle->deviceHandle, packetList);
-
-    MIDI_CHECK_ERROR;
-    TRACE0("< MIDI_OUT_SendShortMessage\n");
-    return (err == noErr ? MIDI_SUCCESS : -1);
-}
-
-
-INT32 MIDI_OUT_SendLongMessage(MidiDeviceHandle* handle, UBYTE* data, UINT32 size, UINT32 timestamp) {
-    OSStatus err = noErr;
-
-    TRACE2("> MIDI_OUT_SendLongMessage size %d, time: %d\n", (int) size, (int) timestamp);
-    if (!handle || !data) {
-        ERROR0("< ERROR: MIDI_OUT_SendLongMessage: handle, or data is NULL\n");
-        return MIDI_INVALID_HANDLE;
-    }
-    if (size == 0) {
-        return MIDI_SUCCESS;
-    }
-
-    MacMidiDeviceHandle* macHandle = (MacMidiDeviceHandle*) handle;
-    UInt8 mBuffers[8196];
-    MIDIPacketList* packetList = (MIDIPacketList*) mBuffers;
-    MIDIPacket* packet = NULL;
-    UINT32 remaining = size;
-    UINT32 increment = 512;
-    UINT32 nData;
-
-    handle->isWaiting = TRUE;
-
-    while (remaining > 0) {
-
-        if (packet == NULL) {
-            packet = MIDIPacketListInit(packetList);
-        }
-
-        if (remaining > increment) {
-            nData = increment;
-        } else {
-            nData = remaining;
-        }
-
-        // Copies the bytes to our current packet.
-        if ((packet = MIDIPacketListAdd(packetList, sizeof(mBuffers), packet, 0, nData, (const Byte*) data)) == NULL) {
-            // Packet list is full, send it.
-            err = MIDISend(macHandle->port, (MIDIEndpointRef) (intptr_t) handle->deviceHandle, packetList);
-            if (err != noErr) {
-                break;
-            }
-        } else {
-            // Moves the data pointer to the next segment.
-            data += nData;
-            remaining -= nData;
-            packet = MIDIPacketNext(packet);
-        }
-    }
-
-    MIDI_CHECK_ERROR;
-    handle->isWaiting = FALSE;
-    TRACE0("< MIDI_OUT_SendLongMessage\n");
-    return (err == noErr ? MIDI_SUCCESS : -1);
-}
-
-#endif /* USE_PLATFORM_MIDI_OUT */
--- a/src/macosx/native/com/sun/media/sound/PLATFORM_API_MacOS_MidiUtils.c	Thu Dec 22 11:05:51 2011 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,703 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code 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
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
-**
-**    Overview:
-**      Implementation of the functions used for both MIDI in and MIDI out.
-**
-**      Java package com.sun.media.sound defines the AbstractMidiDevice class
-**      which encapsulates functionalities shared by both MidiInDevice and
-**      MidiOutDevice classes in the same package.
-**
-**      The Java layer classes MidiInDevice and MidiOutDevice in turn map to
-**      the MIDIEndpointRef data type in the CoreMIDI framework, which
-**      represents a source or destination for a standard 16-channel MIDI data
-**      stream.
-*/
-/*****************************************************************************/
-
-//#define USE_ERROR
-//#define USE_TRACE
-
-#if (USE_PLATFORM_MIDI_IN == TRUE) || (USE_PLATFORM_MIDI_OUT == TRUE)
-
-#include "PLATFORM_API_MacOS_MidiUtils.h"
-#include <pthread.h>
-#include <assert.h>
-
-// Constant character string definitions of CoreMIDI's corresponding error codes.
-
-static const char* strMIDIInvalidClient =
-                        "An invalid MIDIClientRef was passed.";
-static const char* strMIDIInvalidPort =
-                        "An invalid MIDIPortRef was passed.";
-static const char* strMIDIWrongEndpointType =
-                        "A source endpoint was passed to a function expecting a destination, or vice versa.";
-static const char* strMIDINoConnection =
-                        "Attempt to close a non-existant connection.";
-static const char* strMIDIUnknownEndpoint =
-                        "An invalid MIDIEndpointRef was passed.";
-static const char* strMIDIUnknownProperty =
-                        "Attempt to query a property not set on the object.";
-static const char* strMIDIWrongPropertyType =
-                        "Attempt to set a property with a value not of the correct type.";
-static const char* strMIDINoCurrentSetup =
-                        "Internal error; there is no current MIDI setup object.";
-static const char* strMIDIMessageSendErr =
-                        "Communication with MIDIServer failed.";
-static const char* strMIDIServerStartErr =
-                        "Unable to start MIDIServer.";
-static const char* strMIDISetupFormatErr =
-                        "Unable to read the saved state.";
-static const char* strMIDIWrongThread =
-                        "A driver is calling a non-I/O function in the server from a thread other than"
-                        "the server's main thread.";
-static const char* strMIDIObjectNotFound =
-                        "The requested object does not exist.";
-static const char* strMIDIIDNotUnique =
-                        "Attempt to set a non-unique kMIDIPropertyUniqueID on an object.";
-
-static const char* midi_strerror(int err) {
-/*
-    @enum           Error Constants
-    @abstract       The error constants unique to Core MIDI.
-    @discussion     These are the error constants that are unique to Core MIDI. Note that Core MIDI
-                    functions may return other codes that are not listed here.
-*/
-    const char* strerr;
-
-    switch (err) {
-    case kMIDIInvalidClient:
-        strerr = strMIDIInvalidClient;
-        break;
-    case kMIDIInvalidPort:
-        strerr = strMIDIInvalidPort;
-        break;
-    case kMIDIWrongEndpointType:
-        strerr = strMIDIWrongEndpointType;
-        break;
-    case kMIDINoConnection:
-        strerr = strMIDINoConnection;
-        break;
-    case kMIDIUnknownEndpoint:
-        strerr = strMIDIUnknownEndpoint;
-        break;
-    case kMIDIUnknownProperty:
-        strerr = strMIDIUnknownProperty;
-        break;
-    case kMIDIWrongPropertyType:
-        strerr = strMIDIWrongPropertyType;
-        break;
-    case kMIDINoCurrentSetup:
-        strerr = strMIDINoCurrentSetup;
-        break;
-    case kMIDIMessageSendErr:
-        strerr = strMIDIMessageSendErr;
-        break;
-    case kMIDIServerStartErr:
-        strerr = strMIDIServerStartErr;
-        break;
-    case kMIDISetupFormatErr:
-        strerr = strMIDISetupFormatErr;
-        break;
-    case kMIDIWrongThread:
-        strerr = strMIDIWrongThread;
-        break;
-    case kMIDIObjectNotFound:
-        strerr = strMIDIObjectNotFound;
-        break;
-    case kMIDIIDNotUnique:
-        strerr = strMIDIIDNotUnique;
-        break;
-    default:
-        strerr = "Unknown error.";
-        break;
-    }
-    return strerr;
-}
-
-const char* MIDI_Utils_GetErrorMsg(int err) {
-    return midi_strerror(err);
-}
-
-
-void MIDI_Utils_PrintError(int err) {
-#ifdef USE_ERROR
-    const char* s = MIDI_Utils_GetErrorMsg(err);
-    if (s != NULL) {
-        fprintf(stderr, "%s\n", s);
-    }
-#endif
-}
-
-
-// Note direction is either MIDI_IN or MIDI_OUT.
-INT32 MIDI_Utils_GetNumDevices(int direction) {
-    int num_endpoints;
-    if (direction == MIDI_IN) {
-        num_endpoints = MIDIGetNumberOfSources();
-    //fprintf(stdout, "MIDIGetNumberOfSources() returns %d\n", num_endpoints);
-    } else if (direction == MIDI_OUT) {
-        num_endpoints = MIDIGetNumberOfDestinations();
-        //printf(stdout, "MIDIGetNumberOfDestinations() returns %d\n", num_endpoints);
-    } else {
-        assert((direction == MIDI_IN || direction == MIDI_OUT));
-        num_endpoints = 0;
-    }
-    return (INT32) num_endpoints;
-}
-
-// Wraps calls to CFStringGetCStringPtr and CFStringGetCString to make sure
-// we extract the c characters into the buffer and null-terminate it.
-static void CFStringExtractCString(CFStringRef cfs, char* buffer, UINT32 bufferSize, CFStringEncoding encoding) {
-    const char* ptr = CFStringGetCStringPtr(cfs, encoding);
-    if (ptr) {
-        strlcpy(buffer, ptr, bufferSize);
-    } else {
-        if (! CFStringGetCString(cfs, buffer, bufferSize, encoding)) {
-            // There's an error in conversion, make sure we null-terminate the buffer.
-            buffer[bufferSize - 1] = '\0';
-        }
-    }
-}
-
-//
-// @see com.sun.media.sound.AbstractMidiDeviceProvider.getDeviceInfo().
-static int getEndpointProperty(int direction, INT32 deviceID, char *buffer, int bufferLength, CFStringRef propertyID) {
-
-    if (deviceID < 0) {
-        return MIDI_INVALID_DEVICEID;
-    }
-
-    MIDIEndpointRef endpoint;
-
-    if (direction == MIDI_IN) {
-        endpoint = MIDIGetSource(deviceID);
-    } else if (direction == MIDI_OUT) {
-        endpoint = MIDIGetDestination(deviceID);
-    } else {
-        return MIDI_INVALID_ARGUMENT;
-    }
-
-    if (!endpoint) {
-        return MIDI_INVALID_DEVICEID;
-    }
-
-    int status = MIDI_SUCCESS;
-    if (propertyID == kMIDIPropertyDriverVersion) {
-        SInt32 driverVersion;
-        status = MIDIObjectGetIntegerProperty(endpoint, kMIDIPropertyDriverVersion, &driverVersion);
-        if (status != MIDI_SUCCESS) return status;
-        snprintf(buffer,
-                 bufferLength,
-                 "%d",
-                 (int) driverVersion);
-    }
-    else {
-        CFStringRef pname;
-        status = MIDIObjectGetStringProperty(endpoint, propertyID, &pname);
-        if (status != MIDI_SUCCESS) return status;
-        CFStringExtractCString(pname, buffer, bufferLength, 0);
-    }
-    return MIDI_ERROR_NONE;
-}
-
-// A simple utility which encapsulates CoreAudio's HostTime APIs.
-// It returns the current host time in nanoseconds which when subtracted from
-// a previous getCurrentTimeInNanos() result produces the delta in nanos.
-static UInt64 getCurrentTimeInNanos() {
-    UInt64 hostTime = AudioGetCurrentHostTime();
-    UInt64 nanos = AudioConvertHostTimeToNanos(hostTime);
-    return nanos;
-}
-
-
-INT32 MIDI_Utils_GetDeviceName(int direction, INT32 deviceID, char *name, UINT32 bufferLength) {
-    return getEndpointProperty(direction, deviceID, name, bufferLength, kMIDIPropertyName);
-}
-
-
-INT32 MIDI_Utils_GetDeviceVendor(int direction, INT32 deviceID, char *name, UINT32 bufferLength) {
-    return getEndpointProperty(direction, deviceID, name, bufferLength, kMIDIPropertyManufacturer);
-}
-
-
-INT32 MIDI_Utils_GetDeviceDescription(int direction, INT32 deviceID, char *name, UINT32 bufferLength) {
-    return getEndpointProperty(direction, deviceID, name, bufferLength, kMIDIPropertyDisplayName);
-}
-
-
-INT32 MIDI_Utils_GetDeviceVersion(int direction, INT32 deviceID, char *name, UINT32 bufferLength) {
-    return getEndpointProperty(direction, deviceID, name, bufferLength, kMIDIPropertyDriverVersion);
-}
-
-
-static MIDIClientRef client = (MIDIClientRef) NULL;
-static MIDIPortRef inPort = (MIDIPortRef) NULL;
-static MIDIPortRef outPort = (MIDIPortRef) NULL;
-
-// Each MIDIPacket can contain more than one midi messages.
-// This function processes the packet and adds the messages to the specified message queue.
-// @see also src/share/native/com/sun/media/sound/PlatformMidi.h.
-static void processMessagesForPacket(const MIDIPacket* packet, MacMidiDeviceHandle* handle) {
-    const UInt8* data;
-    UInt16 length;
-    UInt8 byte;
-    UInt8 pendingMessageStatus;
-    UInt8 pendingData[2];
-    UInt16 pendingDataIndex, pendingDataLength;
-    UINT32 packedMsg;
-    MIDITimeStamp ts = packet->timeStamp;
-
-    pendingMessageStatus = 0;
-    pendingDataIndex = pendingDataLength = 0;
-
-    data = packet->data;
-    length = packet->length;
-    while (length--) {
-        bool byteIsInvalid = FALSE;
-
-        byte = *data++;
-        packedMsg = byte;
-
-        if (byte >= 0xF8) {
-            // Each RealTime Category message (ie, Status of 0xF8 to 0xFF) consists of only 1 byte, the Status.
-            // Except that 0xFD is an invalid status code.
-            //
-            // 0xF8 -> Midi clock
-            // 0xF9 -> Midi tick
-            // 0xFA -> Midi start
-            // 0xFB -> Midi continue
-            // 0xFC -> Midi stop
-            // 0xFE -> Active sense
-            // 0xFF -> Reset
-            if (byte == 0xFD) {
-                byteIsInvalid = TRUE;
-            } else {
-                pendingDataLength = 0;
-            }
-        } else {
-            if (byte < 0x80) {
-                // Not a status byte -- check our history.
-                if (handle->readingSysExData) {
-                    CFDataAppendBytes(handle->readingSysExData, &byte, 1);
-
-                } else if (pendingDataIndex < pendingDataLength) {
-                    pendingData[pendingDataIndex] = byte;
-                    pendingDataIndex++;
-
-                    if (pendingDataIndex == pendingDataLength) {
-                        // This message is now done -- do the final processing.
-                        if (pendingDataLength == 2) {
-                            packedMsg = pendingMessageStatus | pendingData[0] << 8 | pendingData[1] << 16;
-                        } else if (pendingDataLength == 1) {
-                            packedMsg = pendingMessageStatus | pendingData[0] << 8;
-                        } else {
-                            fprintf(stderr, "%s: %d->internal error: pendingMessageStatus=0x%X, pendingDataLength=%d\n",
-                                    __FILE__, __LINE__, pendingMessageStatus, pendingDataLength);
-                            byteIsInvalid = TRUE;
-                        }
-                        pendingDataLength = 0;
-                    }
-                } else {
-                    // Skip this byte -- it is invalid.
-                    byteIsInvalid = TRUE;
-                }
-            } else {
-                if (handle->readingSysExData /* && (byte == 0xF7) */) {
-                    // We have reached the end of system exclusive message -- send it finally.
-                    const UInt8* bytes = CFDataGetBytePtr(handle->readingSysExData);
-                    CFIndex size = CFDataGetLength(handle->readingSysExData);
-                    MIDI_QueueAddLong(handle->h.queue,
-                                      (UBYTE*) bytes,
-                                      (UINT32) size,
-                                      0, // Don't care, windowish porting only.
-                                      (INT64) (AudioConvertHostTimeToNanos(ts) + 500) / 1000,
-                                      TRUE);
-                    CFRelease(handle->readingSysExData);
-                    handle->readingSysExData = NULL;
-                }
-
-                pendingMessageStatus = byte;
-                pendingDataLength = 0;
-                pendingDataIndex = 0;
-
-                switch (byte & 0xF0) {
-                    case 0x80:    // Note off
-                    case 0x90:    // Note on
-                    case 0xA0:    // Aftertouch
-                    case 0xB0:    // Controller
-                    case 0xE0:    // Pitch wheel
-                        pendingDataLength = 2;
-                        break;
-
-                    case 0xC0:    // Program change
-                    case 0xD0:    // Channel pressure
-                        pendingDataLength = 1;
-                        break;
-
-                    case 0xF0: {
-                        // System common message
-                        switch (byte) {
-                        case 0xF0:
-                            // System exclusive
-                            // Allocates a CFMutableData reference to accumulate the SysEx data until EOX (0xF7) is reached.
-                            handle->readingSysExData = CFDataCreateMutable(NULL, 0);
-                            break;
-
-                        case 0xF7:
-                            // System exclusive ends--already handled above.
-                            // But if this is showing up outside of sysex, it's invalid.
-                            byteIsInvalid = TRUE;
-                            break;
-
-                        case 0xF1:    // MTC quarter frame message
-                        case 0xF3:    // Song select
-                            pendingDataLength = 1;
-                            break;
-
-                        case 0xF2:    // Song position pointer
-                            pendingDataLength = 2;
-                            break;
-
-                        case 0xF6:    // Tune request
-                            pendingDataLength = 0;
-                            break;
-
-                        default:
-                            // Invalid message
-                            byteIsInvalid = TRUE;
-                            break;
-                        }
-                        break;
-                    }
-
-                    default:
-                        // This can't happen, but handle it anyway.
-                        byteIsInvalid = TRUE;
-                        break;
-                }
-            }
-        }
-        if (byteIsInvalid) continue;
-
-        // If the byte is valid and pendingDataLength is 0, we are ready to send the message.
-        if (pendingDataLength == 0) {
-            MIDI_QueueAddShort(handle->h.queue, packedMsg, (INT64) (AudioConvertHostTimeToNanos(ts) + 500) / 1000, TRUE);
-        }
-    }
-
-}
-
-static void midiReadProc(const MIDIPacketList* packetList, void* refCon, void* connRefCon) {
-    unsigned int i;
-    const MIDIPacket* packet;
-    MacMidiDeviceHandle* handle = (MacMidiDeviceHandle*) connRefCon;
-
-    packet = packetList->packet;
-    for (i = 0; i < packetList->numPackets; ++i) {
-        processMessagesForPacket(packet, handle);
-        packet = MIDIPacketNext(packet);
-    }
-
-    // Notify the waiting thread that there's data available.
-    if (handle) {
-        MIDI_SignalConditionVariable(handle->h.platformData);
-    }
-}
-
-static void midiInit() {
-    if (client) {
-        return;
-    }
-
-    OSStatus err = noErr;
-
-    err = MIDIClientCreate(CFSTR("MIDI Client"), NULL, NULL, &client);
-    if (err != noErr) { goto Exit; }
-
-    // This just creates an input port through which the client may receive
-    // incoming MIDI messages from any MIDI source.
-    err = MIDIInputPortCreate(client, CFSTR("MIDI Input Port"), midiReadProc, NULL, &inPort);
-    if (err != noErr) { goto Exit; }
-
-    err = MIDIOutputPortCreate(client, CFSTR("MIDI Output Port"), &outPort);
-    if (err != noErr) { goto Exit; }
-
-Exit:
-    if (err != noErr) {
-        const char* s = MIDI_Utils_GetErrorMsg(err);
-        if (s != NULL) {
-            printf("%s\n", s);
-        }
-    }
-}
-
-
-INT32 MIDI_Utils_OpenDevice(int direction, INT32 deviceID, MacMidiDeviceHandle** handle,
-                            int num_msgs, int num_long_msgs,
-                            size_t lm_size)
-{
-    midiInit();
-
-    int err = MIDI_ERROR_NONE;
-    MIDIEndpointRef endpoint = (MIDIEndpointRef) NULL;
-
-    TRACE0("MIDI_Utils_OpenDevice\n");
-
-    (*handle) = (MacMidiDeviceHandle*) malloc(sizeof(MacMidiDeviceHandle));
-    if (!(*handle)) {
-        ERROR0("ERROR: MIDI_Utils_OpenDevice: out of memory\n");
-        return MIDI_OUT_OF_MEMORY;
-    }
-    memset(*handle, 0, sizeof(MacMidiDeviceHandle));
-
-    // Create the infrastructure for MIDI in/out, and after that,
-    // get the device's endpoint.
-    if (direction == MIDI_IN) {
-        // Create queue and the pthread condition variable.
-        (*handle)->h.queue = MIDI_CreateQueue(num_msgs);
-        (*handle)->h.platformData = MIDI_CreateConditionVariable();
-        if (!(*handle)->h.queue || !(*handle)->h.platformData) {
-            ERROR0("< ERROR: MIDI_IN_OpenDevice: could not create queue or condition variable\n");
-            free(*handle);
-            (*handle) = NULL;
-            return MIDI_OUT_OF_MEMORY;
-        }
-        endpoint = MIDIGetSource(deviceID);
-        (*handle)->port = inPort;
-    } else if (direction == MIDI_OUT) {
-        endpoint = MIDIGetDestination(deviceID);
-        (*handle)->port = outPort;
-    }
-
-    if (!endpoint) {
-        // An error occurred.
-        free(*handle);
-        return MIDI_INVALID_DEVICEID;
-    }
-    (*handle)->h.deviceHandle = (void*) (intptr_t) endpoint;
-    (*handle)->h.startTime = getCurrentTimeInNanos();
-    (*handle)->direction = direction;
-    (*handle)->deviceID = deviceID;
-
-    TRACE0("MIDI_Utils_OpenDevice: succeeded\n");
-    return err;
-}
-
-
-INT32 MIDI_Utils_CloseDevice(MacMidiDeviceHandle* handle) {
-    int err = MIDI_ERROR_NONE;
-    bool midiIn = (handle->direction == MIDI_IN);
-
-    TRACE0("> MIDI_Utils_CloseDevice\n");
-    if (!handle) {
-        ERROR0("< ERROR: MIDI_Utils_CloseDevice: handle is NULL\n");
-        return MIDI_INVALID_HANDLE;
-    }
-    if (!handle->h.deviceHandle) {
-        ERROR0("< ERROR: MIDI_Utils_CloseDevice: native handle is NULL\n");
-        return MIDI_INVALID_HANDLE;
-    }
-    handle->isStarted = FALSE;
-    handle->h.deviceHandle = NULL;
-
-    if (midiIn) {
-        if (handle->h.queue != NULL) {
-            MidiMessageQueue* queue = handle->h.queue;
-            handle->h.queue = NULL;
-            MIDI_DestroyQueue(queue);
-        }
-        if (handle->h.platformData) {
-            MIDI_DestroyConditionVariable(handle->h.platformData);
-        }
-    }
-    free(handle);
-
-    TRACE0("< MIDI_Utils_CloseDevice: succeeded\n");
-    return err;
-}
-
-
-INT32 MIDI_Utils_StartDevice(MacMidiDeviceHandle* handle) {
-    OSStatus err = noErr;
-
-    if (!handle || !handle->h.deviceHandle) {
-        ERROR0("ERROR: MIDI_Utils_StartDevice: handle or native is NULL\n");
-        return MIDI_INVALID_HANDLE;
-    }
-
-    // Clears all the events from the queue.
-    MIDI_QueueClear(handle->h.queue);
-
-    if (!handle->isStarted) {
-        /* set the flag that we can now receive messages */
-        handle->isStarted = TRUE;
-
-        if (handle->direction == MIDI_IN) {
-            // The handle->h.platformData field contains the (pthread_cond_t*)
-            // associated with the source of the MIDI input stream, and is
-            // used in the CoreMIDI's callback to signal the arrival of new
-            // data.
-            //
-            // Similarly, handle->h.queue is used in the CoreMDID's callback
-            // to dispatch the incoming messages to the appropriate queue.
-            //
-            err = MIDIPortConnectSource(inPort, (MIDIEndpointRef) (intptr_t) (handle->h.deviceHandle), (void*) handle);
-        } else if (handle->direction == MIDI_OUT) {
-            // Unschedules previous-sent packets.
-            err = MIDIFlushOutput((MIDIEndpointRef) (intptr_t) handle->h.deviceHandle);
-        }
-
-        MIDI_CHECK_ERROR;
-    }
-    return MIDI_SUCCESS; /* don't fail */
-}
-
-
-INT32 MIDI_Utils_StopDevice(MacMidiDeviceHandle* handle) {
-    OSStatus err = noErr;
-
-    if (!handle || !handle->h.deviceHandle) {
-        ERROR0("ERROR: MIDI_Utils_StopDevice: handle or native handle is NULL\n");
-        return MIDI_INVALID_HANDLE;
-    }
-
-    if (handle->isStarted) {
-        /* set the flag that we don't want to receive messages anymore */
-        handle->isStarted = FALSE;
-
-        if (handle->direction == MIDI_IN) {
-            err = MIDIPortDisconnectSource(inPort, (MIDIEndpointRef) (intptr_t) (handle->h.deviceHandle));
-        } else if (handle->direction == MIDI_OUT) {
-            // Unschedules previously-sent packets.
-            err = MIDIFlushOutput((MIDIEndpointRef) (intptr_t) handle->h.deviceHandle);
-        }
-
-        MIDI_CHECK_ERROR;
-    }
-    return MIDI_SUCCESS;
-}
-
-
-INT64 MIDI_Utils_GetTimeStamp(MacMidiDeviceHandle* handle) {
-
-    if (!handle || !handle->h.deviceHandle) {
-        ERROR0("ERROR: MIDI_Utils_GetTimeStamp: handle or native handle is NULL\n");
-        return (INT64) -1; /* failure */
-    }
-
-    UInt64 delta = getCurrentTimeInNanos() - handle->h.startTime;
-    return (INT64) ((delta + 500) / 1000);
-}
-
-
-/***************************************************************************/
-/*            Condition Variable Support for Mac OS X Port                 */
-/*                                                                         */
-/* This works with the Native Locking Support defined below.  We are using */
-/* POSIX pthread_cond_t/pthread_mutex_t to do locking and synchronization. */
-/*                                                                         */
-/* For MidiDeviceHandle* handle, the mutex reference is stored as handle-> */
-/* queue->lock while the condition variabale reference is stored as handle */
-/* ->platformData.                                                         */
-/***************************************************************************/
-
-// Called from Midi_Utils_Opendevice(...) to create a condition variable
-// used to synchronize between the receive thread created by the CoreMIDI
-// and the Java-initiated MidiInDevice run loop.
-void* MIDI_CreateConditionVariable() {
-    pthread_cond_t* cond = (pthread_cond_t*) malloc(sizeof(pthread_cond_t));
-    pthread_cond_init(cond, NULL);
-    return (void*) cond;
-}
-
-void MIDI_DestroyConditionVariable(void* cond) {
-    while (pthread_cond_destroy((pthread_cond_t*) cond) == EBUSY) {
-        pthread_cond_broadcast((pthread_cond_t*) cond);
-        sched_yield();
-    }
-    return;
-}
-
-// Called from MIDI_IN_GetMessage(...) to wait for MIDI messages to become
-// available via delivery from the CoreMIDI receive thread
-void MIDI_WaitOnConditionVariable(void* cond, void* lock) {
-    if (cond && lock) {
-        pthread_mutex_lock(lock);
-        pthread_cond_wait((pthread_cond_t*) cond, (pthread_mutex_t*) lock);
-        pthread_mutex_unlock(lock);
-    }
-    return;
-}
-
-// Called from midiReadProc(...) to notify the waiting thread to unblock on
-// the condition variable.
-void MIDI_SignalConditionVariable(void* cond) {
-    if (cond) {
-        pthread_cond_signal((pthread_cond_t*) cond);
-    }
-    return;
-}
-
-
-/**************************************************************************/
-/*                     Native Locking Support                             */
-/*                                                                        */
-/* @see src/share/natve/com/sun/media/sound/PlatformMidi.c which contains */
-/* utility functions for platform midi support where the section of code  */
-/* for MessageQueue implementation calls out to these functions.          */
-/**************************************************************************/
-
-void* MIDI_CreateLock() {
-    pthread_mutex_t* lock = (pthread_mutex_t*) malloc(sizeof(pthread_mutex_t));
-    pthread_mutex_init(lock, NULL);
-    TRACE0("MIDI_CreateLock\n");
-    return (void *)lock;
-}
-
-void MIDI_DestroyLock(void* lock) {
-    if (lock) {
-        pthread_mutex_destroy((pthread_mutex_t*) lock);
-        free(lock);
-        TRACE0("MIDI_DestroyLock\n");
-    }
-}
-
-void MIDI_Lock(void* lock) {
-    if (lock) {
-        pthread_mutex_lock((pthread_mutex_t*) lock);
-    }
-}
-
-void MIDI_Unlock(void* lock) {
-    if (lock) {
-        pthread_mutex_unlock((pthread_mutex_t*) lock);
-    }
-}
-
-
-#endif // USE_PLATFORM_MIDI_IN || USE_PLATFORM_MIDI_OUT
--- a/src/macosx/native/com/sun/media/sound/PLATFORM_API_MacOS_MidiUtils.h	Thu Dec 22 11:05:51 2011 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code 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
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#if (USE_PLATFORM_MIDI_IN == TRUE) || (USE_PLATFORM_MIDI_OUT == TRUE)
-
-#include "PlatformMidi.h"                  // JavaSound header for platform midi support.
-#include <CoreMIDI/CoreMIDI.h>             // Umbrella header for the CoreMIDI framework.
-#include <CoreAudio/CoreAudio.h>           // This provides access to the host's time base and translations to nanoseconds.
-#include <CoreFoundation/CoreFoundation.h> // CFDataRef.
-
-/* for memcpy */
-#include <string.h>
-/* for malloc */
-#include <stdlib.h>
-/* for usleep */
-#include <unistd.h>
-
-#ifdef USE_ERROR
-#include <stdio.h>
-#endif
-
-#define MIDI_ERROR_NONE MIDI_SUCCESS
-
-#ifdef USE_ERROR
-#define MIDI_CHECK_ERROR  { if (err != MIDI_ERROR_NONE) MIDI_Utils_PrintError(err); }
-#else
-#define MIDI_CHECK_ERROR
-#endif
-
-typedef struct {
-    MidiDeviceHandle h;                  /* the real handle (must be the first field!) */
-    int direction;                       /* direction of the endpoint */
-    int deviceID;                        /* logical index (0 .. numEndpoints-1) */
-    int isStarted;                       /* whether device is "started" */
-    MIDIPortRef port;                    /* input or output port associated with the endpoint */
-    CFMutableDataRef readingSysExData;   /* Non-Null: in the middle of reading SysEx data; Null: otherwise */
-} MacMidiDeviceHandle;
-
-extern const char* MIDI_Utils_GetErrorMsg(int err);
-extern void MIDI_Utils_PrintError(int err);
-
-// A MIDI endpoint represents a source or a destination for a standard 16-channel MIDI data stream.
-enum {
-    MIDI_IN = 0, // source
-    MIDI_OUT = 1 // destination
-};
-
-// The parameter "direction" is either MIDI_IN or MIDI_OUT.
-// Declarations of functions required by the JavaSound MIDI Porting layer.
-
-extern INT32 MIDI_Utils_GetNumDevices(int direction);
-extern INT32 MIDI_Utils_GetDeviceName(int direction, INT32 deviceID, char *name, UINT32 nameLength);
-extern INT32 MIDI_Utils_GetDeviceVendor(int direction, INT32 deviceID, char *name, UINT32 nameLength);
-extern INT32 MIDI_Utils_GetDeviceDescription(int direction, INT32 deviceID, char *name, UINT32 nameLength);
-extern INT32 MIDI_Utils_GetDeviceVersion(int direction, INT32 deviceID, char *name, UINT32 nameLength);
-extern INT32 MIDI_Utils_OpenDevice(int direction, INT32 deviceID, MacMidiDeviceHandle** handle,
-                   int num_msgs, int num_long_msgs,
-                   size_t lm_size);
-extern INT32 MIDI_Utils_CloseDevice(MacMidiDeviceHandle* handle);
-extern INT32 MIDI_Utils_StartDevice(MacMidiDeviceHandle* handle);
-extern INT32 MIDI_Utils_StopDevice(MacMidiDeviceHandle* handle);
-extern INT64 MIDI_Utils_GetTimeStamp(MacMidiDeviceHandle* handle);
-
-// Mac OS X port for locking and synchronization.
-
-extern void* MIDI_CreateConditionVariable();
-extern void  MIDI_DestroyConditionVariable(void* cond);
-extern void  MIDI_WaitOnConditionVariable(void* cond, void* lock);
-extern void  MIDI_SignalConditionVariable(void* cond);
-
-#endif // USE_PLATFORM_MIDI_IN || USE_PLATFORM_MIDI_OUT
--- a/src/macosx/native/jobjc/src/generator/java/com/apple/internal/jobjc/generator/utils/StructOffsetResolver.java	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/native/jobjc/src/generator/java/com/apple/internal/jobjc/generator/utils/StructOffsetResolver.java	Fri Dec 23 22:01:01 2011 +0300
@@ -188,7 +188,7 @@
     protected static String compileObjC(String nativeSrc, Width arch) throws Exception {
         String execPath = nativeSrc.replace(".mm", "");
         Process p = Runtime.getRuntime().exec(new String[]{
-                "g++", "-Wall", gccFlag.get(arch), "-ObjC++", "-framework", "Foundation", "-o", execPath, nativeSrc
+                "llvm-g++", "-Wall", gccFlag.get(arch), "-ObjC++", "-framework", "Foundation", "-o", execPath, nativeSrc
         });
         BufferedReader stdout = new BufferedReader(new InputStreamReader(p.getInputStream()));
         BufferedReader stderr = new BufferedReader(new InputStreamReader(p.getErrorStream()));
--- a/src/macosx/native/sun/awt/AWTView.m	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/native/sun/awt/AWTView.m	Fri Dec 23 22:01:01 2011 +0300
@@ -81,6 +81,15 @@
     fInPressAndHold = NO;
     fPAHNeedsToSelect = NO;
 
+    if (windowLayer != nil) { 
+        self.cglLayer = windowLayer;
+        [self setWantsLayer: YES];
+        [self.layer addSublayer: (CALayer *)cglLayer];
+        [self setLayerContentsRedrawPolicy: NSViewLayerContentsRedrawDuringViewResize];
+        [self setLayerContentsPlacement: NSViewLayerContentsPlacementTopLeft];
+        [self setAutoresizingMask: NSViewHeightSizable | NSViewWidthSizable];    
+    }
+    
 #if USE_INTERMEDIATE_BUFFER
     self.cglLayer = windowLayer;
     [self setWantsLayer: YES];
@@ -115,6 +124,7 @@
 - (void) dealloc {
 AWT_ASSERT_APPKIT_THREAD;
 
+    self.cglLayer = nil;
 #if USE_INTERMEDIATE_BUFFER
     self.cglLayer = nil;
 #endif
@@ -298,6 +308,7 @@
     NSPoint eventLocation = [event locationInWindow];
     NSPoint localPoint = [self convertPoint: eventLocation fromView: nil];
     NSPoint absP = [NSEvent mouseLocation];
+    NSEventType type = [event type];
 
     // Convert global numbers between Cocoa's coordinate system and Java.
     // TODO: need consitent way for doing that both with global as well as with local coordinates.
@@ -307,19 +318,20 @@
     absP.y = screenRect.size.height - absP.y;
     jint clickCount;
 
-    if ([event type] == NSMouseEntered ||
-    [event type] == NSMouseExited ||
-    [event type] == NSScrollWheel) {
+    if (type == NSMouseEntered || 
+        type == NSMouseExited || 
+        type == NSScrollWheel ||
+        type == NSMouseMoved) {
         clickCount = 0;
     } else {
         clickCount = [event clickCount];
     }
-
+    
     jint modifiers = GetJavaMouseModifiers(event);
     static JNF_CLASS_CACHE(jc_NSEvent, "sun/lwawt/macosx/event/NSEvent");
     static JNF_CTOR_CACHE(jctor_NSEvent, jc_NSEvent, "(IIIIIIIIDD)V");
     jobject jEvent = JNFNewObject(env, jctor_NSEvent,
-                                  [event type],
+                                  type, 
                                   modifiers,
                                   clickCount,
                                   [event buttonNumber],
--- a/src/macosx/native/sun/awt/AWTWindow.h	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/native/sun/awt/AWTWindow.h	Fri Dec 23 22:01:01 2011 +0300
@@ -57,6 +57,7 @@
                     frameRect:(NSRect)frameRect
                   contentView:(NSView *)contentView;
 
+- (void) adjustGrowBoxWindow;
 @end
 
 #endif _AWTWINDOW_H
--- a/src/macosx/native/sun/awt/AWTWindow.m	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/native/sun/awt/AWTWindow.m	Fri Dec 23 22:01:01 2011 +0300
@@ -142,9 +142,13 @@
     if (IS(mask, DOCUMENT_MODIFIED)) {
         [self setDocumentEdited:IS(bits, DOCUMENT_MODIFIED)];
     }
-
-    if ([self respondsToSelector:@selector(toggleFullScreen:)] && IS(mask, FULLSCREENABLE)) {
-        [self setCollectionBehavior:(1 << 7) /*NSWindowCollectionBehaviorFullScreenPrimary*/];
+    
+    if ([self respondsToSelector:@selector(toggleFullScreen:)]) {
+        if (IS(mask, FULLSCREENABLE)) {
+            [self setCollectionBehavior:(1 << 7) /*NSWindowCollectionBehaviorFullScreenPrimary*/];
+        } else {
+            [self setCollectionBehavior:NSWindowCollectionBehaviorDefault];
+        }
     }
 
 }
@@ -928,16 +932,30 @@
 JNF_COCOA_ENTER(env);
 
     AWTWindow *window = OBJC(windowPtr);
-    if (![window respondsToSelector:@selector(toggleFullScreen:)]) return;
+    SEL toggleFullScreenSelector = @selector(toggleFullScreen:);
+    if (![window respondsToSelector:toggleFullScreenSelector]) return;
 
-        [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
-                [window toggleFullScreen:nil];
-        }];
+    [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
+        [window performSelector:toggleFullScreenSelector withObject:nil];
+    }];
 
 JNF_COCOA_EXIT(env);
 }
 
+/*
+ * Class:     sun_lwawt_macosx_CPlatformWindow
+ * Method:    isApplicationActive
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeIsApplicationActive
+(JNIEnv *env, jclass clazz)
+{
+JNF_COCOA_ENTER(env);
 
+    return (jboolean)[NSRunningApplication currentApplication].active;
+
+JNF_COCOA_EXIT(env);
+}
 
 JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CMouseInfoPeer_nativeIsWindowUnderMouse
 (JNIEnv *env, jclass clazz, jlong windowPtr)
--- a/src/macosx/native/sun/awt/AWT_debug.h	Thu Dec 22 11:05:51 2011 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code 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
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#ifndef macosx_port_awt_debug_h
-#define macosx_port_awt_debug_h
-
-#import <Cocoa/Cocoa.h>
-
-
-#define kInternalError "java/lang/InternalError"
-
-#define AWT_DEBUG_LOG(str) \
-    NSLog(@"Cocoa AWT: %@ %@", str, [NSThread callStackSymbols])
-
-#define AWT_DEBUG_BUG_REPORT_MESSAGE \
-    NSLog(@"\tPlease file a bug report at http://java.net/jira/browse/MACOSX_PORT with this message and a reproducible test case.")
-
-#endif
--- a/src/macosx/native/sun/awt/CDragSource.m	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/native/sun/awt/CDragSource.m	Fri Dec 23 22:01:01 2011 +0300
@@ -563,6 +563,8 @@
         JNF_MEMBER_CACHE(dragDropFinishedMethod, CDragSourceContextPeerClass, "dragDropFinished", "(ZIII)V");
         DLog3(@"  -> posting dragDropFinished, point %f, %f", point.x, point.y);
         JNFCallVoidMethod(env, fDragSourceContextPeer, dragDropFinishedMethod, success, dragOp, (jint) point.x, (jint) point.y); // AWT_THREADING Safe (event)
+		JNF_MEMBER_CACHE(resetHoveringMethod, CDragSourceContextPeerClass, "resetHovering", "()V");
+        JNFCallVoidMethod(env, fDragSourceContextPeer, resetHoveringMethod); // Hust reset static variable
     } @finally {
         // Clear the current DragSource
         sCurrentDragSource = nil;
--- a/src/macosx/native/sun/awt/CDropTarget.m	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/native/sun/awt/CDropTarget.m	Fri Dec 23 22:01:01 2011 +0300
@@ -320,7 +320,8 @@
 
 - (jobject) copyDraggingDataForFormat:(jlong)format
 {
-    JNIEnv*      env = [ThreadUtilities getJNIEnv]; // Can be called from threads other than the native event thread!
+    JNIEnv*      env = [ThreadUtilities getJNIEnvUncached]; // Join the main thread by requesting uncached environment
+
     NSData*      data = nil;
 
     // Convert the Java format (datatransferer int index) to a pasteboard format (NSString):
@@ -361,8 +362,10 @@
     (*env)->ReleaseByteArrayElements(env, gbyteArray, jbytes, JNI_COMMIT);
 
     // In case of an error make sure to return nil:
-    if (!(*env)->ExceptionOccurred(env))
+    if ((*env)->ExceptionOccurred(env)) {
+		(*env)->ExceptionDescribe(env);
         gbyteArray = nil;
+	}
 
     return gbyteArray;
 }
@@ -567,6 +570,8 @@
     // Should we notify Java things have changed?
     if (sDraggingError == FALSE && notifyJava) {
         NSPoint javaLocation = [fView convertPoint:sDraggingLocation fromView:nil];
+		// For some reason even after the convertPoint drag events come with the y coordinate reverted
+		javaLocation.y = fView.frame.size.height - javaLocation.y;
         //DLog5(@"  : dragMoved: loc native %f, %f, java %f, %f\n", sDraggingLocation.x, sDraggingLocation.y, javaLocation.x, javaLocation.y);
 
         jlongArray formats = sDraggingFormats;
--- a/src/macosx/native/sun/awt/CDropTargetContextPeer.m	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/native/sun/awt/CDropTargetContextPeer.m	Fri Dec 23 22:01:01 2011 +0300
@@ -79,7 +79,7 @@
     }
 
     JNF_MEMBER_CACHE(newDataMethod, jc_CDropTargetContextPeer, "newData", "(J[B)V");
-    if (!(*env)->ExceptionOccurred(env) || !newDataMethod) {
+    if ((*env)->ExceptionOccurred(env) || !newDataMethod) {
         DLog2(@"[CDropTargetContextPeer startTransfer]: couldn't get newData method for %d.\n", (NSInteger) jdroptarget);
         TransferFailed(env, jthis, jdroptarget, (jlong) 0L, jformat);
         return result;
--- a/src/macosx/native/sun/awt/CRobot.m	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/native/sun/awt/CRobot.m	Fri Dec 23 22:01:01 2011 +0300
@@ -23,21 +23,11 @@
  * questions.
  */
 
-// Directly reading the framebuffer via CGDisplayAddressForPosition()
-// is discouraged, and may not work well for all pointer sizes on some machines.
-// CoreGraphics recommends using a more abstract yet faster mechanisms to
-// read framebuffer content.  The use of OpenGL to read back pixels is
-// generally a good idea.
-
-#import <Carbon/Carbon.h>
 #import <JavaNativeFoundation/JavaNativeFoundation.h>
 #import <ApplicationServices/ApplicationServices.h>
-#import <OpenGL/OpenGL.h>
-#import <OpenGL/gl.h>
-#import <OpenGL/glu.h>
+
 
 #import "LWCToolkit.h"
-
 #import "sun_lwawt_macosx_CRobot.h"
 
 // Theoretically, Quarts works with up to 32 buttons.
@@ -48,14 +38,22 @@
 #define kCGBitmapByteOrder32Host 0
 #endif
 
+// In OS X, left and right mouse button share the same click count.
+// That is, if one starts clicking the left button rapidly and then
+// switches to the right button, then the click count will continue
+// increasing, without dropping to 1 in between. The middle button,
+// however, has its own click count.
+// For robot, we aren't going to emulate all that complexity. All our
+// synhtetic clicks share the same click count.
+static int gsClickCount;
+static NSTimeInterval gsLastClickTime;
+
 static inline CGKeyCode GetCGKeyCode(jint javaKeyCode);
 
-static void SwizzleBitmap(void* data, int rowBytes, int height);
-static void cleanContext(CGLContextObj glContextObj);
-static CGLContextObj InitContext(CGDirectDisplayID display);
+static void postMouseEvent(const CGPoint point, CGMouseButton button, 
+                           CGEventType type, int clickCount);
 
-static void postMouseEvent(const CGPoint point, CGMouseButton button,
-                           CGEventType type);
+static int GetClickCount(BOOL isDown);
 
 static void
 CreateJavaException(JNIEnv* env, CGError err)
@@ -78,7 +76,7 @@
     // Set things up to let our app act like a synthetic keyboard and mouse.
     // Always set all states, in case Apple ever changes default behaviors.
     static int setupDone = 0;
-    if (!setupDone) {
+    if (!setupDone) {        
         setupDone = 1;
         // Don't block local events after posting ours
         CGSetLocalEventsSuppressionInterval(0.0);
@@ -93,6 +91,9 @@
         CGSetLocalEventsFilterDuringSupressionState(
                                     kCGEventFilterMaskPermitAllEvents,
                                     kCGEventSupressionStateRemoteMouseDrag);
+        
+        gsClickCount = 0;
+        gsLastClickTime = 0;
     }
 }
 
@@ -162,8 +163,10 @@
     point.x = mouseLastX + globalDeviceBounds.origin.x;
     point.y = mouseLastY + globalDeviceBounds.origin.y;
 
+    BOOL isDown = NO;
     CGMouseButton button = kCGMouseButtonLeft;
     CGEventType type = kCGEventMouseMoved;
+    int clickCount = 0;
 
     // When moving, the buttons aren't changed from their current state.
     if (mouseMoveAction == JNI_FALSE) {
@@ -174,6 +177,7 @@
             button = kCGMouseButtonLeft;
             if (mouse1State == sun_lwawt_macosx_CRobot_BUTTON_STATE_DOWN) {
                 type = kCGEventLeftMouseDown;
+                isDown = YES;
             } else {
                 type = kCGEventLeftMouseUp;
             }
@@ -184,6 +188,7 @@
             button = kCGMouseButtonCenter;
             if (mouse2State == sun_lwawt_macosx_CRobot_BUTTON_STATE_DOWN) {
                 type = kCGEventOtherMouseDown;
+                isDown = YES;
             } else {
                 type = kCGEventOtherMouseUp;
             }
@@ -194,10 +199,13 @@
             button = kCGMouseButtonRight;
             if (mouse3State == sun_lwawt_macosx_CRobot_BUTTON_STATE_DOWN) {
                 type = kCGEventRightMouseDown;
+                isDown = YES;
             } else {
                 type = kCGEventRightMouseUp;
             }
         }
+        
+        clickCount = GetClickCount(isDown);        
     } else {
         // could be mouse moved or mouse dragged
         if (mouse1State == sun_lwawt_macosx_CRobot_BUTTON_STATE_DOWN) {
@@ -211,7 +219,7 @@
         }
     }
 
-    postMouseEvent(point, button, type);
+    postMouseEvent(point, button, type, clickCount);    
 
     JNF_COCOA_EXIT(env);
 }
@@ -244,12 +252,26 @@
 Java_sun_lwawt_macosx_CRobot_keyEvent
 (JNIEnv *env, jobject peer, jint javaKeyCode, jboolean keyPressed)
 {
+    /*
+     * Well, using CGEventCreateKeyboardEvent/CGEventPost would have been 
+     * a better solution, however, it gives me all kinds of trouble and I have
+     * no idea how to solve them without inserting delays between simulated 
+     * events. So, I've ended up disabling it and opted for another approach 
+     * that uses Accessibility API instead. 
+     */
     CGKeyCode keyCode = GetCGKeyCode(javaKeyCode);
+    AXUIElementRef elem = AXUIElementCreateSystemWide();    
+    AXUIElementPostKeyboardEvent(elem, (CGCharCode)0, keyCode, keyPressed);
+    CFRelease(elem);
+
+    
+#if 0
     CGEventRef event = CGEventCreateKeyboardEvent(NULL, keyCode, keyPressed);
     if (event != NULL) {
         CGEventPost(kCGSessionEventTap, event);
         CFRelease(event);
     }
+#endif
 }
 
 /*
@@ -314,10 +336,11 @@
  ****************************************************/
 
 static void postMouseEvent(const CGPoint point, CGMouseButton button,
-                           CGEventType type)
-{
+                           CGEventType type, int clickCount)
+{ 
     CGEventRef mouseEvent = CGEventCreateMouseEvent(NULL, type, point, button);
     if (mouseEvent != NULL) {
+        CGEventSetIntegerValueField(mouseEvent, kCGMouseEventClickState, clickCount); 
         CGEventPost(kCGSessionEventTap, mouseEvent);
         CFRelease(mouseEvent);
     }
@@ -559,3 +582,28 @@
         return javaToMacKeyCode[javaKeyCode];
     }
 }
+
+static int GetClickCount(BOOL isDown) {    
+    NSTimeInterval now = [[NSDate date] timeIntervalSinceReferenceDate];
+    NSTimeInterval clickInterval = now - gsLastClickTime;
+    BOOL isWithinTreshold = clickInterval < [NSEvent doubleClickInterval]; 
+    
+    if (isDown) {
+        if (isWithinTreshold) {
+            gsClickCount++;
+        } else {
+            gsClickCount = 1;        
+        }
+        
+        gsLastClickTime = now;
+    } else { 
+        // In OS X, a mouse up has the click count of the last mouse down 
+        // if an interval between up and down is within the double click
+        // threshold, and 0 otherwise.
+        if (!isWithinTreshold) {
+            gsClickCount = 0;
+        }
+    }
+    
+    return gsClickCount;
+}
--- a/src/macosx/native/sun/awt/CTrayIcon.h	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/native/sun/awt/CTrayIcon.h	Fri Dec 23 22:01:01 2011 +0300
@@ -36,13 +36,14 @@
 extern "C" {
 #endif
 
+@class AWTTrayIconView;
+
 /*
  * AWTTrayIcon
  */
 @interface AWTTrayIcon : NSObject {
     jobject peer;
-    NSButton *button;
-    // May still be required for representation of the button
+    AWTTrayIconView *view;
     NSStatusItem *theItem;
 }
 
@@ -50,22 +51,25 @@
 - (void) setTooltip:(NSString *)tooltip;
 - (NSStatusItem *)theItem;
 - (jobject) peer;
-- (NSButton *) button;
 - (void) setImage:(NSImage *) imagePtr sizing:(BOOL)autosize;
+- (NSPoint) getLocationOnScreen;
 
 @end //AWTTrayIcon
 
 //==================================================================================
 /*
- * AWTNSButton
- */
-@interface AWTNSButton : NSButton {
+ * AWTTrayIconView */
+@interface AWTTrayIconView : NSView <NSMenuDelegate> {
 @public
     AWTTrayIcon *trayIcon;
+    NSImage* image;
+    BOOL isHighlighted;
 }
 -(id)initWithTrayIcon:(AWTTrayIcon *)theTrayIcon;
+-(void)setHighlighted:(BOOL)aFlag;
+-(void)setImage:(NSImage*)anImage;
 
-@end //AWTNSButton
+@end //AWTTrayIconView
 
 #ifdef __cplusplus
 }
--- a/src/macosx/native/sun/awt/CTrayIcon.m	Thu Dec 22 11:05:51 2011 -0800
+++ b/src/macosx/native/sun/awt/CTrayIcon.m	Fri Dec 23 22:01:01 2011 +0300
@@ -28,7 +28,28 @@
 
 #import "CTrayIcon.h"
 #import "ThreadUtilities.h"
+#include "GeomUtilities.h"
 
+#define kImageInset 4.0
+
+/**
+ * If the image of the specified size won't fit into the status bar,
+ * then scale it down proprtionally. Otherwise, leave it as is.
+ */
+static NSSize ScaledImageSizeForStatusBar(NSSize imageSize) {
+    NSRect imageRect = NSMakeRect(0.0, 0.0, imageSize.width, imageSize.height);
+    
+    // There is a black line at the bottom of the status bar  
+    // that we don't want to cover with image pixels.
+    CGFloat desiredHeight = [[NSStatusBar systemStatusBar] thickness] - 1.0;
+    CGFloat scaleFactor = MIN(1.0, desiredHeight/imageSize.height);
+    
+    imageRect.size.width *= scaleFactor;
+    imageRect.size.height *= scaleFactor;
+    imageRect = NSIntegralRect(imageRect);
+    
+    return imageRect.size;
+}
 
 @implementation AWTTrayIcon
 
@@ -37,14 +58,11 @@
 
     peer = thePeer;
 
-    theItem = [[NSStatusBar systemStatusBar] statusItemWithLength:30.0];
+    theItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];  
     [theItem retain];
 
-    [theItem setTitle: NSLocalizedString(@"123", @"")];
-    [theItem setHighlightMode:YES];
-
-    button = [[AWTNSButton alloc] initWithTrayIcon:self];
-    [theItem setView:button];
+    view = [[AWTTrayIconView alloc] initWithTrayIcon:self];
+    [theItem setView:view];
 
     return self;
 }
@@ -53,17 +71,14 @@
     JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
     JNFDeleteGlobalRef(env, peer);
 
-    [button release];
+    [view release];    
     [theItem release];
 
     [super dealloc];
 }
 
 - (void) setTooltip:(NSString *) tooltip{
-    [[self button] setToolTip:tooltip];
-}
-
-- (void) menuDidClose:(NSMenu *)menu {
+    [view setToolTip:tooltip];
 }
 
 -(NSStatusItem *) theItem{
@@ -74,38 +89,92 @@
     return peer;
 }
 
-
--(NSButton *)button{
-    return button;
+- (void) setImage:(NSImage *) imagePtr sizing:(BOOL)autosize{
+    NSSize imageSize = [imagePtr size];
+    NSSize scaledSize = ScaledImageSizeForStatusBar(imageSize);
+    if (imageSize.width != scaledSize.width || 
+        imageSize.height != scaledSize.height) {
+        [imagePtr setSize: scaledSize];
+    }
+    
+    [view setImage:imagePtr];
 }