The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

241 lines
6.3KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-9 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. #include "../../core/juce_StandardHeader.h"
  19. BEGIN_JUCE_NAMESPACE
  20. #if JUCE_MAC && JUCE_USE_CDREADER
  21. //==============================================================================
  22. // Mac version doesn't need any native code because it's all done with files..
  23. // Windows + Linux versions are in the platform-dependent code sections.
  24. #include "juce_AudioCDReader.h"
  25. #include "juce_AiffAudioFormat.h"
  26. #include "../../io/files/juce_FileInputStream.h"
  27. #include "../../io/streams/juce_BufferedInputStream.h"
  28. static void findCDs (OwnedArray<File>& cds)
  29. {
  30. File volumes ("/Volumes");
  31. volumes.findChildFiles (cds, File::findDirectories, false);
  32. for (int i = cds.size(); --i >= 0;)
  33. if (! cds[i]->getChildFile (".TOC.plist").exists())
  34. cds.remove (i);
  35. }
  36. const StringArray AudioCDReader::getAvailableCDNames()
  37. {
  38. OwnedArray<File> cds;
  39. findCDs (cds);
  40. StringArray names;
  41. for (int i = 0; i < cds.size(); ++i)
  42. names.add (cds[i]->getFileName());
  43. return names;
  44. }
  45. AudioCDReader* AudioCDReader::createReaderForCD (const int index)
  46. {
  47. OwnedArray<File> cds;
  48. findCDs (cds);
  49. if (cds[index] != 0)
  50. return new AudioCDReader (*cds[index]);
  51. else
  52. return 0;
  53. }
  54. AudioCDReader::AudioCDReader (const File& volume)
  55. : AudioFormatReader (0, "CD Audio"),
  56. volumeDir (volume),
  57. currentReaderTrack (-1),
  58. reader (0)
  59. {
  60. sampleRate = 44100.0;
  61. bitsPerSample = 16;
  62. numChannels = 2;
  63. usesFloatingPointData = false;
  64. refreshTrackLengths();
  65. }
  66. AudioCDReader::~AudioCDReader()
  67. {
  68. }
  69. static int getTrackNumber (const File& file)
  70. {
  71. return file.getFileName()
  72. .initialSectionContainingOnly (T("0123456789"))
  73. .getIntValue();
  74. }
  75. int AudioCDReader::compareElements (const File* const first, const File* const second) throw()
  76. {
  77. const int firstTrack = getTrackNumber (*first);
  78. const int secondTrack = getTrackNumber (*second);
  79. jassert (firstTrack > 0 && secondTrack > 0);
  80. return firstTrack - secondTrack;
  81. }
  82. void AudioCDReader::refreshTrackLengths()
  83. {
  84. tracks.clear();
  85. trackStartSamples.clear();
  86. volumeDir.findChildFiles (tracks, File::findFiles | File::ignoreHiddenFiles, false, T("*.aiff"));
  87. tracks.sort (*this);
  88. AiffAudioFormat format;
  89. int sample = 0;
  90. for (int i = 0; i < tracks.size(); ++i)
  91. {
  92. trackStartSamples.add (sample);
  93. FileInputStream* const in = tracks[i]->createInputStream();
  94. if (in != 0)
  95. {
  96. ScopedPointer <AudioFormatReader> r (format.createReaderFor (in, true));
  97. if (r != 0)
  98. sample += (int) r->lengthInSamples;
  99. }
  100. }
  101. trackStartSamples.add (sample);
  102. lengthInSamples = sample;
  103. }
  104. bool AudioCDReader::readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,
  105. int64 startSampleInFile, int numSamples)
  106. {
  107. while (numSamples > 0)
  108. {
  109. int track = -1;
  110. for (int i = 0; i < trackStartSamples.size() - 1; ++i)
  111. {
  112. if (startSampleInFile < trackStartSamples.getUnchecked (i + 1))
  113. {
  114. track = i;
  115. break;
  116. }
  117. }
  118. if (track < 0)
  119. return false;
  120. if (track != currentReaderTrack)
  121. {
  122. reader = 0;
  123. if (tracks [track] != 0)
  124. {
  125. FileInputStream* const in = tracks [track]->createInputStream();
  126. if (in != 0)
  127. {
  128. BufferedInputStream* const bin = new BufferedInputStream (in, 65536, true);
  129. AiffAudioFormat format;
  130. reader = format.createReaderFor (bin, true);
  131. if (reader == 0)
  132. currentReaderTrack = -1;
  133. else
  134. currentReaderTrack = track;
  135. }
  136. }
  137. }
  138. if (reader == 0)
  139. return false;
  140. const int startPos = (int) (startSampleInFile - trackStartSamples.getUnchecked (track));
  141. const int numAvailable = (int) jmin ((int64) numSamples, reader->lengthInSamples - startPos);
  142. reader->readSamples (destSamples, numDestChannels, startOffsetInDestBuffer, startPos, numAvailable);
  143. numSamples -= numAvailable;
  144. startSampleInFile += numAvailable;
  145. }
  146. return true;
  147. }
  148. bool AudioCDReader::isCDStillPresent() const
  149. {
  150. return volumeDir.exists();
  151. }
  152. int AudioCDReader::getNumTracks() const
  153. {
  154. return tracks.size();
  155. }
  156. int AudioCDReader::getPositionOfTrackStart (int trackNum) const
  157. {
  158. return trackStartSamples [trackNum];
  159. }
  160. bool AudioCDReader::isTrackAudio (int trackNum) const
  161. {
  162. return tracks [trackNum] != 0;
  163. }
  164. void AudioCDReader::enableIndexScanning (bool b)
  165. {
  166. // any way to do this on a Mac??
  167. }
  168. int AudioCDReader::getLastIndex() const
  169. {
  170. return 0;
  171. }
  172. const Array <int> AudioCDReader::findIndexesInTrack (const int trackNumber)
  173. {
  174. return Array <int>();
  175. }
  176. int AudioCDReader::getCDDBId()
  177. {
  178. return 0; //xxx
  179. }
  180. #endif
  181. END_JUCE_NAMESPACE