Browse Source

tags/2021-05-28
jules 17 years ago
parent
commit
ad0f73dad6
26 changed files with 5535 additions and 3896 deletions
  1. +191
    -191
      build/macosx/platform_specific_code/juce_mac_Network.cpp
  2. +1
    -1
      build/macosx/platform_specific_code/juce_mac_Threads.cpp
  3. +3604
    -3604
      build/macosx/platform_specific_code/juce_mac_Windowing.cpp
  4. +382
    -0
      build/win32/platform_specific_code/juce_win32_AudioCDReader.cpp
  5. +1
    -1
      build/win32/platform_specific_code/juce_win32_Network.cpp
  6. +32
    -0
      build/win32/vc8/JUCE.vcproj
  7. +4
    -0
      docs/JUCE changelist.txt
  8. +8
    -6
      extras/juce demo/build/macosx/jucedemo.xcodeproj/project.pbxproj
  9. +9
    -0
      src/juce_app_includes.h
  10. +89
    -0
      src/juce_appframework/audio/audio_file_formats/juce_AudioCDBurner.h
  11. +535
    -0
      src/juce_appframework/audio/audio_file_formats/juce_AudioThumbnail.cpp
  12. +194
    -0
      src/juce_appframework/audio/audio_file_formats/juce_AudioThumbnail.h
  13. +145
    -0
      src/juce_appframework/audio/audio_file_formats/juce_AudioThumbnailCache.cpp
  14. +98
    -0
      src/juce_appframework/audio/audio_file_formats/juce_AudioThumbnailCache.h
  15. +2
    -2
      src/juce_appframework/gui/components/controls/juce_ListBox.cpp
  16. +2
    -2
      src/juce_appframework/gui/components/controls/juce_ListBox.h
  17. +1
    -1
      src/juce_appframework/gui/components/controls/juce_TableListBox.cpp
  18. +4
    -4
      src/juce_appframework/gui/components/controls/juce_TableListBox.h
  19. +6
    -6
      src/juce_core/basics/juce_DataConversions.h
  20. +1
    -1
      src/juce_core/io/juce_OutputStream.cpp
  21. +66
    -0
      src/juce_core/io/streams/juce_FileInputSource.cpp
  22. +67
    -0
      src/juce_core/io/streams/juce_FileInputSource.h
  23. +80
    -0
      src/juce_core/io/streams/juce_InputSource.h
  24. +3
    -41
      src/juce_core/text/juce_XmlDocument.cpp
  25. +4
    -36
      src/juce_core/text/juce_XmlDocument.h
  26. +6
    -0
      src/juce_core_includes.h

+ 191
- 191
build/macosx/platform_specific_code/juce_mac_Network.cpp View File

@@ -1,191 +1,191 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-7 by Raw Material Software ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the
GNU General Public License, as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.
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.
You should have received a copy of the GNU General Public License
along with JUCE; if not, visit www.gnu.org/licenses or write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
------------------------------------------------------------------------------
If you'd like to release a closed-source product which uses JUCE, commercial
licenses are also available: visit www.rawmaterialsoftware.com/juce for
more information.
==============================================================================
*/
#include "../../../src/juce_core/basics/juce_StandardHeader.h"
#include <IOKit/IOKitLib.h>
#include <IOKit/network/IOEthernetInterface.h>
#include <IOKit/network/IONetworkInterface.h>
#include <IOKit/network/IOEthernetController.h>
#include <Carbon/Carbon.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
BEGIN_JUCE_NAMESPACE
#include "../../../src/juce_core/text/juce_String.h"
#include "../../../src/juce_core/basics/juce_Time.h"
#include "../../../src/juce_core/basics/juce_SystemStats.h"
#include "../../../src/juce_core/containers/juce_MemoryBlock.h"
#include "../../../src/juce_core/text/juce_StringArray.h"
#include "../../../src/juce_core/misc/juce_PlatformUtilities.h"
#include "../../../src/juce_core/io/network/juce_URL.h"
#include "juce_mac_HTTPStream.h"
//==============================================================================
static bool GetEthernetIterator (io_iterator_t* matchingServices) throw()
{
mach_port_t masterPort;
if (IOMasterPort (MACH_PORT_NULL, &masterPort) == KERN_SUCCESS)
{
CFMutableDictionaryRef dict = IOServiceMatching (kIOEthernetInterfaceClass);
if (dict != 0)
{
CFMutableDictionaryRef propDict = CFDictionaryCreateMutable (kCFAllocatorDefault,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if (propDict != 0)
{
CFDictionarySetValue (propDict, CFSTR (kIOPrimaryInterface), kCFBooleanTrue);
CFDictionarySetValue (dict, CFSTR (kIOPropertyMatchKey), propDict);
CFRelease (propDict);
}
}
return IOServiceGetMatchingServices (masterPort, dict, matchingServices) == KERN_SUCCESS;
}
return false;
}
int SystemStats::getMACAddresses (int64* addresses, int maxNum, const bool littleEndian) throw()
{
int numResults = 0;
io_iterator_t it;
if (GetEthernetIterator (&it))
{
io_object_t i;
while ((i = IOIteratorNext (it)) != 0)
{
io_object_t controller;
if (IORegistryEntryGetParentEntry (i, kIOServicePlane, &controller) == KERN_SUCCESS)
{
CFTypeRef data = IORegistryEntryCreateCFProperty (controller,
CFSTR (kIOMACAddress),
kCFAllocatorDefault,
0);
if (data != 0)
{
UInt8 addr [kIOEthernetAddressSize];
zeromem (addr, sizeof (addr));
CFDataGetBytes ((CFDataRef) data, CFRangeMake (0, sizeof (addr)), addr);
CFRelease (data);
int64 a = 0;
for (int i = 6; --i >= 0;)
a = (a << 8) | addr[i];
if (! littleEndian)
a = (int64) swapByteOrder ((uint64) a);
if (numResults < maxNum)
{
*addresses++ = a;
++numResults;
}
}
IOObjectRelease (controller);
}
IOObjectRelease (i);
}
IOObjectRelease (it);
}
return numResults;
}
//==============================================================================
bool PlatformUtilities::launchEmailWithAttachments (const String& targetEmailAddress,
const String& emailSubject,
const String& bodyText,
const StringArray& filesToAttach)
{
String script;
script << "tell application \"Mail\"\r\n"
"set newMessage to make new outgoing message with properties {subject:\""
<< emailSubject
<< "\", content:\""
<< bodyText
<< "\" & return & return}\r\n"
"tell newMessage\r\n"
"set visible to true\r\n"
"set sender to \"sdfsdfsdfewf\"\r\n"
"make new to recipient at end of to recipients with properties {address:\""
<< targetEmailAddress
<< "\"}\r\n";
for (int i = 0; i < filesToAttach.size(); ++i)
{
script << "tell content\r\n"
"make new attachment with properties {file name:\""
<< filesToAttach[i]
<< "\"} at after the last paragraph\r\n"
"end tell\r\n";
}
script << "end tell\r\n"
"end tell\r\n";
DBG (script);
ComponentInstance comp = OpenDefaultComponent (kOSAComponentType, kOSAGenericScriptingComponentSubtype);
OSAID resultID;
AEDesc source;
AECreateDesc (typeUTF8Text, (Ptr) script.toUTF8(), strlen (script.toUTF8()), &source);
OSAError err = OSACompileExecute (comp, &source,
kOSANullScript, kOSAModeNull,
&resultID);
AEDisposeDesc (&source);
CloseComponent (comp);
return false;
}
END_JUCE_NAMESPACE
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-7 by Raw Material Software ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the
GNU General Public License, as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.
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.
You should have received a copy of the GNU General Public License
along with JUCE; if not, visit www.gnu.org/licenses or write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
------------------------------------------------------------------------------
If you'd like to release a closed-source product which uses JUCE, commercial
licenses are also available: visit www.rawmaterialsoftware.com/juce for
more information.
==============================================================================
*/
#include "../../../src/juce_core/basics/juce_StandardHeader.h"
#include <IOKit/IOKitLib.h>
#include <IOKit/network/IOEthernetInterface.h>
#include <IOKit/network/IONetworkInterface.h>
#include <IOKit/network/IOEthernetController.h>
#include <Carbon/Carbon.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
BEGIN_JUCE_NAMESPACE
#include "../../../src/juce_core/text/juce_String.h"
#include "../../../src/juce_core/basics/juce_Time.h"
#include "../../../src/juce_core/basics/juce_SystemStats.h"
#include "../../../src/juce_core/containers/juce_MemoryBlock.h"
#include "../../../src/juce_core/text/juce_StringArray.h"
#include "../../../src/juce_core/misc/juce_PlatformUtilities.h"
#include "../../../src/juce_core/io/network/juce_URL.h"
#include "juce_mac_HTTPStream.h"
//==============================================================================
static bool GetEthernetIterator (io_iterator_t* matchingServices) throw()
{
mach_port_t masterPort;
if (IOMasterPort (MACH_PORT_NULL, &masterPort) == KERN_SUCCESS)
{
CFMutableDictionaryRef dict = IOServiceMatching (kIOEthernetInterfaceClass);
if (dict != 0)
{
CFMutableDictionaryRef propDict = CFDictionaryCreateMutable (kCFAllocatorDefault,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if (propDict != 0)
{
CFDictionarySetValue (propDict, CFSTR (kIOPrimaryInterface), kCFBooleanTrue);
CFDictionarySetValue (dict, CFSTR (kIOPropertyMatchKey), propDict);
CFRelease (propDict);
}
}
return IOServiceGetMatchingServices (masterPort, dict, matchingServices) == KERN_SUCCESS;
}
return false;
}
int SystemStats::getMACAddresses (int64* addresses, int maxNum, const bool littleEndian) throw()
{
int numResults = 0;
io_iterator_t it;
if (GetEthernetIterator (&it))
{
io_object_t i;
while ((i = IOIteratorNext (it)) != 0)
{
io_object_t controller;
if (IORegistryEntryGetParentEntry (i, kIOServicePlane, &controller) == KERN_SUCCESS)
{
CFTypeRef data = IORegistryEntryCreateCFProperty (controller,
CFSTR (kIOMACAddress),
kCFAllocatorDefault,
0);
if (data != 0)
{
UInt8 addr [kIOEthernetAddressSize];
zeromem (addr, sizeof (addr));
CFDataGetBytes ((CFDataRef) data, CFRangeMake (0, sizeof (addr)), addr);
CFRelease (data);
int64 a = 0;
for (int i = 6; --i >= 0;)
a = (a << 8) | addr[i];
if (! littleEndian)
a = (int64) swapByteOrder ((uint64) a);
if (numResults < maxNum)
{
*addresses++ = a;
++numResults;
}
}
IOObjectRelease (controller);
}
IOObjectRelease (i);
}
IOObjectRelease (it);
}
return numResults;
}
//==============================================================================
bool PlatformUtilities::launchEmailWithAttachments (const String& targetEmailAddress,
const String& emailSubject,
const String& bodyText,
const StringArray& filesToAttach)
{
String script;
script << "tell application \"Mail\"\r\n"
"set newMessage to make new outgoing message with properties {subject:\""
<< emailSubject
<< "\", content:\""
<< bodyText
<< "\" & return & return}\r\n"
"tell newMessage\r\n"
"set visible to true\r\n"
"set sender to \"sdfsdfsdfewf\"\r\n"
"make new to recipient at end of to recipients with properties {address:\""
<< targetEmailAddress
<< "\"}\r\n";
for (int i = 0; i < filesToAttach.size(); ++i)
{
script << "tell content\r\n"
"make new attachment with properties {file name:\""
<< filesToAttach[i]
<< "\"} at after the last paragraph\r\n"
"end tell\r\n";
}
script << "end tell\r\n"
"end tell\r\n";
DBG (script);
ComponentInstance comp = OpenDefaultComponent (kOSAComponentType, kOSAGenericScriptingComponentSubtype);
OSAID resultID;
AEDesc source;
AECreateDesc (typeUTF8Text, (Ptr) script.toUTF8(), strlen (script.toUTF8()), &source);
OSAError err = OSACompileExecute (comp, &source,
kOSANullScript, kOSAModeNull,
&resultID);
AEDisposeDesc (&source);
CloseComponent (comp);
return false;
}
END_JUCE_NAMESPACE

+ 1
- 1
build/macosx/platform_specific_code/juce_mac_Threads.cpp View File

@@ -235,7 +235,7 @@ bool JUCE_CALLTYPE juce_isRunningUnderDebugger() throw()
int m[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid() }; int m[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid() };
size_t sz = sizeof (info); size_t sz = sizeof (info);
sysctl (m, 4, &info, &sz, 0, 0); sysctl (m, 4, &info, &sz, 0, 0);
testResult = (info.kp_proc.p_flag & P_TRACED) == P_TRACED ? 1 : -1;
testResult = ((info.kp_proc.p_flag & P_TRACED) != 0) ? 1 : -1;
} }
return testResult > 0; return testResult > 0;


+ 3604
- 3604
build/macosx/platform_specific_code/juce_mac_Windowing.cpp
File diff suppressed because it is too large
View File


+ 382
- 0
build/win32/platform_specific_code/juce_win32_AudioCDReader.cpp View File

@@ -36,13 +36,18 @@
#include "win32_headers.h" #include "win32_headers.h"
#include <stddef.h> #include <stddef.h>
#include <imapi.h>
#include <imapierror.h>
#include "../../../src/juce_core/basics/juce_StandardHeader.h" #include "../../../src/juce_core/basics/juce_StandardHeader.h"
BEGIN_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE
#include "../../../src/juce_appframework/audio/audio_file_formats/juce_AudioCDReader.h" #include "../../../src/juce_appframework/audio/audio_file_formats/juce_AudioCDReader.h"
#include "../../../src/juce_appframework/audio/audio_file_formats/juce_AudioCDBurner.h"
#include "../../../src/juce_appframework/events/juce_Timer.h" #include "../../../src/juce_appframework/events/juce_Timer.h"
#include "../../../src/juce_appframework/application/juce_DeletedAtShutdown.h" #include "../../../src/juce_appframework/application/juce_DeletedAtShutdown.h"
#include "../../../src/juce_appframework/audio/dsp/juce_AudioDataConverters.h"
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning (pop) #pragma warning (pop)
@@ -2108,4 +2113,381 @@ void AudioCDReader::ejectDisk()
((CDDeviceWrapper*) handle)->cdH->openDrawer (true); ((CDDeviceWrapper*) handle)->cdH->openDrawer (true);
} }
//==============================================================================
static IDiscRecorder* enumCDBurners (StringArray* list, int indexToOpen, IDiscMaster** master)
{
CoInitialize (0);
IDiscMaster* dm;
IDiscRecorder* result = 0;
if (SUCCEEDED (CoCreateInstance (CLSID_MSDiscMasterObj, 0,
CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
IID_IDiscMaster,
(void**) &dm)))
{
if (SUCCEEDED (dm->Open()))
{
IEnumDiscRecorders* drEnum = 0;
if (SUCCEEDED (dm->EnumDiscRecorders (&drEnum)))
{
IDiscRecorder* dr = 0;
DWORD dummy;
int index = 0;
while (drEnum->Next (1, &dr, &dummy) == S_OK)
{
if (indexToOpen == index)
{
result = dr;
break;
}
else if (list != 0)
{
BSTR path;
if (SUCCEEDED (dr->GetPath (&path)))
list->add ((const WCHAR*) path);
}
++index;
dr->Release();
}
drEnum->Release();
}
/*if (redbookFormat != 0)
{
IEnumDiscMasterFormats* mfEnum;
if (SUCCEEDED (dm->EnumDiscMasterFormats (&mfEnum)))
{
IID formatIID;
DWORD dummy;
while (mfEnum->Next (1, &formatIID, &dummy) == S_OK)
{
}
mfEnum->Release();
}
redbookFormat
}*/
if (master == 0)
dm->Close();
}
if (master != 0)
*master = dm;
else
dm->Release();
}
return result;
}
const StringArray AudioCDBurner::findAvailableDevices()
{
StringArray devs;
enumCDBurners (&devs, -1, 0);
return devs;
}
AudioCDBurner* AudioCDBurner::openDevice (const int deviceIndex)
{
AudioCDBurner* b = new AudioCDBurner (deviceIndex);
if (b->internal == 0)
deleteAndZero (b);
return b;
}
class CDBurnerInfo : public IDiscMasterProgressEvents
{
public:
CDBurnerInfo()
: refCount (1),
progress (0),
shouldCancel (false),
listener (0)
{
}
~CDBurnerInfo()
{
}
HRESULT __stdcall QueryInterface (REFIID id, void __RPC_FAR* __RPC_FAR* result)
{
if (result == 0)
return E_POINTER;
if (id == IID_IUnknown || id == IID_IDiscMasterProgressEvents)
{
AddRef();
*result = this;
return S_OK;
}
*result = 0;
return E_NOINTERFACE;
}
ULONG __stdcall AddRef() { return ++refCount; }
ULONG __stdcall Release() { jassert (refCount > 0); const int r = --refCount; if (r == 0) delete this; return r; }
HRESULT __stdcall QueryCancel (boolean* pbCancel)
{
if (listener != 0 && ! shouldCancel)
shouldCancel = listener->audioCDBurnProgress (progress);
*pbCancel = shouldCancel;
return S_OK;
}
HRESULT __stdcall NotifyBlockProgress (long nCompleted, long nTotal)
{
progress = nCompleted / (float) nTotal;
shouldCancel = listener != 0 && listener->audioCDBurnProgress (progress);
return E_NOTIMPL;
}
HRESULT __stdcall NotifyPnPActivity (void) { return E_NOTIMPL; }
HRESULT __stdcall NotifyAddProgress (long /*nCompletedSteps*/, long /*nTotalSteps*/) { return E_NOTIMPL; }
HRESULT __stdcall NotifyTrackProgress (long /*nCurrentTrack*/, long /*nTotalTracks*/) { return E_NOTIMPL; }
HRESULT __stdcall NotifyPreparingBurn (long /*nEstimatedSeconds*/) { return E_NOTIMPL; }
HRESULT __stdcall NotifyClosingDisc (long /*nEstimatedSeconds*/) { return E_NOTIMPL; }
HRESULT __stdcall NotifyBurnComplete (HRESULT /*status*/) { return E_NOTIMPL; }
HRESULT __stdcall NotifyEraseComplete (HRESULT /*status*/) { return E_NOTIMPL; }
IDiscMaster* discMaster;
IDiscRecorder* discRecorder;
IRedbookDiscMaster* redbook;
AudioCDBurner::BurnProgressListener* listener;
float progress;
bool shouldCancel;
private:
int refCount;
};
AudioCDBurner::AudioCDBurner (const int deviceIndex)
: internal (0)
{
IDiscMaster* discMaster;
IDiscRecorder* dr = enumCDBurners (0, deviceIndex, &discMaster);
if (dr != 0)
{
IRedbookDiscMaster* redbook;
HRESULT hr = discMaster->SetActiveDiscMasterFormat (IID_IRedbookDiscMaster, (void**) &redbook);
hr = discMaster->SetActiveDiscRecorder (dr);
CDBurnerInfo* const info = new CDBurnerInfo();
internal = info;
info->discMaster = discMaster;
info->discRecorder = dr;
info->redbook = redbook;
}
}
AudioCDBurner::~AudioCDBurner()
{
CDBurnerInfo* const info = (CDBurnerInfo*) internal;
if (info != 0)
{
info->discRecorder->Close();
info->redbook->Release();
info->discRecorder->Release();
info->discMaster->Release();
info->Release();
}
}
bool AudioCDBurner::isDiskPresent() const
{
CDBurnerInfo* const info = (CDBurnerInfo*) internal;
HRESULT hr = info->discRecorder->OpenExclusive();
long type, flags;
hr = info->discRecorder->QueryMediaType (&type, &flags);
info->discRecorder->Close();
return hr == S_OK && type != 0 && (flags & MEDIA_WRITABLE) != 0;
}
int AudioCDBurner::getNumAvailableAudioBlocks() const
{
CDBurnerInfo* const info = (CDBurnerInfo*) internal;
long blocksFree = 0;
info->redbook->GetAvailableAudioTrackBlocks (&blocksFree);
return blocksFree;
}
const String AudioCDBurner::burn (AudioCDBurner::BurnProgressListener* listener,
const bool ejectDiscAfterwards)
{
CDBurnerInfo* const info = (CDBurnerInfo*) internal;
info->listener = listener;
info->progress = 0;
info->shouldCancel = false;
UINT cookie;
HRESULT hr = info->discMaster->ProgressAdvise (info, &cookie);
hr = info->discMaster->RecordDisc (FALSE, // set this to TRUE to make it do a fake burn, without actually writing to the disc
ejectDiscAfterwards);
String error;
if (hr != S_OK)
{
const char* e = "Couldn't open or write to the CD device";
if (hr == IMAPI_E_USERABORT)
e = "User cancelled the write operation";
else if (hr == IMAPI_E_MEDIUM_NOTPRESENT || hr == IMAPI_E_TRACKOPEN)
e = "No Disk present";
error = e;
}
info->discMaster->ProgressUnadvise (cookie);
info->listener = 0;
return error;
}
bool AudioCDBurner::addAudioTrack (AudioFormatReader& source, int numSamples)
{
CDBurnerInfo* const info = (CDBurnerInfo*) internal;
long bytesPerBlock;
HRESULT hr = info->redbook->GetAudioBlockSize (&bytesPerBlock);
const int samplesPerBlock = bytesPerBlock / 4;
bool ok = true;
hr = info->redbook->CreateAudioTrack ((long) numSamples / (bytesPerBlock * 4));
byte* const buffer = (byte*) juce_malloc (bytesPerBlock);
int* sourceBuffers[2];
sourceBuffers[0] = (int*) juce_malloc (samplesPerBlock * 4);
sourceBuffers[1] = (int*) juce_malloc (samplesPerBlock * 4);
int samplesDone = 0;
for (;;)
{
zeromem (buffer, bytesPerBlock);
if (! source.read (sourceBuffers, samplesDone, samplesPerBlock))
{
ok = false;
break;
}
short* destBuffer = (short*) buffer;
for (int j = 0; j < samplesPerBlock; ++j)
{
*destBuffer++ = (short) (sourceBuffers [0][j] >> 16);
*destBuffer++ = (short) (sourceBuffers [jmin (1, source.numChannels - 1)][j] >> 16);
}
hr = info->redbook->AddAudioTrackBlocks (buffer, bytesPerBlock);
if (hr != S_OK)
{
ok = false;
break;
}
samplesDone += samplesPerBlock;
if (samplesDone >= numSamples)
break;
}
juce_free (sourceBuffers[0]);
juce_free (sourceBuffers[1]);
juce_free (buffer);
hr = info->redbook->CloseAudioTrack();
return ok && hr == S_OK;
}
bool AudioCDBurner::addAudioTrack (AudioSource& source, int numSamples)
{
CDBurnerInfo* const info = (CDBurnerInfo*) internal;
long bytesPerBlock;
HRESULT hr = info->redbook->GetAudioBlockSize (&bytesPerBlock);
const int samplesPerBlock = bytesPerBlock / 4;
bool ok = true;
hr = info->redbook->CreateAudioTrack ((long) numSamples / (bytesPerBlock * 4));
byte* const buffer = (byte*) juce_malloc (bytesPerBlock);
AudioSampleBuffer sourceBuffer (2, samplesPerBlock);
int samplesDone = 0;
source.prepareToPlay (samplesPerBlock, 44100.0);
while (ok)
{
{
AudioSourceChannelInfo info;
info.buffer = &sourceBuffer;
info.numSamples = samplesPerBlock;
info.startSample = 0;
sourceBuffer.clear();
source.getNextAudioBlock (info);
}
zeromem (buffer, bytesPerBlock);
AudioDataConverters::convertFloatToInt16LE (sourceBuffer.getSampleData (0, 0),
buffer, samplesPerBlock, 4);
AudioDataConverters::convertFloatToInt16LE (sourceBuffer.getSampleData (1, 0),
buffer + 2, samplesPerBlock, 4);
hr = info->redbook->AddAudioTrackBlocks (buffer, bytesPerBlock);
if (hr != S_OK)
ok = false;
samplesDone += samplesPerBlock;
if (samplesDone >= numSamples)
break;
}
juce_free (buffer);
hr = info->redbook->CloseAudioTrack();
return ok && hr == S_OK;
}
END_JUCE_NAMESPACE END_JUCE_NAMESPACE

+ 1
- 1
build/win32/platform_specific_code/juce_win32_Network.cpp View File

@@ -417,7 +417,7 @@ bool PlatformUtilities::launchEmailWithAttachments (const String& targetEmailAdd
files[i].lpszPathName = (LPTSTR) (LPCTSTR) filesToAttach [i]; files[i].lpszPathName = (LPTSTR) (LPCTSTR) filesToAttach [i];
} }
ok = (mapiSendMail (0, 0, &message, MAPI_DIALOG, 0) == SUCCESS_SUCCESS);
ok = (mapiSendMail (0, 0, &message, MAPI_DIALOG | MAPI_LOGON_UI, 0) == SUCCESS_SUCCESS);
} }
FreeLibrary (h); FreeLibrary (h);


+ 32
- 0
build/win32/vc8/JUCE.vcproj View File

@@ -533,6 +533,10 @@
RelativePath="..\..\..\src\juce_appframework\audio\audio_file_formats\juce_AiffAudioFormat.h" RelativePath="..\..\..\src\juce_appframework\audio\audio_file_formats\juce_AiffAudioFormat.h"
> >
</File> </File>
<File
RelativePath="..\..\..\src\juce_appframework\audio\audio_file_formats\juce_AudioCDBurner.h"
>
</File>
<File <File
RelativePath="..\..\..\src\juce_appframework\audio\audio_file_formats\juce_AudioCDReader.h" RelativePath="..\..\..\src\juce_appframework\audio\audio_file_formats\juce_AudioCDReader.h"
> >
@@ -641,6 +645,22 @@
RelativePath="..\..\..\src\juce_appframework\audio\audio_file_formats\juce_AudioSubsectionReader.h" RelativePath="..\..\..\src\juce_appframework\audio\audio_file_formats\juce_AudioSubsectionReader.h"
> >
</File> </File>
<File
RelativePath="..\..\..\src\juce_appframework\audio\audio_file_formats\juce_AudioThumbnail.cpp"
>
</File>
<File
RelativePath="..\..\..\src\juce_appframework\audio\audio_file_formats\juce_AudioThumbnail.h"
>
</File>
<File
RelativePath="..\..\..\src\juce_appframework\audio\audio_file_formats\juce_AudioThumbnailCache.cpp"
>
</File>
<File
RelativePath="..\..\..\src\juce_appframework\audio\audio_file_formats\juce_AudioThumbnailCache.h"
>
</File>
<File <File
RelativePath="..\..\..\src\juce_appframework\audio\audio_file_formats\juce_FlacAudioFormat.cpp" RelativePath="..\..\..\src\juce_appframework\audio\audio_file_formats\juce_FlacAudioFormat.cpp"
> >
@@ -5242,6 +5262,14 @@
RelativePath="..\..\..\src\juce_core\io\streams\juce_BufferedInputStream.h" RelativePath="..\..\..\src\juce_core\io\streams\juce_BufferedInputStream.h"
> >
</File> </File>
<File
RelativePath="..\..\..\src\juce_core\io\streams\juce_FileInputSource.cpp"
>
</File>
<File
RelativePath="..\..\..\src\juce_core\io\streams\juce_FileInputSource.h"
>
</File>
<File <File
RelativePath="..\..\..\src\juce_core\io\streams\juce_GZIPCompressorOutputStream.cpp" RelativePath="..\..\..\src\juce_core\io\streams\juce_GZIPCompressorOutputStream.cpp"
> >
@@ -5330,6 +5358,10 @@
RelativePath="..\..\..\src\juce_core\io\streams\juce_GZIPDecompressorInputStream.h" RelativePath="..\..\..\src\juce_core\io\streams\juce_GZIPDecompressorInputStream.h"
> >
</File> </File>
<File
RelativePath="..\..\..\src\juce_core\io\streams\juce_InputSource.h"
>
</File>
<File <File
RelativePath="..\..\..\src\juce_core\io\streams\juce_MemoryInputStream.cpp" RelativePath="..\..\..\src\juce_core\io\streams\juce_MemoryInputStream.cpp"
> >


+ 4
- 0
docs/JUCE changelist.txt View File

@@ -20,6 +20,10 @@ Changelist for version 1.46
- added a parameter to DragAndDropTarget::isInterestedInDragSource(). This ma - added a parameter to DragAndDropTarget::isInterestedInDragSource(). This ma
- changed the parameters to AudioIODeviceCallback::audioDeviceAboutToStart(), so that it now just supplies a pointer to the device. If you need to, you can still find out the sample rate and block size by asking the device for them. - changed the parameters to AudioIODeviceCallback::audioDeviceAboutToStart(), so that it now just supplies a pointer to the device. If you need to, you can still find out the sample rate and block size by asking the device for them.
- changes to the URL class to allow file uploading - changes to the URL class to allow file uploading
- new method: PlatformUtilities::launchEmailWithAttachments
- new classes: AudioThumbnail and AudioThumbnailCache, which allow easy rendering of low-res waveform previews
- new classes: InputSource and FileInputSource. These encapsulate some kind of resource, and also replace the XmlInputSource class.



============================================================================== ==============================================================================
Changelist for version 1.45 Changelist for version 1.45


+ 8
- 6
extras/juce demo/build/macosx/jucedemo.xcodeproj/project.pbxproj View File

@@ -32,7 +32,7 @@
84EAE2F309DAAF0B00288D0A /* AGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84EAE2F109DAAF0B00288D0A /* AGL.framework */; }; 84EAE2F309DAAF0B00288D0A /* AGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84EAE2F109DAAF0B00288D0A /* AGL.framework */; };
84EAE2F409DAAF0B00288D0A /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84EAE2F209DAAF0B00288D0A /* OpenGL.framework */; }; 84EAE2F409DAAF0B00288D0A /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84EAE2F209DAAF0B00288D0A /* OpenGL.framework */; };
84F8DB0B099CA8DD00E911ED /* QuickTimeDemo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84F8DB0A099CA8DD00E911ED /* QuickTimeDemo.cpp */; }; 84F8DB0B099CA8DD00E911ED /* QuickTimeDemo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84F8DB0A099CA8DD00E911ED /* QuickTimeDemo.cpp */; };
84FDB0950C15BDDD00CD0087 /* libjuce.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 84FDB0940C15BDCE00CD0087 /* libjuce.a */; };
84FDB0950C15BDDD00CD0087 /* libjucedebug.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 84FDB0940C15BDCE00CD0087 /* libjucedebug.a */; };
8D0C4E8D0486CD37000505A6 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0867D6AAFE840B52C02AAC07 /* InfoPlist.strings */; }; 8D0C4E8D0486CD37000505A6 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0867D6AAFE840B52C02AAC07 /* InfoPlist.strings */; };
8D0C4E920486CD37000505A6 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 20286C33FDCF999611CA2CEA /* Carbon.framework */; }; 8D0C4E920486CD37000505A6 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 20286C33FDCF999611CA2CEA /* Carbon.framework */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
@@ -77,7 +77,7 @@
84EAE2F909DAAF2F00288D0A /* Juce.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Juce.xcodeproj; path = ../../../../build/macosx/Juce.xcodeproj; sourceTree = SOURCE_ROOT; }; 84EAE2F909DAAF2F00288D0A /* Juce.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Juce.xcodeproj; path = ../../../../build/macosx/Juce.xcodeproj; sourceTree = SOURCE_ROOT; };
84F8DB0A099CA8DD00E911ED /* QuickTimeDemo.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = QuickTimeDemo.cpp; sourceTree = "<group>"; }; 84F8DB0A099CA8DD00E911ED /* QuickTimeDemo.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = QuickTimeDemo.cpp; sourceTree = "<group>"; };
8D0C4E960486CD37000505A6 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; }; 8D0C4E960486CD37000505A6 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
8D0C4E970486CD37000505A6 /* jucedemo.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = jucedemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
8D0C4E970486CD37000505A6 /* jucedemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = jucedemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */ /* End PBXFileReference section */


/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@@ -85,7 +85,7 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
84FDB0950C15BDDD00CD0087 /* libjuce.a in Frameworks */,
84FDB0950C15BDDD00CD0087 /* libjucedebug.a in Frameworks */,
8D0C4E920486CD37000505A6 /* Carbon.framework in Frameworks */, 8D0C4E920486CD37000505A6 /* Carbon.framework in Frameworks */,
84C49F2606C0F3200066071B /* CoreAudio.framework in Frameworks */, 84C49F2606C0F3200066071B /* CoreAudio.framework in Frameworks */,
84C4A41106C0F9A00066071B /* IOKit.framework in Frameworks */, 84C4A41106C0F9A00066071B /* IOKit.framework in Frameworks */,
@@ -181,7 +181,7 @@
84FDB0900C15BDCE00CD0087 /* Products */ = { 84FDB0900C15BDCE00CD0087 /* Products */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
84FDB0940C15BDCE00CD0087 /* libjuce.a */,
84FDB0940C15BDCE00CD0087 /* libjucedebug.a */,
); );
name = Products; name = Products;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -228,6 +228,7 @@
20286C28FDCF999611CA2CEA /* Project object */ = { 20286C28FDCF999611CA2CEA /* Project object */ = {
isa = PBXProject; isa = PBXProject;
buildConfigurationList = 84CFBCCF085F14F000C52F85 /* Build configuration list for PBXProject "jucedemo" */; buildConfigurationList = 84CFBCCF085F14F000C52F85 /* Build configuration list for PBXProject "jucedemo" */;
compatibilityVersion = "Xcode 2.4";
hasScannedForEncodings = 1; hasScannedForEncodings = 1;
mainGroup = 20286C29FDCF999611CA2CEA /* jucedemo */; mainGroup = 20286C29FDCF999611CA2CEA /* jucedemo */;
projectDirPath = ""; projectDirPath = "";
@@ -237,6 +238,7 @@
ProjectRef = 84EAE2F909DAAF2F00288D0A /* Juce.xcodeproj */; ProjectRef = 84EAE2F909DAAF2F00288D0A /* Juce.xcodeproj */;
}, },
); );
projectRoot = "";
targets = ( targets = (
8D0C4E890486CD37000505A6 /* jucedemo */, 8D0C4E890486CD37000505A6 /* jucedemo */,
); );
@@ -244,10 +246,10 @@
/* End PBXProject section */ /* End PBXProject section */


/* Begin PBXReferenceProxy section */ /* Begin PBXReferenceProxy section */
84FDB0940C15BDCE00CD0087 /* libjuce.a */ = {
84FDB0940C15BDCE00CD0087 /* libjucedebug.a */ = {
isa = PBXReferenceProxy; isa = PBXReferenceProxy;
fileType = archive.ar; fileType = archive.ar;
path = libjuce.a;
path = libjucedebug.a;
remoteRef = 84FDB0930C15BDCE00CD0087 /* PBXContainerItemProxy */; remoteRef = 84FDB0930C15BDCE00CD0087 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR; sourceTree = BUILT_PRODUCTS_DIR;
}; };


+ 9
- 0
src/juce_app_includes.h View File

@@ -197,6 +197,9 @@
#ifndef __JUCE_AIFFAUDIOFORMAT_JUCEHEADER__ #ifndef __JUCE_AIFFAUDIOFORMAT_JUCEHEADER__
#include "juce_appframework/audio/audio_file_formats/juce_AiffAudioFormat.h" #include "juce_appframework/audio/audio_file_formats/juce_AiffAudioFormat.h"
#endif #endif
#ifndef __JUCE_AUDIOCDBURNER_JUCEHEADER__
#include "juce_appframework/audio/audio_file_formats/juce_AudioCDBurner.h"
#endif
#ifndef __JUCE_AUDIOCDREADER_JUCEHEADER__ #ifndef __JUCE_AUDIOCDREADER_JUCEHEADER__
#include "juce_appframework/audio/audio_file_formats/juce_AudioCDReader.h" #include "juce_appframework/audio/audio_file_formats/juce_AudioCDReader.h"
#endif #endif
@@ -215,6 +218,12 @@
#ifndef __JUCE_AUDIOSUBSECTIONREADER_JUCEHEADER__ #ifndef __JUCE_AUDIOSUBSECTIONREADER_JUCEHEADER__
#include "juce_appframework/audio/audio_file_formats/juce_AudioSubsectionReader.h" #include "juce_appframework/audio/audio_file_formats/juce_AudioSubsectionReader.h"
#endif #endif
#ifndef __JUCE_AUDIOTHUMBNAIL_JUCEHEADER__
#include "juce_appframework/audio/audio_file_formats/juce_AudioThumbnail.h"
#endif
#ifndef __JUCE_AUDIOTHUMBNAILCACHE_JUCEHEADER__
#include "juce_appframework/audio/audio_file_formats/juce_AudioThumbnailCache.h"
#endif
#ifndef __JUCE_FLACAUDIOFORMAT_JUCEHEADER__ #ifndef __JUCE_FLACAUDIOFORMAT_JUCEHEADER__
#include "juce_appframework/audio/audio_file_formats/juce_FlacAudioFormat.h" #include "juce_appframework/audio/audio_file_formats/juce_FlacAudioFormat.h"
#endif #endif


+ 89
- 0
src/juce_appframework/audio/audio_file_formats/juce_AudioCDBurner.h View File

@@ -0,0 +1,89 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-7 by Raw Material Software ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the
GNU General Public License, as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.
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.
You should have received a copy of the GNU General Public License
along with JUCE; if not, visit www.gnu.org/licenses or write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
------------------------------------------------------------------------------
If you'd like to release a closed-source product which uses JUCE, commercial
licenses are also available: visit www.rawmaterialsoftware.com/juce for
more information.
==============================================================================
*/
#ifndef __JUCE_AUDIOCDBURNER_JUCEHEADER__
#define __JUCE_AUDIOCDBURNER_JUCEHEADER__
#include "juce_AudioFormatReader.h"
#include "../audio_sources/juce_AudioSource.h"
//==============================================================================
/**
*/
class AudioCDBurner
{
public:
//==============================================================================
static const StringArray findAvailableDevices();
static AudioCDBurner* openDevice (const int deviceIndex);
~AudioCDBurner();
//==============================================================================
bool isDiskPresent() const;
int getNumAvailableAudioBlocks() const;
bool addAudioTrack (AudioFormatReader& source, int numSamples);
bool addAudioTrack (AudioSource& source, int numSamples);
/**
Return true to cancel the current burn operation
*/
class BurnProgressListener
{
public:
BurnProgressListener() throw() {}
virtual ~BurnProgressListener() {}
/** Called at intervals to report on the progress of the AudioCDBurner.
To cancel the burn, return true from this.
*/
virtual bool audioCDBurnProgress (float proportionComplete) = 0;
};
const String burn (BurnProgressListener* listener,
const bool ejectDiscAfterwards);
//==============================================================================
juce_UseDebuggingNewOperator
private:
AudioCDBurner (const int deviceIndex);
void* internal;
};
#endif // __JUCE_AUDIOCDBURNER_JUCEHEADER__

+ 535
- 0
src/juce_appframework/audio/audio_file_formats/juce_AudioThumbnail.cpp View File

@@ -0,0 +1,535 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-7 by Raw Material Software ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the
GNU General Public License, as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.
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.
You should have received a copy of the GNU General Public License
along with JUCE; if not, visit www.gnu.org/licenses or write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
------------------------------------------------------------------------------
If you'd like to release a closed-source product which uses JUCE, commercial
licenses are also available: visit www.rawmaterialsoftware.com/juce for
more information.
==============================================================================
*/
#include "../../../juce_core/basics/juce_StandardHeader.h"
BEGIN_JUCE_NAMESPACE
#include "juce_AudioThumbnail.h"
#include "juce_AudioThumbnailCache.h"
const int timeBeforeDeletingReader = 1000;
//==============================================================================
struct AudioThumbnailDataFormat
{
char thumbnailMagic[4];
int samplesPerThumbSample;
int64 totalSamples; // source samples
int64 numFinishedSamples; // source samples
int numThumbnailSamples;
int numChannels;
int sampleRate;
char future[16];
char data[1];
};
#if JUCE_BIG_ENDIAN
static void swap (int& n) { n = (int) swapByteOrder ((uint32) n); }
static void swap (int64& n) { n = (int64) swapByteOrder ((uint64) n); }
#endif
static void swapEndiannessIfNeeded (AudioThumbnailDataFormat* const d)
{
(void) d;
#if JUCE_BIG_ENDIAN
swap (d->samplesPerThumbSample);
swap (d->totalSamples);
swap (d->numFinishedSamples);
swap (d->numThumbnailSamples);
swap (d->numChannels);
swap (d->sampleRate);
#endif
}
//==============================================================================
AudioThumbnail::AudioThumbnail (const int orginalSamplesPerThumbnailSample_,
AudioFormatManager& formatManagerToUse_,
AudioThumbnailCache& cacheToUse)
: cache (cacheToUse),
formatManagerToUse (formatManagerToUse_),
source (0),
reader (0),
orginalSamplesPerThumbnailSample (orginalSamplesPerThumbnailSample_)
{
clear();
}
AudioThumbnail::~AudioThumbnail()
{
cache.removeThumbnail (this);
const ScopedLock sl (readerLock);
deleteAndZero (reader);
delete source;
}
void AudioThumbnail::setSource (InputSource* const newSource)
{
cache.removeThumbnail (this);
delete source;
source = newSource;
{
const ScopedLock sl (readerLock);
deleteAndZero (reader);
reader = createReader();
}
clear();
if (reader != 0)
{
startTimer (timeBeforeDeletingReader);
initialiseFromAudioFile (*reader);
cache.loadThumb (*this, newSource->hashCode());
if (! isFullyLoaded())
cache.addThumbnail (this);
}
}
bool AudioThumbnail::useTimeSlice()
{
const ScopedLock sl (readerLock);
if (isFullyLoaded())
{
if (reader != 0)
startTimer (timeBeforeDeletingReader);
cache.removeThumbnail (this);
return false;
}
if (reader == 0)
reader = createReader();
if (reader != 0)
{
readNextBlockFromAudioFile (*reader);
startTimer (timeBeforeDeletingReader);
sendChangeMessage (this);
const bool justFinished = isFullyLoaded();
if (justFinished)
cache.storeThumb (*this, source->hashCode());
return ! justFinished;
}
return false;
}
AudioFormatReader* AudioThumbnail::createReader() const
{
if (source != 0)
{
InputStream* const audioFileStream = source->createInputStream();
if (audioFileStream != 0)
return formatManagerToUse.createReaderFor (audioFileStream);
}
return 0;
}
void AudioThumbnail::timerCallback()
{
stopTimer();
const ScopedLock sl (readerLock);
deleteAndZero (reader);
}
void AudioThumbnail::clear()
{
data.setSize (sizeof (AudioThumbnailDataFormat) + 3);
AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData();
d->thumbnailMagic[0] = 'j';
d->thumbnailMagic[1] = 'a';
d->thumbnailMagic[2] = 't';
d->thumbnailMagic[3] = 'm';
d->samplesPerThumbSample = orginalSamplesPerThumbnailSample;
d->totalSamples = 0;
d->numFinishedSamples = 0;
d->numThumbnailSamples = 0;
d->numChannels = 0;
d->sampleRate = 0;
numSamplesCached = 0;
}
void AudioThumbnail::loadFrom (InputStream& input)
{
data.setSize (0);
input.readIntoMemoryBlock (data);
AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData();
swapEndiannessIfNeeded (d);
if (! (d->thumbnailMagic[0] == 'j'
&& d->thumbnailMagic[1] == 'a'
&& d->thumbnailMagic[2] == 't'
&& d->thumbnailMagic[3] == 'm'))
{
clear();
}
numSamplesCached = 0;
}
void AudioThumbnail::saveTo (OutputStream& output) const
{
AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData();
swapEndiannessIfNeeded (d);
output.write (data.getData(), data.getSize());
swapEndiannessIfNeeded (d);
}
bool AudioThumbnail::initialiseFromAudioFile (AudioFormatReader& reader)
{
AudioThumbnailDataFormat* d = (AudioThumbnailDataFormat*) data.getData();
d->totalSamples = reader.lengthInSamples;
d->numChannels = jmin (2, reader.numChannels);
d->numFinishedSamples = 0;
d->sampleRate = roundDoubleToInt (reader.sampleRate);
d->numThumbnailSamples = (int) (d->totalSamples / d->samplesPerThumbSample) + 1;
data.setSize (sizeof (AudioThumbnailDataFormat) + 3 + d->numThumbnailSamples * d->numChannels * 2);
d = (AudioThumbnailDataFormat*) data.getData();
zeromem (&(d->data[0]), d->numThumbnailSamples * d->numChannels * 2);
return d->totalSamples > 0;
}
bool AudioThumbnail::readNextBlockFromAudioFile (AudioFormatReader& reader)
{
AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData();
if (d->numFinishedSamples < d->totalSamples)
{
const int numToDo = (int) jmin ((int64) 65536, d->totalSamples - d->numFinishedSamples);
generateSection (reader,
d->numFinishedSamples,
numToDo);
d->numFinishedSamples += numToDo;
}
numSamplesCached = 0; // zap the cache
return (d->numFinishedSamples < d->totalSamples);
}
int AudioThumbnail::getNumChannels() const throw()
{
const AudioThumbnailDataFormat* const d = (const AudioThumbnailDataFormat*) data.getData();
jassert (d != 0);
return d->numChannels;
}
double AudioThumbnail::getTotalLength() const throw()
{
const AudioThumbnailDataFormat* const d = (const AudioThumbnailDataFormat*) data.getData();
jassert (d != 0);
if (d->sampleRate > 0)
return d->totalSamples / (double)d->sampleRate;
else
return 0.0;
}
void AudioThumbnail::generateSection (AudioFormatReader& reader,
int64 startSample,
int numSamples)
{
AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData();
jassert (d != 0);
int firstDataPos = (int) (startSample / d->samplesPerThumbSample);
int lastDataPos = (int) ((startSample + numSamples) / d->samplesPerThumbSample);
char* l = getChannelData (0);
char* r = getChannelData (1);
for (int i = firstDataPos; i < lastDataPos; ++i)
{
const int sourceStart = i * d->samplesPerThumbSample;
const int sourceEnd = sourceStart + d->samplesPerThumbSample;
float lowestLeft, highestLeft, lowestRight, highestRight;
reader.readMaxLevels (sourceStart,
sourceEnd - sourceStart,
lowestLeft,
highestLeft,
lowestRight,
highestRight);
int n = i * 2;
if (r != 0)
{
l [n] = (char) jlimit (-128.0f, 127.0f, lowestLeft * 127.0f);
r [n++] = (char) jlimit (-128.0f, 127.0f, lowestRight * 127.0f);
l [n] = (char) jlimit (-128.0f, 127.0f, highestLeft * 127.0f);
r [n++] = (char) jlimit (-128.0f, 127.0f, highestRight * 127.0f);
}
else
{
l [n++] = (char) jlimit (-128.0f, 127.0f, lowestLeft * 127.0f);
l [n++] = (char) jlimit (-128.0f, 127.0f, highestLeft * 127.0f);
}
}
}
char* AudioThumbnail::getChannelData (int channel) const
{
AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData();
jassert (d != 0);
if (channel >= 0 && channel < d->numChannels)
return d->data + (channel * 2 * d->numThumbnailSamples);
return 0;
}
bool AudioThumbnail::isFullyLoaded() const throw()
{
const AudioThumbnailDataFormat* const d = (const AudioThumbnailDataFormat*) data.getData();
jassert (d != 0);
return d->numFinishedSamples >= d->totalSamples;
}
void AudioThumbnail::refillCache (const int numSamples,
double startTime,
const double timePerPixel)
{
const AudioThumbnailDataFormat* const d = (const AudioThumbnailDataFormat*) data.getData();
jassert (d != 0);
if (numSamples <= 0
|| timePerPixel <= 0.0
|| d->sampleRate <= 0)
{
numSamplesCached = 0;
return;
}
if (numSamples == numSamplesCached
&& numChannelsCached == d->numChannels
&& startTime == cachedStart
&& timePerPixel == cachedTimePerPixel)
{
return;
}
numSamplesCached = numSamples;
numChannelsCached = d->numChannels;
cachedStart = startTime;
cachedTimePerPixel = timePerPixel;
cachedLevels.ensureSize (2 * numChannelsCached * numSamples);
const bool needExtraDetail = (timePerPixel * d->sampleRate <= d->samplesPerThumbSample);
const ScopedLock sl (readerLock);
if (needExtraDetail && reader == 0)
reader = createReader();
if (reader != 0 && timePerPixel * d->sampleRate <= d->samplesPerThumbSample)
{
startTimer (timeBeforeDeletingReader);
char* cacheData = (char*) cachedLevels;
int sample = roundDoubleToInt (startTime * d->sampleRate);
for (int i = numSamples; --i >= 0;)
{
const int nextSample = roundDoubleToInt ((startTime + timePerPixel) * d->sampleRate);
if (sample >= 0)
{
if (sample >= reader->lengthInSamples)
break;
float lmin, lmax, rmin, rmax;
reader->readMaxLevels (sample,
jmax (1, nextSample - sample),
lmin, lmax, rmin, rmax);
cacheData[0] = (char) jlimit (-128, 127, roundFloatToInt (lmin * 127.0f));
cacheData[1] = (char) jlimit (-128, 127, roundFloatToInt (lmax * 127.0f));
if (numChannelsCached > 1)
{
cacheData[2] = (char) jlimit (-128, 127, roundFloatToInt (rmin * 127.0f));
cacheData[3] = (char) jlimit (-128, 127, roundFloatToInt (rmax * 127.0f));
}
cacheData += 2 * numChannelsCached;
}
startTime += timePerPixel;
sample = nextSample;
}
}
else
{
for (int channelNum = 0; channelNum < 2; ++channelNum)
{
char* const data = getChannelData (channelNum);
char* cacheData = ((char*) cachedLevels) + channelNum * 2;
const double timeToThumbSampleFactor = d->sampleRate / (double) d->samplesPerThumbSample;
startTime = cachedStart;
int sample = roundDoubleToInt (startTime * timeToThumbSampleFactor);
const int numFinished = (int) (d->numFinishedSamples / d->samplesPerThumbSample);
for (int i = numSamples; --i >= 0;)
{
const int nextSample = roundDoubleToInt ((startTime + timePerPixel) * timeToThumbSampleFactor);
if (sample >= 0 && data != 0)
{
char mx = -128;
char mn = 127;
while (sample <= nextSample)
{
if (sample >= numFinished)
break;
const int n = sample << 1;
const char sampMin = data [n];
const char sampMax = data [n + 1];
if (sampMin < mn)
mn = sampMin;
if (sampMax > mx)
mx = sampMax;
++sample;
}
if (mn <= mx)
{
cacheData[0] = mn;
cacheData[1] = mx;
}
else
{
cacheData[0] = 1;
cacheData[1] = 0;
}
}
else
{
cacheData[0] = 1;
cacheData[1] = 0;
}
cacheData += numChannelsCached * 2;
startTime += timePerPixel;
sample = nextSample;
}
}
}
}
void AudioThumbnail::drawChannel (Graphics& g,
int x, int y, int w, int h,
double startTime,
double endTime,
int channelNum,
const float verticalZoomFactor)
{
refillCache (w, startTime, (endTime - startTime) / w);
if (numSamplesCached >= w
&& channelNum >= 0
&& channelNum < numChannelsCached)
{
const float topY = (float) y;
const float bottomY = topY + h;
const float midY = topY + h * 0.5f;
const float vscale = verticalZoomFactor * h / 256.0f;
const Rectangle clip (g.getClipBounds());
const int skipLeft = clip.getX() - x;
w -= skipLeft;
x += skipLeft;
const char* cacheData = ((const char*) cachedLevels)
+ (channelNum << 1)
+ skipLeft * (numChannelsCached << 1);
while (--w >= 0)
{
const char mn = cacheData[0];
const char mx = cacheData[1];
cacheData += numChannelsCached << 1;
if (mn <= mx) // if the wrong way round, signifies that the sample's not yet known
g.drawLine ((float) x, jmax (midY - mx * vscale - 0.3f, topY),
(float) x, jmin (midY - mn * vscale + 0.3f, bottomY));
++x;
if (x >= clip.getRight())
break;
}
}
}
END_JUCE_NAMESPACE

+ 194
- 0
src/juce_appframework/audio/audio_file_formats/juce_AudioThumbnail.h View File

@@ -0,0 +1,194 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-7 by Raw Material Software ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the
GNU General Public License, as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.
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.
You should have received a copy of the GNU General Public License
along with JUCE; if not, visit www.gnu.org/licenses or write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
------------------------------------------------------------------------------
If you'd like to release a closed-source product which uses JUCE, commercial
licenses are also available: visit www.rawmaterialsoftware.com/juce for
more information.
==============================================================================
*/
#ifndef __JUCE_AUDIOTHUMBNAIL_JUCEHEADER__
#define __JUCE_AUDIOTHUMBNAIL_JUCEHEADER__
#include "../../../juce_core/threads/juce_TimeSliceThread.h"
#include "../../../juce_core/io/streams/juce_InputSource.h"
#include "../../../juce_core/io/juce_OutputStream.h"
#include "../../events/juce_ChangeBroadcaster.h"
#include "../../events/juce_Timer.h"
#include "../../gui/graphics/contexts/juce_Graphics.h"
#include "juce_AudioFormatReader.h"
#include "juce_AudioFormatManager.h"
class AudioThumbnailCache;
//==============================================================================
/**
Makes it easy to quickly draw scaled views of the waveform shape of an
audio file.
To use this class, just create an AudioThumbNail class for the file you want
to draw, call setSource to tell it which file or resource to use, then call
drawChannel() to draw it.
The class will asynchronously scan the wavefile to create its scaled-down view,
so you should make your UI repaint itself as this data comes in. To do this, the
AudioThumbnail is a ChangeBroadcaster, and will broadcast a message when its
listeners should repaint themselves.
The thumbnail stores an internal low-res version of the wave data, and this can
be loaded and saved to avoid having to scan the file again.
@see AudioThumbnailCache
*/
class JUCE_API AudioThumbnail : public ChangeBroadcaster,
public TimeSliceClient,
private Timer
{
public:
//==============================================================================
/** Creates an audio thumbnail.
@param sourceSamplesPerThumbnailSample when creating a stored, low-res version
of the audio data, this is the scale at which it should be done
@param formatManagerToUse the audio format manager that is used to open the file
@param cacheToUse an instance of an AudioThumbnailCache - this provides a background
thread and storage that is used to by the thumbnail, and the cache
object can be shared between multiple thumbnails
*/
AudioThumbnail (const int sourceSamplesPerThumbnailSample,
AudioFormatManager& formatManagerToUse,
AudioThumbnailCache& cacheToUse);
/** Destructor. */
~AudioThumbnail();
//==============================================================================
/** Specifies the file or stream that contains the audio file.
For a file, just call
@code
setSource (new FileInputSource (file))
@endcode
You can pass a zero in here to clear the thumbnail.
The source that is passed in will be deleted by this object when it is no
longer needed
*/
void setSource (InputSource* const newSource);
/** Reloads the low res thumbnail data from an input stream.
The thumb will automatically attempt to reload itself from its
AudioThumbnailCache.
*/
void loadFrom (InputStream& input);
/** Saves the low res thumbnail data to an output stream.
The thumb will automatically attempt to save itself to its
AudioThumbnailCache after it finishes scanning the wave file.
*/
void saveTo (OutputStream& output) const;
//==============================================================================
/** Returns the number of channels in the file.
*/
int getNumChannels() const throw();
/** Returns the length of the audio file.
*/
double getTotalLength() const throw();
/** Renders the waveform shape for a channel.
The waveform will be drawn within the specified rectangle, where startTime
and endTime specify the times within the audio file that should be positioned
at the left and right edges of the rectangle.
The waveform will be scaled vertically so that a full-volume sample will fill
the rectangle vertically, but you can also specify an extra vertical scale factor
with the verticalZoomFactor parameter.
*/
void drawChannel (Graphics& g,
int x, int y, int w, int h,
double startTime,
double endTime,
int channelNum,
const float verticalZoomFactor);
/** Returns true if the low res preview is fully generated.
*/
bool isFullyLoaded() const throw();
//==============================================================================
/** @internal */
bool useTimeSlice();
/** @internal */
void timerCallback();
//==============================================================================
juce_UseDebuggingNewOperator
private:
AudioFormatManager& formatManagerToUse;
AudioThumbnailCache& cache;
InputSource* source;
CriticalSection readerLock;
AudioFormatReader* reader;
MemoryBlock data, cachedLevels;
int orginalSamplesPerThumbnailSample;
int numChannelsCached, numSamplesCached;
double cachedStart, cachedTimePerPixel;
void clear();
AudioFormatReader* createReader() const;
void generateSection (AudioFormatReader& reader,
int64 startSample,
int numSamples);
char* getChannelData (int channel) const;
void refillCache (const int numSamples,
double startTime,
const double timePerPixel);
friend class AudioThumbnailCache;
// true if it needs more callbacks from the readNextBlockFromAudioFile() method
bool initialiseFromAudioFile (AudioFormatReader& reader);
// returns true if more needs to be read
bool readNextBlockFromAudioFile (AudioFormatReader& reader);
};
#endif // __JUCE_AUDIOTHUMBNAIL_JUCEHEADER__

+ 145
- 0
src/juce_appframework/audio/audio_file_formats/juce_AudioThumbnailCache.cpp View File

@@ -0,0 +1,145 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-7 by Raw Material Software ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the
GNU General Public License, as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.
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.
You should have received a copy of the GNU General Public License
along with JUCE; if not, visit www.gnu.org/licenses or write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
------------------------------------------------------------------------------
If you'd like to release a closed-source product which uses JUCE, commercial
licenses are also available: visit www.rawmaterialsoftware.com/juce for
more information.
==============================================================================
*/
#include "../../../juce_core/basics/juce_StandardHeader.h"
BEGIN_JUCE_NAMESPACE
#include "juce_AudioThumbnailCache.h"
#include "../../../juce_core/io/streams/juce_MemoryInputStream.h"
#include "../../../juce_core/io/streams/juce_MemoryOutputStream.h"
//==============================================================================
struct ThumbnailCacheEntry
{
int64 hash;
uint32 lastUsed;
MemoryBlock data;
juce_UseDebuggingNewOperator
};
//==============================================================================
AudioThumbnailCache::AudioThumbnailCache (const int maxNumThumbsToStore_)
: TimeSliceThread (T("thumb cache")),
maxNumThumbsToStore (maxNumThumbsToStore_)
{
startThread (2);
}
AudioThumbnailCache::~AudioThumbnailCache()
{
}
bool AudioThumbnailCache::loadThumb (AudioThumbnail& thumb, const int64 hashCode)
{
for (int i = thumbs.size(); --i >= 0;)
{
if (thumbs[i]->hash == hashCode)
{
MemoryInputStream in ((const char*) thumbs[i]->data,
thumbs[i]->data.getSize(),
false);
thumb.loadFrom (in);
thumbs[i]->lastUsed = Time::getMillisecondCounter();
return true;
}
}
return false;
}
void AudioThumbnailCache::storeThumb (const AudioThumbnail& thumb,
const int64 hashCode)
{
MemoryOutputStream out;
thumb.saveTo (out);
ThumbnailCacheEntry* te = 0;
for (int i = thumbs.size(); --i >= 0;)
{
if (thumbs[i]->hash == hashCode)
{
te = thumbs[i];
break;
}
}
if (te == 0)
{
te = new ThumbnailCacheEntry();
te->hash = hashCode;
if (thumbs.size() < maxNumThumbsToStore)
{
thumbs.add (te);
}
else
{
int oldest = 0;
unsigned int oldestTime = Time::getMillisecondCounter() + 1;
int i;
for (i = thumbs.size(); --i >= 0;)
if (thumbs[i]->lastUsed < oldestTime)
oldest = i;
thumbs.set (i, te);
}
}
te->lastUsed = Time::getMillisecondCounter();
te->data.setSize (0);
te->data.append (out.getData(), out.getDataSize());
}
void AudioThumbnailCache::clear()
{
thumbs.clear();
}
//==============================================================================
void AudioThumbnailCache::addThumbnail (AudioThumbnail* const thumb)
{
addTimeSliceClient (thumb);
}
void AudioThumbnailCache::removeThumbnail (AudioThumbnail* const thumb)
{
removeTimeSliceClient (thumb);
}
END_JUCE_NAMESPACE

+ 98
- 0
src/juce_appframework/audio/audio_file_formats/juce_AudioThumbnailCache.h View File

@@ -0,0 +1,98 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-7 by Raw Material Software ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the
GNU General Public License, as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.
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.
You should have received a copy of the GNU General Public License
along with JUCE; if not, visit www.gnu.org/licenses or write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
------------------------------------------------------------------------------
If you'd like to release a closed-source product which uses JUCE, commercial
licenses are also available: visit www.rawmaterialsoftware.com/juce for
more information.
==============================================================================
*/
#ifndef __JUCE_AUDIOTHUMBNAILCACHE_JUCEHEADER__
#define __JUCE_AUDIOTHUMBNAILCACHE_JUCEHEADER__
#include "juce_AudioThumbnail.h"
struct ThumbnailCacheEntry;
//==============================================================================
/**
An instance of this class is used to manage multiple AudioThumbnail objects.
The cache runs a single background thread that is shared by all the thumbnails
that need it, and it maintains a set of low-res previews in memory, to avoid
having to re-scan audio files too often.
@see AudioThumbnail
*/
class JUCE_API AudioThumbnailCache : public TimeSliceThread
{
public:
//==============================================================================
/** Creates a cache object.
The maxNumThumbsToStore parameter lets you specify how many previews should
be kept in memory at once.
*/
AudioThumbnailCache (const int maxNumThumbsToStore);
/** Destructor. */
~AudioThumbnailCache();
//==============================================================================
/** Clears out any stored thumbnails.
*/
void clear();
/** Reloads the specified thumb if this cache contains the appropriate stored
data.
This is called automatically by the AudioThumbnail class, so you shouldn't
normally need to call it directly.
*/
bool loadThumb (AudioThumbnail& thumb, const int64 hashCode);
/** Stores the cachable data from the specified thumb in this cache.
This is called automatically by the AudioThumbnail class, so you shouldn't
normally need to call it directly.
*/
void storeThumb (const AudioThumbnail& thumb, const int64 hashCode);
//==============================================================================
juce_UseDebuggingNewOperator
private:
//==============================================================================
OwnedArray <ThumbnailCacheEntry> thumbs;
int maxNumThumbsToStore;
friend class AudioThumbnail;
void addThumbnail (AudioThumbnail* const thumb);
void removeThumbnail (AudioThumbnail* const thumb);
};
#endif // __JUCE_AUDIOTHUMBNAILCACHE_JUCEHEADER__

+ 2
- 2
src/juce_appframework/gui/components/controls/juce_ListBox.cpp View File

@@ -666,7 +666,7 @@ int ListBox::getRowNumberOfComponent (Component* const rowComponent) const throw
return viewport->getRowNumberOfComponent (rowComponent); return viewport->getRowNumberOfComponent (rowComponent);
} }
const Rectangle ListBox::getRowPosition (const int rowNumber,
const Rectangle ListBox::getRowPosition (const int rowNumber,
const bool relativeToComponentTopLeft) const throw() const bool relativeToComponentTopLeft) const throw()
{ {
const int rowHeight = getRowHeight(); const int rowHeight = getRowHeight();
@@ -675,7 +675,7 @@ const Rectangle ListBox::getRowPosition (const int rowNumber,
if (relativeToComponentTopLeft) if (relativeToComponentTopLeft)
y -= viewport->getViewPositionY(); y -= viewport->getViewPositionY();
return Rectangle (viewport->getX(), y,
return Rectangle (viewport->getX(), y,
viewport->getViewedComponent()->getWidth(), rowHeight); viewport->getViewedComponent()->getWidth(), rowHeight);
} }


+ 2
- 2
src/juce_appframework/gui/components/controls/juce_ListBox.h View File

@@ -384,8 +384,8 @@ public:
/** Finds a row index that would be the most suitable place to insert a new /** Finds a row index that would be the most suitable place to insert a new
item for a given position. item for a given position.
This is useful when the user is e.g. dragging and dropping onto the listbox,
because it lets you easily choose the best position to insert the item that
This is useful when the user is e.g. dragging and dropping onto the listbox,
because it lets you easily choose the best position to insert the item that
they drop, based on where they drop it. they drop, based on where they drop it.
If the position is out of range, this will return -1. If the position is If the position is out of range, this will return -1. If the position is


+ 1
- 1
src/juce_appframework/gui/components/controls/juce_TableListBox.cpp View File

@@ -388,7 +388,7 @@ bool TableListBox::isAutoSizeMenuOptionShown() const throw()
return autoSizeOptionsShown; return autoSizeOptionsShown;
} }
const Rectangle TableListBox::getCellPosition (const int columnId,
const Rectangle TableListBox::getCellPosition (const int columnId,
const int rowNumber, const int rowNumber,
const bool relativeToComponentTopLeft) const const bool relativeToComponentTopLeft) const
{ {


+ 4
- 4
src/juce_appframework/gui/components/controls/juce_TableListBox.h View File

@@ -264,14 +264,14 @@ public:
/** Returns the position of one of the cells in the table. /** Returns the position of one of the cells in the table.
If relativeToComponentTopLeft is true, the co-ordinates are relative to
the table component's top-left. The row number isn't checked to see if it's
If relativeToComponentTopLeft is true, the co-ordinates are relative to
the table component's top-left. The row number isn't checked to see if it's
in-range, but the column ID must exist or this will return an empty rectangle. in-range, but the column ID must exist or this will return an empty rectangle.
If relativeToComponentTopLeft is false, the co-ords are relative to the
If relativeToComponentTopLeft is false, the co-ords are relative to the
top-left of the table's top-left cell. top-left of the table's top-left cell.
*/ */
const Rectangle getCellPosition (const int columnId,
const Rectangle getCellPosition (const int columnId,
const int rowNumber, const int rowNumber,
const bool relativeToComponentTopLeft) const; const bool relativeToComponentTopLeft) const;


+ 6
- 6
src/juce_core/basics/juce_DataConversions.h View File

@@ -155,10 +155,10 @@ inline void bigEndian24BitToChars (const int value, char* const destBytes) throw
This is faster than using the normal c++ cast to convert a double to an int, and This is faster than using the normal c++ cast to convert a double to an int, and
it will round the value to the nearest integer, rather than rounding it down it will round the value to the nearest integer, rather than rounding it down
like the normal cast does.
Note that this routine gets its speed at the expense of some accuracy, and when
rounding values whose floating point component is exactly 0.5, odd numbers and
like the normal cast does.
Note that this routine gets its speed at the expense of some accuracy, and when
rounding values whose floating point component is exactly 0.5, odd numbers and
even numbers will be rounded up or down differently. For a more accurate conversion, even numbers will be rounded up or down differently. For a more accurate conversion,
see roundDoubleToIntAccurate(). see roundDoubleToIntAccurate().
*/ */
@@ -190,8 +190,8 @@ inline int roundDoubleToIntAccurate (const double value) throw()
it will round the value to the nearest integer, rather than rounding it down it will round the value to the nearest integer, rather than rounding it down
like the normal cast does. like the normal cast does.
Note that this routine gets its speed at the expense of some accuracy, and when
rounding values whose floating point component is exactly 0.5, odd numbers and
Note that this routine gets its speed at the expense of some accuracy, and when
rounding values whose floating point component is exactly 0.5, odd numbers and
even numbers will be rounded up or down differently. even numbers will be rounded up or down differently.
*/ */
inline int roundFloatToInt (const float value) throw() inline int roundFloatToInt (const float value) throw()


+ 1
- 1
src/juce_core/io/juce_OutputStream.cpp View File

@@ -46,7 +46,7 @@ static VoidArray activeStreams;
void juce_CheckForDanglingStreams() void juce_CheckForDanglingStreams()
{ {
/*
/*
It's always a bad idea to leak any object, but if you're leaking output It's always a bad idea to leak any object, but if you're leaking output
streams, then there's a good chance that you're failing to flush a file streams, then there's a good chance that you're failing to flush a file
to disk properly, which could result in corrupted data and other similar to disk properly, which could result in corrupted data and other similar


+ 66
- 0
src/juce_core/io/streams/juce_FileInputSource.cpp View File

@@ -0,0 +1,66 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-7 by Raw Material Software ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the
GNU General Public License, as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.
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.
You should have received a copy of the GNU General Public License
along with JUCE; if not, visit www.gnu.org/licenses or write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
------------------------------------------------------------------------------
If you'd like to release a closed-source product which uses JUCE, commercial
licenses are also available: visit www.rawmaterialsoftware.com/juce for
more information.
==============================================================================
*/
#include "../../basics/juce_StandardHeader.h"
BEGIN_JUCE_NAMESPACE
#include "juce_FileInputSource.h"
#include "../files/juce_FileInputStream.h"
//==============================================================================
FileInputSource::FileInputSource (const File& file_) throw()
: file (file_)
{
}
FileInputSource::~FileInputSource()
{
}
InputStream* FileInputSource::createInputStream()
{
return file.createInputStream();
}
InputStream* FileInputSource::createInputStreamFor (const String& relatedItemPath)
{
return file.getSiblingFile (relatedItemPath).createInputStream();
}
int64 FileInputSource::hashCode() const
{
return file.hashCode();
}
END_JUCE_NAMESPACE

+ 67
- 0
src/juce_core/io/streams/juce_FileInputSource.h View File

@@ -0,0 +1,67 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-7 by Raw Material Software ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the
GNU General Public License, as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.
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.
You should have received a copy of the GNU General Public License
along with JUCE; if not, visit www.gnu.org/licenses or write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
------------------------------------------------------------------------------
If you'd like to release a closed-source product which uses JUCE, commercial
licenses are also available: visit www.rawmaterialsoftware.com/juce for
more information.
==============================================================================
*/
#ifndef __JUCE_FILEINPUTSOURCE_JUCEHEADER__
#define __JUCE_FILEINPUTSOURCE_JUCEHEADER__
#include "juce_InputSource.h"
#include "../files/juce_File.h"
//==============================================================================
/**
A type of InputSource that represents a normal file.
@see InputSource
*/
class JUCE_API FileInputSource : public InputSource
{
public:
//==============================================================================
FileInputSource (const File& file) throw();
~FileInputSource();
InputStream* createInputStream();
InputStream* createInputStreamFor (const String& relatedItemPath);
int64 hashCode() const;
//==============================================================================
juce_UseDebuggingNewOperator
private:
const File file;
FileInputSource (const FileInputSource&);
const FileInputSource& operator= (const FileInputSource&);
};
#endif // __JUCE_FILEINPUTSOURCE_JUCEHEADER__

+ 80
- 0
src/juce_core/io/streams/juce_InputSource.h View File

@@ -0,0 +1,80 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-7 by Raw Material Software ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the
GNU General Public License, as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.
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.
You should have received a copy of the GNU General Public License
along with JUCE; if not, visit www.gnu.org/licenses or write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
------------------------------------------------------------------------------
If you'd like to release a closed-source product which uses JUCE, commercial
licenses are also available: visit www.rawmaterialsoftware.com/juce for
more information.
==============================================================================
*/
#ifndef __JUCE_INPUTSOURCE_JUCEHEADER__
#define __JUCE_INPUTSOURCE_JUCEHEADER__
#include "../juce_InputStream.h"
//==============================================================================
/**
A lightweight object that can create a stream to read some kind of resource.
This may be used to refer to a file, or some other kind of source, allowing a
caller to create an input stream that can read from it when required.
@see FileInputSource
*/
class JUCE_API InputSource
{
public:
//==============================================================================
InputSource() throw() {}
/** Destructor. */
virtual ~InputSource() {}
//==============================================================================
/** Returns a new InputStream to read this item.
@returns an inputstream that the caller will delete, or 0 if
the filename isn't found.
*/
virtual InputStream* createInputStream() = 0;
/** Returns a new InputStream to read an item, relative.
@param relatedItemPath the relative pathname of the resource that is required
@returns an inputstream that the caller will delete, or 0 if
the item isn't found.
*/
virtual InputStream* createInputStreamFor (const String& relatedItemPath) = 0;
/** Returns a hash code that uniquely represents this item.
*/
virtual int64 hashCode() const = 0;
//==============================================================================
juce_UseDebuggingNewOperator
};
#endif // __JUCE_INPUTSOURCE_JUCEHEADER__

+ 3
- 41
src/juce_core/text/juce_XmlDocument.cpp View File

@@ -34,17 +34,7 @@
BEGIN_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE
#include "juce_XmlDocument.h" #include "juce_XmlDocument.h"
#include "../io/files/juce_FileInputStream.h"
//==============================================================================
XmlInputSource::XmlInputSource() throw()
{
}
XmlInputSource::~XmlInputSource()
{
}
#include "../io/streams/juce_FileInputSource.h"
//============================================================================== //==============================================================================
@@ -60,34 +50,6 @@ static bool isXmlIdentifierChar_Slow (const tchar c) throw()
#define isXmlIdentifierChar(c) \ #define isXmlIdentifierChar(c) \
((c > 0 && c <= 127) ? identifierLookupTable [(int) c] : isXmlIdentifierChar_Slow (c)) ((c > 0 && c <= 127) ? identifierLookupTable [(int) c] : isXmlIdentifierChar_Slow (c))
//==============================================================================
class FileInputSource : public XmlInputSource
{
public:
FileInputSource (const File& file_) throw()
: file (file_)
{
}
~FileInputSource()
{
}
InputStream* createInputStreamFor (const String& filename)
{
if (filename.isEmpty())
return file.createInputStream();
else
return file.getSiblingFile (filename).createInputStream();
}
private:
const File file;
FileInputSource (const FileInputSource&);
const FileInputSource& operator= (const FileInputSource&);
};
//============================================================================== //==============================================================================
XmlDocument::XmlDocument (const String& documentText) throw() XmlDocument::XmlDocument (const String& documentText) throw()
@@ -106,7 +68,7 @@ XmlDocument::~XmlDocument() throw()
delete inputSource; delete inputSource;
} }
void XmlDocument::setInputSource (XmlInputSource* const newSource) throw()
void XmlDocument::setInputSource (InputSource* const newSource) throw()
{ {
if (inputSource != newSource) if (inputSource != newSource)
{ {
@@ -121,7 +83,7 @@ XmlElement* XmlDocument::getDocumentElement (const bool onlyReadOuterDocumentEle
if (textToParse.isEmpty() && inputSource != 0) if (textToParse.isEmpty() && inputSource != 0)
{ {
InputStream* const in = inputSource->createInputStreamFor (String::empty);
InputStream* const in = inputSource->createInputStream();
if (in != 0) if (in != 0)
{ {


+ 4
- 36
src/juce_core/text/juce_XmlDocument.h View File

@@ -35,39 +35,7 @@
#include "juce_XmlElement.h" #include "juce_XmlElement.h"
#include "juce_StringArray.h" #include "juce_StringArray.h"
#include "../io/files/juce_File.h" #include "../io/files/juce_File.h"
#include "../io/juce_InputStream.h"
//==============================================================================
/**
Used by the XmlDocument class to find a document's associated files.
Because an XML document might need to reference other files for its
external DTDs, this class can be used to create input streams for
these files.
@see XmlDocument
*/
class JUCE_API XmlInputSource
{
protected:
/** Creates a default source that can read from files. */
XmlInputSource() throw();
public:
/** Destructor. */
virtual ~XmlInputSource();
/** Returns a new InputStream to read a required file.
@param filename the partial filename of a file that needs to be read,
or an empty string to open the root document that the
source refers to
@returns an inputstream that the caller will delete, or 0 if
the filename isn't found.
*/
virtual InputStream* createInputStreamFor (const String& filename) = 0;
};
#include "../io/streams/juce_InputSource.h"
//============================================================================== //==============================================================================
@@ -150,9 +118,9 @@ public:
The object that is passed-in will be deleted automatically when no longer needed. The object that is passed-in will be deleted automatically when no longer needed.
@see XmlInputSource
@see InputSource
*/ */
void setInputSource (XmlInputSource* const newSource) throw();
void setInputSource (InputSource* const newSource) throw();
//============================================================================== //==============================================================================
@@ -167,7 +135,7 @@ private:
String lastError, dtdText; String lastError, dtdText;
StringArray tokenisedDTD; StringArray tokenisedDTD;
bool needToLoadDTD; bool needToLoadDTD;
XmlInputSource* inputSource;
InputSource* inputSource;
void setLastError (const String& desc, const bool carryOn) throw(); void setLastError (const String& desc, const bool carryOn) throw();
void skipHeader() throw(); void skipHeader() throw();


+ 6
- 0
src/juce_core_includes.h View File

@@ -155,12 +155,18 @@
#ifndef __JUCE_BUFFEREDINPUTSTREAM_JUCEHEADER__ #ifndef __JUCE_BUFFEREDINPUTSTREAM_JUCEHEADER__
#include "juce_core/io/streams/juce_BufferedInputStream.h" #include "juce_core/io/streams/juce_BufferedInputStream.h"
#endif #endif
#ifndef __JUCE_FILEINPUTSOURCE_JUCEHEADER__
#include "juce_core/io/streams/juce_FileInputSource.h"
#endif
#ifndef __JUCE_GZIPCOMPRESSOROUTPUTSTREAM_JUCEHEADER__ #ifndef __JUCE_GZIPCOMPRESSOROUTPUTSTREAM_JUCEHEADER__
#include "juce_core/io/streams/juce_GZIPCompressorOutputStream.h" #include "juce_core/io/streams/juce_GZIPCompressorOutputStream.h"
#endif #endif
#ifndef __JUCE_GZIPDECOMPRESSORINPUTSTREAM_JUCEHEADER__ #ifndef __JUCE_GZIPDECOMPRESSORINPUTSTREAM_JUCEHEADER__
#include "juce_core/io/streams/juce_GZIPDecompressorInputStream.h" #include "juce_core/io/streams/juce_GZIPDecompressorInputStream.h"
#endif #endif
#ifndef __JUCE_INPUTSOURCE_JUCEHEADER__
#include "juce_core/io/streams/juce_InputSource.h"
#endif
#ifndef __JUCE_MEMORYINPUTSTREAM_JUCEHEADER__ #ifndef __JUCE_MEMORYINPUTSTREAM_JUCEHEADER__
#include "juce_core/io/streams/juce_MemoryInputStream.h" #include "juce_core/io/streams/juce_MemoryInputStream.h"
#endif #endif


Loading…
Cancel
Save