diff --git a/extras/Jucer (experimental)/Source/Project/jucer_Project.cpp b/extras/Jucer (experimental)/Source/Project/jucer_Project.cpp index a51d3c9a6a..b3c081d8fc 100644 --- a/extras/Jucer (experimental)/Source/Project/jucer_Project.cpp +++ b/extras/Jucer (experimental)/Source/Project/jucer_Project.cpp @@ -322,6 +322,31 @@ void Project::createPropertyEditors (Array & props) props.add (new TextPropertyComponent (getBundleIdentifier(), "Bundle Identifier", 256, false)); props.getLast()->setTooltip ("A unique identifier for this product, mainly for use in Mac builds. It should be something like 'com.yourcompanyname.yourproductname'"); + { + OwnedArray images; + findAllImageItems (images); + + StringArray choices; + Array ids; + + choices.add (""); + ids.add (var::null); + choices.add (String::empty); + ids.add (var::null); + + for (int i = 0; i < images.size(); ++i) + { + choices.add (images.getUnchecked(i)->getName().toString()); + ids.add (images.getUnchecked(i)->getID()); + } + + props.add (new ChoicePropertyComponent (getSmallIconImageItemID(), "Icon (small)", choices, ids)); + props.getLast()->setTooltip ("Sets an icon to use for the executable."); + + props.add (new ChoicePropertyComponent (getBigIconImageItemID(), "Icon (large)", choices, ids)); + props.getLast()->setTooltip ("Sets an icon to use for the executable."); + } + if (isAudioPlugin()) { props.add (new BooleanPropertyComponent (shouldBuildVST(), "Build VST", "Enabled")); @@ -387,6 +412,26 @@ void Project::createPropertyEditors (Array & props) props.getUnchecked(i)->setPreferredHeight (22); } +const Image Project::getBigIcon() +{ + Item icon (getMainGroup().findItemWithID (getBigIconImageItemID().toString())); + + if (icon.isValid()) + return ImageCache::getFromFile (icon.getFile()); + + return Image(); +} + +const Image Project::getSmallIcon() +{ + Item icon (getMainGroup().findItemWithID (getSmallIconImageItemID().toString())); + + if (icon.isValid()) + return ImageCache::getFromFile (icon.getFile()); + + return Image(); +} + //============================================================================== Project::Item Project::getMainGroup() { @@ -659,18 +704,24 @@ bool Project::Item::addFile (const File& file, int insertIndex) DirectoryIterator iter (file, false, "*", File::findFilesAndDirectories); while (iter.next()) - group.addFile (iter.getFile(), -1); + { + if (! project.getMainGroup().findItemForFile (iter.getFile()).isValid()) + group.addFile (iter.getFile(), -1); + } group.sortAlphabetically(); } else if (file.existsAsFile()) { - Item item (project.createNewItem (file)); - - if (canContain (item)) + if (! project.getMainGroup().findItemForFile (file).isValid()) { - item.setFile (file); - addChild (item, insertIndex); + Item item (project.createNewItem (file)); + + if (canContain (item)) + { + item.setFile (file); + addChild (item, insertIndex); + } } } else diff --git a/extras/Jucer (experimental)/Source/Project/jucer_Project.h b/extras/Jucer (experimental)/Source/Project/jucer_Project.h index 2f1abf26a2..996adbe212 100644 --- a/extras/Jucer (experimental)/Source/Project/jucer_Project.h +++ b/extras/Jucer (experimental)/Source/Project/jucer_Project.h @@ -102,6 +102,11 @@ public: //============================================================================== Value getProjectValue (const Identifier& name) const { return projectRoot.getPropertyAsValue (name, getUndoManagerFor (projectRoot)); } + Value getBigIconImageItemID() const { return getProjectValue ("bigIcon"); } + Value getSmallIconImageItemID() const { return getProjectValue ("smallIcon"); } + const Image getBigIcon(); + const Image getSmallIcon(); + Value shouldBuildVST() const { return getProjectValue ("buildVST"); } Value shouldBuildRTAS() const { return getProjectValue ("buildRTAS"); } Value shouldBuildAU() const { return getProjectValue ("buildAU"); } diff --git a/extras/Jucer (experimental)/Source/Project/jucer_ProjectContentComponent.cpp b/extras/Jucer (experimental)/Source/Project/jucer_ProjectContentComponent.cpp index e0e018454e..ed354fe305 100644 --- a/extras/Jucer (experimental)/Source/Project/jucer_ProjectContentComponent.cpp +++ b/extras/Jucer (experimental)/Source/Project/jucer_ProjectContentComponent.cpp @@ -102,7 +102,7 @@ void ProjectContentComponent::setProject (Project* newProject) project->addChangeListener (this); if (currentDocument == 0) - commandManager->invoke (CommandIDs::showProjectSettings, true); + invokeDirectly (CommandIDs::showProjectSettings, true); updateMissingFileStatuses(); } diff --git a/extras/Jucer (experimental)/Source/Project/jucer_ProjectExport_MSVC.h b/extras/Jucer (experimental)/Source/Project/jucer_ProjectExport_MSVC.h index ab7885f08a..0fa44c825f 100644 --- a/extras/Jucer (experimental)/Source/Project/jucer_ProjectExport_MSVC.h +++ b/extras/Jucer (experimental)/Source/Project/jucer_ProjectExport_MSVC.h @@ -35,7 +35,7 @@ class MSVCProjectExporterBase : public ProjectExporter public: //============================================================================== MSVCProjectExporterBase (Project& project_, const ValueTree& settings_, const char* const folderName) - : ProjectExporter (project_, settings_) + : ProjectExporter (project_, settings_), hasIcon (false) { if (getTargetLocation().toString().isEmpty()) getTargetLocation() = getDefaultBuildsRootFolder() + folderName; @@ -78,6 +78,8 @@ public: protected: String projectGUID; + File rcFile, iconFile; + bool hasIcon; const File getProjectFile (const String& extension) const { return getTargetFolder().getChildFile (project.getProjectFilenameRoot()).withFileExtension (extension); } @@ -255,6 +257,180 @@ protected: << "EndGlobal" << newLine; } + //============================================================================== + static bool writeRCFile (const File& file, const File& iconFile) + { + return file.deleteFile() + && file.appendText ("IDI_ICON1 ICON DISCARDABLE " + + iconFile.getFileName().quoted(), false, false); + } + + static void writeIconFile (const Array& images, OutputStream& out) + { + out.writeShort (0); // reserved + out.writeShort (1); // .ico tag + out.writeShort ((short) images.size()); + + MemoryOutputStream dataBlock; + + const int imageDirEntrySize = 16; + const int dataBlockStart = 6 + images.size() * imageDirEntrySize; + + for (int i = 0; i < images.size(); ++i) + { + const Image& image = images.getReference (i); + const int w = image.getWidth(); + const int h = image.getHeight(); + const int maskStride = (w / 8 + 3) & ~3; + + const size_t oldDataSize = dataBlock.getDataSize(); + dataBlock.writeInt (40); // bitmapinfoheader size + dataBlock.writeInt (w); + dataBlock.writeInt (h * 2); + dataBlock.writeShort (1); // planes + dataBlock.writeShort (32); // bits + dataBlock.writeInt (0); // compression + dataBlock.writeInt ((h * w * 4) + (h * maskStride)); // size image + dataBlock.writeInt (0); // x pixels per meter + dataBlock.writeInt (0); // y pixels per meter + dataBlock.writeInt (0); // clr used + dataBlock.writeInt (0); // clr important + + const Image::BitmapData bitmap (image, 0, 0, w, h); + const int alphaThreshold = 5; + + int y; + for (y = h; --y >= 0;) + { + for (int x = 0; x < w; ++x) + { + const Colour pixel (bitmap.getPixelColour (x, y)); + + if (pixel.getAlpha() <= alphaThreshold) + { + dataBlock.writeInt (0); + } + else + { + dataBlock.writeByte ((char) pixel.getBlue()); + dataBlock.writeByte ((char) pixel.getGreen()); + dataBlock.writeByte ((char) pixel.getRed()); + dataBlock.writeByte ((char) pixel.getAlpha()); + } + } + } + + for (y = h; --y >= 0;) + { + int mask = 0, count = 0; + + for (int x = 0; x < w; ++x) + { + const Colour pixel (bitmap.getPixelColour (x, y)); + + mask <<= 1; + if (pixel.getAlpha() <= alphaThreshold) + mask |= 1; + + if (++count == 8) + { + dataBlock.writeByte (mask); + count = 0; + mask = 0; + } + } + + if (mask != 0) + dataBlock.writeByte (mask); + + for (int i = maskStride - w / 8; --i >= 0;) + dataBlock.writeByte (0); + } + + out.writeByte ((char) w); + out.writeByte ((char) h); + out.writeByte (0); + out.writeByte (0); + out.writeShort (1); // colour planes + out.writeShort (32); // bits per pixel + out.writeInt ((int) (dataBlock.getDataSize() - oldDataSize)); + out.writeInt (dataBlockStart + oldDataSize); + } + + jassert (out.getPosition() == dataBlockStart); + out << dataBlock; + } + + static const Image getBestIconImage (const Image& im1, const Image& im2, int size) + { + Image im; + + if (im1.isValid() && im2.isValid()) + { + if (im1.getWidth() >= size && im2.getWidth() >= size) + im = im1.getWidth() < im2.getWidth() ? im1 : im2; + else if (im1.getWidth() >= size) + im = im1; + else if (im2.getWidth() >= size) + im = im2; + else + return Image(); + } + else + { + im = im1.isValid() ? im1 : im2; + } + + if (size == im.getWidth() && size == im.getHeight()) + return im; + + if (im.getWidth() < size && im.getHeight() < size) + return Image(); + + Image newIm (Image::ARGB, size, size, true); + Graphics g (newIm); + g.drawImageWithin (im, 0, 0, size, size, + RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize, false); + return newIm; + } + + bool createIconFile() + { + Array images; + + const Image smallIcon (project.getSmallIcon()); + const Image bigIcon (project.getBigIcon()); + + Image im (getBestIconImage (smallIcon, bigIcon, 16)); + if (im.isValid()) + images.add (im); + + im = getBestIconImage (smallIcon, bigIcon, 32); + if (im.isValid()) + images.add (im); + + im = getBestIconImage (smallIcon, bigIcon, 48); + if (im.isValid()) + images.add (im); + + im = getBestIconImage (smallIcon, bigIcon, 128); + if (im.isValid()) + images.add (im); + + if (images.size() == 0) + return true; + + MemoryOutputStream mo; + writeIconFile (images, mo); + + iconFile = getTargetFolder().getChildFile ("icon.ico"); + rcFile = getTargetFolder().getChildFile ("resources.rc"); + + hasIcon = FileHelpers::overwriteFileWithNewDataIfDifferent (iconFile, mo) + && writeRCFile (rcFile, iconFile); + return hasIcon; + } + MSVCProjectExporterBase (const MSVCProjectExporterBase&); MSVCProjectExporterBase& operator= (const MSVCProjectExporterBase&); }; @@ -298,6 +474,14 @@ public: //============================================================================== const String create() { + createIconFile(); + + if (hasIcon) + { + juceWrapperFiles.add (RelativePath (iconFile.getFileName(), RelativePath::buildTargetFolder)); + juceWrapperFiles.add (RelativePath (rcFile.getFileName(), RelativePath::buildTargetFolder)); + } + { XmlElement projectXml ("VisualStudioProject"); fillInProjectXml (projectXml); @@ -413,7 +597,7 @@ protected: XmlElement* const group = createGroup (groupName, parent); for (int i = 0; i < files.size(); ++i) - if (files.getReference(i).hasFileExtension ("cpp;c;h")) + if (files.getReference(i).hasFileExtension ("cpp;c;cc;h;hpp;rc;ico")) addFile (files.getReference(i), *group, false, useStdcall && shouldFileBeCompiledByDefault (files.getReference(i))); } @@ -953,6 +1137,8 @@ public: //============================================================================== const String create() { + createIconFile(); + { XmlElement projectXml ("Project"); fillInProjectXml (projectXml); @@ -1171,6 +1357,21 @@ protected: addFilesToCompile (getRTASFilesRequired(), *cppFiles, *headerFiles, true); } + if (hasIcon) + { + { + XmlElement* iconGroup = projectXml.createNewChildElement ("ItemGroup"); + XmlElement* e = iconGroup->createNewChildElement ("None"); + e->setAttribute ("Include", ".\\" + iconFile.getFileName()); + } + + { + XmlElement* rcGroup = projectXml.createNewChildElement ("ItemGroup"); + XmlElement* e = rcGroup->createNewChildElement ("ResourceCompile"); + e->setAttribute ("Include", ".\\" + rcFile.getFileName()); + } + } + { XmlElement* e = projectXml.createNewChildElement ("Import"); e->setAttribute ("Project", "$(VCTargetsPath)\\Microsoft.Cpp.targets"); @@ -1313,6 +1514,23 @@ protected: addFilesToFilter (juceWrapperFiles, project.getJuceCodeGroupName(), *cpps, *headers, *groups); addFilesToFilter (getVSTFilesRequired(), "Juce VST Wrapper", *cpps, *headers, *groups); addFilesToFilter (getRTASFilesRequired(), "Juce RTAS Wrapper", *cpps, *headers, *groups); + + if (iconFile.exists()) + { + { + XmlElement* iconGroup = filterXml.createNewChildElement ("ItemGroup"); + XmlElement* e = iconGroup->createNewChildElement ("None"); + e->setAttribute ("Include", ".\\" + iconFile.getFileName()); + e->createNewChildElement ("Filter")->addTextElement (project.getJuceCodeGroupName()); + } + + { + XmlElement* rcGroup = filterXml.createNewChildElement ("ItemGroup"); + XmlElement* e = rcGroup->createNewChildElement ("ResourceCompile"); + e->setAttribute ("Include", ".\\" + rcFile.getFileName()); + e->createNewChildElement ("Filter")->addTextElement (project.getJuceCodeGroupName()); + } + } } //============================================================================== diff --git a/extras/Jucer (experimental)/Source/Project/jucer_ProjectExport_XCode.h b/extras/Jucer (experimental)/Source/Project/jucer_ProjectExport_XCode.h index 35d1d5e90e..f5970fa9bf 100644 --- a/extras/Jucer (experimental)/Source/Project/jucer_ProjectExport_XCode.h +++ b/extras/Jucer (experimental)/Source/Project/jucer_ProjectExport_XCode.h @@ -109,6 +109,9 @@ public: { infoPlistFile = getTargetFolder().getChildFile ("Info.plist"); + if (! createIconFile()) + return "Can't write the icon file"; + File projectBundle (getProjectBundle()); if (! projectBundle.createDirectory()) return "Can't write to the target directory"; @@ -135,7 +138,7 @@ private: OwnedArray pbxBuildFiles, pbxFileReferences, groups, misc, projectConfigs, targetConfigs; StringArray buildPhaseIDs, resourceIDs, sourceIDs, frameworkIDs; StringArray frameworkFileIDs, rezFileIDs, resourceFileRefs; - File infoPlistFile; + File infoPlistFile, iconFile; int64 projectIDSalt; const bool iPhone; @@ -179,6 +182,14 @@ private: resourceFileRefs.add (createID (plistPath)); } + if (iconFile.exists()) + { + RelativePath iconPath (iconFile, getTargetFolder(), RelativePath::buildTargetFolder); + addFileReference (iconPath); + resourceIDs.add (addBuildFile (iconPath, false, false)); + resourceFileRefs.add (createID (iconPath)); + } + addProjectItem (project.getMainGroup()); for (int i = 0; i < project.getNumConfigurations(); ++i) @@ -210,6 +221,109 @@ private: addProjectObject(); } + static const Image fixMacIconImageSize (Image& image) + { + const int w = image.getWidth(); + const int h = image.getHeight(); + + if (w != h || (w != 16 && w != 32 && w != 48 && w != 64)) + { + const int newSize = w >= 128 ? 128 : (w >= 64 ? 64 : (w >= 32 ? 32 : 16)); + Image newIm (Image::ARGB, newSize, newSize, true); + Graphics g (newIm); + g.drawImageWithin (image, 0, 0, newSize, newSize, + RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize, false); + return newIm; + } + + return image; + } + + void writeIcnsFile (const Array& images, OutputStream& out) + { + MemoryOutputStream data; + + for (int i = 0; i < images.size(); ++i) + { + Image image (fixMacIconImageSize (images.getReference (i))); + + const int w = image.getWidth(); + const int h = image.getHeight(); + + const char* type = 0; + const char* maskType = 0; + + if (w == h) + { + if (w == 16) { type = "is32"; maskType = "s8mk"; } + if (w == 32) { type = "il32"; maskType = "l8mk"; } + if (w == 48) { type = "ih32"; maskType = "h8mk"; } + if (w == 128) { type = "it32"; maskType = "t8mk"; } + } + + if (type != 0) + { + data.write (type, 4); + data.writeIntBigEndian (8 + 4 * w * h); + + const Image::BitmapData bitmap (image, 0, 0, w, h); + + int y; + for (y = 0; y < h; ++y) + { + for (int x = 0; x < w; ++x) + { + const Colour pixel (bitmap.getPixelColour (x, y)); + data.writeByte ((char) pixel.getAlpha()); + data.writeByte ((char) pixel.getRed()); + data.writeByte ((char) pixel.getGreen()); + data.writeByte ((char) pixel.getBlue()); + } + } + + data.write (maskType, 4); + data.writeIntBigEndian (8 + w * h); + + for (y = 0; y < h; ++y) + { + for (int x = 0; x < w; ++x) + { + const Colour pixel (bitmap.getPixelColour (x, y)); + data.writeByte ((char) pixel.getAlpha()); + } + } + } + } + + jassert (data.getDataSize() > 0); // no suitable sized images? + + out.write ("icns", 4); + out.writeIntBigEndian (data.getDataSize() + 8); + out << data; + } + + bool createIconFile() + { + Array images; + + Image bigIcon (project.getBigIcon()); + if (bigIcon.isValid()) + images.add (bigIcon); + + Image smallIcon (project.getSmallIcon()); + if (smallIcon.isValid()) + images.add (smallIcon); + + if (images.size() == 0) + return true; + + MemoryOutputStream mo; + writeIcnsFile (images, mo); + + iconFile = getTargetFolder().getChildFile ("Icon.icns"); + return FileHelpers::overwriteFileWithNewDataIfDifferent (iconFile, mo); + } + bool writeInfoPlistFile() { if (! hasPList()) @@ -219,7 +333,7 @@ private: XmlElement* dict = plist.createNewChildElement ("dict"); addPlistDictionaryKey (dict, "CFBundleExecutable", "${EXECUTABLE_NAME}"); - addPlistDictionaryKey (dict, "CFBundleIconFile", ""); + addPlistDictionaryKey (dict, "CFBundleIconFile", iconFile.exists() ? iconFile.getFileName() : String::empty); addPlistDictionaryKey (dict, "CFBundleIdentifier", project.getBundleIdentifier().toString()); addPlistDictionaryKey (dict, "CFBundleName", project.getProjectName().toString()); diff --git a/extras/juce demo/Binary Data/juce_icon.png b/extras/juce demo/Binary Data/juce_icon.png new file mode 100644 index 0000000000..396aaeccb8 Binary files /dev/null and b/extras/juce demo/Binary Data/juce_icon.png differ diff --git a/extras/juce demo/Builds/MacOSX/Icon.icns b/extras/juce demo/Builds/MacOSX/Icon.icns new file mode 100644 index 0000000000..a1d2ba8423 Binary files /dev/null and b/extras/juce demo/Builds/MacOSX/Icon.icns differ diff --git a/extras/juce demo/Builds/MacOSX/Info.plist b/extras/juce demo/Builds/MacOSX/Info.plist index fbc0914d22..328d0a0fd8 100644 --- a/extras/juce demo/Builds/MacOSX/Info.plist +++ b/extras/juce demo/Builds/MacOSX/Info.plist @@ -6,7 +6,7 @@ CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIconFile - + Icon.icns CFBundleIdentifier com.rawmaterialsoftware.jucedemo CFBundleName diff --git a/extras/juce demo/Builds/MacOSX/Juce Demo.xcodeproj/project.pbxproj b/extras/juce demo/Builds/MacOSX/Juce Demo.xcodeproj/project.pbxproj index 0144a3582b..30d0ca4e39 100644 --- a/extras/juce demo/Builds/MacOSX/Juce Demo.xcodeproj/project.pbxproj +++ b/extras/juce demo/Builds/MacOSX/Juce Demo.xcodeproj/project.pbxproj @@ -17,6 +17,7 @@ F1BAE9DCD179C8784FF28F8D = { isa = PBXBuildFile; fileRef = 4A96850C150C1C6D87A0D21A; }; B9911F3AC6CADFB47D1EA8D7 = { isa = PBXBuildFile; fileRef = 4D3E0D18D24F78B6BDE0E5DA; }; 452052BBDBAF17DCC06EF521 = { isa = PBXBuildFile; fileRef = E0C3359BB4B5260CEB917D46; }; + C0A3C433D146C7E1FFCADFB2 = { isa = PBXBuildFile; fileRef = 4ADECB09FD213B2E910EA229; }; 78A66C2F9A9E2E6D011D8E5E = { isa = PBXBuildFile; fileRef = 885A20D277AD743C21C822B5; }; CE5C46E66485B7D77B5ADB4E = { isa = PBXBuildFile; fileRef = 42291DB48BF81754D90FE200; }; 2E2DB52D03DD6A56FAC937A4 = { isa = PBXBuildFile; fileRef = 0704E2D6B0D1B38FBBBC6B85; }; @@ -56,6 +57,7 @@ E0C3359BB4B5260CEB917D46 = { isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuickTime.framework; path = System/Library/Frameworks/QuickTime.framework; sourceTree = SDKROOT; }; 39B98C60B57B831FE5215CDD = { isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JuceDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 1A9DEA62F6A3CD1FB5CF105B = { isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Info.plist; sourceTree = SOURCE_ROOT; }; + 4ADECB09FD213B2E910EA229 = { isa = PBXFileReference; lastKnownFileType = file.icns; name = Icon.icns; path = Icon.icns; sourceTree = SOURCE_ROOT; }; 885A20D277AD743C21C822B5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ApplicationStartup.cpp; path = ../../Source/ApplicationStartup.cpp; sourceTree = SOURCE_ROOT; }; 42291DB48BF81754D90FE200 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = MainDemoWindow.cpp; path = ../../Source/MainDemoWindow.cpp; sourceTree = SOURCE_ROOT; }; 49138F5652E637AA67CD4B70 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MainDemoWindow.h; path = ../../Source/MainDemoWindow.h; sourceTree = SOURCE_ROOT; }; @@ -90,6 +92,7 @@ A869663CA0E96FE15BB42A97 = { isa = PBXFileReference; lastKnownFileType = file.xml; name = "demo table data.xml"; path = "../../Binary Data/demo table data.xml"; sourceTree = SOURCE_ROOT; }; A76B69386F1F19647804510D = { isa = PBXFileReference; lastKnownFileType = file.zip; name = icons.zip; path = "../../Binary Data/icons.zip"; sourceTree = SOURCE_ROOT; }; 013E12213AD7B4BEB28A31BE = { isa = PBXFileReference; lastKnownFileType = image.png; name = juce.png; path = "../../Binary Data/juce.png"; sourceTree = SOURCE_ROOT; }; + 3369CDF7AFD79D6F3B3744B1 = { isa = PBXFileReference; lastKnownFileType = image.png; name = juce_icon.png; path = "../../Binary Data/juce_icon.png"; sourceTree = SOURCE_ROOT; }; C7327AD5191A22C1FBD4F5F9 = { isa = PBXFileReference; lastKnownFileType = file.xml; name = treedemo.xml; path = "../../Binary Data/treedemo.xml"; sourceTree = SOURCE_ROOT; }; EE37A0ECE471A928C6170F9B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AppConfig.h; path = ../../JuceLibraryCode/AppConfig.h; sourceTree = SOURCE_ROOT; }; A6B37799E63CCE882A3383FB = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = JuceHeader.h; path = ../../JuceLibraryCode/JuceHeader.h; sourceTree = SOURCE_ROOT; }; @@ -131,6 +134,7 @@ A869663CA0E96FE15BB42A97, A76B69386F1F19647804510D, 013E12213AD7B4BEB28A31BE, + 3369CDF7AFD79D6F3B3744B1, C7327AD5191A22C1FBD4F5F9 ); name = "Binary Data"; sourceTree = ""; }; A10CCE1B2A215D5AE12386E3 = { isa = PBXGroup; children = ( 885A20D277AD743C21C822B5, @@ -149,7 +153,8 @@ 4D526A336B2E97ED42CADAD7, 8679333E781A0A0116AE5D26 ); name = "Juce Library Code"; sourceTree = ""; }; 019CD423F1EFF7A1A0A079DD = { isa = PBXGroup; children = ( - 1A9DEA62F6A3CD1FB5CF105B ); name = Resources; sourceTree = ""; }; + 1A9DEA62F6A3CD1FB5CF105B, + 4ADECB09FD213B2E910EA229 ); name = Resources; sourceTree = ""; }; 244B9AF7D858999910FD243E = { isa = PBXGroup; children = ( 2B37CDCFCBC0AC0AEAA9A479, 6A7D4DC561F2DD95ABD76F0D, @@ -234,7 +239,8 @@ C264FE1BF62B589B345E0C81 = { isa = XCConfigurationList; buildConfigurations = ( F46B3E8DBAFA746E04F4F62C, 8EF7C7FFD55219581A5075F3 ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; - AE930F136F638C3C939F7146 = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; + AE930F136F638C3C939F7146 = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + C0A3C433D146C7E1FFCADFB2 ); runOnlyForDeploymentPostprocessing = 0; }; 7A3A0C722E5F96990CA1B5F2 = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 78A66C2F9A9E2E6D011D8E5E, CE5C46E66485B7D77B5ADB4E, diff --git a/extras/juce demo/Builds/VisualStudio2005/Juce Demo.vcproj b/extras/juce demo/Builds/VisualStudio2005/Juce Demo.vcproj index 0032c41608..189a5ceede 100644 --- a/extras/juce demo/Builds/VisualStudio2005/Juce Demo.vcproj +++ b/extras/juce demo/Builds/VisualStudio2005/Juce Demo.vcproj @@ -202,6 +202,7 @@ + @@ -224,6 +225,8 @@ + + diff --git a/extras/juce demo/Builds/VisualStudio2005/icon.ico b/extras/juce demo/Builds/VisualStudio2005/icon.ico new file mode 100644 index 0000000000..853e63debc Binary files /dev/null and b/extras/juce demo/Builds/VisualStudio2005/icon.ico differ diff --git a/extras/juce demo/Builds/VisualStudio2005/resources.rc b/extras/juce demo/Builds/VisualStudio2005/resources.rc new file mode 100644 index 0000000000..b20115c096 --- /dev/null +++ b/extras/juce demo/Builds/VisualStudio2005/resources.rc @@ -0,0 +1 @@ +IDI_ICON1 ICON DISCARDABLE "icon.ico" \ No newline at end of file diff --git a/extras/juce demo/Builds/VisualStudio2008/Juce Demo.vcproj b/extras/juce demo/Builds/VisualStudio2008/Juce Demo.vcproj index 22b71fbe6f..89859b2f07 100644 --- a/extras/juce demo/Builds/VisualStudio2008/Juce Demo.vcproj +++ b/extras/juce demo/Builds/VisualStudio2008/Juce Demo.vcproj @@ -202,6 +202,7 @@ + @@ -224,6 +225,8 @@ + + diff --git a/extras/juce demo/Builds/VisualStudio2008/icon.ico b/extras/juce demo/Builds/VisualStudio2008/icon.ico new file mode 100644 index 0000000000..853e63debc Binary files /dev/null and b/extras/juce demo/Builds/VisualStudio2008/icon.ico differ diff --git a/extras/juce demo/Builds/VisualStudio2008/resources.rc b/extras/juce demo/Builds/VisualStudio2008/resources.rc new file mode 100644 index 0000000000..b20115c096 --- /dev/null +++ b/extras/juce demo/Builds/VisualStudio2008/resources.rc @@ -0,0 +1 @@ +IDI_ICON1 ICON DISCARDABLE "icon.ico" \ No newline at end of file diff --git a/extras/juce demo/Builds/VisualStudio2010/Juce Demo.vcxproj b/extras/juce demo/Builds/VisualStudio2010/Juce Demo.vcxproj index 0b51703f25..f3ec3fc9e4 100644 --- a/extras/juce demo/Builds/VisualStudio2010/Juce Demo.vcxproj +++ b/extras/juce demo/Builds/VisualStudio2010/Juce Demo.vcxproj @@ -163,6 +163,12 @@ + + + + + + diff --git a/extras/juce demo/Builds/VisualStudio2010/Juce Demo.vcxproj.filters b/extras/juce demo/Builds/VisualStudio2010/Juce Demo.vcxproj.filters index 651b8d318a..17106637a0 100644 --- a/extras/juce demo/Builds/VisualStudio2010/Juce Demo.vcxproj.filters +++ b/extras/juce demo/Builds/VisualStudio2010/Juce Demo.vcxproj.filters @@ -94,6 +94,9 @@ Juce Demo\Source\Binary Data + + Juce Demo\Source\Binary Data + Juce Demo\Source\Binary Data @@ -151,4 +154,14 @@ Juce Library Code + + + Juce Library Code + + + + + Juce Library Code + + diff --git a/extras/juce demo/Builds/VisualStudio2010/icon.ico b/extras/juce demo/Builds/VisualStudio2010/icon.ico new file mode 100644 index 0000000000..853e63debc Binary files /dev/null and b/extras/juce demo/Builds/VisualStudio2010/icon.ico differ diff --git a/extras/juce demo/Builds/VisualStudio2010/resources.rc b/extras/juce demo/Builds/VisualStudio2010/resources.rc new file mode 100644 index 0000000000..b20115c096 --- /dev/null +++ b/extras/juce demo/Builds/VisualStudio2010/resources.rc @@ -0,0 +1 @@ +IDI_ICON1 ICON DISCARDABLE "icon.ico" \ No newline at end of file diff --git a/extras/juce demo/Builds/iPhone/Icon.icns b/extras/juce demo/Builds/iPhone/Icon.icns new file mode 100644 index 0000000000..a1d2ba8423 Binary files /dev/null and b/extras/juce demo/Builds/iPhone/Icon.icns differ diff --git a/extras/juce demo/Builds/iPhone/Info.plist b/extras/juce demo/Builds/iPhone/Info.plist index fbc0914d22..328d0a0fd8 100644 --- a/extras/juce demo/Builds/iPhone/Info.plist +++ b/extras/juce demo/Builds/iPhone/Info.plist @@ -6,7 +6,7 @@ CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIconFile - + Icon.icns CFBundleIdentifier com.rawmaterialsoftware.jucedemo CFBundleName diff --git a/extras/juce demo/Builds/iPhone/Juce Demo.xcodeproj/project.pbxproj b/extras/juce demo/Builds/iPhone/Juce Demo.xcodeproj/project.pbxproj index 9ac58cf86c..3e9c9a00bc 100644 --- a/extras/juce demo/Builds/iPhone/Juce Demo.xcodeproj/project.pbxproj +++ b/extras/juce demo/Builds/iPhone/Juce Demo.xcodeproj/project.pbxproj @@ -12,6 +12,7 @@ 36AEC0EAE7AB9D061AD9EFEF = { isa = PBXBuildFile; fileRef = 7B6D428682221857EAEA1C7D; }; F1BAE9DCD179C8784FF28F8D = { isa = PBXBuildFile; fileRef = 4A96850C150C1C6D87A0D21A; }; 268F2BF480CF9844E2F2B974 = { isa = PBXBuildFile; fileRef = B72353F9624D99DB6F93E400; }; + C0A3C433D146C7E1FFCADFB2 = { isa = PBXBuildFile; fileRef = 4ADECB09FD213B2E910EA229; }; 78A66C2F9A9E2E6D011D8E5E = { isa = PBXBuildFile; fileRef = 885A20D277AD743C21C822B5; }; CE5C46E66485B7D77B5ADB4E = { isa = PBXBuildFile; fileRef = 42291DB48BF81754D90FE200; }; 2E2DB52D03DD6A56FAC937A4 = { isa = PBXBuildFile; fileRef = 0704E2D6B0D1B38FBBBC6B85; }; @@ -46,6 +47,7 @@ B72353F9624D99DB6F93E400 = { isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; }; 39B98C60B57B831FE5215CDD = { isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JuceDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 1A9DEA62F6A3CD1FB5CF105B = { isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Info.plist; sourceTree = SOURCE_ROOT; }; + 4ADECB09FD213B2E910EA229 = { isa = PBXFileReference; lastKnownFileType = file.icns; name = Icon.icns; path = Icon.icns; sourceTree = SOURCE_ROOT; }; 885A20D277AD743C21C822B5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ApplicationStartup.cpp; path = ../../Source/ApplicationStartup.cpp; sourceTree = SOURCE_ROOT; }; 42291DB48BF81754D90FE200 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = MainDemoWindow.cpp; path = ../../Source/MainDemoWindow.cpp; sourceTree = SOURCE_ROOT; }; 49138F5652E637AA67CD4B70 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MainDemoWindow.h; path = ../../Source/MainDemoWindow.h; sourceTree = SOURCE_ROOT; }; @@ -80,6 +82,7 @@ A869663CA0E96FE15BB42A97 = { isa = PBXFileReference; lastKnownFileType = file.xml; name = "demo table data.xml"; path = "../../Binary Data/demo table data.xml"; sourceTree = SOURCE_ROOT; }; A76B69386F1F19647804510D = { isa = PBXFileReference; lastKnownFileType = file.zip; name = icons.zip; path = "../../Binary Data/icons.zip"; sourceTree = SOURCE_ROOT; }; 013E12213AD7B4BEB28A31BE = { isa = PBXFileReference; lastKnownFileType = image.png; name = juce.png; path = "../../Binary Data/juce.png"; sourceTree = SOURCE_ROOT; }; + 3369CDF7AFD79D6F3B3744B1 = { isa = PBXFileReference; lastKnownFileType = image.png; name = juce_icon.png; path = "../../Binary Data/juce_icon.png"; sourceTree = SOURCE_ROOT; }; C7327AD5191A22C1FBD4F5F9 = { isa = PBXFileReference; lastKnownFileType = file.xml; name = treedemo.xml; path = "../../Binary Data/treedemo.xml"; sourceTree = SOURCE_ROOT; }; EE37A0ECE471A928C6170F9B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AppConfig.h; path = ../../JuceLibraryCode/AppConfig.h; sourceTree = SOURCE_ROOT; }; A6B37799E63CCE882A3383FB = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = JuceHeader.h; path = ../../JuceLibraryCode/JuceHeader.h; sourceTree = SOURCE_ROOT; }; @@ -121,6 +124,7 @@ A869663CA0E96FE15BB42A97, A76B69386F1F19647804510D, 013E12213AD7B4BEB28A31BE, + 3369CDF7AFD79D6F3B3744B1, C7327AD5191A22C1FBD4F5F9 ); name = "Binary Data"; sourceTree = ""; }; A10CCE1B2A215D5AE12386E3 = { isa = PBXGroup; children = ( 885A20D277AD743C21C822B5, @@ -139,7 +143,8 @@ 4D526A336B2E97ED42CADAD7, 8679333E781A0A0116AE5D26 ); name = "Juce Library Code"; sourceTree = ""; }; 019CD423F1EFF7A1A0A079DD = { isa = PBXGroup; children = ( - 1A9DEA62F6A3CD1FB5CF105B ); name = Resources; sourceTree = ""; }; + 1A9DEA62F6A3CD1FB5CF105B, + 4ADECB09FD213B2E910EA229 ); name = Resources; sourceTree = ""; }; 244B9AF7D858999910FD243E = { isa = PBXGroup; children = ( CE3A43E4FB4D61350C000764, 90E63FC1333F952D526FF194, @@ -219,7 +224,8 @@ C264FE1BF62B589B345E0C81 = { isa = XCConfigurationList; buildConfigurations = ( F46B3E8DBAFA746E04F4F62C, 8EF7C7FFD55219581A5075F3 ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; - AE930F136F638C3C939F7146 = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; + AE930F136F638C3C939F7146 = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + C0A3C433D146C7E1FFCADFB2 ); runOnlyForDeploymentPostprocessing = 0; }; 7A3A0C722E5F96990CA1B5F2 = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 78A66C2F9A9E2E6D011D8E5E, CE5C46E66485B7D77B5ADB4E, diff --git a/extras/juce demo/Juce Demo.jucer b/extras/juce demo/Juce Demo.jucer index 4a9fc8780f..02d4ef142c 100644 --- a/extras/juce demo/Juce Demo.jucer +++ b/extras/juce demo/Juce Demo.jucer @@ -7,7 +7,8 @@ pluginCode="Abcd" pluginChannelConfigs="{ {1, 1}, {2, 2} }" pluginIsSynth="0" pluginWantsMidiIn="0" pluginProducesMidiOut="0" pluginSilenceInIsSilenceOut="0" pluginTailLength="0" pluginEditorRequiresKeys="0" pluginAUExportPrefix="JuceDemoAU" - pluginAUViewClass="JuceDemoAU_V1" pluginRTASCategory=""> + pluginAUViewClass="JuceDemoAU_V1" pluginRTASCategory="" icon="Duj062Top" + bigIcon="f4hwldS"> @@ -97,6 +98,7 @@ file="Binary Data/demo table data.xml"/> + diff --git a/extras/the jucer/src/model/jucer_BinaryResources.cpp b/extras/the jucer/src/model/jucer_BinaryResources.cpp index 30413fe056..d3770b3632 100644 --- a/extras/the jucer/src/model/jucer_BinaryResources.cpp +++ b/extras/the jucer/src/model/jucer_BinaryResources.cpp @@ -308,7 +308,7 @@ void BinaryResources::fillInGeneratedCode (GeneratedCode& code) const defs += line1; - MemoryOutputStream out (65536, 16384); + MemoryOutputStream out (65536); int charsOnLine = line1.length(); for (size_t j = 0; j < mb.getSize(); ++j) diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index a2b744951b..adb9a8b447 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -721,7 +721,7 @@ protected: #include #include #include -#include +#include #include #include #include @@ -4252,9 +4252,9 @@ const var var::readFromStream (InputStream& input) case 4: return var (input.readDouble()); case 5: { - MemoryBlock mb; - input.readIntoMemoryBlock (mb, numBytes - 1); - return var (String::fromUTF8 (static_cast (mb.getData()), (int) mb.getSize())); + MemoryOutputStream mo; + mo.writeFromInputStream (input, numBytes - 1); + return var (mo.toUTF8()); } default: input.skipNextBytes (numBytes - 1); break; @@ -5579,62 +5579,15 @@ const String InputStream::readNextLine() int InputStream::readIntoMemoryBlock (MemoryBlock& block, int numBytes) { - const int64 totalLength = getTotalLength(); - - if (totalLength >= 0) - { - const int totalBytesRemaining = (int) jmin ((int64) 0x7fffffff, - totalLength - getPosition()); - - if (numBytes < 0) - numBytes = totalBytesRemaining; - else if (numBytes > 0) - numBytes = jmin (numBytes, totalBytesRemaining); - else - return 0; - } - - const size_t originalBlockSize = block.getSize(); - int totalBytesRead = 0; - - if (numBytes > 0) - { - // know how many bytes we want, so we can resize the block first.. - block.setSize (originalBlockSize + numBytes, false); - totalBytesRead = read (static_cast (block.getData()) + originalBlockSize, numBytes); - } - else - { - // read until end of stram.. - const int chunkSize = 32768; - - for (;;) - { - block.ensureSize (originalBlockSize + totalBytesRead + chunkSize, false); - - const int bytesJustIn = read (static_cast (block.getData()) - + originalBlockSize - + totalBytesRead, - chunkSize); - - if (bytesJustIn == 0) - break; - - totalBytesRead += bytesJustIn; - } - } - - // trim off any excess left at the end - block.setSize (originalBlockSize + totalBytesRead, false); - return totalBytesRead; + MemoryOutputStream mo (block, true); + return mo.writeFromInputStream (*this, numBytes); } const String InputStream::readEntireStreamAsString() { - MemoryBlock mb; - const int size = readIntoMemoryBlock (mb); - - return String::createStringFromData (static_cast (mb.getData()), size); + MemoryOutputStream mo; + mo.writeFromInputStream (*this, -1); + return mo.toString(); } void InputStream::skipNextBytes (int64 numBytesToSkip) @@ -8333,7 +8286,7 @@ private: void createHeadersAndPostData (const URL& url) { - MemoryOutputStream data (256, 256, &postData); + MemoryOutputStream data (postData, false); if (url.getFilesToUpload().size() > 0) { @@ -8415,7 +8368,7 @@ bool URL::readEntireBinaryStream (MemoryBlock& destData, if (in != 0) { - in->readIntoMemoryBlock (destData, -1); + in->readIntoMemoryBlock (destData); return true; } @@ -8796,18 +8749,22 @@ END_JUCE_NAMESPACE /*** Start of inlined file: juce_MemoryOutputStream.cpp ***/ BEGIN_JUCE_NAMESPACE -MemoryOutputStream::MemoryOutputStream (const size_t initialSize, - const size_t blockSizeToIncreaseBy, - MemoryBlock* const memoryBlockToWriteTo) +MemoryOutputStream::MemoryOutputStream (const size_t initialSize) + : data (internalBlock), + position (0), + size (0) +{ + internalBlock.setSize (initialSize, false); +} + +MemoryOutputStream::MemoryOutputStream (MemoryBlock& memoryBlockToWriteTo, + const bool appendToExistingBlockContent) : data (memoryBlockToWriteTo), position (0), - size (0), - blockSize (jmax ((size_t) 16, blockSizeToIncreaseBy)) + size (0) { - if (data == 0) - dataToDelete = data = new MemoryBlock (initialSize); - else - data->setSize (initialSize, false); + if (appendToExistingBlockContent) + position = size = memoryBlockToWriteTo.getSize(); } MemoryOutputStream::~MemoryOutputStream() @@ -8817,8 +8774,13 @@ MemoryOutputStream::~MemoryOutputStream() void MemoryOutputStream::flush() { - if (dataToDelete == 0) - data->setSize (size, false); + if (&data != &internalBlock) + data.setSize (size, false); +} + +void MemoryOutputStream::preallocate (const size_t bytesToPreallocate) +{ + data.ensureSize (bytesToPreallocate + 1); } void MemoryOutputStream::reset() throw() @@ -8831,18 +8793,12 @@ bool MemoryOutputStream::write (const void* const buffer, int howMany) { if (howMany > 0) { - size_t storageNeeded = position + howMany; + const size_t storageNeeded = position + howMany; - if (storageNeeded >= data->getSize()) - { - // if we need more space, increase the block by at least 10%.. - storageNeeded += jmax (blockSize, storageNeeded / 10); - storageNeeded = storageNeeded - (storageNeeded % blockSize) + blockSize; + if (storageNeeded >= data.getSize()) + data.ensureSize ((storageNeeded + jmin (storageNeeded / 2, (size_t) (1024 * 1024)) + 32) & ~31); - data->ensureSize (storageNeeded); - } - - data->copyFrom (buffer, (int) position, howMany); + memcpy (static_cast (data.getData()) + position, buffer, howMany); position += howMany; size = jmax (size, position); } @@ -8850,12 +8806,12 @@ bool MemoryOutputStream::write (const void* const buffer, int howMany) return true; } -const char* MemoryOutputStream::getData() const throw() +const void* MemoryOutputStream::getData() const throw() { - char* const d = static_cast (data->getData()); + void* const d = data.getData(); - if (data->getSize() > size) - d [size] = 0; + if (data.getSize() > size) + static_cast (d) [size] = 0; return d; } @@ -8875,9 +8831,36 @@ bool MemoryOutputStream::setPosition (int64 newPosition) } } +int MemoryOutputStream::writeFromInputStream (InputStream& source, int64 maxNumBytesToWrite) +{ + // before writing from an input, see if we can preallocate to make it more efficient.. + int64 availableData = source.getTotalLength() - source.getPosition(); + + if (availableData > 0) + { + if (maxNumBytesToWrite > 0 && maxNumBytesToWrite < availableData) + availableData = maxNumBytesToWrite; + + preallocate (data.getSize() + (size_t) maxNumBytesToWrite); + } + + return OutputStream::writeFromInputStream (source, maxNumBytesToWrite); +} + const String MemoryOutputStream::toUTF8() const { - return String (getData(), getDataSize()); + return String (static_cast (getData()), getDataSize()); +} + +const String MemoryOutputStream::toString() const +{ + return String::createStringFromData (getData(), getDataSize()); +} + +OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const MemoryOutputStream& streamToRead) +{ + stream.write (streamToRead.getData(), streamToRead.getDataSize()); + return stream; } END_JUCE_NAMESPACE @@ -10867,52 +10850,52 @@ int64 String::hashCode64() const throw() return result; } -bool JUCE_CALLTYPE operator== (const String& string1, const String& string2) throw() +bool JUCE_PUBLIC_FUNCTION operator== (const String& string1, const String& string2) throw() { return string1.compare (string2) == 0; } -bool JUCE_CALLTYPE operator== (const String& string1, const char* string2) throw() +bool JUCE_PUBLIC_FUNCTION operator== (const String& string1, const char* string2) throw() { return string1.compare (string2) == 0; } -bool JUCE_CALLTYPE operator== (const String& string1, const juce_wchar* string2) throw() +bool JUCE_PUBLIC_FUNCTION operator== (const String& string1, const juce_wchar* string2) throw() { return string1.compare (string2) == 0; } -bool JUCE_CALLTYPE operator!= (const String& string1, const String& string2) throw() +bool JUCE_PUBLIC_FUNCTION operator!= (const String& string1, const String& string2) throw() { return string1.compare (string2) != 0; } -bool JUCE_CALLTYPE operator!= (const String& string1, const char* string2) throw() +bool JUCE_PUBLIC_FUNCTION operator!= (const String& string1, const char* string2) throw() { return string1.compare (string2) != 0; } -bool JUCE_CALLTYPE operator!= (const String& string1, const juce_wchar* string2) throw() +bool JUCE_PUBLIC_FUNCTION operator!= (const String& string1, const juce_wchar* string2) throw() { return string1.compare (string2) != 0; } -bool JUCE_CALLTYPE operator> (const String& string1, const String& string2) throw() +bool JUCE_PUBLIC_FUNCTION operator> (const String& string1, const String& string2) throw() { return string1.compare (string2) > 0; } -bool JUCE_CALLTYPE operator< (const String& string1, const String& string2) throw() +bool JUCE_PUBLIC_FUNCTION operator< (const String& string1, const String& string2) throw() { return string1.compare (string2) < 0; } -bool JUCE_CALLTYPE operator>= (const String& string1, const String& string2) throw() +bool JUCE_PUBLIC_FUNCTION operator>= (const String& string1, const String& string2) throw() { return string1.compare (string2) >= 0; } -bool JUCE_CALLTYPE operator<= (const String& string1, const String& string2) throw() +bool JUCE_PUBLIC_FUNCTION operator<= (const String& string1, const String& string2) throw() { return string1.compare (string2) <= 0; } @@ -11029,114 +11012,114 @@ void String::append (const juce_wchar* const other, const int howMany) } } -const String JUCE_CALLTYPE operator+ (const char* const string1, const String& string2) +const String JUCE_PUBLIC_FUNCTION operator+ (const char* const string1, const String& string2) { String s (string1); return s += string2; } -const String JUCE_CALLTYPE operator+ (const juce_wchar* const string1, const String& string2) +const String JUCE_PUBLIC_FUNCTION operator+ (const juce_wchar* const string1, const String& string2) { String s (string1); return s += string2; } -const String JUCE_CALLTYPE operator+ (const char string1, const String& string2) +const String JUCE_PUBLIC_FUNCTION operator+ (const char string1, const String& string2) { return String::charToString (string1) + string2; } -const String JUCE_CALLTYPE operator+ (const juce_wchar string1, const String& string2) +const String JUCE_PUBLIC_FUNCTION operator+ (const juce_wchar string1, const String& string2) { return String::charToString (string1) + string2; } -const String JUCE_CALLTYPE operator+ (String string1, const String& string2) +const String JUCE_PUBLIC_FUNCTION operator+ (String string1, const String& string2) { return string1 += string2; } -const String JUCE_CALLTYPE operator+ (String string1, const char* const string2) +const String JUCE_PUBLIC_FUNCTION operator+ (String string1, const char* const string2) { return string1 += string2; } -const String JUCE_CALLTYPE operator+ (String string1, const juce_wchar* const string2) +const String JUCE_PUBLIC_FUNCTION operator+ (String string1, const juce_wchar* const string2) { return string1 += string2; } -const String JUCE_CALLTYPE operator+ (String string1, const char string2) +const String JUCE_PUBLIC_FUNCTION operator+ (String string1, const char string2) { return string1 += string2; } -const String JUCE_CALLTYPE operator+ (String string1, const juce_wchar string2) +const String JUCE_PUBLIC_FUNCTION operator+ (String string1, const juce_wchar string2) { return string1 += string2; } -String& JUCE_CALLTYPE operator<< (String& string1, const char characterToAppend) +String& JUCE_PUBLIC_FUNCTION operator<< (String& string1, const char characterToAppend) { return string1 += characterToAppend; } -String& JUCE_CALLTYPE operator<< (String& string1, const juce_wchar characterToAppend) +String& JUCE_PUBLIC_FUNCTION operator<< (String& string1, const juce_wchar characterToAppend) { return string1 += characterToAppend; } -String& JUCE_CALLTYPE operator<< (String& string1, const char* const string2) +String& JUCE_PUBLIC_FUNCTION operator<< (String& string1, const char* const string2) { return string1 += string2; } -String& JUCE_CALLTYPE operator<< (String& string1, const juce_wchar* const string2) +String& JUCE_PUBLIC_FUNCTION operator<< (String& string1, const juce_wchar* const string2) { return string1 += string2; } -String& JUCE_CALLTYPE operator<< (String& string1, const String& string2) +String& JUCE_PUBLIC_FUNCTION operator<< (String& string1, const String& string2) { return string1 += string2; } -String& JUCE_CALLTYPE operator<< (String& string1, const short number) +String& JUCE_PUBLIC_FUNCTION operator<< (String& string1, const short number) { return string1 += (int) number; } -String& JUCE_CALLTYPE operator<< (String& string1, const int number) +String& JUCE_PUBLIC_FUNCTION operator<< (String& string1, const int number) { return string1 += number; } -String& JUCE_CALLTYPE operator<< (String& string1, const unsigned int number) +String& JUCE_PUBLIC_FUNCTION operator<< (String& string1, const unsigned int number) { return string1 += number; } -String& JUCE_CALLTYPE operator<< (String& string1, const long number) +String& JUCE_PUBLIC_FUNCTION operator<< (String& string1, const long number) { return string1 += (int) number; } -String& JUCE_CALLTYPE operator<< (String& string1, const unsigned long number) +String& JUCE_PUBLIC_FUNCTION operator<< (String& string1, const unsigned long number) { return string1 += (unsigned int) number; } -String& JUCE_CALLTYPE operator<< (String& string1, const float number) +String& JUCE_PUBLIC_FUNCTION operator<< (String& string1, const float number) { return string1 += String (number); } -String& JUCE_CALLTYPE operator<< (String& string1, const double number) +String& JUCE_PUBLIC_FUNCTION operator<< (String& string1, const double number) { return string1 += String (number); } -OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const String& text) +OutputStream& JUCE_PUBLIC_FUNCTION operator<< (OutputStream& stream, const String& text) { // (This avoids using toUTF8() to prevent the memory bloat that it would leave behind // if lots of large, persistent strings were to be written to streams). @@ -13281,20 +13264,9 @@ XmlElement* XmlDocument::getDocumentElement (const bool onlyReadOuterDocumentEle if (in != 0) { - MemoryBlock data; - - in->readIntoMemoryBlock (data, onlyReadOuterDocumentElement ? 8192 : -1); - - if (data.getSize() >= 2 - && ((data[0] == (char)-2 && data[1] == (char)-1) - || (data[0] == (char)-1 && data[1] == (char)-2))) - { - textToParse = String::createStringFromData (static_cast (data.getData()), (int) data.getSize()); - } - else - { - textToParse = String::fromUTF8 (static_cast (data.getData()), (int) data.getSize()); - } + MemoryOutputStream data; + data.writeFromInputStream (*in, onlyReadOuterDocumentElement ? 8192 : -1); + textToParse = data.toString(); if (! onlyReadOuterDocumentElement) originalText = textToParse; @@ -14424,7 +14396,7 @@ const String XmlElement::createDocument (const String& dtdToUse, const String& encodingType, const int lineWrapLength) const { - MemoryOutputStream mem (2048, 4096); + MemoryOutputStream mem (2048); writeToStream (mem, dtdToUse, allOnOneLine, includeXmlHeader, encodingType, lineWrapLength); return mem.toUTF8(); @@ -17433,6 +17405,8 @@ int JUCEApplication::shutdownAppAndClearUp() JUCE_TRY { + app->releaseMessageListener(); + shutdownJuce_GUI(); returnValue = app->getApplicationReturnValue(); @@ -17892,6 +17866,11 @@ ApplicationCommandTarget::ApplicationCommandTarget() } ApplicationCommandTarget::~ApplicationCommandTarget() +{ + releaseMessageListener(); +} + +void ApplicationCommandTarget::releaseMessageListener() { messageInvoker = 0; } @@ -85179,10 +85158,10 @@ Drawable* Drawable::createFromImageData (const void* data, const size_t numBytes Drawable* Drawable::createFromImageDataStream (InputStream& dataSource) { - MemoryBlock mb; - dataSource.readIntoMemoryBlock (mb); + MemoryOutputStream mo; + mo.writeFromInputStream (dataSource, -1); - return createFromImageData (mb.getData(), mb.getSize()); + return createFromImageData (mo.getData(), mo.getDataSize()); } Drawable* Drawable::createFromImageFile (const File& file) @@ -92189,7 +92168,7 @@ void Path::writePathToStream (OutputStream& dest) const const String Path::toString() const { - MemoryOutputStream s (2048, 2048); + MemoryOutputStream s (2048); if (! useNonZeroWinding) s << 'a'; @@ -210801,12 +210780,12 @@ const Image JPEGImageFormat::decodeImage (InputStream& in) using namespace jpeglibNamespace; using namespace JPEGHelpers; - MemoryBlock mb; - in.readIntoMemoryBlock (mb); + MemoryOutputStream mb; + mb.writeFromInputStream (in, -1); Image image; - if (mb.getSize() > 16) + if (mb.getDataSize() > 16) { struct jpeg_decompress_struct jpegDecompStruct; @@ -210826,7 +210805,7 @@ const Image JPEGImageFormat::decodeImage (InputStream& in) jpegDecompStruct.src->term_source = dummyCallback1; jpegDecompStruct.src->next_input_byte = static_cast (mb.getData()); - jpegDecompStruct.src->bytes_in_buffer = mb.getSize(); + jpegDecompStruct.src->bytes_in_buffer = mb.getDataSize(); try { diff --git a/juce_amalgamated.h b/juce_amalgamated.h index 9d0b9e20f0..6d3ee6f15e 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -64,7 +64,7 @@ */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 52 -#define JUCE_BUILDNUMBER 34 +#define JUCE_BUILDNUMBER 35 /** Current Juce version number. @@ -2574,83 +2574,83 @@ private: }; /** Concatenates two strings. */ -const String JUCE_CALLTYPE operator+ (const char* string1, const String& string2); +const String JUCE_PUBLIC_FUNCTION operator+ (const char* string1, const String& string2); /** Concatenates two strings. */ -const String JUCE_CALLTYPE operator+ (const juce_wchar* string1, const String& string2); +const String JUCE_PUBLIC_FUNCTION operator+ (const juce_wchar* string1, const String& string2); /** Concatenates two strings. */ -const String JUCE_CALLTYPE operator+ (char string1, const String& string2); +const String JUCE_PUBLIC_FUNCTION operator+ (char string1, const String& string2); /** Concatenates two strings. */ -const String JUCE_CALLTYPE operator+ (juce_wchar string1, const String& string2); +const String JUCE_PUBLIC_FUNCTION operator+ (juce_wchar string1, const String& string2); /** Concatenates two strings. */ -const String JUCE_CALLTYPE operator+ (String string1, const String& string2); +const String JUCE_PUBLIC_FUNCTION operator+ (String string1, const String& string2); /** Concatenates two strings. */ -const String JUCE_CALLTYPE operator+ (String string1, const char* string2); +const String JUCE_PUBLIC_FUNCTION operator+ (String string1, const char* string2); /** Concatenates two strings. */ -const String JUCE_CALLTYPE operator+ (String string1, const juce_wchar* string2); +const String JUCE_PUBLIC_FUNCTION operator+ (String string1, const juce_wchar* string2); /** Concatenates two strings. */ -const String JUCE_CALLTYPE operator+ (String string1, char characterToAppend); +const String JUCE_PUBLIC_FUNCTION operator+ (String string1, char characterToAppend); /** Concatenates two strings. */ -const String JUCE_CALLTYPE operator+ (String string1, juce_wchar characterToAppend); +const String JUCE_PUBLIC_FUNCTION operator+ (String string1, juce_wchar characterToAppend); /** Appends a character at the end of a string. */ -String& JUCE_CALLTYPE operator<< (String& string1, char characterToAppend); +String& JUCE_PUBLIC_FUNCTION operator<< (String& string1, char characterToAppend); /** Appends a character at the end of a string. */ -String& JUCE_CALLTYPE operator<< (String& string1, juce_wchar characterToAppend); +String& JUCE_PUBLIC_FUNCTION operator<< (String& string1, juce_wchar characterToAppend); /** Appends a string to the end of the first one. */ -String& JUCE_CALLTYPE operator<< (String& string1, const char* string2); +String& JUCE_PUBLIC_FUNCTION operator<< (String& string1, const char* string2); /** Appends a string to the end of the first one. */ -String& JUCE_CALLTYPE operator<< (String& string1, const juce_wchar* string2); +String& JUCE_PUBLIC_FUNCTION operator<< (String& string1, const juce_wchar* string2); /** Appends a string to the end of the first one. */ -String& JUCE_CALLTYPE operator<< (String& string1, const String& string2); +String& JUCE_PUBLIC_FUNCTION operator<< (String& string1, const String& string2); /** Appends a decimal number at the end of a string. */ -String& JUCE_CALLTYPE operator<< (String& string1, short number); +String& JUCE_PUBLIC_FUNCTION operator<< (String& string1, short number); /** Appends a decimal number at the end of a string. */ -String& JUCE_CALLTYPE operator<< (String& string1, int number); +String& JUCE_PUBLIC_FUNCTION operator<< (String& string1, int number); /** Appends a decimal number at the end of a string. */ -String& JUCE_CALLTYPE operator<< (String& string1, unsigned int number); +String& JUCE_PUBLIC_FUNCTION operator<< (String& string1, unsigned int number); /** Appends a decimal number at the end of a string. */ -String& JUCE_CALLTYPE operator<< (String& string1, long number); +String& JUCE_PUBLIC_FUNCTION operator<< (String& string1, long number); /** Appends a decimal number at the end of a string. */ -String& JUCE_CALLTYPE operator<< (String& string1, unsigned long number); +String& JUCE_PUBLIC_FUNCTION operator<< (String& string1, unsigned long number); /** Appends a decimal number at the end of a string. */ -String& JUCE_CALLTYPE operator<< (String& string1, float number); +String& JUCE_PUBLIC_FUNCTION operator<< (String& string1, float number); /** Appends a decimal number at the end of a string. */ -String& JUCE_CALLTYPE operator<< (String& string1, double number); +String& JUCE_PUBLIC_FUNCTION operator<< (String& string1, double number); /** Case-sensitive comparison of two strings. */ -bool JUCE_CALLTYPE operator== (const String& string1, const String& string2) throw(); +bool JUCE_PUBLIC_FUNCTION operator== (const String& string1, const String& string2) throw(); /** Case-sensitive comparison of two strings. */ -bool JUCE_CALLTYPE operator== (const String& string1, const char* string2) throw(); +bool JUCE_PUBLIC_FUNCTION operator== (const String& string1, const char* string2) throw(); /** Case-sensitive comparison of two strings. */ -bool JUCE_CALLTYPE operator== (const String& string1, const juce_wchar* string2) throw(); +bool JUCE_PUBLIC_FUNCTION operator== (const String& string1, const juce_wchar* string2) throw(); /** Case-sensitive comparison of two strings. */ -bool JUCE_CALLTYPE operator!= (const String& string1, const String& string2) throw(); +bool JUCE_PUBLIC_FUNCTION operator!= (const String& string1, const String& string2) throw(); /** Case-sensitive comparison of two strings. */ -bool JUCE_CALLTYPE operator!= (const String& string1, const char* string2) throw(); +bool JUCE_PUBLIC_FUNCTION operator!= (const String& string1, const char* string2) throw(); /** Case-sensitive comparison of two strings. */ -bool JUCE_CALLTYPE operator!= (const String& string1, const juce_wchar* string2) throw(); +bool JUCE_PUBLIC_FUNCTION operator!= (const String& string1, const juce_wchar* string2) throw(); /** Case-sensitive comparison of two strings. */ -bool JUCE_CALLTYPE operator> (const String& string1, const String& string2) throw(); +bool JUCE_PUBLIC_FUNCTION operator> (const String& string1, const String& string2) throw(); /** Case-sensitive comparison of two strings. */ -bool JUCE_CALLTYPE operator< (const String& string1, const String& string2) throw(); +bool JUCE_PUBLIC_FUNCTION operator< (const String& string1, const String& string2) throw(); /** Case-sensitive comparison of two strings. */ -bool JUCE_CALLTYPE operator>= (const String& string1, const String& string2) throw(); +bool JUCE_PUBLIC_FUNCTION operator>= (const String& string1, const String& string2) throw(); /** Case-sensitive comparison of two strings. */ -bool JUCE_CALLTYPE operator<= (const String& string1, const String& string2) throw(); +bool JUCE_PUBLIC_FUNCTION operator<= (const String& string1, const String& string2) throw(); /** This streaming override allows you to pass a juce String directly into std output streams. This is very handy for writing strings to std::cout, std::cerr, etc. */ template -std::basic_ostream & JUCE_CALLTYPE operator<< (std::basic_ostream & stream, const String& stringToWrite) +std::basic_ostream & JUCE_PUBLIC_FUNCTION operator<< (std::basic_ostream & stream, const String& stringToWrite) { return stream << stringToWrite.toUTF8(); } /** Writes a string to an OutputStream as UTF8. */ -OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const String& text); +OutputStream& JUCE_PUBLIC_FUNCTION operator<< (OutputStream& stream, const String& text); #endif // __JUCE_STRING_JUCEHEADER__ /*** End of inlined file: juce_String.h ***/ @@ -5847,7 +5847,7 @@ public: This is exposed publically in case you need to manipulate it directly for performance reasons. */ - Type value; + volatile Type value; }; /* @@ -5859,9 +5859,9 @@ public: #if JUCE_PPC || JUCE_IPHONE // None of these atomics are available for PPC or for iPhoneOS 3.1 or earlier!! - template static Type OSAtomicAdd64 (Type b, volatile Type* a) throw() { jassertfalse; return *a += b; } - template static Type OSAtomicIncrement64 (volatile Type* a) throw() { jassertfalse; return ++*a; } - template static Type OSAtomicDecrement64 (volatile Type* a) throw() { jassertfalse; return --*a; } + template static Type OSAtomicAdd64Barrier (Type b, volatile Type* a) throw() { jassertfalse; return *a += b; } + template static Type OSAtomicIncrement64Barrier (volatile Type* a) throw() { jassertfalse; return ++*a; } + template static Type OSAtomicDecrement64Barrier (volatile Type* a) throw() { jassertfalse; return --*a; } template static bool OSAtomicCompareAndSwap64Barrier (Type old, Type newValue, volatile Type* value) throw() { jassertfalse; if (old == *value) { *value = newValue; return true; } return false; } #define JUCE_64BIT_ATOMICS_UNAVAILABLE 1 @@ -5948,8 +5948,8 @@ template inline Type Atomic::operator+= (const Type amountToAdd) throw() { #if JUCE_ATOMICS_MAC - return sizeof (Type) == 4 ? (Type) OSAtomicAdd32 ((int32_t) amountToAdd, (int32_t*) &value) - : (Type) OSAtomicAdd64 ((int64_t) amountToAdd, (int64_t*) &value); + return sizeof (Type) == 4 ? (Type) OSAtomicAdd32Barrier ((int32_t) amountToAdd, (int32_t*) &value) + : (Type) OSAtomicAdd64Barrier ((int64_t) amountToAdd, (int64_t*) &value); #elif JUCE_ATOMICS_WINDOWS return sizeof (Type) == 4 ? (Type) (juce_InterlockedExchangeAdd ((volatile long*) &value, (long) amountToAdd) + (long) amountToAdd) : (Type) (juce_InterlockedExchangeAdd64 ((volatile __int64*) &value, (__int64) amountToAdd) + (__int64) amountToAdd); @@ -5968,8 +5968,8 @@ template inline Type Atomic::operator++() throw() { #if JUCE_ATOMICS_MAC - return sizeof (Type) == 4 ? (Type) OSAtomicIncrement32 ((int32_t*) &value) - : (Type) OSAtomicIncrement64 ((int64_t*) &value); + return sizeof (Type) == 4 ? (Type) OSAtomicIncrement32Barrier ((int32_t*) &value) + : (Type) OSAtomicIncrement64Barrier ((int64_t*) &value); #elif JUCE_ATOMICS_WINDOWS return sizeof (Type) == 4 ? (Type) juce_InterlockedIncrement ((volatile long*) &value) : (Type) juce_InterlockedIncrement64 ((volatile __int64*) &value); @@ -5982,8 +5982,8 @@ template inline Type Atomic::operator--() throw() { #if JUCE_ATOMICS_MAC - return sizeof (Type) == 4 ? (Type) OSAtomicDecrement32 ((int32_t*) &value) - : (Type) OSAtomicDecrement64 ((int64_t*) &value); + return sizeof (Type) == 4 ? (Type) OSAtomicDecrement32Barrier ((int32_t*) &value) + : (Type) OSAtomicDecrement64Barrier ((int64_t*) &value); #elif JUCE_ATOMICS_WINDOWS return sizeof (Type) == 4 ? (Type) juce_InterlockedDecrement ((volatile long*) &value) : (Type) juce_InterlockedDecrement64 ((volatile __int64*) &value); @@ -16706,21 +16706,28 @@ class JUCE_API MemoryOutputStream : public OutputStream { public: - /** Creates a memory stream ready for writing into. + /** Creates an empty memory stream ready for writing into. - @param initialSize the intial amount of space to allocate for writing into - @param granularity the increments by which the internal storage will be increased - @param memoryBlockToWriteTo if this is non-zero, then this block will be used as the - place that the data gets stored. If it's zero, the stream - will allocate its own storage internally, which you can - access using getData() and getDataSize() + @param initialSize the intial amount of capacity to allocate for writing into */ - MemoryOutputStream (size_t initialSize = 256, - size_t granularity = 256, - MemoryBlock* memoryBlockToWriteTo = 0); + MemoryOutputStream (size_t initialSize = 256); + + /** Creates a memory stream for writing into into a pre-existing MemoryBlock object. + + Note that the destination block will always be larger than the amount of data + that has been written to the stream, because the MemoryOutputStream keeps some + spare capactity at its end. To trim the block's size down to fit the actual + data, call flush(), or delete the MemoryOutputStream. + + @param memoryBlockToWriteTo the block into which new data will be written. + @param appendToExistingBlockContent if this is true, the contents of the block will be + kept, and new data will be appended to it. If false, + the block will be cleared before use + */ + MemoryOutputStream (MemoryBlock& memoryBlockToWriteTo, + bool appendToExistingBlockContent); /** Destructor. - This will free any data that was written to it. */ ~MemoryOutputStream(); @@ -16729,7 +16736,7 @@ public: @see getDataSize */ - const char* getData() const throw(); + const void* getData() const throw(); /** Returns the number of bytes of data that have been written to the stream. @@ -16740,25 +16747,44 @@ public: /** Resets the stream, clearing any data that has been written to it so far. */ void reset() throw(); + /** Increases the internal storage capacity to be able to contain at least the specified + amount of data without needing to be resized. + */ + void preallocate (size_t bytesToPreallocate); + /** Returns a String created from the (UTF8) data that has been written to the stream. */ const String toUTF8() const; + /** Attempts to detect the encoding of the data and convert it to a string. + @see String::createStringFromData + */ + const String toString() const; + + /** If the stream is writing to a user-supplied MemoryBlock, this will trim any excess + capacity off the block, so that its length matches the amount of actual data that + has been written so far. + */ void flush(); + bool write (const void* buffer, int howMany); int64 getPosition() { return position; } bool setPosition (int64 newPosition); + int writeFromInputStream (InputStream& source, int64 maxNumBytesToWrite); juce_UseDebuggingNewOperator private: - MemoryBlock* data; - ScopedPointer dataToDelete; - size_t position, size, blockSize; + MemoryBlock& data; + MemoryBlock internalBlock; + size_t position, size; MemoryOutputStream (const MemoryOutputStream&); MemoryOutputStream& operator= (const MemoryOutputStream&); }; +/** Copies all the data that has been written to a MemoryOutputStream into another stream. */ +OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const MemoryOutputStream& streamToRead); + #endif // __JUCE_MEMORYOUTPUTSTREAM_JUCEHEADER__ /*** End of inlined file: juce_MemoryOutputStream.h ***/ @@ -27731,6 +27757,9 @@ public: juce_UseDebuggingNewOperator + /** @internal */ + void releaseMessageListener(); + private: // (for async invocation of commands) class CommandTargetMessageInvoker : public MessageListener diff --git a/src/io/streams/juce_MemoryOutputStream.h b/src/io/streams/juce_MemoryOutputStream.h index c358eb8cae..1f65919819 100644 --- a/src/io/streams/juce_MemoryOutputStream.h +++ b/src/io/streams/juce_MemoryOutputStream.h @@ -115,7 +115,7 @@ public: private: MemoryBlock& data; MemoryBlock internalBlock; - size_t position, size, blockSize; + size_t position, size; MemoryOutputStream (const MemoryOutputStream&); MemoryOutputStream& operator= (const MemoryOutputStream&);