| @@ -3,6 +3,8 @@ | |||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |||
| <plist> | |||
| <dict> | |||
| <key>LSRequiresIPhoneOS</key> | |||
| <true/> | |||
| <key>CFBundleExecutable</key> | |||
| <string>${EXECUTABLE_NAME}</string> | |||
| <key>CFBundleIconFile</key> | |||
| @@ -43,7 +43,7 @@ public: | |||
| //============================================================================== | |||
| void initialise (const String& /*commandLine*/) | |||
| { | |||
| #if JUCE_IOS | |||
| #if JUCE_IOS || JUCE_ANDROID | |||
| theMainWindow.setVisible (true); | |||
| theMainWindow.setFullScreen (true); | |||
| #else | |||
| @@ -58,7 +58,7 @@ public: | |||
| getSDKPath() = "${user.home}/SDKs/android-sdk-mac_86"; | |||
| if (getNDKPath().toString().isEmpty()) | |||
| getNDKPath() = "${user.home}/SDKs/android-ndk-r4-crystax"; | |||
| getNDKPath() = "${user.home}/SDKs/android-ndk-r5"; | |||
| } | |||
| //============================================================================== | |||
| @@ -186,7 +186,7 @@ private: | |||
| mo << "# Automatically generated makefile, created by the Jucer" << newLine | |||
| << "# Don't edit this file! Your changes will be overwritten when you re-save the Jucer project!" << newLine | |||
| << newLine | |||
| << "APP_STL := stlport_static" << newLine | |||
| << "APP_STL := gnustl_static" << newLine | |||
| << "APP_CPPFLAGS += -fsigned-char -fexceptions -frtti" << newLine; | |||
| overwriteFileIfDifferentOrThrow (file, mo); | |||
| @@ -3,6 +3,8 @@ | |||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |||
| <plist> | |||
| <dict> | |||
| <key>LSRequiresIPhoneOS</key> | |||
| <true/> | |||
| <key>CFBundleExecutable</key> | |||
| <string>${EXECUTABLE_NAME}</string> | |||
| <key>CFBundleIconFile</key> | |||
| @@ -32376,7 +32376,7 @@ void AudioUnitPluginInstance::setCurrentProgram (int newIndex) | |||
| current.presetName = 0; | |||
| AudioUnitSetProperty (audioUnit, | |||
| kAudioUnitProperty_FactoryPresets, | |||
| kAudioUnitProperty_PresentPreset, | |||
| kAudioUnitScope_Global, | |||
| 0, ¤t, sizeof (AUPreset)); | |||
| } | |||
| @@ -69159,7 +69159,7 @@ public: | |||
| if (shortcutKey.isNotEmpty()) | |||
| shortcutKey << ", "; | |||
| if (key.length() == 1) | |||
| if (key.length() == 1 && key[0] < 128) | |||
| shortcutKey << "shortcut: '" << key << '\''; | |||
| else | |||
| shortcutKey << key; | |||
| @@ -259074,7 +259074,6 @@ public: | |||
| wildCard (wildCard_), | |||
| dir (opendir (directory.getFullPathName().toUTF8())) | |||
| { | |||
| wildcardUTF8 = wildCard.toUTF8(); | |||
| } | |||
| ~Pimpl() | |||
| @@ -259089,6 +259088,8 @@ public: | |||
| { | |||
| if (dir != 0) | |||
| { | |||
| const char* wildcardUTF8 = 0; | |||
| for (;;) | |||
| { | |||
| struct dirent* const de = readdir (dir); | |||
| @@ -259096,6 +259097,9 @@ public: | |||
| if (de == 0) | |||
| break; | |||
| if (wildcardUTF8 == 0) | |||
| wildcardUTF8 = wildCard.toUTF8(); | |||
| if (fnmatch (wildcardUTF8, de->d_name, FNM_CASEFOLD) == 0) | |||
| { | |||
| filenameFound = CharPointer_UTF8 (de->d_name); | |||
| @@ -259115,7 +259119,6 @@ public: | |||
| private: | |||
| String parentDir, wildCard; | |||
| const char* wildcardUTF8; | |||
| DIR* dir; | |||
| JUCE_DECLARE_NON_COPYABLE (Pimpl); | |||
| @@ -269059,8 +269062,6 @@ public: | |||
| const ScopedAutoReleasePool pool; | |||
| enumerator = [[[NSFileManager defaultManager] enumeratorAtPath: juceStringToNS (directory.getFullPathName())] retain]; | |||
| wildcardUTF8 = wildCard.toUTF8(); | |||
| } | |||
| ~Pimpl() | |||
| @@ -269073,6 +269074,7 @@ public: | |||
| Time* const modTime, Time* const creationTime, bool* const isReadOnly) | |||
| { | |||
| const ScopedAutoReleasePool pool; | |||
| const char* wildcardUTF8 = 0; | |||
| for (;;) | |||
| { | |||
| @@ -269083,6 +269085,9 @@ public: | |||
| [enumerator skipDescendents]; | |||
| filenameFound = nsStringToJuce (file); | |||
| if (wildcardUTF8 == 0) | |||
| wildcardUTF8 = wildCard.toUTF8(); | |||
| if (fnmatch (wildcardUTF8, filenameFound.toUTF8(), FNM_CASEFOLD) != 0) | |||
| continue; | |||
| @@ -269098,7 +269103,6 @@ public: | |||
| private: | |||
| String parentDir, wildCard; | |||
| const char* wildcardUTF8; | |||
| NSDirectoryEnumerator* enumerator; | |||
| JUCE_DECLARE_NON_COPYABLE (Pimpl); | |||
| @@ -283444,6 +283448,7 @@ BEGIN_JUCE_NAMESPACE | |||
| JAVACLASS (activityClass, "com/juce/JuceAppActivity") \ | |||
| JAVACLASS (componentPeerViewClass, "com/juce/ComponentPeerView") \ | |||
| JAVACLASS (fileClass, "java/io/File") \ | |||
| JAVACLASS (systemClass, "java/lang/System") \ | |||
| JAVACLASS (contextClass, "android/content/Context") \ | |||
| JAVACLASS (canvasClass, "android/graphics/Canvas") \ | |||
| JAVACLASS (paintClass, "android/graphics/Paint") \ | |||
| @@ -283482,6 +283487,7 @@ BEGIN_JUCE_NAMESPACE | |||
| METHOD (activityClass, renderGlyph, "renderGlyph", "(CLandroid/graphics/Paint;Landroid/graphics/Matrix;Landroid/graphics/Rect;)[I") \ | |||
| \ | |||
| METHOD (fileClass, fileExists, "exists", "()Z") \ | |||
| STATICMETHOD (systemClass, getProperty, "getProperty", "(Ljava/lang/String;)Ljava/lang/String;") \ | |||
| \ | |||
| METHOD (componentPeerViewClass, setViewName, "setViewName", "(Ljava/lang/String;)V") \ | |||
| METHOD (componentPeerViewClass, layout, "layout", "(IIII)V") \ | |||
| @@ -283982,6 +283988,16 @@ const String SystemClipboard::getTextFromClipboard() | |||
| // compiled on its own). | |||
| #if JUCE_INCLUDED_FILE | |||
| namespace AndroidStatsHelpers | |||
| { | |||
| const String getSystemProperty (const String& name) | |||
| { | |||
| return juceString (LocalRef<jstring> ((jstring) getEnv()->CallStaticObjectMethod (android.systemClass, | |||
| android.getProperty, | |||
| javaString (name).get()))); | |||
| } | |||
| } | |||
| SystemStats::OperatingSystemType SystemStats::getOperatingSystemType() | |||
| { | |||
| return Android; | |||
| @@ -283989,7 +284005,7 @@ SystemStats::OperatingSystemType SystemStats::getOperatingSystemType() | |||
| const String SystemStats::getOperatingSystemName() | |||
| { | |||
| return "Android"; | |||
| return "Android " + AndroidStatsHelpers::getSystemProperty ("os.version"); | |||
| } | |||
| bool SystemStats::isOperatingSystem64Bit() | |||
| @@ -284001,52 +284017,35 @@ bool SystemStats::isOperatingSystem64Bit() | |||
| #endif | |||
| } | |||
| namespace AndroidStatsHelpers | |||
| { | |||
| // TODO | |||
| const String getCpuInfo (const char* const key) | |||
| { | |||
| StringArray lines; | |||
| lines.addLines (File ("/proc/cpuinfo").loadFileAsString()); | |||
| for (int i = lines.size(); --i >= 0;) // (NB - it's important that this runs in reverse order) | |||
| if (lines[i].startsWithIgnoreCase (key)) | |||
| return lines[i].fromFirstOccurrenceOf (":", false, false).trim(); | |||
| return String::empty; | |||
| } | |||
| } | |||
| const String SystemStats::getCpuVendor() | |||
| { | |||
| return AndroidStatsHelpers::getCpuInfo ("vendor_id"); | |||
| return AndroidStatsHelpers::getSystemProperty ("os.arch"); | |||
| } | |||
| int SystemStats::getCpuSpeedInMegaherz() | |||
| { | |||
| return roundToInt (AndroidStatsHelpers::getCpuInfo ("cpu MHz").getFloatValue()); | |||
| return 0; // TODO | |||
| } | |||
| int SystemStats::getMemorySizeInMegabytes() | |||
| { | |||
| struct sysinfo sysi; | |||
| // xxx they forgot to implement sysinfo in the library, dammit! Should put this stuff back when they fix it. | |||
| /* struct sysinfo sysi; | |||
| if (sysinfo (&sysi) == 0) | |||
| return (sysi.totalram * sysi.mem_unit / (1024 * 1024)); | |||
| */ | |||
| DBG ("warning! memory size is unavailable due to an Android bug!"); | |||
| return 0; | |||
| } | |||
| int SystemStats::getPageSize() | |||
| { | |||
| // TODO | |||
| return sysconf (_SC_PAGESIZE); | |||
| } | |||
| const String SystemStats::getLogonName() | |||
| { | |||
| // TODO | |||
| const char* user = getenv ("USER"); | |||
| if (user == 0) | |||
| @@ -284067,11 +284066,10 @@ const String SystemStats::getFullUserName() | |||
| void SystemStats::initialiseStats() | |||
| { | |||
| // TODO | |||
| const String flags (AndroidStatsHelpers::getCpuInfo ("flags")); | |||
| cpuFlags.hasMMX = flags.contains ("mmx"); | |||
| cpuFlags.hasSSE = flags.contains ("sse"); | |||
| cpuFlags.hasSSE2 = flags.contains ("sse2"); | |||
| cpuFlags.has3DNow = flags.contains ("3dnow"); | |||
| cpuFlags.hasMMX = false; | |||
| cpuFlags.hasSSE = false; | |||
| cpuFlags.hasSSE2 = false; | |||
| cpuFlags.has3DNow = false; | |||
| cpuFlags.numCpus = jmax (1, sysconf (_SC_NPROCESSORS_ONLN)); | |||
| } | |||
| @@ -284080,7 +284078,6 @@ void PlatformUtilities::fpuReset() {} | |||
| uint32 juce_millisecondsSinceStartup() throw() | |||
| { | |||
| // TODO | |||
| timespec t; | |||
| clock_gettime (CLOCK_MONOTONIC, &t); | |||
| @@ -284089,8 +284086,6 @@ uint32 juce_millisecondsSinceStartup() throw() | |||
| int64 Time::getHighResolutionTicks() throw() | |||
| { | |||
| // TODO | |||
| timespec t; | |||
| clock_gettime (CLOCK_MONOTONIC, &t); | |||
| @@ -284099,8 +284094,6 @@ int64 Time::getHighResolutionTicks() throw() | |||
| int64 Time::getHighResolutionTicksPerSecond() throw() | |||
| { | |||
| // TODO | |||
| return 1000000; // (microseconds) | |||
| } | |||
| @@ -284911,8 +284904,6 @@ void Thread::setCurrentThreadAffinityMask (const uint32 affinityMask) | |||
| bool File::copyInternal (const File& dest) const | |||
| { | |||
| // TODO | |||
| FileInputStream in (*this); | |||
| if (dest.deleteFile()) | |||
| @@ -284935,8 +284926,6 @@ bool File::copyInternal (const File& dest) const | |||
| void File::findFileSystemRoots (Array<File>& destArray) | |||
| { | |||
| // TODO | |||
| destArray.add (File ("/")); | |||
| } | |||
| @@ -284957,8 +284946,6 @@ bool File::isOnRemovableDrive() const | |||
| bool File::isHidden() const | |||
| { | |||
| // TODO | |||
| return getFileName().startsWithChar ('.'); | |||
| } | |||
| @@ -284981,7 +284968,6 @@ namespace | |||
| const File File::getLinkedTarget() const | |||
| { | |||
| // TODO | |||
| return juce_readlink (getFullPathName().toUTF8(), *this); | |||
| } | |||
| @@ -284994,19 +284980,18 @@ const File File::getSpecialLocation (const SpecialLocationType type) | |||
| case userMusicDirectory: | |||
| case userMoviesDirectory: | |||
| case userApplicationDataDirectory: | |||
| return File (android.appDataDir); | |||
| case userDesktopDirectory: | |||
| return File ("~/Desktop"); | |||
| return File (android.appDataDir); | |||
| case commonApplicationDataDirectory: | |||
| return File (android.appDataDir); | |||
| case globalApplicationsDirectory: | |||
| return File ("/usr"); | |||
| return File ("/system/app"); | |||
| case tempDirectory: | |||
| return File ("~/.temp"); | |||
| //return File (AndroidStatsHelpers::getSystemProperty ("java.io.tmpdir")); | |||
| return File (android.appDataDir).getChildFile (".temp"); | |||
| case invokedExecutableFile: | |||
| case currentExecutableFile: | |||
| @@ -285045,7 +285030,6 @@ public: | |||
| wildCard (wildCard_), | |||
| dir (opendir (directory.getFullPathName().toUTF8())) | |||
| { | |||
| wildcardUTF8 = wildCard.toUTF8(); | |||
| } | |||
| ~Pimpl() | |||
| @@ -285060,6 +285044,8 @@ public: | |||
| { | |||
| if (dir != 0) | |||
| { | |||
| const char* wildcardUTF8 = 0; | |||
| for (;;) | |||
| { | |||
| struct dirent* const de = readdir (dir); | |||
| @@ -285067,6 +285053,9 @@ public: | |||
| if (de == 0) | |||
| break; | |||
| if (wildcardUTF8 == 0) | |||
| wildcardUTF8 = wildCard.toUTF8(); | |||
| if (fnmatch (wildcardUTF8, de->d_name, FNM_CASEFOLD) == 0) | |||
| { | |||
| filenameFound = CharPointer_UTF8 (de->d_name); | |||
| @@ -285086,7 +285075,6 @@ public: | |||
| private: | |||
| String parentDir, wildCard; | |||
| const char* wildcardUTF8; | |||
| DIR* dir; | |||
| JUCE_DECLARE_NON_COPYABLE (Pimpl); | |||
| @@ -287092,17 +287080,17 @@ void juce_updateMultiMonitorInfo (Array <Rectangle<int> >& monitorCoords, const | |||
| JUCE_JNI_CALLBACK (JuceAppActivity, setScreenSize, void, (JNIEnv* env, jobject activity, | |||
| jint screenWidth, jint screenHeight)) | |||
| { | |||
| const bool isSystemInitialised = android.screenWidth != 0; | |||
| android.screenWidth = screenWidth; | |||
| android.screenHeight = screenHeight; | |||
| if (isSystemInitialised) | |||
| Desktop::getInstance().refreshMonitorSizes(); | |||
| } | |||
| const Image juce_createIconForFile (const File& file) | |||
| { | |||
| Image image; | |||
| // TODO | |||
| return image; | |||
| return Image::null; | |||
| } | |||
| void* MouseCursor::createMouseCursorFromImage (const Image& image, int hotspotX, int hotspotY) | |||
| @@ -73,7 +73,7 @@ namespace JuceDummyNamespace {} | |||
| */ | |||
| #define JUCE_MAJOR_VERSION 1 | |||
| #define JUCE_MINOR_VERSION 53 | |||
| #define JUCE_BUILDNUMBER 39 | |||
| #define JUCE_BUILDNUMBER 40 | |||
| /** Current Juce version number. | |||
| @@ -1310,7 +1310,7 @@ void AudioUnitPluginInstance::setCurrentProgram (int newIndex) | |||
| current.presetName = 0; | |||
| AudioUnitSetProperty (audioUnit, | |||
| kAudioUnitProperty_FactoryPresets, | |||
| kAudioUnitProperty_PresentPreset, | |||
| kAudioUnitScope_Global, | |||
| 0, ¤t, sizeof (AUPreset)); | |||
| } | |||
| @@ -33,7 +33,7 @@ | |||
| */ | |||
| #define JUCE_MAJOR_VERSION 1 | |||
| #define JUCE_MINOR_VERSION 53 | |||
| #define JUCE_BUILDNUMBER 39 | |||
| #define JUCE_BUILDNUMBER 40 | |||
| /** Current Juce version number. | |||
| @@ -81,7 +81,7 @@ public: | |||
| if (shortcutKey.isNotEmpty()) | |||
| shortcutKey << ", "; | |||
| if (key.length() == 1) | |||
| if (key.length() == 1 && key[0] < 128) | |||
| shortcutKey << "shortcut: '" << key << '\''; | |||
| else | |||
| shortcutKey << key; | |||
| @@ -1,199 +1,199 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-10 by Raw Material Software Ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the GNU General | |||
| Public License (Version 2), as published by the Free Software Foundation. | |||
| A copy of the license is included in the JUCE distribution, or can be found | |||
| online at www.gnu.org/licenses. | |||
| JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||
| A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||
| ------------------------------------------------------------------------------ | |||
| To release a closed-source product which uses JUCE, commercial licenses are | |||
| available: visit www.rawmaterialsoftware.com/juce for more information. | |||
| ============================================================================== | |||
| */ | |||
| package com.juce; | |||
| import android.app.Activity; | |||
| import android.os.Bundle; | |||
| import android.content.Context; | |||
| import android.view.ViewGroup; | |||
| import android.graphics.Paint; | |||
| import android.graphics.Canvas; | |||
| import android.graphics.Path; | |||
| import android.graphics.Bitmap; | |||
| import android.graphics.Matrix; | |||
| import android.graphics.RectF; | |||
| import android.graphics.Rect; | |||
| import android.text.ClipboardManager; | |||
| import com.juce.ComponentPeerView; | |||
| //============================================================================== | |||
| public final class JuceAppActivity extends Activity | |||
| { | |||
| //============================================================================== | |||
| static | |||
| { | |||
| System.loadLibrary ("juce_jni"); | |||
| } | |||
| @Override | |||
| public final void onCreate (Bundle savedInstanceState) | |||
| { | |||
| super.onCreate (savedInstanceState); | |||
| viewHolder = new ViewHolder (this); | |||
| setContentView (viewHolder); | |||
| } | |||
| @Override | |||
| protected final void onDestroy() | |||
| { | |||
| quitApp(); | |||
| super.onDestroy(); | |||
| } | |||
| private void callAppLauncher() | |||
| { | |||
| launchApp (getApplicationInfo().publicSourceDir, | |||
| getApplicationInfo().dataDir); | |||
| } | |||
| //============================================================================== | |||
| public native void launchApp (String appFile, String appDataDir); | |||
| public native void quitApp(); | |||
| public native void setScreenSize (int screenWidth, int screenHeight); | |||
| //============================================================================== | |||
| public static final void printToConsole (String s) | |||
| { | |||
| android.util.Log.i ("Juce", s); | |||
| } | |||
| //============================================================================== | |||
| public native void deliverMessage (long value); | |||
| private android.os.Handler messageHandler = new android.os.Handler(); | |||
| public final void postMessage (long value) | |||
| { | |||
| messageHandler.post (new MessageCallback (value)); | |||
| } | |||
| final class MessageCallback implements Runnable | |||
| { | |||
| public MessageCallback (long value_) | |||
| { | |||
| value = value_; | |||
| } | |||
| public final void run() | |||
| { | |||
| deliverMessage (value); | |||
| } | |||
| private long value; | |||
| } | |||
| //============================================================================== | |||
| private ViewHolder viewHolder; | |||
| public final ComponentPeerView createNewView (boolean opaque) | |||
| { | |||
| ComponentPeerView v = new ComponentPeerView (this, opaque); | |||
| viewHolder.addView (v); | |||
| return v; | |||
| } | |||
| public final void deleteView (ComponentPeerView view) | |||
| { | |||
| viewHolder.removeView (view); | |||
| } | |||
| final class ViewHolder extends ViewGroup | |||
| { | |||
| public ViewHolder (Context context) | |||
| { | |||
| super (context); | |||
| setDescendantFocusability (ViewGroup.FOCUS_AFTER_DESCENDANTS); | |||
| setFocusable (false); | |||
| } | |||
| protected final void onLayout (boolean changed, int left, int top, int right, int bottom) | |||
| { | |||
| setScreenSize (getWidth(), getHeight()); | |||
| if (isFirstResize) | |||
| { | |||
| isFirstResize = false; | |||
| callAppLauncher(); | |||
| } | |||
| } | |||
| private boolean isFirstResize = true; | |||
| } | |||
| public final void excludeClipRegion (android.graphics.Canvas canvas, float left, float top, float right, float bottom) | |||
| { | |||
| canvas.clipRect (left, top, right, bottom, android.graphics.Region.Op.DIFFERENCE); | |||
| } | |||
| //============================================================================== | |||
| public final String getClipboardContent() | |||
| { | |||
| ClipboardManager clipboard = (ClipboardManager) getSystemService (CLIPBOARD_SERVICE); | |||
| return clipboard.getText().toString(); | |||
| } | |||
| public final void setClipboardContent (String newText) | |||
| { | |||
| ClipboardManager clipboard = (ClipboardManager) getSystemService (CLIPBOARD_SERVICE); | |||
| clipboard.setText (newText); | |||
| } | |||
| //============================================================================== | |||
| public final int[] renderGlyph (char glyph, Paint paint, Matrix matrix, Rect bounds) | |||
| { | |||
| Path p = new Path(); | |||
| paint.getTextPath (String.valueOf (glyph), 0, 1, 0.0f, 0.0f, p); | |||
| RectF boundsF = new RectF(); | |||
| p.computeBounds (boundsF, true); | |||
| matrix.mapRect (boundsF); | |||
| boundsF.roundOut (bounds); | |||
| bounds.left--; | |||
| bounds.right++; | |||
| final int w = bounds.width(); | |||
| final int h = bounds.height(); | |||
| Bitmap bm = Bitmap.createBitmap (w, h, Bitmap.Config.ARGB_8888); | |||
| Canvas c = new Canvas (bm); | |||
| matrix.postTranslate (-bounds.left, -bounds.top); | |||
| c.setMatrix (matrix); | |||
| c.drawPath (p, paint); | |||
| int sizeNeeded = w * h; | |||
| if (cachedRenderArray.length < sizeNeeded) | |||
| cachedRenderArray = new int [sizeNeeded]; | |||
| bm.getPixels (cachedRenderArray, 0, w, 0, 0, w, h); | |||
| bm.recycle(); | |||
| return cachedRenderArray; | |||
| } | |||
| private int[] cachedRenderArray = new int [256]; | |||
| } | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-10 by Raw Material Software Ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the GNU General | |||
| Public License (Version 2), as published by the Free Software Foundation. | |||
| A copy of the license is included in the JUCE distribution, or can be found | |||
| online at www.gnu.org/licenses. | |||
| JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||
| A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||
| ------------------------------------------------------------------------------ | |||
| To release a closed-source product which uses JUCE, commercial licenses are | |||
| available: visit www.rawmaterialsoftware.com/juce for more information. | |||
| ============================================================================== | |||
| */ | |||
| package com.juce; | |||
| import android.app.Activity; | |||
| import android.os.Bundle; | |||
| import android.content.Context; | |||
| import android.view.ViewGroup; | |||
| import android.graphics.Paint; | |||
| import android.graphics.Canvas; | |||
| import android.graphics.Path; | |||
| import android.graphics.Bitmap; | |||
| import android.graphics.Matrix; | |||
| import android.graphics.RectF; | |||
| import android.graphics.Rect; | |||
| import android.text.ClipboardManager; | |||
| import com.juce.ComponentPeerView; | |||
| //============================================================================== | |||
| public final class JuceAppActivity extends Activity | |||
| { | |||
| //============================================================================== | |||
| static | |||
| { | |||
| System.loadLibrary ("juce_jni"); | |||
| } | |||
| @Override | |||
| public final void onCreate (Bundle savedInstanceState) | |||
| { | |||
| super.onCreate (savedInstanceState); | |||
| viewHolder = new ViewHolder (this); | |||
| setContentView (viewHolder); | |||
| } | |||
| @Override | |||
| protected final void onDestroy() | |||
| { | |||
| quitApp(); | |||
| super.onDestroy(); | |||
| } | |||
| private void callAppLauncher() | |||
| { | |||
| launchApp (getApplicationInfo().publicSourceDir, | |||
| getApplicationInfo().dataDir); | |||
| } | |||
| //============================================================================== | |||
| public native void launchApp (String appFile, String appDataDir); | |||
| public native void quitApp(); | |||
| public native void setScreenSize (int screenWidth, int screenHeight); | |||
| //============================================================================== | |||
| public static final void printToConsole (String s) | |||
| { | |||
| android.util.Log.i ("Juce", s); | |||
| } | |||
| //============================================================================== | |||
| public native void deliverMessage (long value); | |||
| private android.os.Handler messageHandler = new android.os.Handler(); | |||
| public final void postMessage (long value) | |||
| { | |||
| messageHandler.post (new MessageCallback (value)); | |||
| } | |||
| final class MessageCallback implements Runnable | |||
| { | |||
| public MessageCallback (long value_) | |||
| { | |||
| value = value_; | |||
| } | |||
| public final void run() | |||
| { | |||
| deliverMessage (value); | |||
| } | |||
| private long value; | |||
| } | |||
| //============================================================================== | |||
| private ViewHolder viewHolder; | |||
| public final ComponentPeerView createNewView (boolean opaque) | |||
| { | |||
| ComponentPeerView v = new ComponentPeerView (this, opaque); | |||
| viewHolder.addView (v); | |||
| return v; | |||
| } | |||
| public final void deleteView (ComponentPeerView view) | |||
| { | |||
| viewHolder.removeView (view); | |||
| } | |||
| final class ViewHolder extends ViewGroup | |||
| { | |||
| public ViewHolder (Context context) | |||
| { | |||
| super (context); | |||
| setDescendantFocusability (ViewGroup.FOCUS_AFTER_DESCENDANTS); | |||
| setFocusable (false); | |||
| } | |||
| protected final void onLayout (boolean changed, int left, int top, int right, int bottom) | |||
| { | |||
| setScreenSize (getWidth(), getHeight()); | |||
| if (isFirstResize) | |||
| { | |||
| isFirstResize = false; | |||
| callAppLauncher(); | |||
| } | |||
| } | |||
| private boolean isFirstResize = true; | |||
| } | |||
| public final void excludeClipRegion (android.graphics.Canvas canvas, float left, float top, float right, float bottom) | |||
| { | |||
| canvas.clipRect (left, top, right, bottom, android.graphics.Region.Op.DIFFERENCE); | |||
| } | |||
| //============================================================================== | |||
| public final String getClipboardContent() | |||
| { | |||
| ClipboardManager clipboard = (ClipboardManager) getSystemService (CLIPBOARD_SERVICE); | |||
| return clipboard.getText().toString(); | |||
| } | |||
| public final void setClipboardContent (String newText) | |||
| { | |||
| ClipboardManager clipboard = (ClipboardManager) getSystemService (CLIPBOARD_SERVICE); | |||
| clipboard.setText (newText); | |||
| } | |||
| //============================================================================== | |||
| public final int[] renderGlyph (char glyph, Paint paint, Matrix matrix, Rect bounds) | |||
| { | |||
| Path p = new Path(); | |||
| paint.getTextPath (String.valueOf (glyph), 0, 1, 0.0f, 0.0f, p); | |||
| RectF boundsF = new RectF(); | |||
| p.computeBounds (boundsF, true); | |||
| matrix.mapRect (boundsF); | |||
| boundsF.roundOut (bounds); | |||
| bounds.left--; | |||
| bounds.right++; | |||
| final int w = bounds.width(); | |||
| final int h = bounds.height(); | |||
| Bitmap bm = Bitmap.createBitmap (w, h, Bitmap.Config.ARGB_8888); | |||
| Canvas c = new Canvas (bm); | |||
| matrix.postTranslate (-bounds.left, -bounds.top); | |||
| c.setMatrix (matrix); | |||
| c.drawPath (p, paint); | |||
| int sizeNeeded = w * h; | |||
| if (cachedRenderArray.length < sizeNeeded) | |||
| cachedRenderArray = new int [sizeNeeded]; | |||
| bm.getPixels (cachedRenderArray, 0, w, 0, 0, w, h); | |||
| bm.recycle(); | |||
| return cachedRenderArray; | |||
| } | |||
| private int[] cachedRenderArray = new int [256]; | |||
| } | |||
| @@ -31,8 +31,6 @@ | |||
| //============================================================================== | |||
| bool File::copyInternal (const File& dest) const | |||
| { | |||
| // TODO | |||
| FileInputStream in (*this); | |||
| if (dest.deleteFile()) | |||
| @@ -55,8 +53,6 @@ bool File::copyInternal (const File& dest) const | |||
| void File::findFileSystemRoots (Array<File>& destArray) | |||
| { | |||
| // TODO | |||
| destArray.add (File ("/")); | |||
| } | |||
| @@ -78,8 +74,6 @@ bool File::isOnRemovableDrive() const | |||
| bool File::isHidden() const | |||
| { | |||
| // TODO | |||
| return getFileName().startsWithChar ('.'); | |||
| } | |||
| @@ -103,7 +97,6 @@ namespace | |||
| const File File::getLinkedTarget() const | |||
| { | |||
| // TODO | |||
| return juce_readlink (getFullPathName().toUTF8(), *this); | |||
| } | |||
| @@ -117,19 +110,18 @@ const File File::getSpecialLocation (const SpecialLocationType type) | |||
| case userMusicDirectory: | |||
| case userMoviesDirectory: | |||
| case userApplicationDataDirectory: | |||
| return File (android.appDataDir); | |||
| case userDesktopDirectory: | |||
| return File ("~/Desktop"); | |||
| return File (android.appDataDir); | |||
| case commonApplicationDataDirectory: | |||
| return File (android.appDataDir); | |||
| case globalApplicationsDirectory: | |||
| return File ("/usr"); | |||
| return File ("/system/app"); | |||
| case tempDirectory: | |||
| return File ("~/.temp"); | |||
| //return File (AndroidStatsHelpers::getSystemProperty ("java.io.tmpdir")); | |||
| return File (android.appDataDir).getChildFile (".temp"); | |||
| case invokedExecutableFile: | |||
| case currentExecutableFile: | |||
| @@ -171,7 +163,6 @@ public: | |||
| wildCard (wildCard_), | |||
| dir (opendir (directory.getFullPathName().toUTF8())) | |||
| { | |||
| wildcardUTF8 = wildCard.toUTF8(); | |||
| } | |||
| ~Pimpl() | |||
| @@ -186,6 +177,8 @@ public: | |||
| { | |||
| if (dir != 0) | |||
| { | |||
| const char* wildcardUTF8 = 0; | |||
| for (;;) | |||
| { | |||
| struct dirent* const de = readdir (dir); | |||
| @@ -193,6 +186,9 @@ public: | |||
| if (de == 0) | |||
| break; | |||
| if (wildcardUTF8 == 0) | |||
| wildcardUTF8 = wildCard.toUTF8(); | |||
| if (fnmatch (wildcardUTF8, de->d_name, FNM_CASEFOLD) == 0) | |||
| { | |||
| filenameFound = CharPointer_UTF8 (de->d_name); | |||
| @@ -212,7 +208,6 @@ public: | |||
| private: | |||
| String parentDir, wildCard; | |||
| const char* wildcardUTF8; | |||
| DIR* dir; | |||
| JUCE_DECLARE_NON_COPYABLE (Pimpl); | |||
| @@ -102,6 +102,7 @@ BEGIN_JUCE_NAMESPACE | |||
| JAVACLASS (activityClass, "com/juce/JuceAppActivity") \ | |||
| JAVACLASS (componentPeerViewClass, "com/juce/ComponentPeerView") \ | |||
| JAVACLASS (fileClass, "java/io/File") \ | |||
| JAVACLASS (systemClass, "java/lang/System") \ | |||
| JAVACLASS (contextClass, "android/content/Context") \ | |||
| JAVACLASS (canvasClass, "android/graphics/Canvas") \ | |||
| JAVACLASS (paintClass, "android/graphics/Paint") \ | |||
| @@ -143,6 +144,7 @@ BEGIN_JUCE_NAMESPACE | |||
| METHOD (activityClass, renderGlyph, "renderGlyph", "(CLandroid/graphics/Paint;Landroid/graphics/Matrix;Landroid/graphics/Rect;)[I") \ | |||
| \ | |||
| METHOD (fileClass, fileExists, "exists", "()Z") \ | |||
| STATICMETHOD (systemClass, getProperty, "getProperty", "(Ljava/lang/String;)Ljava/lang/String;") \ | |||
| \ | |||
| METHOD (componentPeerViewClass, setViewName, "setViewName", "(Ljava/lang/String;)V") \ | |||
| METHOD (componentPeerViewClass, layout, "layout", "(IIII)V") \ | |||
| @@ -27,6 +27,16 @@ | |||
| // compiled on its own). | |||
| #if JUCE_INCLUDED_FILE | |||
| //============================================================================== | |||
| namespace AndroidStatsHelpers | |||
| { | |||
| const String getSystemProperty (const String& name) | |||
| { | |||
| return juceString (LocalRef<jstring> ((jstring) getEnv()->CallStaticObjectMethod (android.systemClass, | |||
| android.getProperty, | |||
| javaString (name).get()))); | |||
| } | |||
| } | |||
| //============================================================================== | |||
| SystemStats::OperatingSystemType SystemStats::getOperatingSystemType() | |||
| @@ -36,7 +46,7 @@ SystemStats::OperatingSystemType SystemStats::getOperatingSystemType() | |||
| const String SystemStats::getOperatingSystemName() | |||
| { | |||
| return "Android"; | |||
| return "Android " + AndroidStatsHelpers::getSystemProperty ("os.version"); | |||
| } | |||
| bool SystemStats::isOperatingSystem64Bit() | |||
| @@ -48,54 +58,36 @@ bool SystemStats::isOperatingSystem64Bit() | |||
| #endif | |||
| } | |||
| //============================================================================== | |||
| namespace AndroidStatsHelpers | |||
| { | |||
| // TODO | |||
| const String getCpuInfo (const char* const key) | |||
| { | |||
| StringArray lines; | |||
| lines.addLines (File ("/proc/cpuinfo").loadFileAsString()); | |||
| for (int i = lines.size(); --i >= 0;) // (NB - it's important that this runs in reverse order) | |||
| if (lines[i].startsWithIgnoreCase (key)) | |||
| return lines[i].fromFirstOccurrenceOf (":", false, false).trim(); | |||
| return String::empty; | |||
| } | |||
| } | |||
| const String SystemStats::getCpuVendor() | |||
| { | |||
| return AndroidStatsHelpers::getCpuInfo ("vendor_id"); | |||
| return AndroidStatsHelpers::getSystemProperty ("os.arch"); | |||
| } | |||
| int SystemStats::getCpuSpeedInMegaherz() | |||
| { | |||
| return roundToInt (AndroidStatsHelpers::getCpuInfo ("cpu MHz").getFloatValue()); | |||
| return 0; // TODO | |||
| } | |||
| int SystemStats::getMemorySizeInMegabytes() | |||
| { | |||
| struct sysinfo sysi; | |||
| // xxx they forgot to implement sysinfo in the library, dammit! Should put this stuff back when they fix it. | |||
| /* struct sysinfo sysi; | |||
| if (sysinfo (&sysi) == 0) | |||
| return (sysi.totalram * sysi.mem_unit / (1024 * 1024)); | |||
| */ | |||
| DBG ("warning! memory size is unavailable due to an Android bug!"); | |||
| return 0; | |||
| } | |||
| int SystemStats::getPageSize() | |||
| { | |||
| // TODO | |||
| return sysconf (_SC_PAGESIZE); | |||
| } | |||
| //============================================================================== | |||
| const String SystemStats::getLogonName() | |||
| { | |||
| // TODO | |||
| const char* user = getenv ("USER"); | |||
| if (user == 0) | |||
| @@ -117,11 +109,10 @@ const String SystemStats::getFullUserName() | |||
| void SystemStats::initialiseStats() | |||
| { | |||
| // TODO | |||
| const String flags (AndroidStatsHelpers::getCpuInfo ("flags")); | |||
| cpuFlags.hasMMX = flags.contains ("mmx"); | |||
| cpuFlags.hasSSE = flags.contains ("sse"); | |||
| cpuFlags.hasSSE2 = flags.contains ("sse2"); | |||
| cpuFlags.has3DNow = flags.contains ("3dnow"); | |||
| cpuFlags.hasMMX = false; | |||
| cpuFlags.hasSSE = false; | |||
| cpuFlags.hasSSE2 = false; | |||
| cpuFlags.has3DNow = false; | |||
| cpuFlags.numCpus = jmax (1, sysconf (_SC_NPROCESSORS_ONLN)); | |||
| } | |||
| @@ -131,7 +122,6 @@ void PlatformUtilities::fpuReset() {} | |||
| //============================================================================== | |||
| uint32 juce_millisecondsSinceStartup() throw() | |||
| { | |||
| // TODO | |||
| timespec t; | |||
| clock_gettime (CLOCK_MONOTONIC, &t); | |||
| @@ -140,8 +130,6 @@ uint32 juce_millisecondsSinceStartup() throw() | |||
| int64 Time::getHighResolutionTicks() throw() | |||
| { | |||
| // TODO | |||
| timespec t; | |||
| clock_gettime (CLOCK_MONOTONIC, &t); | |||
| @@ -150,8 +138,6 @@ int64 Time::getHighResolutionTicks() throw() | |||
| int64 Time::getHighResolutionTicksPerSecond() throw() | |||
| { | |||
| // TODO | |||
| return 1000000; // (microseconds) | |||
| } | |||
| @@ -625,18 +625,18 @@ void juce_updateMultiMonitorInfo (Array <Rectangle<int> >& monitorCoords, const | |||
| JUCE_JNI_CALLBACK (JuceAppActivity, setScreenSize, void, (JNIEnv* env, jobject activity, | |||
| jint screenWidth, jint screenHeight)) | |||
| { | |||
| const bool isSystemInitialised = android.screenWidth != 0; | |||
| android.screenWidth = screenWidth; | |||
| android.screenHeight = screenHeight; | |||
| if (isSystemInitialised) | |||
| Desktop::getInstance().refreshMonitorSizes(); | |||
| } | |||
| //============================================================================== | |||
| const Image juce_createIconForFile (const File& file) | |||
| { | |||
| Image image; | |||
| // TODO | |||
| return image; | |||
| return Image::null; | |||
| } | |||
| //============================================================================== | |||
| @@ -236,7 +236,6 @@ public: | |||
| wildCard (wildCard_), | |||
| dir (opendir (directory.getFullPathName().toUTF8())) | |||
| { | |||
| wildcardUTF8 = wildCard.toUTF8(); | |||
| } | |||
| ~Pimpl() | |||
| @@ -251,6 +250,8 @@ public: | |||
| { | |||
| if (dir != 0) | |||
| { | |||
| const char* wildcardUTF8 = 0; | |||
| for (;;) | |||
| { | |||
| struct dirent* const de = readdir (dir); | |||
| @@ -258,6 +259,9 @@ public: | |||
| if (de == 0) | |||
| break; | |||
| if (wildcardUTF8 == 0) | |||
| wildcardUTF8 = wildCard.toUTF8(); | |||
| if (fnmatch (wildcardUTF8, de->d_name, FNM_CASEFOLD) == 0) | |||
| { | |||
| filenameFound = CharPointer_UTF8 (de->d_name); | |||
| @@ -277,7 +281,6 @@ public: | |||
| private: | |||
| String parentDir, wildCard; | |||
| const char* wildcardUTF8; | |||
| DIR* dir; | |||
| JUCE_DECLARE_NON_COPYABLE (Pimpl); | |||
| @@ -328,8 +328,6 @@ public: | |||
| const ScopedAutoReleasePool pool; | |||
| enumerator = [[[NSFileManager defaultManager] enumeratorAtPath: juceStringToNS (directory.getFullPathName())] retain]; | |||
| wildcardUTF8 = wildCard.toUTF8(); | |||
| } | |||
| ~Pimpl() | |||
| @@ -342,6 +340,7 @@ public: | |||
| Time* const modTime, Time* const creationTime, bool* const isReadOnly) | |||
| { | |||
| const ScopedAutoReleasePool pool; | |||
| const char* wildcardUTF8 = 0; | |||
| for (;;) | |||
| { | |||
| @@ -352,6 +351,9 @@ public: | |||
| [enumerator skipDescendents]; | |||
| filenameFound = nsStringToJuce (file); | |||
| if (wildcardUTF8 == 0) | |||
| wildcardUTF8 = wildCard.toUTF8(); | |||
| if (fnmatch (wildcardUTF8, filenameFound.toUTF8(), FNM_CASEFOLD) != 0) | |||
| continue; | |||
| @@ -367,7 +369,6 @@ public: | |||
| private: | |||
| String parentDir, wildCard; | |||
| const char* wildcardUTF8; | |||
| NSDirectoryEnumerator* enumerator; | |||
| JUCE_DECLARE_NON_COPYABLE (Pimpl); | |||