diff --git a/extras/Jucer (experimental)/Builds/Linux/Makefile b/extras/Jucer (experimental)/Builds/Linux/Makefile index e9fe579416..522443f489 100644 --- a/extras/Jucer (experimental)/Builds/Linux/Makefile +++ b/extras/Jucer (experimental)/Builds/Linux/Makefile @@ -45,6 +45,7 @@ endif OBJECTS := \ $(OBJDIR)/jucer_DocumentEditorComponent_695dff1d.o \ $(OBJDIR)/jucer_FilePreviewComponent_55512f53.o \ + $(OBJDIR)/jucer_JuceUpdater_cf7865c4.o \ $(OBJDIR)/jucer_Main_f8488f5b.o \ $(OBJDIR)/jucer_MainWindow_1e163aeb.o \ $(OBJDIR)/jucer_OpenDocumentManager_4c72d210.o \ @@ -95,6 +96,11 @@ $(OBJDIR)/jucer_FilePreviewComponent_55512f53.o: ../../Source/Application/jucer_ @echo "Compiling jucer_FilePreviewComponent.cpp" @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" +$(OBJDIR)/jucer_JuceUpdater_cf7865c4.o: ../../Source/Application/jucer_JuceUpdater.cpp + -@mkdir -p $(OBJDIR) + @echo "Compiling jucer_JuceUpdater.cpp" + @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" + $(OBJDIR)/jucer_Main_f8488f5b.o: ../../Source/Application/jucer_Main.cpp -@mkdir -p $(OBJDIR) @echo "Compiling jucer_Main.cpp" diff --git a/extras/Jucer (experimental)/Builds/MacOSX/The Jucer.xcodeproj/project.pbxproj b/extras/Jucer (experimental)/Builds/MacOSX/The Jucer.xcodeproj/project.pbxproj index 7878f237aa..f530ef56d3 100644 --- a/extras/Jucer (experimental)/Builds/MacOSX/The Jucer.xcodeproj/project.pbxproj +++ b/extras/Jucer (experimental)/Builds/MacOSX/The Jucer.xcodeproj/project.pbxproj @@ -19,6 +19,7 @@ 2E6836738CE7EB452FDC7E9A = { isa = PBXBuildFile; fileRef = D9FB1A5365FEEB854A0FF7BF; }; D6D0659F3F3504012246F13D = { isa = PBXBuildFile; fileRef = AA3CBE4A2AC3E9411426F630; }; 8BAE4D8EA7F247DA0A4D3A5C = { isa = PBXBuildFile; fileRef = F617CE0630ADB0628A34D6BF; }; + 280FE650B3F02AD9E821EA37 = { isa = PBXBuildFile; fileRef = 832701705EC0EC9484F9D9C2; }; 9950893AA82F86F1EEE55BED = { isa = PBXBuildFile; fileRef = D77EAC704C96F798B1C69A0D; }; C2F198C7058FC1A88A600645 = { isa = PBXBuildFile; fileRef = B06694E3C7EB89E3DDEFCBD0; }; A7C05B907BBCB4288FBC6428 = { isa = PBXBuildFile; fileRef = 194F6B951CBC3E8F897FB646; }; @@ -64,6 +65,8 @@ F617CE0630ADB0628A34D6BF = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = jucer_FilePreviewComponent.cpp; path = ../../Source/Application/jucer_FilePreviewComponent.cpp; sourceTree = SOURCE_ROOT; }; 330CB15608DEAF19D28C18DD = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_FilePreviewComponent.h; path = ../../Source/Application/jucer_FilePreviewComponent.h; sourceTree = SOURCE_ROOT; }; 0CA0CCCEBFA0AC8C577FC915 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_Headers.h; path = ../../Source/jucer_Headers.h; sourceTree = SOURCE_ROOT; }; + 832701705EC0EC9484F9D9C2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = jucer_JuceUpdater.cpp; path = ../../Source/Application/jucer_JuceUpdater.cpp; sourceTree = SOURCE_ROOT; }; + AFC2F9A887CDBF7A0051CD09 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_JuceUpdater.h; path = ../../Source/Application/jucer_JuceUpdater.h; sourceTree = SOURCE_ROOT; }; D77EAC704C96F798B1C69A0D = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = jucer_Main.cpp; path = ../../Source/Application/jucer_Main.cpp; sourceTree = SOURCE_ROOT; }; B06694E3C7EB89E3DDEFCBD0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = jucer_MainWindow.cpp; path = ../../Source/Application/jucer_MainWindow.cpp; sourceTree = SOURCE_ROOT; }; 24378294003DC2D038D0534D = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_MainWindow.h; path = ../../Source/Application/jucer_MainWindow.h; sourceTree = SOURCE_ROOT; }; @@ -139,6 +142,8 @@ F617CE0630ADB0628A34D6BF, 330CB15608DEAF19D28C18DD, 0CA0CCCEBFA0AC8C577FC915, + 832701705EC0EC9484F9D9C2, + AFC2F9A887CDBF7A0051CD09, D77EAC704C96F798B1C69A0D, B06694E3C7EB89E3DDEFCBD0, 24378294003DC2D038D0534D, @@ -304,6 +309,7 @@ 5362E03ADF975A126C1F2F7B = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( D6D0659F3F3504012246F13D, 8BAE4D8EA7F247DA0A4D3A5C, + 280FE650B3F02AD9E821EA37, 9950893AA82F86F1EEE55BED, C2F198C7058FC1A88A600645, A7C05B907BBCB4288FBC6428, diff --git a/extras/Jucer (experimental)/Builds/VisualStudio2005/The Jucer.vcproj b/extras/Jucer (experimental)/Builds/VisualStudio2005/The Jucer.vcproj index 3a7e47847c..cced041554 100644 --- a/extras/Jucer (experimental)/Builds/VisualStudio2005/The Jucer.vcproj +++ b/extras/Jucer (experimental)/Builds/VisualStudio2005/The Jucer.vcproj @@ -137,6 +137,8 @@ + + diff --git a/extras/Jucer (experimental)/Builds/VisualStudio2008/The Jucer.vcproj b/extras/Jucer (experimental)/Builds/VisualStudio2008/The Jucer.vcproj index 7c66c03ab2..6558ce1a29 100644 --- a/extras/Jucer (experimental)/Builds/VisualStudio2008/The Jucer.vcproj +++ b/extras/Jucer (experimental)/Builds/VisualStudio2008/The Jucer.vcproj @@ -137,6 +137,8 @@ + + diff --git a/extras/Jucer (experimental)/Builds/VisualStudio2010/The Jucer.vcxproj b/extras/Jucer (experimental)/Builds/VisualStudio2010/The Jucer.vcxproj index 71ddd84911..1d06fb7029 100644 --- a/extras/Jucer (experimental)/Builds/VisualStudio2010/The Jucer.vcxproj +++ b/extras/Jucer (experimental)/Builds/VisualStudio2010/The Jucer.vcxproj @@ -124,6 +124,7 @@ + @@ -156,6 +157,7 @@ + diff --git a/extras/Jucer (experimental)/Builds/VisualStudio2010/The Jucer.vcxproj.filters b/extras/Jucer (experimental)/Builds/VisualStudio2010/The Jucer.vcxproj.filters index 4c0e921e7d..e077948cb6 100644 --- a/extras/Jucer (experimental)/Builds/VisualStudio2010/The Jucer.vcxproj.filters +++ b/extras/Jucer (experimental)/Builds/VisualStudio2010/The Jucer.vcxproj.filters @@ -31,6 +31,9 @@ The Jucer\Application + + The Jucer\Application + The Jucer\Application @@ -150,6 +153,9 @@ The Jucer\Application + + The Jucer\Application + The Jucer\Application diff --git a/extras/Jucer (experimental)/Jucer.jucer b/extras/Jucer (experimental)/Jucer.jucer index 963b44bb2d..e8d53e8e5e 100644 --- a/extras/Jucer (experimental)/Jucer.jucer +++ b/extras/Jucer (experimental)/Jucer.jucer @@ -45,6 +45,10 @@ resource="0" file="Source/Application/jucer_FilePreviewComponent.h"/> + + diff --git a/extras/Jucer (experimental)/Source/Application/jucer_Application.h b/extras/Jucer (experimental)/Source/Application/jucer_Application.h index 3236bbde09..18a27e776e 100644 --- a/extras/Jucer (experimental)/Source/Application/jucer_Application.h +++ b/extras/Jucer (experimental)/Source/Application/jucer_Application.h @@ -28,6 +28,7 @@ #include "../jucer_Headers.h" #include "jucer_MainWindow.h" +#include "jucer_JuceUpdater.h" #include "../Project/jucer_NewProjectWizard.h" @@ -161,7 +162,7 @@ public: const StringArray getMenuBarNames() { - const char* const names[] = { "File", "Edit", "View", "Window", 0 }; + const char* const names[] = { "File", "Edit", "View", "Window", "Update", 0 }; return StringArray ((const char**) names); } @@ -251,6 +252,10 @@ public: menu.addSeparator(); menu.addCommandItem (commandManager, CommandIDs::closeAllDocuments); } + else if (topLevelMenuIndex == 4) // "Juce" menu + { + menu.addCommandItem (commandManager, CommandIDs::showJuceVersion); + } return menu; } @@ -287,7 +292,8 @@ public: CommandIDs::open, CommandIDs::showPrefs, CommandIDs::closeAllDocuments, - CommandIDs::saveAll }; + CommandIDs::saveAll, + CommandIDs::showJuceVersion }; commands.addArray (ids, numElementsInArray (ids)); } @@ -321,6 +327,10 @@ public: result.setActive (OpenDocumentManager::getInstance()->anyFilesNeedSaving()); break; + case CommandIDs::showJuceVersion: + result.setInfo ("Download the latest JUCE version", "Checks online for any Juce updates", CommandCategories::general, 0); + break; + default: JUCEApplication::getCommandInfo (commandID, result); break; @@ -336,6 +346,7 @@ public: case CommandIDs::showPrefs: showPrefsPanel(); break; case CommandIDs::saveAll: OpenDocumentManager::getInstance()->saveAll(); break; case CommandIDs::closeAllDocuments: closeAllDocuments (true); break; + case CommandIDs::showJuceVersion: JuceUpdater::show (mainWindows[0]); break; default: return JUCEApplication::perform (info); } diff --git a/extras/Jucer (experimental)/Source/Application/jucer_CommandIDs.h b/extras/Jucer (experimental)/Source/Application/jucer_CommandIDs.h index a74b834af2..a10af1dc36 100644 --- a/extras/Jucer (experimental)/Source/Application/jucer_CommandIDs.h +++ b/extras/Jucer (experimental)/Source/Application/jucer_CommandIDs.h @@ -39,6 +39,7 @@ namespace CommandIDs static const int saveProjectAs = 0x200070; static const int openProjectInIDE = 0x200071; static const int showProjectSettings = 0x200072; + static const int showJuceVersion = 0x200073; static const int saveAll = 0x200080; static const int undo = 0x200090; diff --git a/extras/Jucer (experimental)/Source/Application/jucer_JuceUpdater.cpp b/extras/Jucer (experimental)/Source/Application/jucer_JuceUpdater.cpp new file mode 100644 index 0000000000..7de8f5fb6a --- /dev/null +++ b/extras/Jucer (experimental)/Source/Application/jucer_JuceUpdater.cpp @@ -0,0 +1,402 @@ +/* + ============================================================================== + + 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. + + ============================================================================== +*/ + +#include "../jucer_Headers.h" +#include "jucer_JuceUpdater.h" + + +//============================================================================== +JuceUpdater::JuceUpdater() + : filenameComp ("Juce Folder", StoredSettings::getInstance()->getLastKnownJuceFolder(), + true, true, false, "*", String::empty, "Select your Juce folder"), + checkNowButton ("Check Online for Available Updates...", + "Contacts the website to see if this version is up-to-date") +{ + addAndMakeVisible (&label); + addAndMakeVisible (&filenameComp); + addAndMakeVisible (&checkNowButton); + addAndMakeVisible (¤tVersionLabel); + checkNowButton.addButtonListener (this); + filenameComp.addListener (this); + + currentVersionLabel.setFont (Font (14.0f, Font::italic)); + label.setFont (Font (12.0f)); + label.setText ("Destination folder:", false); + + addAndMakeVisible (&availableVersionsList); + availableVersionsList.setModel (this); + + setSize (600, 300); +} + +JuceUpdater::~JuceUpdater() +{ + checkNowButton.removeButtonListener (this); + filenameComp.removeListener (this); +} + +void JuceUpdater::show (Component* mainWindow) +{ + JuceUpdater updater; + DialogWindow::showModalDialog ("Juce Update...", &updater, mainWindow, + Colours::lightgrey, + true, false, false); +} + +void JuceUpdater::resized() +{ + filenameComp.setBounds (20, 40, getWidth() - 40, 22); + label.setBounds (filenameComp.getX(), filenameComp.getY() - 18, filenameComp.getWidth(), 18); + currentVersionLabel.setBounds (filenameComp.getX(), filenameComp.getBottom(), filenameComp.getWidth(), 25); + checkNowButton.changeWidthToFitText (20); + checkNowButton.setCentrePosition (getWidth() / 2, filenameComp.getBottom() + 40); + availableVersionsList.setBounds (filenameComp.getX(), checkNowButton.getBottom() + 20, filenameComp.getWidth(), getHeight() - (checkNowButton.getBottom() + 20)); +} + +void JuceUpdater::paint (Graphics& g) +{ + g.fillAll (Colours::white); +} + +const String findVersionNum (const String& file, const String& token) +{ + return file.fromFirstOccurrenceOf (token, false, false) + .upToFirstOccurrenceOf ("\n", false, false) + .trim(); +} + +const String JuceUpdater::getCurrentVersion() +{ + const String header (filenameComp.getCurrentFile() + .getChildFile ("src/core/juce_StandardHeader.h").loadFileAsString()); + + const String v1 (findVersionNum (header, "JUCE_MAJOR_VERSION")); + const String v2 (findVersionNum (header, "JUCE_MINOR_VERSION")); + const String v3 (findVersionNum (header, "JUCE_BUILDNUMBER")); + + if ((v1 + v2 + v3).isEmpty()) + return String::empty; + + return v1 + "." + v2 + "." + v3; +} + +XmlElement* JuceUpdater::downloadVersionList() +{ + return URL ("http://www.rawmaterialsoftware.com/juce/downloads/juce_versions.php").readEntireXmlStream(); +} + +void JuceUpdater::updateVersions (const XmlElement& xml) +{ + availableVersions.clear(); + + forEachXmlChildElementWithTagName (xml, v, "VERSION") + { + VersionInfo* vi = new VersionInfo(); + vi->url = URL (v->getStringAttribute ("url")); + vi->desc = v->getStringAttribute ("desc"); + vi->version = v->getStringAttribute ("version"); + vi->date = v->getStringAttribute ("date"); + availableVersions.add (vi); + } + + availableVersionsList.updateContent(); +} + +void JuceUpdater::buttonClicked (Button*) +{ + ScopedPointer xml (downloadVersionList()); + + if (xml == 0 || xml->hasTagName ("html")) + { + AlertWindow::showMessageBox (AlertWindow::WarningIcon, "Connection Problems...", + "Couldn't connect to the Raw Material Software website!"); + + return; + } + + if (! xml->hasTagName ("JUCEVERSIONS")) + { + AlertWindow::showMessageBox (AlertWindow::WarningIcon, "Update Problems...", + "This version of the Jucer may be too old to receive automatic updates!\n\n" + "Please visit www.rawmaterialsoftware.com and get the latest version manually!"); + return; + } + + const String currentVersion (getCurrentVersion()); + + OwnedArray versions; + updateVersions (*xml); +} + +//============================================================================== +class NewVersionDownloader : public ThreadWithProgressWindow +{ +public: + NewVersionDownloader (const String& title, const URL& url_, const File& target_) + : ThreadWithProgressWindow (title, true, true), + url (url_), target (target_) + { + } + + void run() + { + setStatusMessage ("Contacting website..."); + + ScopedPointer input (url.createInputStream (false)); + + if (input == 0) + { + error = "Couldn't connect to the website..."; + return; + } + + if (! target.deleteFile()) + { + error = "Couldn't delete the destination file..."; + return; + } + + ScopedPointer output (target.createOutputStream (32768)); + + if (output == 0) + { + error = "Couldn't write to the destination file..."; + return; + } + + setStatusMessage ("Downloading..."); + + int totalBytes = (int) input->getTotalLength(); + int bytesSoFar = 0; + + while (! (input->isExhausted() || threadShouldExit())) + { + HeapBlock buffer (8192); + const int num = input->read (buffer, 8192); + + if (num == 0) + break; + + output->write (buffer, num); + bytesSoFar += num; + + setProgress (totalBytes > 0 ? bytesSoFar / (double) totalBytes : -1.0); + } + } + + String error; + +private: + URL url; + File target; +}; + +//============================================================================== +class Unzipper : public ThreadWithProgressWindow +{ +public: + Unzipper (ZipFile& zipFile_, const File& targetDir_) + : ThreadWithProgressWindow ("Unzipping...", true, true), + zipFile (zipFile_), targetDir (targetDir_), worked (true) + { + } + + void run() + { + for (int i = 0; i < zipFile.getNumEntries(); ++i) + { + if (threadShouldExit()) + break; + + const ZipFile::ZipEntry* e = zipFile.getEntry (i); + setStatusMessage ("Unzipping " + e->filename + "..."); + setProgress (i / (double) zipFile.getNumEntries()); + + worked = zipFile.uncompressEntry (i, targetDir, true) && worked; + } + } + + bool worked; + +private: + ZipFile& zipFile; + File targetDir; +}; + +//============================================================================== +void JuceUpdater::applyVersion (VersionInfo* version) +{ + File destDir (filenameComp.getCurrentFile()); + + const bool destDirExisted = destDir.isDirectory(); + + if (destDirExisted && destDir.getNumberOfChildFiles (File::findFilesAndDirectories, "*") > 0) + { + int r = AlertWindow::showYesNoCancelBox (AlertWindow::WarningIcon, "Folder already exists", + "The folder " + destDir.getFullPathName() + "\nalready contains some files...\n\n" + "Do you want to delete everything in the folder and replace it entirely, or just merge the new files into the existing folder?", + "Delete and replace entire folder", + "Add and overwrite existing files", + "Cancel"); + + if (r == 0) + return; + + if (r == 1) + { + if (! destDir.deleteRecursively()) + { + AlertWindow::showMessageBox (AlertWindow::WarningIcon, "Problems...", + "Couldn't delete the existing folder!"); + return; + } + } + } + + if (! (destDir.isDirectory() || destDir.createDirectory())) + { + AlertWindow::showMessageBox (AlertWindow::WarningIcon, "Problems...", + "Couldn't create that target folder.."); + return; + } + + File zipFile (destDir.getNonexistentChildFile ("juce_download", ".tar.gz", false)); + + bool worked = false; + + { + NewVersionDownloader downloader ("Downloading Version " + version->version + "...", + version->url, zipFile); + worked = downloader.runThread(); + } + + if (worked) + { + ZipFile zip (zipFile); + Unzipper unzipper (zip, destDir); + worked = unzipper.runThread() && unzipper.worked; + } + + zipFile.deleteFile(); + + if ((! destDirExisted) && (destDir.getNumberOfChildFiles (File::findFilesAndDirectories, "*") == 0 || ! worked)) + destDir.deleteRecursively(); + + filenameComponentChanged (&filenameComp); +} + +void JuceUpdater::filenameComponentChanged (FilenameComponent*) +{ + const String version (getCurrentVersion()); + + if (version.isEmpty()) + currentVersionLabel.setText ("(Not a Juce folder)", false); + else + currentVersionLabel.setText ("(Current version in this folder: " + version + ")", false); +} + +//============================================================================== +int JuceUpdater::getNumRows() +{ + return availableVersions.size(); +} + +void JuceUpdater::paintListBoxItem (int rowNumber, Graphics& g, int width, int height, bool rowIsSelected) +{ + if (rowIsSelected) + g.fillAll (findColour (TextEditor::highlightColourId)); +} + +Component* JuceUpdater::refreshComponentForRow (int rowNumber, bool isRowSelected, Component* existingComponentToUpdate) +{ + class UpdateListComponent : public Component, + public ButtonListener + { + public: + UpdateListComponent (JuceUpdater& updater_) + : updater (updater_), version (0), applyButton ("Install this version...") + { + addAndMakeVisible (&applyButton); + applyButton.addButtonListener (this); + setInterceptsMouseClicks (false, true); + } + + ~UpdateListComponent() + { + applyButton.removeButtonListener (this); + } + + void setVersion (VersionInfo* v) + { + if (version != v) + { + version = v; + repaint(); + resized(); + } + } + + void paint (Graphics& g) + { + if (version != 0) + { + g.setColour (Colours::green.withAlpha (0.12f)); + + g.fillRect (0, 1, getWidth(), getHeight() - 2); + g.setColour (Colours::black); + g.setFont (getHeight() * 0.7f); + + String s; + s << "Version " << version->version << " - " << version->desc << " - " << version->date; + + g.drawText (s, 4, 0, applyButton.getX() - 4, getHeight(), Justification::centredLeft, true); + } + } + + void resized() + { + applyButton.changeWidthToFitText (getHeight() - 4); + applyButton.setTopRightPosition (getWidth(), 2); + applyButton.setVisible (version != 0); + } + + void buttonClicked (Button*) + { + updater.applyVersion (version); + } + + private: + JuceUpdater& updater; + TextButton applyButton; + VersionInfo* version; + }; + + UpdateListComponent* c = dynamic_cast (existingComponentToUpdate); + if (c == 0) + c = new UpdateListComponent (*this); + + c->setVersion (availableVersions [rowNumber]); + return c; +} diff --git a/extras/Jucer (experimental)/Source/Application/jucer_JuceUpdater.h b/extras/Jucer (experimental)/Source/Application/jucer_JuceUpdater.h new file mode 100644 index 0000000000..47aabe952a --- /dev/null +++ b/extras/Jucer (experimental)/Source/Application/jucer_JuceUpdater.h @@ -0,0 +1,77 @@ +/* + ============================================================================== + + 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. + + ============================================================================== +*/ + +#ifndef __JUCER_JUCEUPDATER_H_81537815__ +#define __JUCER_JUCEUPDATER_H_81537815__ + + +//============================================================================== +class JuceUpdater : public Component, + public ButtonListener, + public FilenameComponentListener, + public ListBoxModel +{ +public: + JuceUpdater(); + ~JuceUpdater(); + + static void show (Component* mainWindow); + + //============================================================================== + void resized(); + void paint (Graphics& g); + void buttonClicked (Button*); + void filenameComponentChanged (FilenameComponent* fileComponentThatHasChanged); + + int getNumRows(); + void paintListBoxItem (int rowNumber, Graphics& g, int width, int height, bool rowIsSelected); + Component* refreshComponentForRow (int rowNumber, bool isRowSelected, Component* existingComponentToUpdate); + +private: + Label label, currentVersionLabel; + FilenameComponent filenameComp; + TextButton checkNowButton; + ListBox availableVersionsList; + + XmlElement* downloadVersionList(); + const String getCurrentVersion(); + bool isAlreadyUpToDate(); + + struct VersionInfo + { + URL url; + String desc; + String version; + String date; + }; + + OwnedArray availableVersions; + + void updateVersions (const XmlElement& xml); + void applyVersion (VersionInfo* version); +}; + + +#endif // __JUCER_JUCEUPDATER_H_81537815__ diff --git a/extras/audio plugins/demo/JuceLibraryCode/JucePluginCharacteristics.h b/extras/audio plugins/demo/JuceLibraryCode/JucePluginCharacteristics.h index 1b044bce19..5d836bbcbd 100644 --- a/extras/audio plugins/demo/JuceLibraryCode/JucePluginCharacteristics.h +++ b/extras/audio plugins/demo/JuceLibraryCode/JucePluginCharacteristics.h @@ -11,9 +11,9 @@ #ifndef __PLUGINCHARACTERISTICS_D4EFFF1A__ #define __PLUGINCHARACTERISTICS_D4EFFF1A__ -#define JucePlugin_Build_VST 1 // (If you change this you'll also need to re-export the projects using the Jucer) -#define JucePlugin_Build_AU 1 // (If you change this you'll also need to re-export the projects using the Jucer) -#define JucePlugin_Build_RTAS 0 // (If you change this you'll also need to re-export the projects using the Jucer) +#define JucePlugin_Build_VST 1 // (If you change this value, you'll also need to re-export the projects using the Jucer) +#define JucePlugin_Build_AU 1 // (If you change this value, you'll also need to re-export the projects using the Jucer) +#define JucePlugin_Build_RTAS 0 // (If you change this value, you'll also need to re-export the projects using the Jucer) #define JucePlugin_Name "Juce Demo Plugin" #define JucePlugin_Desc "Juce Demo Plugin" diff --git a/extras/juce demo/Builds/MacOSX/Icon.icns b/extras/juce demo/Builds/MacOSX/Icon.icns index a1d2ba8423..fea3a04779 100644 Binary files a/extras/juce demo/Builds/MacOSX/Icon.icns and b/extras/juce demo/Builds/MacOSX/Icon.icns differ diff --git a/extras/juce demo/Builds/VisualStudio2005/icon.ico b/extras/juce demo/Builds/VisualStudio2005/icon.ico index 853e63debc..9dfea84c64 100644 Binary files a/extras/juce demo/Builds/VisualStudio2005/icon.ico and b/extras/juce demo/Builds/VisualStudio2005/icon.ico differ diff --git a/extras/juce demo/Builds/VisualStudio2008/icon.ico b/extras/juce demo/Builds/VisualStudio2008/icon.ico index 853e63debc..9dfea84c64 100644 Binary files a/extras/juce demo/Builds/VisualStudio2008/icon.ico and b/extras/juce demo/Builds/VisualStudio2008/icon.ico differ diff --git a/extras/juce demo/Builds/VisualStudio2010/icon.ico b/extras/juce demo/Builds/VisualStudio2010/icon.ico index 853e63debc..9dfea84c64 100644 Binary files a/extras/juce demo/Builds/VisualStudio2010/icon.ico and b/extras/juce demo/Builds/VisualStudio2010/icon.ico differ diff --git a/extras/juce demo/Builds/iPhone/Icon.icns b/extras/juce demo/Builds/iPhone/Icon.icns index a1d2ba8423..fea3a04779 100644 Binary files a/extras/juce demo/Builds/iPhone/Icon.icns and b/extras/juce demo/Builds/iPhone/Icon.icns differ diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index 1bc39b284a..3848a1459f 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -7464,97 +7464,40 @@ const String File::loadFileAsString() const return in.readEntireStreamAsString(); } -bool File::fileTypeMatches (const int whatToLookFor, const bool isDir, const bool isHidden) -{ - return (whatToLookFor & (isDir ? findDirectories - : findFiles)) != 0 - && ((! isHidden) || (whatToLookFor & File::ignoreHiddenFiles) == 0); -} - int File::findChildFiles (Array& results, const int whatToLookFor, const bool searchRecursively, const String& wildCardPattern) const { - // you have to specify the type of files you're looking for! - jassert ((whatToLookFor & (findFiles | findDirectories)) != 0); + DirectoryIterator di (*this, searchRecursively, wildCardPattern, whatToLookFor); int total = 0; - - if (isDirectory()) + while (di.next()) { - // find child files or directories in this directory first.. - String path (addTrailingSeparator (fullPath)), filename; - bool itemIsDirectory, itemIsHidden; - - DirectoryIterator::NativeIterator i (path, wildCardPattern); - - while (i.next (filename, &itemIsDirectory, &itemIsHidden, 0, 0, 0, 0)) - { - if (! filename.containsOnly (".")) - { - const File fileFound (path + filename, 0); - - if (fileTypeMatches (whatToLookFor, itemIsDirectory, itemIsHidden)) - { - results.add (fileFound); - ++total; - } - - if (searchRecursively && itemIsDirectory - && ((! itemIsHidden) || (whatToLookFor & File::ignoreHiddenFiles) == 0)) - - { - total += fileFound.findChildFiles (results, whatToLookFor, true, wildCardPattern); - } - } - } + results.add (di.getFile()); + ++total; } return total; } -int File::getNumberOfChildFiles (const int whatToLookFor, - const String& wildCardPattern) const +int File::getNumberOfChildFiles (const int whatToLookFor, const String& wildCardPattern) const { - // you have to specify the type of files you're looking for! - jassert (whatToLookFor > 0 && whatToLookFor <= 3); + DirectoryIterator di (*this, false, "*", whatToLookFor); - int count = 0; - - if (isDirectory()) - { - String filename; - bool itemIsDirectory, itemIsHidden; - - DirectoryIterator::NativeIterator i (*this, wildCardPattern); - - while (i.next (filename, &itemIsDirectory, &itemIsHidden, 0, 0, 0, 0)) - if (fileTypeMatches (whatToLookFor, itemIsDirectory, itemIsHidden) - && ! filename.containsOnly (".")) - ++count; - } - else - { - // trying to search for files inside a non-directory? - jassertfalse; - } + int total = 0; + while (di.next()) + ++total; - return count; + return total; } bool File::containsSubDirectories() const { if (isDirectory()) { - String filename; - bool itemIsDirectory; - - DirectoryIterator::NativeIterator i (*this, "*"); - - while (i.next (filename, &itemIsDirectory, 0, 0, 0, 0, 0)) - if (itemIsDirectory) - return true; + DirectoryIterator di (*this, false, "*", findDirectories); + return di.next(); } return false; @@ -10498,46 +10441,60 @@ int ZipFile::findEndOfZipEntryTable (InputStream* input, int& numEntries) return 0; } -void ZipFile::uncompressTo (const File& targetDirectory, +bool ZipFile::uncompressTo (const File& targetDirectory, const bool shouldOverwriteFiles) { for (int i = 0; i < entries.size(); ++i) - { - const ZipEntry& zei = entries.getUnchecked(i)->entry; + if (! uncompressEntry (i, targetDirectory, shouldOverwriteFiles)) + return false; + + return true; +} + +bool ZipFile::uncompressEntry (const int index, + const File& targetDirectory, + bool shouldOverwriteFiles) +{ + const ZipEntryInfo* zei = entries [index]; - const File targetFile (targetDirectory.getChildFile (zei.filename)); + if (zei != 0) + { + const File targetFile (targetDirectory.getChildFile (zei->entry.filename)); - if (zei.filename.endsWithChar ('/')) + if (zei->entry.filename.endsWithChar ('/')) { targetFile.createDirectory(); // (entry is a directory, not a file) } else { - ScopedPointer in (createStreamForEntry (i)); + ScopedPointer in (createStreamForEntry (index)); if (in != 0) { - if (shouldOverwriteFiles) - targetFile.deleteFile(); + if (shouldOverwriteFiles && ! targetFile.deleteFile()) + return false; - if ((! targetFile.exists()) - && targetFile.getParentDirectory().createDirectory()) + if ((! targetFile.exists()) && targetFile.getParentDirectory().createDirectory()) { - ScopedPointer out (targetFile.createOutputStream()); + ScopedPointer out (targetFile.createOutputStream()); if (out != 0) { out->writeFromInputStream (*in, -1); out = 0; - targetFile.setCreationTime (zei.fileTime); - targetFile.setLastModificationTime (zei.fileTime); - targetFile.setLastAccessTime (zei.fileTime); + targetFile.setCreationTime (zei->entry.fileTime); + targetFile.setLastModificationTime (zei->entry.fileTime); + targetFile.setLastAccessTime (zei->entry.fileTime); + + return true; } } } } } + + return false; } END_JUCE_NAMESPACE @@ -29276,8 +29233,6 @@ const MidiMessage MidiMessage::noteOff (const int channel, const MidiMessage MidiMessage::allNotesOff (const int channel) throw() { - jassert (channel > 0 && channel <= 16); - return controllerEvent (channel, 123, 0); } @@ -33121,6 +33076,21 @@ static float vst_swapFloat (const float x) throw() #endif } +static double getVSTHostTimeNanoseconds() +{ + #if JUCE_WINDOWS + return timeGetTime() * 1000000.0; + #elif JUCE_LINUX + timeval micro; + gettimeofday (µ, 0); + return micro.tv_usec * 1000.0; + #elif JUCE_MAC + UnsignedWide micro; + Microseconds (µ); + return micro.lo * 1000.0; + #endif +} + typedef AEffect* (*MainCall) (audioMasterCallback); static VstIntPtr VSTCALLBACK audioMaster (AEffect* effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt); @@ -33227,22 +33197,16 @@ static void translateJuceToXButtonModifiers (const MouseEvent& e, XEvent& ev) th static void translateJuceToXMotionModifiers (const MouseEvent& e, XEvent& ev) throw() { - if (e.mods.isLeftButtonDown()) - ev.xmotion.state |= Button1Mask; - else if (e.mods.isRightButtonDown()) - ev.xmotion.state |= Button3Mask; - else if (e.mods.isMiddleButtonDown()) - ev.xmotion.state |= Button2Mask; + if (e.mods.isLeftButtonDown()) ev.xmotion.state |= Button1Mask; + else if (e.mods.isRightButtonDown()) ev.xmotion.state |= Button3Mask; + else if (e.mods.isMiddleButtonDown()) ev.xmotion.state |= Button2Mask; } static void translateJuceToXCrossingModifiers (const MouseEvent& e, XEvent& ev) throw() { - if (e.mods.isLeftButtonDown()) - ev.xcrossing.state |= Button1Mask; - else if (e.mods.isRightButtonDown()) - ev.xcrossing.state |= Button3Mask; - else if (e.mods.isMiddleButtonDown()) - ev.xcrossing.state |= Button2Mask; + if (e.mods.isLeftButtonDown()) ev.xcrossing.state |= Button1Mask; + else if (e.mods.isRightButtonDown()) ev.xcrossing.state |= Button3Mask; + else if (e.mods.isMiddleButtonDown()) ev.xcrossing.state |= Button2Mask; } static void translateJuceToXMouseWheelModifiers (const MouseEvent& e, const float increment, XEvent& ev) throw() @@ -33328,7 +33292,6 @@ public: ~ModuleHandle() { getActiveModules().removeValue (this); - close(); } @@ -33626,7 +33589,7 @@ public: } const String getName() const { return name; } - int getUID() const throw(); + int getUID() const; bool acceptsMidi() const { return wantsMidiMessages; } bool producesMidi() const { return dispatch (effCanDo, 0, 0, (void*) "sendVstMidiEvent", 0) > 0; } @@ -33683,14 +33646,13 @@ private: MidiBuffer incomingMidi; VSTMidiEventList midiEventsToSend; VstTimeInfo vstHostTime; - HeapBlock channels; ReferenceCountedObjectPtr module; int dispatch (const int opcode, const int index, const int value, void* const ptr, float opt) const; bool restoreProgramSettings (const fxProgram* const prog); const String getCurrentProgramName(); - void setParamsInProgramBlock (fxProgram* const prog) throw(); + void setParamsInProgramBlock (fxProgram* const prog); void updateStoredProgramNames(); void initialise(); void handleMidiFromPlugin (const VstEvents* const events); @@ -33705,8 +33667,8 @@ private: bool saveToFXBFile (MemoryBlock& dest, bool isFXB, int maxSizeMB); int getVersionNumber() const throw() { return effect != 0 ? effect->version : 0; } - const String getVersion() const throw(); - const String getCategory() const throw(); + const String getVersion() const; + const String getCategory() const; bool hasEditor() const throw() { return effect != 0 && (effect->flags & effFlagsHasEditor) != 0; } void setPower (const bool on); @@ -33777,34 +33739,32 @@ VSTPluginInstance::VSTPluginInstance (const ReferenceCountedObjectPtr magic == kEffectMagic) + if (effect != 0 && effect->magic == kEffectMagic) + { + try { - try - { #if JUCE_MAC - if (module->resFileId != 0) - UseResFile (module->resFileId); + if (module->resFileId != 0) + UseResFile (module->resFileId); #endif - // Must delete any editors before deleting the plugin instance! - jassert (getActiveEditor() == 0); + // Must delete any editors before deleting the plugin instance! + jassert (getActiveEditor() == 0); - _fpreset(); // some dodgy plugs fuck around with this + _fpreset(); // some dodgy plugs fuck around with this - module->closeEffect (effect); - } - catch (...) - {} + module->closeEffect (effect); } - - module = 0; - effect = 0; + catch (...) + {} } + + module = 0; + effect = 0; } void VSTPluginInstance::initialise() @@ -33869,8 +33829,6 @@ void VSTPluginInstance::prepareToPlay (double sampleRate_, setLatencySamples (effect->initialDelay); - channels.calloc (jmax (16, getNumOutputChannels(), getNumInputChannels()) + 2); - vstHostTime.tempo = 120.0; vstHostTime.timeSigNumerator = 4; vstHostTime.timeSigDenominator = 4; @@ -33924,7 +33882,6 @@ void VSTPluginInstance::releaseResources() incomingMidi.clear(); midiEventsToSend.freeEvents(); - channels.free(); } void VSTPluginInstance::processBlock (AudioSampleBuffer& buffer, @@ -33954,17 +33911,7 @@ void VSTPluginInstance::processBlock (AudioSampleBuffer& buffer, vstHostTime.flags &= ~kVstTransportPlaying; } -#if JUCE_WINDOWS - vstHostTime.nanoSeconds = timeGetTime() * 1000000.0; -#elif JUCE_LINUX - timeval micro; - gettimeofday (µ, 0); - vstHostTime.nanoSeconds = micro.tv_usec * 1000.0; -#elif JUCE_MAC - UnsignedWide micro; - Microseconds (µ); - vstHostTime.nanoSeconds = micro.lo * 1000.0; -#endif + vstHostTime.nanoSeconds = getVSTHostTimeNanoseconds(); if (wantsMidiMessages) { @@ -33989,21 +33936,13 @@ void VSTPluginInstance::processBlock (AudioSampleBuffer& buffer, {} } - int i; - const int maxChans = jmax (effect->numInputs, effect->numOutputs); - - for (i = 0; i < maxChans; ++i) - channels[i] = buffer.getSampleData (i); - - channels [maxChans] = 0; - _clearfp(); if ((effect->flags & effFlagsCanReplacing) != 0) { try { - effect->processReplacing (effect, channels, channels, numSamples); + effect->processReplacing (effect, buffer.getArrayOfChannels(), buffer.getArrayOfChannels(), numSamples); } catch (...) {} @@ -34013,22 +33952,15 @@ void VSTPluginInstance::processBlock (AudioSampleBuffer& buffer, tempBuffer.setSize (effect->numOutputs, numSamples); tempBuffer.clear(); - float* outs [64]; - - for (i = effect->numOutputs; --i >= 0;) - outs[i] = tempBuffer.getSampleData (i); - - outs [effect->numOutputs] = 0; - try { - effect->process (effect, channels, outs, numSamples); + effect->process (effect, buffer.getArrayOfChannels(), tempBuffer.getArrayOfChannels(), numSamples); } catch (...) {} - for (i = effect->numOutputs; --i >= 0;) - buffer.copyFrom (i, 0, outs[i], numSamples); + for (int i = effect->numOutputs; --i >= 0;) + buffer.copyFrom (i, 0, tempBuffer.getSampleData (i), numSamples); } } else @@ -34496,7 +34428,7 @@ private: } #if JUCE_WINDOWS - void checkPluginWindowSize() throw() + void checkPluginWindowSize() { RECT r; GetWindowRect (pluginHWND, &r); @@ -34517,7 +34449,7 @@ private: { for (int i = activeVSTWindows.size(); --i >= 0;) { - const VSTPluginWindow* const w = (const VSTPluginWindow*) activeVSTWindows.getUnchecked (i); + const VSTPluginWindow* const w = activeVSTWindows.getUnchecked (i); if (w->pluginHWND == hW) { @@ -34913,7 +34845,7 @@ bool VSTPluginInstance::loadFromFXBFile (const void* const data, return true; } -void VSTPluginInstance::setParamsInProgramBlock (fxProgram* const prog) throw() +void VSTPluginInstance::setParamsInProgramBlock (fxProgram* const prog) { const int numParams = getNumParameters(); @@ -35070,30 +35002,16 @@ int VSTPluginInstance::dispatch (const int opcode, const int index, const int va { if (effect != 0) { -#if JUCE_MAC + #if JUCE_MAC if (module->resFileId != 0) UseResFile (module->resFileId); - - CGrafPtr oldPort; - - if (getActiveEditor() != 0) - { - const Point pos (getActiveEditor()->relativePositionToOtherComponent (getActiveEditor()->getTopLevelComponent(), Point())); - - GetPort (&oldPort); - SetPortWindowPort ((WindowRef) getActiveEditor()->getWindowHandle()); - SetOrigin (-pos.getX(), -pos.getY()); - } -#endif + #endif result = effect->dispatcher (effect, opcode, index, value, ptr, opt); -#if JUCE_MAC - if (getActiveEditor() != 0) - SetPort (oldPort); - + #if JUCE_MAC module->resFileId = CurResFile(); -#endif + #endif --insideVSTCallback; return result; @@ -35120,7 +35038,7 @@ static VstIntPtr handleGeneralCallback (VstInt32 opcode, VstInt32 index, VstInt3 switch (opcode) { - case audioMasterCanDo: + case audioMasterCanDo: { static const char* canDos[] = { "supplyIdle", "sendVstEvents", @@ -35138,19 +35056,14 @@ static VstIntPtr handleGeneralCallback (VstInt32 opcode, VstInt32 index, VstInt3 return 0; } - case audioMasterVersion: - return 0x2400; - case audioMasterCurrentId: - return shellUIDToCreate; - case audioMasterGetNumAutomatableParameters: - return 0; - case audioMasterGetAutomationState: - return 1; + case audioMasterVersion: return 0x2400; + case audioMasterCurrentId: return shellUIDToCreate; + case audioMasterGetNumAutomatableParameters: return 0; + case audioMasterGetAutomationState: return 1; + case audioMasterGetVendorVersion: return 0x0101; - case audioMasterGetVendorVersion: - return 0x0101; - case audioMasterGetVendorString: - case audioMasterGetProductString: + case audioMasterGetVendorString: + case audioMasterGetProductString: { String hostName ("Juce VST Host"); @@ -35158,21 +35071,16 @@ static VstIntPtr handleGeneralCallback (VstInt32 opcode, VstInt32 index, VstInt3 hostName = JUCEApplication::getInstance()->getApplicationName(); hostName.copyToCString ((char*) ptr, jmin (kVstMaxVendorStrLen, kVstMaxProductStrLen) - 1); + break; } - break; - case audioMasterGetSampleRate: - return (VstIntPtr) defaultVSTSampleRateValue; + case audioMasterGetSampleRate: return (VstIntPtr) defaultVSTSampleRateValue; + case audioMasterGetBlockSize: return (VstIntPtr) defaultVSTBlockSizeValue; + case audioMasterSetOutputSampleRate: return 0; - case audioMasterGetBlockSize: - return (VstIntPtr) defaultVSTBlockSizeValue; - - case audioMasterSetOutputSampleRate: - return 0; - - default: - DBG ("*** Unhandled VST Callback: " + String ((int) opcode)); - break; + default: + DBG ("*** Unhandled VST Callback: " + String ((int) opcode)); + break; } return 0; @@ -35313,7 +35221,7 @@ static VstIntPtr VSTCALLBACK audioMaster (AEffect* effect, VstInt32 opcode, VstI } } -const String VSTPluginInstance::getVersion() const throw() +const String VSTPluginInstance::getVersion() const { unsigned int v = dispatch (effGetVendorVersion, 0, 0, 0, 0); @@ -35347,7 +35255,7 @@ const String VSTPluginInstance::getVersion() const throw() return s; } -int VSTPluginInstance::getUID() const throw() +int VSTPluginInstance::getUID() const { int uid = effect != 0 ? effect->uniqueID : 0; @@ -35357,50 +35265,22 @@ int VSTPluginInstance::getUID() const throw() return uid; } -const String VSTPluginInstance::getCategory() const throw() +const String VSTPluginInstance::getCategory() const { const char* result = 0; switch (dispatch (effGetPlugCategory, 0, 0, 0, 0)) { - case kPlugCategEffect: - result = "Effect"; - break; - - case kPlugCategSynth: - result = "Synth"; - break; - - case kPlugCategAnalysis: - result = "Anaylsis"; - break; - - case kPlugCategMastering: - result = "Mastering"; - break; - - case kPlugCategSpacializer: - result = "Spacial"; - break; - - case kPlugCategRoomFx: - result = "Reverb"; - break; - - case kPlugSurroundFx: - result = "Surround"; - break; - - case kPlugCategRestoration: - result = "Restoration"; - break; - - case kPlugCategGenerator: - result = "Tone generation"; - break; - - default: - break; + case kPlugCategEffect: result = "Effect"; break; + case kPlugCategSynth: result = "Synth"; break; + case kPlugCategAnalysis: result = "Anaylsis"; break; + case kPlugCategMastering: result = "Mastering"; break; + case kPlugCategSpacializer: result = "Spacial"; break; + case kPlugCategRoomFx: result = "Reverb"; break; + case kPlugSurroundFx: result = "Surround"; break; + case kPlugCategRestoration: result = "Restoration"; break; + case kPlugCategGenerator: result = "Tone generation"; break; + default: break; } return result; @@ -35833,11 +35713,9 @@ bool VSTPluginFormat::fileMightContainThisPluginType (const String& fileOrIdenti return false; #elif JUCE_WINDOWS - return f.existsAsFile() - && f.hasFileExtension (".dll"); + return f.existsAsFile() && f.hasFileExtension (".dll"); #elif JUCE_LINUX - return f.existsAsFile() - && f.hasFileExtension (".so"); + return f.existsAsFile() && f.hasFileExtension (".so"); #endif } @@ -262076,6 +261954,42 @@ public: outputNames.clear(); outputIds.clear(); +/* void** hints = 0; + if (snd_device_name_hint (-1, "pcm", &hints) >= 0) + { + for (void** hint = hints; *hint != 0; ++hint) + { + const String name (getHint (*hint, "NAME")); + + if (name.isNotEmpty()) + { + const String ioid (getHint (*hint, "IOID")); + + String desc (getHint (*hint, "DESC")); + if (desc.isEmpty()) + desc = name; + + desc = desc.replaceCharacters ("\n\r", " "); + + DBG ("name: " << name << "\ndesc: " << desc << "\nIO: " << ioid); + + if (ioid.isEmpty() || ioid == "Input") + { + inputNames.add (desc); + inputIds.add (name); + } + + if (ioid.isEmpty() || ioid == "Output") + { + outputNames.add (desc); + outputIds.add (name); + } + } + } + + snd_device_name_free_hint (hints); + } +*/ snd_ctl_t* handle = 0; snd_ctl_card_info_t* info = 0; snd_ctl_card_info_alloca (&info); @@ -262211,6 +262125,14 @@ private: return (isInput || isOutput) && rates.size() > 0; } + /*static const String getHint (void* hint, const char* type) + { + char* const n = snd_device_name_get_hint (hint, type); + const String s ((const char*) n); + free (n); + return s; + }*/ + ALSAAudioIODeviceType (const ALSAAudioIODeviceType&); ALSAAudioIODeviceType& operator= (const ALSAAudioIODeviceType&); }; diff --git a/juce_amalgamated.h b/juce_amalgamated.h index a4737b4a59..2ae7a610dc 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 60 +#define JUCE_BUILDNUMBER 61 /** Current Juce version number. @@ -9433,7 +9433,6 @@ private: bool setFileReadOnlyInternal (bool shouldBeReadOnly) const; static const String parseAbsolutePath (const String& path); - static bool fileTypeMatches (int whatToLookFor, bool isDir, bool isHidden); }; @@ -15461,7 +15460,6 @@ public: juce_UseDebuggingNewOperator private: - friend class File; class NativeIterator { @@ -16145,17 +16143,42 @@ public: */ InputStream* createStreamForEntry (int index); + /** Creates a stream that can read from one of the zip file's entries. + + The stream that is returned must be deleted by the caller (and + zero might be returned if a stream can't be opened for some reason). + + The stream must not be used after the ZipFile object that created + has been deleted. + */ + InputStream* createStreamForEntry (ZipEntry& entry); + /** Uncompresses all of the files in the zip file. - This will expand all the entires into a target directory. The relative + This will expand all the entries into a target directory. The relative paths of the entries are used. @param targetDirectory the root folder to uncompress to @param shouldOverwriteFiles whether to overwrite existing files with similarly-named ones + @returns true if all the files are successfully unzipped */ - void uncompressTo (const File& targetDirectory, + bool uncompressTo (const File& targetDirectory, bool shouldOverwriteFiles = true); + /** Uncompresses one of the entries from the zip file. + + This will expand the entry and write it in a target directory. The entry's path is used to + determine which subfolder of the target should contain the new file. + + @param index the index of the entry to uncompress + @param targetDirectory the root folder to uncompress into + @param shouldOverwriteFiles whether to overwrite existing files with similarly-named ones + @returns true if the files is successfully unzipped + */ + bool uncompressEntry (int index, + const File& targetDirectory, + bool shouldOverwriteFiles = true); + juce_UseDebuggingNewOperator private: @@ -40269,8 +40292,8 @@ public: The model pointer passed-in can be null, in which case you can set it later with setModel(). */ - ListBox (const String& componentName, - ListBoxModel* model); + ListBox (const String& componentName = String::empty, + ListBoxModel* model = 0); /** Destructor. */ ~ListBox(); diff --git a/src/audio/midi/juce_MidiMessage.cpp b/src/audio/midi/juce_MidiMessage.cpp index b000a6e5da..ff002b8a40 100644 --- a/src/audio/midi/juce_MidiMessage.cpp +++ b/src/audio/midi/juce_MidiMessage.cpp @@ -494,8 +494,6 @@ const MidiMessage MidiMessage::noteOff (const int channel, const MidiMessage MidiMessage::allNotesOff (const int channel) throw() { - jassert (channel > 0 && channel <= 16); - return controllerEvent (channel, 123, 0); } diff --git a/src/audio/plugins/formats/juce_VSTPluginFormat.cpp b/src/audio/plugins/formats/juce_VSTPluginFormat.cpp index 2c7f8cc3af..489961b0e9 100644 --- a/src/audio/plugins/formats/juce_VSTPluginFormat.cpp +++ b/src/audio/plugins/formats/juce_VSTPluginFormat.cpp @@ -172,7 +172,6 @@ struct fxProgramSet char chunk[8]; // variable }; - static long vst_swap (const long x) throw() { #ifdef JUCE_LITTLE_ENDIAN @@ -194,6 +193,21 @@ static float vst_swapFloat (const float x) throw() #endif } +static double getVSTHostTimeNanoseconds() +{ + #if JUCE_WINDOWS + return timeGetTime() * 1000000.0; + #elif JUCE_LINUX + timeval micro; + gettimeofday (µ, 0); + return micro.tv_usec * 1000.0; + #elif JUCE_MAC + UnsignedWide micro; + Microseconds (µ); + return micro.lo * 1000.0; + #endif +} + //============================================================================== typedef AEffect* (*MainCall) (audioMasterCallback); @@ -304,22 +318,16 @@ static void translateJuceToXButtonModifiers (const MouseEvent& e, XEvent& ev) th static void translateJuceToXMotionModifiers (const MouseEvent& e, XEvent& ev) throw() { - if (e.mods.isLeftButtonDown()) - ev.xmotion.state |= Button1Mask; - else if (e.mods.isRightButtonDown()) - ev.xmotion.state |= Button3Mask; - else if (e.mods.isMiddleButtonDown()) - ev.xmotion.state |= Button2Mask; + if (e.mods.isLeftButtonDown()) ev.xmotion.state |= Button1Mask; + else if (e.mods.isRightButtonDown()) ev.xmotion.state |= Button3Mask; + else if (e.mods.isMiddleButtonDown()) ev.xmotion.state |= Button2Mask; } static void translateJuceToXCrossingModifiers (const MouseEvent& e, XEvent& ev) throw() { - if (e.mods.isLeftButtonDown()) - ev.xcrossing.state |= Button1Mask; - else if (e.mods.isRightButtonDown()) - ev.xcrossing.state |= Button3Mask; - else if (e.mods.isMiddleButtonDown()) - ev.xcrossing.state |= Button2Mask; + if (e.mods.isLeftButtonDown()) ev.xcrossing.state |= Button1Mask; + else if (e.mods.isRightButtonDown()) ev.xcrossing.state |= Button3Mask; + else if (e.mods.isMiddleButtonDown()) ev.xcrossing.state |= Button2Mask; } static void translateJuceToXMouseWheelModifiers (const MouseEvent& e, const float increment, XEvent& ev) throw() @@ -408,7 +416,6 @@ public: ~ModuleHandle() { getActiveModules().removeValue (this); - close(); } @@ -710,7 +717,7 @@ public: } const String getName() const { return name; } - int getUID() const throw(); + int getUID() const; bool acceptsMidi() const { return wantsMidiMessages; } bool producesMidi() const { return dispatch (effCanDo, 0, 0, (void*) "sendVstMidiEvent", 0) > 0; } @@ -773,7 +780,6 @@ private: MidiBuffer incomingMidi; VSTMidiEventList midiEventsToSend; VstTimeInfo vstHostTime; - HeapBlock channels; ReferenceCountedObjectPtr module; @@ -781,7 +787,7 @@ private: int dispatch (const int opcode, const int index, const int value, void* const ptr, float opt) const; bool restoreProgramSettings (const fxProgram* const prog); const String getCurrentProgramName(); - void setParamsInProgramBlock (fxProgram* const prog) throw(); + void setParamsInProgramBlock (fxProgram* const prog); void updateStoredProgramNames(); void initialise(); void handleMidiFromPlugin (const VstEvents* const events); @@ -796,8 +802,8 @@ private: bool saveToFXBFile (MemoryBlock& dest, bool isFXB, int maxSizeMB); int getVersionNumber() const throw() { return effect != 0 ? effect->version : 0; } - const String getVersion() const throw(); - const String getCategory() const throw(); + const String getVersion() const; + const String getCategory() const; bool hasEditor() const throw() { return effect != 0 && (effect->flags & effFlagsHasEditor) != 0; } void setPower (const bool on); @@ -869,34 +875,32 @@ VSTPluginInstance::VSTPluginInstance (const ReferenceCountedObjectPtr magic == kEffectMagic) + if (effect != 0 && effect->magic == kEffectMagic) + { + try { - try - { #if JUCE_MAC - if (module->resFileId != 0) - UseResFile (module->resFileId); + if (module->resFileId != 0) + UseResFile (module->resFileId); #endif - // Must delete any editors before deleting the plugin instance! - jassert (getActiveEditor() == 0); + // Must delete any editors before deleting the plugin instance! + jassert (getActiveEditor() == 0); - _fpreset(); // some dodgy plugs fuck around with this + _fpreset(); // some dodgy plugs fuck around with this - module->closeEffect (effect); - } - catch (...) - {} + module->closeEffect (effect); } - - module = 0; - effect = 0; + catch (...) + {} } + + module = 0; + effect = 0; } //============================================================================== @@ -964,8 +968,6 @@ void VSTPluginInstance::prepareToPlay (double sampleRate_, setLatencySamples (effect->initialDelay); - channels.calloc (jmax (16, getNumOutputChannels(), getNumInputChannels()) + 2); - vstHostTime.tempo = 120.0; vstHostTime.timeSigNumerator = 4; vstHostTime.timeSigDenominator = 4; @@ -1019,7 +1021,6 @@ void VSTPluginInstance::releaseResources() incomingMidi.clear(); midiEventsToSend.freeEvents(); - channels.free(); } void VSTPluginInstance::processBlock (AudioSampleBuffer& buffer, @@ -1049,17 +1050,7 @@ void VSTPluginInstance::processBlock (AudioSampleBuffer& buffer, vstHostTime.flags &= ~kVstTransportPlaying; } -#if JUCE_WINDOWS - vstHostTime.nanoSeconds = timeGetTime() * 1000000.0; -#elif JUCE_LINUX - timeval micro; - gettimeofday (µ, 0); - vstHostTime.nanoSeconds = micro.tv_usec * 1000.0; -#elif JUCE_MAC - UnsignedWide micro; - Microseconds (µ); - vstHostTime.nanoSeconds = micro.lo * 1000.0; -#endif + vstHostTime.nanoSeconds = getVSTHostTimeNanoseconds(); if (wantsMidiMessages) { @@ -1084,21 +1075,13 @@ void VSTPluginInstance::processBlock (AudioSampleBuffer& buffer, {} } - int i; - const int maxChans = jmax (effect->numInputs, effect->numOutputs); - - for (i = 0; i < maxChans; ++i) - channels[i] = buffer.getSampleData (i); - - channels [maxChans] = 0; - _clearfp(); if ((effect->flags & effFlagsCanReplacing) != 0) { try { - effect->processReplacing (effect, channels, channels, numSamples); + effect->processReplacing (effect, buffer.getArrayOfChannels(), buffer.getArrayOfChannels(), numSamples); } catch (...) {} @@ -1108,22 +1091,15 @@ void VSTPluginInstance::processBlock (AudioSampleBuffer& buffer, tempBuffer.setSize (effect->numOutputs, numSamples); tempBuffer.clear(); - float* outs [64]; - - for (i = effect->numOutputs; --i >= 0;) - outs[i] = tempBuffer.getSampleData (i); - - outs [effect->numOutputs] = 0; - try { - effect->process (effect, channels, outs, numSamples); + effect->process (effect, buffer.getArrayOfChannels(), tempBuffer.getArrayOfChannels(), numSamples); } catch (...) {} - for (i = effect->numOutputs; --i >= 0;) - buffer.copyFrom (i, 0, outs[i], numSamples); + for (int i = effect->numOutputs; --i >= 0;) + buffer.copyFrom (i, 0, tempBuffer.getSampleData (i), numSamples); } } else @@ -1604,7 +1580,7 @@ private: //============================================================================== #if JUCE_WINDOWS - void checkPluginWindowSize() throw() + void checkPluginWindowSize() { RECT r; GetWindowRect (pluginHWND, &r); @@ -1625,7 +1601,7 @@ private: { for (int i = activeVSTWindows.size(); --i >= 0;) { - const VSTPluginWindow* const w = (const VSTPluginWindow*) activeVSTWindows.getUnchecked (i); + const VSTPluginWindow* const w = activeVSTWindows.getUnchecked (i); if (w->pluginHWND == hW) { @@ -2026,7 +2002,7 @@ bool VSTPluginInstance::loadFromFXBFile (const void* const data, } //============================================================================== -void VSTPluginInstance::setParamsInProgramBlock (fxProgram* const prog) throw() +void VSTPluginInstance::setParamsInProgramBlock (fxProgram* const prog) { const int numParams = getNumParameters(); @@ -2184,30 +2160,16 @@ int VSTPluginInstance::dispatch (const int opcode, const int index, const int va { if (effect != 0) { -#if JUCE_MAC + #if JUCE_MAC if (module->resFileId != 0) UseResFile (module->resFileId); - - CGrafPtr oldPort; - - if (getActiveEditor() != 0) - { - const Point pos (getActiveEditor()->relativePositionToOtherComponent (getActiveEditor()->getTopLevelComponent(), Point())); - - GetPort (&oldPort); - SetPortWindowPort ((WindowRef) getActiveEditor()->getWindowHandle()); - SetOrigin (-pos.getX(), -pos.getY()); - } -#endif + #endif result = effect->dispatcher (effect, opcode, index, value, ptr, opt); -#if JUCE_MAC - if (getActiveEditor() != 0) - SetPort (oldPort); - + #if JUCE_MAC module->resFileId = CurResFile(); -#endif + #endif --insideVSTCallback; return result; @@ -2236,7 +2198,7 @@ static VstIntPtr handleGeneralCallback (VstInt32 opcode, VstInt32 index, VstInt3 switch (opcode) { - case audioMasterCanDo: + case audioMasterCanDo: { static const char* canDos[] = { "supplyIdle", "sendVstEvents", @@ -2254,19 +2216,14 @@ static VstIntPtr handleGeneralCallback (VstInt32 opcode, VstInt32 index, VstInt3 return 0; } - case audioMasterVersion: - return 0x2400; - case audioMasterCurrentId: - return shellUIDToCreate; - case audioMasterGetNumAutomatableParameters: - return 0; - case audioMasterGetAutomationState: - return 1; + case audioMasterVersion: return 0x2400; + case audioMasterCurrentId: return shellUIDToCreate; + case audioMasterGetNumAutomatableParameters: return 0; + case audioMasterGetAutomationState: return 1; + case audioMasterGetVendorVersion: return 0x0101; - case audioMasterGetVendorVersion: - return 0x0101; - case audioMasterGetVendorString: - case audioMasterGetProductString: + case audioMasterGetVendorString: + case audioMasterGetProductString: { String hostName ("Juce VST Host"); @@ -2274,21 +2231,16 @@ static VstIntPtr handleGeneralCallback (VstInt32 opcode, VstInt32 index, VstInt3 hostName = JUCEApplication::getInstance()->getApplicationName(); hostName.copyToCString ((char*) ptr, jmin (kVstMaxVendorStrLen, kVstMaxProductStrLen) - 1); + break; } - break; - - case audioMasterGetSampleRate: - return (VstIntPtr) defaultVSTSampleRateValue; - case audioMasterGetBlockSize: - return (VstIntPtr) defaultVSTBlockSizeValue; - - case audioMasterSetOutputSampleRate: - return 0; + case audioMasterGetSampleRate: return (VstIntPtr) defaultVSTSampleRateValue; + case audioMasterGetBlockSize: return (VstIntPtr) defaultVSTBlockSizeValue; + case audioMasterSetOutputSampleRate: return 0; - default: - DBG ("*** Unhandled VST Callback: " + String ((int) opcode)); - break; + default: + DBG ("*** Unhandled VST Callback: " + String ((int) opcode)); + break; } return 0; @@ -2430,7 +2382,7 @@ static VstIntPtr VSTCALLBACK audioMaster (AEffect* effect, VstInt32 opcode, VstI } //============================================================================== -const String VSTPluginInstance::getVersion() const throw() +const String VSTPluginInstance::getVersion() const { unsigned int v = dispatch (effGetVendorVersion, 0, 0, 0, 0); @@ -2464,7 +2416,7 @@ const String VSTPluginInstance::getVersion() const throw() return s; } -int VSTPluginInstance::getUID() const throw() +int VSTPluginInstance::getUID() const { int uid = effect != 0 ? effect->uniqueID : 0; @@ -2474,50 +2426,22 @@ int VSTPluginInstance::getUID() const throw() return uid; } -const String VSTPluginInstance::getCategory() const throw() +const String VSTPluginInstance::getCategory() const { const char* result = 0; switch (dispatch (effGetPlugCategory, 0, 0, 0, 0)) { - case kPlugCategEffect: - result = "Effect"; - break; - - case kPlugCategSynth: - result = "Synth"; - break; - - case kPlugCategAnalysis: - result = "Anaylsis"; - break; - - case kPlugCategMastering: - result = "Mastering"; - break; - - case kPlugCategSpacializer: - result = "Spacial"; - break; - - case kPlugCategRoomFx: - result = "Reverb"; - break; - - case kPlugSurroundFx: - result = "Surround"; - break; - - case kPlugCategRestoration: - result = "Restoration"; - break; - - case kPlugCategGenerator: - result = "Tone generation"; - break; - - default: - break; + case kPlugCategEffect: result = "Effect"; break; + case kPlugCategSynth: result = "Synth"; break; + case kPlugCategAnalysis: result = "Anaylsis"; break; + case kPlugCategMastering: result = "Mastering"; break; + case kPlugCategSpacializer: result = "Spacial"; break; + case kPlugCategRoomFx: result = "Reverb"; break; + case kPlugSurroundFx: result = "Surround"; break; + case kPlugCategRestoration: result = "Restoration"; break; + case kPlugCategGenerator: result = "Tone generation"; break; + default: break; } return result; @@ -2957,11 +2881,9 @@ bool VSTPluginFormat::fileMightContainThisPluginType (const String& fileOrIdenti return false; #elif JUCE_WINDOWS - return f.existsAsFile() - && f.hasFileExtension (".dll"); + return f.existsAsFile() && f.hasFileExtension (".dll"); #elif JUCE_LINUX - return f.existsAsFile() - && f.hasFileExtension (".so"); + return f.existsAsFile() && f.hasFileExtension (".so"); #endif } diff --git a/src/core/juce_StandardHeader.h b/src/core/juce_StandardHeader.h index 0f73be32ad..468edfa80a 100644 --- a/src/core/juce_StandardHeader.h +++ b/src/core/juce_StandardHeader.h @@ -33,7 +33,7 @@ */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 52 -#define JUCE_BUILDNUMBER 60 +#define JUCE_BUILDNUMBER 61 /** Current Juce version number. diff --git a/src/gui/components/controls/juce_ListBox.h b/src/gui/components/controls/juce_ListBox.h index b880c5eb84..b288063d34 100644 --- a/src/gui/components/controls/juce_ListBox.h +++ b/src/gui/components/controls/juce_ListBox.h @@ -175,8 +175,8 @@ public: The model pointer passed-in can be null, in which case you can set it later with setModel(). */ - ListBox (const String& componentName, - ListBoxModel* model); + ListBox (const String& componentName = String::empty, + ListBoxModel* model = 0); /** Destructor. */ ~ListBox(); diff --git a/src/io/files/juce_DirectoryIterator.h b/src/io/files/juce_DirectoryIterator.h index 75f57a7db5..133a1f190d 100644 --- a/src/io/files/juce_DirectoryIterator.h +++ b/src/io/files/juce_DirectoryIterator.h @@ -115,8 +115,6 @@ public: juce_UseDebuggingNewOperator private: - friend class File; - //============================================================================== class NativeIterator { diff --git a/src/io/files/juce_File.cpp b/src/io/files/juce_File.cpp index 86ad8d2d14..bb321af780 100644 --- a/src/io/files/juce_File.cpp +++ b/src/io/files/juce_File.cpp @@ -532,97 +532,40 @@ const String File::loadFileAsString() const } //============================================================================== -bool File::fileTypeMatches (const int whatToLookFor, const bool isDir, const bool isHidden) -{ - return (whatToLookFor & (isDir ? findDirectories - : findFiles)) != 0 - && ((! isHidden) || (whatToLookFor & File::ignoreHiddenFiles) == 0); -} - int File::findChildFiles (Array& results, const int whatToLookFor, const bool searchRecursively, const String& wildCardPattern) const { - // you have to specify the type of files you're looking for! - jassert ((whatToLookFor & (findFiles | findDirectories)) != 0); + DirectoryIterator di (*this, searchRecursively, wildCardPattern, whatToLookFor); int total = 0; - - if (isDirectory()) + while (di.next()) { - // find child files or directories in this directory first.. - String path (addTrailingSeparator (fullPath)), filename; - bool itemIsDirectory, itemIsHidden; - - DirectoryIterator::NativeIterator i (path, wildCardPattern); - - while (i.next (filename, &itemIsDirectory, &itemIsHidden, 0, 0, 0, 0)) - { - if (! filename.containsOnly (".")) - { - const File fileFound (path + filename, 0); - - if (fileTypeMatches (whatToLookFor, itemIsDirectory, itemIsHidden)) - { - results.add (fileFound); - ++total; - } - - if (searchRecursively && itemIsDirectory - && ((! itemIsHidden) || (whatToLookFor & File::ignoreHiddenFiles) == 0)) - - { - total += fileFound.findChildFiles (results, whatToLookFor, true, wildCardPattern); - } - } - } + results.add (di.getFile()); + ++total; } return total; } -int File::getNumberOfChildFiles (const int whatToLookFor, - const String& wildCardPattern) const +int File::getNumberOfChildFiles (const int whatToLookFor, const String& wildCardPattern) const { - // you have to specify the type of files you're looking for! - jassert (whatToLookFor > 0 && whatToLookFor <= 3); - - int count = 0; - - if (isDirectory()) - { - String filename; - bool itemIsDirectory, itemIsHidden; - - DirectoryIterator::NativeIterator i (*this, wildCardPattern); + DirectoryIterator di (*this, false, "*", whatToLookFor); - while (i.next (filename, &itemIsDirectory, &itemIsHidden, 0, 0, 0, 0)) - if (fileTypeMatches (whatToLookFor, itemIsDirectory, itemIsHidden) - && ! filename.containsOnly (".")) - ++count; - } - else - { - // trying to search for files inside a non-directory? - jassertfalse; - } + int total = 0; + while (di.next()) + ++total; - return count; + return total; } bool File::containsSubDirectories() const { if (isDirectory()) { - String filename; - bool itemIsDirectory; - - DirectoryIterator::NativeIterator i (*this, "*"); - - while (i.next (filename, &itemIsDirectory, 0, 0, 0, 0, 0)) - if (itemIsDirectory) - return true; + DirectoryIterator di (*this, false, "*", findDirectories); + return di.next(); } return false; diff --git a/src/io/files/juce_File.h b/src/io/files/juce_File.h index 435639b71c..fcd69e3b57 100644 --- a/src/io/files/juce_File.h +++ b/src/io/files/juce_File.h @@ -939,7 +939,6 @@ private: bool setFileReadOnlyInternal (bool shouldBeReadOnly) const; static const String parseAbsolutePath (const String& path); - static bool fileTypeMatches (int whatToLookFor, bool isDir, bool isHidden); }; diff --git a/src/io/files/juce_ZipFile.cpp b/src/io/files/juce_ZipFile.cpp index a8685dbd45..7eea5e68bb 100644 --- a/src/io/files/juce_ZipFile.cpp +++ b/src/io/files/juce_ZipFile.cpp @@ -374,46 +374,61 @@ int ZipFile::findEndOfZipEntryTable (InputStream* input, int& numEntries) return 0; } -void ZipFile::uncompressTo (const File& targetDirectory, +bool ZipFile::uncompressTo (const File& targetDirectory, const bool shouldOverwriteFiles) { for (int i = 0; i < entries.size(); ++i) - { - const ZipEntry& zei = entries.getUnchecked(i)->entry; + if (! uncompressEntry (i, targetDirectory, shouldOverwriteFiles)) + return false; + + return true; +} + +bool ZipFile::uncompressEntry (const int index, + const File& targetDirectory, + bool shouldOverwriteFiles) +{ + const ZipEntryInfo* zei = entries [index]; - const File targetFile (targetDirectory.getChildFile (zei.filename)); + if (zei != 0) + { + const File targetFile (targetDirectory.getChildFile (zei->entry.filename)); - if (zei.filename.endsWithChar ('/')) + if (zei->entry.filename.endsWithChar ('/')) { targetFile.createDirectory(); // (entry is a directory, not a file) } else { - ScopedPointer in (createStreamForEntry (i)); + ScopedPointer in (createStreamForEntry (index)); if (in != 0) { - if (shouldOverwriteFiles) - targetFile.deleteFile(); + if (shouldOverwriteFiles && ! targetFile.deleteFile()) + return false; - if ((! targetFile.exists()) - && targetFile.getParentDirectory().createDirectory()) + if ((! targetFile.exists()) && targetFile.getParentDirectory().createDirectory()) { - ScopedPointer out (targetFile.createOutputStream()); + ScopedPointer out (targetFile.createOutputStream()); if (out != 0) { out->writeFromInputStream (*in, -1); out = 0; - targetFile.setCreationTime (zei.fileTime); - targetFile.setLastModificationTime (zei.fileTime); - targetFile.setLastAccessTime (zei.fileTime); + targetFile.setCreationTime (zei->entry.fileTime); + targetFile.setLastModificationTime (zei->entry.fileTime); + targetFile.setLastAccessTime (zei->entry.fileTime); + + return true; } } } } } + + return false; } + END_JUCE_NAMESPACE diff --git a/src/io/files/juce_ZipFile.h b/src/io/files/juce_ZipFile.h index 48e6c648c3..52f1a83697 100644 --- a/src/io/files/juce_ZipFile.h +++ b/src/io/files/juce_ZipFile.h @@ -128,18 +128,42 @@ public: */ InputStream* createStreamForEntry (int index); + /** Creates a stream that can read from one of the zip file's entries. + + The stream that is returned must be deleted by the caller (and + zero might be returned if a stream can't be opened for some reason). + + The stream must not be used after the ZipFile object that created + has been deleted. + */ + InputStream* createStreamForEntry (ZipEntry& entry); + //============================================================================== /** Uncompresses all of the files in the zip file. - This will expand all the entires into a target directory. The relative + This will expand all the entries into a target directory. The relative paths of the entries are used. @param targetDirectory the root folder to uncompress to @param shouldOverwriteFiles whether to overwrite existing files with similarly-named ones + @returns true if all the files are successfully unzipped */ - void uncompressTo (const File& targetDirectory, + bool uncompressTo (const File& targetDirectory, bool shouldOverwriteFiles = true); + /** Uncompresses one of the entries from the zip file. + + This will expand the entry and write it in a target directory. The entry's path is used to + determine which subfolder of the target should contain the new file. + + @param index the index of the entry to uncompress + @param targetDirectory the root folder to uncompress into + @param shouldOverwriteFiles whether to overwrite existing files with similarly-named ones + @returns true if the files is successfully unzipped + */ + bool uncompressEntry (int index, + const File& targetDirectory, + bool shouldOverwriteFiles = true); //============================================================================== juce_UseDebuggingNewOperator diff --git a/src/native/linux/juce_linux_Audio.cpp b/src/native/linux/juce_linux_Audio.cpp index 97f6502dd3..72d8218752 100644 --- a/src/native/linux/juce_linux_Audio.cpp +++ b/src/native/linux/juce_linux_Audio.cpp @@ -789,6 +789,42 @@ public: outputNames.clear(); outputIds.clear(); +/* void** hints = 0; + if (snd_device_name_hint (-1, "pcm", &hints) >= 0) + { + for (void** hint = hints; *hint != 0; ++hint) + { + const String name (getHint (*hint, "NAME")); + + if (name.isNotEmpty()) + { + const String ioid (getHint (*hint, "IOID")); + + String desc (getHint (*hint, "DESC")); + if (desc.isEmpty()) + desc = name; + + desc = desc.replaceCharacters ("\n\r", " "); + + DBG ("name: " << name << "\ndesc: " << desc << "\nIO: " << ioid); + + if (ioid.isEmpty() || ioid == "Input") + { + inputNames.add (desc); + inputIds.add (name); + } + + if (ioid.isEmpty() || ioid == "Output") + { + outputNames.add (desc); + outputIds.add (name); + } + } + } + + snd_device_name_free_hint (hints); + } +*/ snd_ctl_t* handle = 0; snd_ctl_card_info_t* info = 0; snd_ctl_card_info_alloca (&info); @@ -925,6 +961,14 @@ private: return (isInput || isOutput) && rates.size() > 0; } + /*static const String getHint (void* hint, const char* type) + { + char* const n = snd_device_name_get_hint (hint, type); + const String s ((const char*) n); + free (n); + return s; + }*/ + ALSAAudioIODeviceType (const ALSAAudioIODeviceType&); ALSAAudioIODeviceType& operator= (const ALSAAudioIODeviceType&); };