| @@ -1,4 +1,3 @@ | |||
| Microsoft Visual Studio Solution File, Format Version 8.00 | |||
| # Visual C++ Express 2005 | |||
| Project("{30DE6365-A0C4-171D-3ADD-E102A1BD1BB8}") = "Juce", "Juce.vcproj", "{2F2AF28C-CD42-F164-1AC5-90A9ACD39DD3}" | |||
| @@ -1,4 +1,3 @@ | |||
| Microsoft Visual Studio Solution File, Format Version 10.00 | |||
| # Visual C++ Express 2008 | |||
| Project("{30DE6365-A0C4-171D-3ADD-E102A1BD1BB8}") = "Juce", "Juce.vcproj", "{2F2AF28C-CD42-F164-1AC5-90A9ACD39DD3}" | |||
| @@ -1,4 +1,3 @@ | |||
| Microsoft Visual Studio Solution File, Format Version 10.00 | |||
| # Visual C++ Express 2008 | |||
| Project("{30DE6365-A0C4-171D-3ADD-E102A1BD1BB8}") = "Juce", "Juce.vcproj", "{2F2AF28C-CD42-F164-1AC5-90A9ACD39DD3}" | |||
| @@ -1,4 +1,3 @@ | |||
| Microsoft Visual Studio Solution File, Format Version 11.00 | |||
| Project("{30DE6365-A0C4-171D-3ADD-E102A1BD1BB8}") = "Juce", "Juce.vcxproj", "{2F2AF28C-CD42-F164-1AC5-90A9ACD39DD3}" | |||
| EndProject | |||
| @@ -1,4 +1,3 @@ | |||
| Microsoft Visual Studio Solution File, Format Version 8.00 | |||
| # Visual C++ Express 2005 | |||
| Project("{4E9D0CBA-BFAB-E5E4-0A60-A20FD97F37CA}") = "The Jucer", "The Jucer.vcproj", "{C9C4A72E-8CC9-D57E-C0D0-2E6109E48884}" | |||
| @@ -1,4 +1,3 @@ | |||
| Microsoft Visual Studio Solution File, Format Version 10.00 | |||
| # Visual C++ Express 2008 | |||
| Project("{4E9D0CBA-BFAB-E5E4-0A60-A20FD97F37CA}") = "The Jucer", "The Jucer.vcproj", "{C9C4A72E-8CC9-D57E-C0D0-2E6109E48884}" | |||
| @@ -1,4 +1,3 @@ | |||
| Microsoft Visual Studio Solution File, Format Version 11.00 | |||
| Project("{4E9D0CBA-BFAB-E5E4-0A60-A20FD97F37CA}") = "The Jucer", "The Jucer.vcxproj", "{C9C4A72E-8CC9-D57E-C0D0-2E6109E48884}" | |||
| EndProject | |||
| @@ -430,12 +430,12 @@ static const unsigned char temp_891b85da[] = | |||
| " return String::empty;\r\n" | |||
| "}\r\n" | |||
| "\r\n" | |||
| "const String FILTERCLASSNAME::getInputChannelName (const int channelIndex) const\r\n" | |||
| "const String FILTERCLASSNAME::getInputChannelName (int channelIndex) const\r\n" | |||
| "{\r\n" | |||
| " return String (channelIndex + 1);\r\n" | |||
| "}\r\n" | |||
| "\r\n" | |||
| "const String FILTERCLASSNAME::getOutputChannelName (const int channelIndex) const\r\n" | |||
| "const String FILTERCLASSNAME::getOutputChannelName (int channelIndex) const\r\n" | |||
| "{\r\n" | |||
| " return String (channelIndex + 1);\r\n" | |||
| "}\r\n" | |||
| @@ -607,8 +607,8 @@ static const unsigned char temp_356ba65f[] = | |||
| " const String getParameterName (int index);\r\n" | |||
| " const String getParameterText (int index);\r\n" | |||
| "\r\n" | |||
| " const String getInputChannelName (const int channelIndex) const;\r\n" | |||
| " const String getOutputChannelName (const int channelIndex) const;\r\n" | |||
| " const String getInputChannelName (int channelIndex) const;\r\n" | |||
| " const String getOutputChannelName (int channelIndex) const;\r\n" | |||
| " bool isInputChannelStereoPair (int index) const;\r\n" | |||
| " bool isOutputChannelStereoPair (int index) const;\r\n" | |||
| "\r\n" | |||
| @@ -20,10 +20,10 @@ namespace BinaryData | |||
| const int jucer_AudioPluginEditorTemplate_hSize = 794; | |||
| extern const char* jucer_AudioPluginFilterTemplate_cpp; | |||
| const int jucer_AudioPluginFilterTemplate_cppSize = 4480; | |||
| const int jucer_AudioPluginFilterTemplate_cppSize = 4468; | |||
| extern const char* jucer_AudioPluginFilterTemplate_h; | |||
| const int jucer_AudioPluginFilterTemplate_hSize = 2425; | |||
| const int jucer_AudioPluginFilterTemplate_hSize = 2413; | |||
| extern const char* jucer_MainConsoleAppTemplate_cpp; | |||
| const int jucer_MainConsoleAppTemplate_cppSize = 749; | |||
| @@ -1,4 +1,3 @@ | |||
| Microsoft Visual Studio Solution File, Format Version 8.00 | |||
| # Visual C++ Express 2005 | |||
| Project("{23A76270-2B37-F8DD-86F3-00609C833A1B}") = "Amalgamator", "Amalgamator.vcproj", "{4285DA55-C038-FF64-E3EC-DA7F0E5D4310}" | |||
| @@ -1,4 +1,3 @@ | |||
| Microsoft Visual Studio Solution File, Format Version 10.00 | |||
| # Visual C++ Express 2008 | |||
| Project("{23A76270-2B37-F8DD-86F3-00609C833A1B}") = "Amalgamator", "Amalgamator.vcproj", "{4285DA55-C038-FF64-E3EC-DA7F0E5D4310}" | |||
| @@ -1,4 +1,3 @@ | |||
| Microsoft Visual Studio Solution File, Format Version 8.00 | |||
| # Visual C++ Express 2005 | |||
| Project("{F57C92E4-2379-4C6D-78F7-AFF26BF4F962}") = "Plugin Host", "Plugin Host.vcproj", "{7CD310E8-9077-342C-EB06-869D4775A4F4}" | |||
| @@ -1,4 +1,3 @@ | |||
| Microsoft Visual Studio Solution File, Format Version 10.00 | |||
| # Visual C++ Express 2008 | |||
| Project("{F57C92E4-2379-4C6D-78F7-AFF26BF4F962}") = "Plugin Host", "Plugin Host.vcproj", "{7CD310E8-9077-342C-EB06-869D4775A4F4}" | |||
| @@ -1,4 +1,3 @@ | |||
| Microsoft Visual Studio Solution File, Format Version 8.00 | |||
| # Visual C++ Express 2005 | |||
| Project("{D0B67FB6-D62A-09D8-46A8-2927CB6D2B82}") = "JuceDemoPlugin", "JuceDemoPlugin.vcproj", "{BC07A08E-8205-B220-39D4-B2685FFC59CA}" | |||
| @@ -1,4 +1,3 @@ | |||
| Microsoft Visual Studio Solution File, Format Version 10.00 | |||
| # Visual C++ Express 2008 | |||
| Project("{D0B67FB6-D62A-09D8-46A8-2927CB6D2B82}") = "JuceDemoPlugin", "JuceDemoPlugin.vcproj", "{BC07A08E-8205-B220-39D4-B2685FFC59CA}" | |||
| @@ -1,4 +1,3 @@ | |||
| Microsoft Visual Studio Solution File, Format Version 8.00 | |||
| # Visual C++ Express 2005 | |||
| Project("{D7FD13D0-EADB-347A-0525-9F0597899B5A}") = "BinaryBuilder", "BinaryBuilder.vcproj", "{07A3F0B4-D234-EC23-96A2-85290D0A0775}" | |||
| @@ -1,4 +1,3 @@ | |||
| Microsoft Visual Studio Solution File, Format Version 10.00 | |||
| # Visual C++ Express 2008 | |||
| Project("{D7FD13D0-EADB-347A-0525-9F0597899B5A}") = "BinaryBuilder", "BinaryBuilder.vcproj", "{07A3F0B4-D234-EC23-96A2-85290D0A0775}" | |||
| @@ -1,4 +1,3 @@ | |||
| Microsoft Visual Studio Solution File, Format Version 8.00 | |||
| # Visual C++ Express 2005 | |||
| Project("{B2F78CC9-CD50-16B6-2910-2265E55052A4}") = "HelloWorld", "HelloWorld.vcproj", "{6ABB053F-FD6B-A828-D0FF-2D3BE343D9F7}" | |||
| @@ -1,4 +1,3 @@ | |||
| Microsoft Visual Studio Solution File, Format Version 10.00 | |||
| # Visual C++ Express 2008 | |||
| Project("{B2F78CC9-CD50-16B6-2910-2265E55052A4}") = "HelloWorld", "HelloWorld.vcproj", "{6ABB053F-FD6B-A828-D0FF-2D3BE343D9F7}" | |||
| @@ -1,4 +1,3 @@ | |||
| Microsoft Visual Studio Solution File, Format Version 8.00 | |||
| # Visual C++ Express 2005 | |||
| Project("{7A947A64-CDD8-D41D-F886-5E65A8ABDF81}") = "Juce Demo", "Juce Demo.vcproj", "{36211E76-A802-50EE-3B95-0202F4EB67ED}" | |||
| @@ -1,4 +1,3 @@ | |||
| Microsoft Visual Studio Solution File, Format Version 10.00 | |||
| # Visual C++ Express 2008 | |||
| Project("{7A947A64-CDD8-D41D-F886-5E65A8ABDF81}") = "Juce Demo", "Juce Demo.vcproj", "{36211E76-A802-50EE-3B95-0202F4EB67ED}" | |||
| @@ -1,4 +1,3 @@ | |||
| Microsoft Visual Studio Solution File, Format Version 11.00 | |||
| Project("{7A947A64-CDD8-D41D-F886-5E65A8ABDF81}") = "Juce Demo", "Juce Demo.vcxproj", "{36211E76-A802-50EE-3B95-0202F4EB67ED}" | |||
| EndProject | |||
| @@ -29376,6 +29376,10 @@ public: | |||
| /** Returns the mouse position. | |||
| The co-ordinates are relative to the top-left of the main monitor. | |||
| Note that this is just a shortcut for calling getMainMouseSource().getScreenPosition(), and | |||
| you should only resort to grabbing the global mouse position if there's really no | |||
| way to get the coordinates via a mouse event callback instead. | |||
| */ | |||
| static const Point<int> getMousePosition(); | |||
| @@ -29386,15 +29390,20 @@ public: | |||
| static void setMousePosition (const Point<int>& newPosition); | |||
| /** Returns the last position at which a mouse button was pressed. | |||
| Note that this is just a shortcut for calling getMainMouseSource().getLastMouseDownPosition(), | |||
| and in a multi-touch environment, it doesn't make much sense. ALWAYS prefer to | |||
| get this information via other means, such as MouseEvent::getMouseDownScreenPosition() | |||
| if possible, and only ever call this as a last resort. | |||
| */ | |||
| static const Point<int> getLastMouseDownPosition() throw(); | |||
| static const Point<int> getLastMouseDownPosition(); | |||
| /** Returns the number of times the mouse button has been clicked since the | |||
| app started. | |||
| Each mouse-down event increments this number by 1. | |||
| */ | |||
| static int getMouseButtonClickCounter() throw(); | |||
| static int getMouseButtonClickCounter(); | |||
| /** This lets you prevent the screensaver from becoming active. | |||
| @@ -29608,6 +29617,8 @@ private: | |||
| ComponentAnimator animator; | |||
| static const Point<int> getRawMousePosition(); | |||
| void timerCallback(); | |||
| void resetTimer(); | |||
| @@ -32598,7 +32609,13 @@ public: | |||
| /** Gives the thumbnail an AudioFormatReader to use directly. | |||
| This will start parsing the audio in a background thread (unless the hash code | |||
| can be looked-up successfully in the thumbnail cache). | |||
| can be looked-up successfully in the thumbnail cache). Note that the reader | |||
| object will be held by the thumbnail and deleted later when no longer needed. | |||
| The thumbnail will actually keep hold of this reader until you clear the thumbnail | |||
| or change the input source, so the file will be held open for all this time. If | |||
| you don't want the thumbnail to keep a file handle open continuously, you | |||
| should use the setSource() method instead, which will only open the file when | |||
| it needs to. | |||
| */ | |||
| void setReader (AudioFormatReader* newReader, int64 hashCode); | |||
| @@ -182,7 +182,8 @@ void AudioFormatReader::readMaxLevels (int64 startSampleInFile, | |||
| while (numSamples > 0) | |||
| { | |||
| const int numToDo = (int) jmin (numSamples, (int64) bufferSize); | |||
| read (tempBuffer, 2, startSampleInFile, numToDo, false); | |||
| if (! read (tempBuffer, 2, startSampleInFile, numToDo, false)) | |||
| break; | |||
| numSamples -= numToDo; | |||
| startSampleInFile += numToDo; | |||
| @@ -40,10 +40,6 @@ namespace CDReaderHelpers | |||
| #define FILE_WRITE_ACCESS 2 | |||
| #endif | |||
| #define SCSI_INQUIRY 0x12 | |||
| #define SERROR_CURRENT 0x70 | |||
| #define SERROR_DEFERED 0x71 | |||
| #define DTYPE_CROM 0x05 | |||
| #define METHOD_BUFFERED 0 | |||
| #define IOCTL_SCSI_BASE 4 | |||
| #define SCSI_IOCTL_DATA_OUT 0 | |||
| @@ -65,7 +61,6 @@ namespace CDReaderHelpers | |||
| #define SS_PENDING 0x00 | |||
| #define SS_COMP 0x01 | |||
| #define SS_ERR 0x04 | |||
| #define SS_NO_ADAPTERS 0xE8 | |||
| enum | |||
| { | |||
| @@ -132,22 +127,6 @@ struct SCSI_ADDRESS | |||
| #pragma pack(1) | |||
| struct SRB_HAInquiry | |||
| { | |||
| BYTE SRB_Cmd; | |||
| BYTE SRB_Status; | |||
| BYTE SRB_HaID; | |||
| BYTE SRB_Flags; | |||
| DWORD SRB_Hdr_Rsvd; | |||
| BYTE HA_Count; | |||
| BYTE HA_SCSI_ID; | |||
| BYTE HA_ManagerId[16]; | |||
| BYTE HA_Identifier[16]; | |||
| BYTE HA_Unique[16]; | |||
| WORD HA_Rsvd1; | |||
| BYTE pad[20]; | |||
| }; | |||
| struct SRB_GDEVBlock | |||
| { | |||
| BYTE SRB_Cmd; | |||
| @@ -214,9 +193,9 @@ struct TOC | |||
| #pragma pack() | |||
| //============================================================================== | |||
| struct CDDeviceInfo | |||
| struct CDDeviceDescription | |||
| { | |||
| CDDeviceInfo() : ha (0), tgt (0), lun (0), scsiDriveLetter (0) | |||
| CDDeviceDescription() : ha (0), tgt (0), lun (0), scsiDriveLetter (0) | |||
| { | |||
| } | |||
| @@ -288,7 +267,7 @@ public: | |||
| class CDDeviceHandle | |||
| { | |||
| public: | |||
| CDDeviceHandle (const CDDeviceInfo& device, HANDLE scsiHandle_) | |||
| CDDeviceHandle (const CDDeviceDescription& device, HANDLE scsiHandle_) | |||
| : info (device), scsiHandle (scsiHandle_), readType (READTYPE_ANY) | |||
| { | |||
| } | |||
| @@ -308,8 +287,9 @@ public: | |||
| bool readTOC (TOC* lpToc); | |||
| bool readAudio (CDReadBuffer& buffer, CDReadBuffer* overlapBuffer = 0); | |||
| void openDrawer (bool shouldBeOpen); | |||
| void performScsiCommand (HANDLE event, SRB_ExecSCSICmd& s); | |||
| CDDeviceInfo info; | |||
| CDDeviceDescription info; | |||
| HANDLE scsiHandle; | |||
| BYTE readType; | |||
| @@ -320,328 +300,129 @@ private: | |||
| }; | |||
| //============================================================================== | |||
| class CDDeviceManager : public Timer, | |||
| public DeletedAtShutdown | |||
| HANDLE createSCSIDeviceHandle (const char driveLetter) | |||
| { | |||
| private: | |||
| CDDeviceManager() | |||
| : fGetASPI32SupportInfo (0), fSendASPI32Command (0), userCount (0), | |||
| usingScsi (SystemStats::getOperatingSystemType() >= SystemStats::Win2000) | |||
| { | |||
| if (! usingScsi) | |||
| { | |||
| // xxx can the winaspi stuff be ditched? Seems like it's only needed in win98.. | |||
| if (winAspiLib.load ("WNASPI32.DLL")) | |||
| { | |||
| fGetASPI32SupportInfo = (DWORD (*) (void)) winAspiLib.findProcAddress ("GetASPI32SupportInfo"); | |||
| fSendASPI32Command = (DWORD (*) (SRB*)) winAspiLib.findProcAddress ("SendASPI32Command"); | |||
| } | |||
| else | |||
| { | |||
| usingScsi = true; | |||
| } | |||
| } | |||
| } | |||
| public: | |||
| static CDDeviceManager* getInstance() | |||
| { | |||
| static CDDeviceManager* manager = 0; | |||
| if (manager == 0) | |||
| { | |||
| ScopedPointer<CDDeviceManager> newOne (new CDDeviceManager()); | |||
| if (newOne->ok()) | |||
| manager = newOne.release(); | |||
| } | |||
| return manager; | |||
| } | |||
| TCHAR devicePath[] = { '\\', '\\', '.', '\\', driveLetter, ':', 0, 0 }; | |||
| DWORD flags = GENERIC_READ | GENERIC_WRITE; | |||
| HANDLE h = CreateFile (devicePath, flags, FILE_SHARE_WRITE | FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); | |||
| void retain() | |||
| if (h == INVALID_HANDLE_VALUE) | |||
| { | |||
| ++userCount; | |||
| flags ^= GENERIC_WRITE; | |||
| h = CreateFile (devicePath, flags, FILE_SHARE_WRITE | FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); | |||
| } | |||
| void release() | |||
| { | |||
| --userCount; | |||
| startTimer (4000); | |||
| } | |||
| return h; | |||
| } | |||
| void findCDDevices (Array<CDDeviceInfo>& list) | |||
| void findCDDevices (Array<CDDeviceDescription>& list) | |||
| { | |||
| for (char driveLetter = 'b'; driveLetter <= 'z'; ++driveLetter) | |||
| { | |||
| if (usingScsi) | |||
| { | |||
| for (char driveLetter = 'b'; driveLetter <= 'z'; ++driveLetter) | |||
| { | |||
| TCHAR drivePath[] = { driveLetter, ':', '\\', 0, 0 }; | |||
| if (GetDriveType (drivePath) == DRIVE_CDROM) | |||
| { | |||
| HANDLE h = createSCSIDeviceHandle (driveLetter); | |||
| TCHAR drivePath[] = { driveLetter, ':', '\\', 0, 0 }; | |||
| if (h != INVALID_HANDLE_VALUE) | |||
| { | |||
| char buffer[100]; | |||
| zeromem (buffer, sizeof (buffer)); | |||
| SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER p; | |||
| zerostruct (p); | |||
| p.spt.Length = sizeof (SCSI_PASS_THROUGH); | |||
| p.spt.CdbLength = 6; | |||
| p.spt.SenseInfoLength = 24; | |||
| p.spt.DataIn = SCSI_IOCTL_DATA_IN; | |||
| p.spt.DataTransferLength = sizeof (buffer); | |||
| p.spt.TimeOutValue = 2; | |||
| p.spt.DataBuffer = buffer; | |||
| p.spt.SenseInfoOffset = offsetof (SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, ucSenseBuf); | |||
| p.spt.Cdb[0] = 0x12; | |||
| p.spt.Cdb[4] = 100; | |||
| DWORD bytesReturned = 0; | |||
| if (DeviceIoControl (h, IOCTL_SCSI_PASS_THROUGH_DIRECT, | |||
| &p, sizeof (p), &p, sizeof (p), | |||
| &bytesReturned, 0) != 0) | |||
| { | |||
| CDDeviceInfo dev; | |||
| dev.scsiDriveLetter = driveLetter; | |||
| dev.createDescription (buffer); | |||
| SCSI_ADDRESS scsiAddr; | |||
| zerostruct (scsiAddr); | |||
| scsiAddr.Length = sizeof (scsiAddr); | |||
| if (DeviceIoControl (h, IOCTL_SCSI_GET_ADDRESS, | |||
| 0, 0, &scsiAddr, sizeof (scsiAddr), | |||
| &bytesReturned, 0) != 0) | |||
| { | |||
| dev.ha = scsiAddr.PortNumber; | |||
| dev.tgt = scsiAddr.TargetId; | |||
| dev.lun = scsiAddr.Lun; | |||
| list.add (dev); | |||
| } | |||
| } | |||
| CloseHandle (h); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| else | |||
| if (GetDriveType (drivePath) == DRIVE_CDROM) | |||
| { | |||
| const DWORD d = fGetASPI32SupportInfo(); | |||
| BYTE status = HIBYTE (LOWORD (d)); | |||
| if (status != SS_COMP || status == SS_NO_ADAPTERS) | |||
| return; | |||
| HANDLE h = createSCSIDeviceHandle (driveLetter); | |||
| const int numAdapters = LOBYTE (LOWORD (d)); | |||
| for (BYTE ha = 0; ha < numAdapters; ++ha) | |||
| if (h != INVALID_HANDLE_VALUE) | |||
| { | |||
| SRB_HAInquiry s; | |||
| zerostruct (s); | |||
| s.SRB_Cmd = SC_HA_INQUIRY; | |||
| s.SRB_HaID = ha; | |||
| fSendASPI32Command ((SRB*) &s); | |||
| if (s.SRB_Status == SS_COMP) | |||
| char buffer[100]; | |||
| zeromem (buffer, sizeof (buffer)); | |||
| SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER p; | |||
| zerostruct (p); | |||
| p.spt.Length = sizeof (SCSI_PASS_THROUGH); | |||
| p.spt.CdbLength = 6; | |||
| p.spt.SenseInfoLength = 24; | |||
| p.spt.DataIn = SCSI_IOCTL_DATA_IN; | |||
| p.spt.DataTransferLength = sizeof (buffer); | |||
| p.spt.TimeOutValue = 2; | |||
| p.spt.DataBuffer = buffer; | |||
| p.spt.SenseInfoOffset = offsetof (SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, ucSenseBuf); | |||
| p.spt.Cdb[0] = 0x12; | |||
| p.spt.Cdb[4] = 100; | |||
| DWORD bytesReturned = 0; | |||
| if (DeviceIoControl (h, IOCTL_SCSI_PASS_THROUGH_DIRECT, | |||
| &p, sizeof (p), &p, sizeof (p), | |||
| &bytesReturned, 0) != 0) | |||
| { | |||
| int maxItems = (int) s.HA_Unique[3]; | |||
| if (maxItems == 0) | |||
| maxItems = 8; | |||
| CDDeviceDescription dev; | |||
| dev.scsiDriveLetter = driveLetter; | |||
| dev.createDescription (buffer); | |||
| for (BYTE tgt = 0; tgt < maxItems; ++tgt) | |||
| SCSI_ADDRESS scsiAddr; | |||
| zerostruct (scsiAddr); | |||
| scsiAddr.Length = sizeof (scsiAddr); | |||
| if (DeviceIoControl (h, IOCTL_SCSI_GET_ADDRESS, | |||
| 0, 0, &scsiAddr, sizeof (scsiAddr), | |||
| &bytesReturned, 0) != 0) | |||
| { | |||
| for (BYTE lun = 0; lun < 8; ++lun) | |||
| { | |||
| SRB_GDEVBlock sb; | |||
| zerostruct (sb); | |||
| sb.SRB_Cmd = SC_GET_DEV_TYPE; | |||
| sb.SRB_HaID = ha; | |||
| sb.SRB_Target = tgt; | |||
| sb.SRB_Lun = lun; | |||
| fSendASPI32Command ((SRB*) &sb); | |||
| if (sb.SRB_Status == SS_COMP && sb.SRB_DeviceType == DTYPE_CROM) | |||
| { | |||
| CDDeviceInfo dev; | |||
| dev.ha = ha; | |||
| dev.tgt = tgt; | |||
| dev.lun = lun; | |||
| getAspiDeviceInfo (dev); | |||
| list.add (dev); | |||
| } | |||
| } | |||
| dev.ha = scsiAddr.PortNumber; | |||
| dev.tgt = scsiAddr.TargetId; | |||
| dev.lun = scsiAddr.Lun; | |||
| list.add (dev); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| CDDeviceHandle* openHandle (const CDDeviceInfo& device) | |||
| { | |||
| SRB_GDEVBlock s; | |||
| zerostruct (s); | |||
| s.SRB_Cmd = SC_GET_DEV_TYPE; | |||
| s.SRB_HaID = device.ha; | |||
| s.SRB_Target = device.tgt; | |||
| s.SRB_Lun = device.lun; | |||
| if (usingScsi) | |||
| { | |||
| HANDLE h = createSCSIDeviceHandle (device.scsiDriveLetter); | |||
| if (h != INVALID_HANDLE_VALUE) | |||
| return new CDDeviceHandle (device, h); | |||
| } | |||
| else | |||
| { | |||
| if (fSendASPI32Command ((SRB*) &s) == SS_COMP && s.SRB_DeviceType == DTYPE_CROM) | |||
| return new CDDeviceHandle (device, 0); | |||
| CloseHandle (h); | |||
| } | |||
| } | |||
| return 0; | |||
| } | |||
| } | |||
| void perform (HANDLE event, SRB_ExecSCSICmd& s, char scsiDriveLetter, HANDLE scsiHandle) | |||
| { | |||
| ResetEvent (event); | |||
| DWORD status = usingScsi ? performScsiPassThroughCommand ((SRB_ExecSCSICmd*) &s, scsiDriveLetter, scsiHandle) | |||
| : fSendASPI32Command ((SRB*) &s); | |||
| DWORD performScsiPassThroughCommand (SRB_ExecSCSICmd* const srb, const char driveLetter, | |||
| HANDLE& deviceHandle, const bool retryOnFailure) | |||
| { | |||
| SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER s; | |||
| zerostruct (s); | |||
| if (status == SS_PENDING) | |||
| WaitForSingleObject (event, 4000); | |||
| s.spt.Length = sizeof (SCSI_PASS_THROUGH); | |||
| s.spt.CdbLength = srb->SRB_CDBLen; | |||
| CloseHandle (event); | |||
| } | |||
| s.spt.DataIn = (BYTE) ((srb->SRB_Flags & SRB_DIR_IN) | |||
| ? SCSI_IOCTL_DATA_IN | |||
| : ((srb->SRB_Flags & SRB_DIR_OUT) | |||
| ? SCSI_IOCTL_DATA_OUT | |||
| : SCSI_IOCTL_DATA_UNSPECIFIED)); | |||
| void timerCallback() | |||
| { | |||
| stopTimer(); | |||
| s.spt.DataTransferLength = srb->SRB_BufLen; | |||
| s.spt.TimeOutValue = 5; | |||
| s.spt.DataBuffer = srb->SRB_BufPointer; | |||
| s.spt.SenseInfoOffset = offsetof (SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, ucSenseBuf); | |||
| if (userCount == 0) | |||
| delete this; | |||
| } | |||
| memcpy (s.spt.Cdb, srb->CDBByte, srb->SRB_CDBLen); | |||
| private: | |||
| DynamicLibraryLoader winAspiLib; | |||
| DWORD (*fGetASPI32SupportInfo) (void); | |||
| DWORD (*fSendASPI32Command) (SRB*); | |||
| int userCount; | |||
| bool usingScsi; | |||
| srb->SRB_Status = SS_ERR; | |||
| srb->SRB_TargStat = 0x0004; | |||
| bool ok() const { return usingScsi || (fGetASPI32SupportInfo != 0 && fSendASPI32Command != 0); } | |||
| DWORD bytesReturned = 0; | |||
| void getAspiDeviceInfo (CDDeviceInfo& dev) | |||
| if (DeviceIoControl (deviceHandle, IOCTL_SCSI_PASS_THROUGH_DIRECT, | |||
| &s, sizeof (s), &s, sizeof (s), &bytesReturned, 0) != 0) | |||
| { | |||
| HANDLE event = CreateEvent (0, TRUE, FALSE, 0); | |||
| char buffer[128]; | |||
| zeromem (buffer, sizeof (buffer)); | |||
| SRB_ExecSCSICmd s; | |||
| zerostruct (s); | |||
| s.SRB_Cmd = SC_EXEC_SCSI_CMD; | |||
| s.SRB_HaID = dev.ha; | |||
| s.SRB_Target = dev.tgt; | |||
| s.SRB_Lun = dev.lun; | |||
| s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; | |||
| s.SRB_BufLen = sizeof (buffer); | |||
| s.SRB_BufPointer = (BYTE*) buffer; | |||
| s.SRB_SenseLen = SENSE_LEN; | |||
| s.SRB_CDBLen = 6; | |||
| s.SRB_PostProc = event; | |||
| s.CDBByte[0] = SCSI_INQUIRY; | |||
| s.CDBByte[4] = 100; | |||
| ResetEvent (event); | |||
| if (fSendASPI32Command ((SRB*) &s) == SS_PENDING) | |||
| WaitForSingleObject (event, 4000); | |||
| CloseHandle (event); | |||
| if (s.SRB_Status == SS_COMP) | |||
| dev.createDescription (buffer); | |||
| srb->SRB_Status = SS_COMP; | |||
| } | |||
| HANDLE createSCSIDeviceHandle (char driveLetter) | |||
| else if (retryOnFailure) | |||
| { | |||
| TCHAR devicePath[] = { '\\', '\\', '.', '\\', driveLetter, ':', 0, 0 }; | |||
| DWORD flags = GENERIC_READ; | |||
| const DWORD error = GetLastError(); | |||
| if (SystemStats::getOperatingSystemType() >= SystemStats::Win2000) | |||
| flags = GENERIC_READ | GENERIC_WRITE; | |||
| HANDLE h = CreateFile (devicePath, flags, FILE_SHARE_WRITE | FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); | |||
| if (h == INVALID_HANDLE_VALUE) | |||
| if ((error == ERROR_MEDIA_CHANGED) || (error == ERROR_INVALID_HANDLE)) | |||
| { | |||
| flags ^= GENERIC_WRITE; | |||
| h = CreateFile (devicePath, flags, FILE_SHARE_WRITE | FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); | |||
| } | |||
| return h; | |||
| } | |||
| DWORD performScsiPassThroughCommand (SRB_ExecSCSICmd* const srb, const char driveLetter, | |||
| HANDLE& deviceHandle, const bool retryOnFailure = true) | |||
| { | |||
| SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER s; | |||
| zerostruct (s); | |||
| s.spt.Length = sizeof (SCSI_PASS_THROUGH); | |||
| s.spt.CdbLength = srb->SRB_CDBLen; | |||
| s.spt.DataIn = (BYTE) ((srb->SRB_Flags & SRB_DIR_IN) | |||
| ? SCSI_IOCTL_DATA_IN | |||
| : ((srb->SRB_Flags & SRB_DIR_OUT) | |||
| ? SCSI_IOCTL_DATA_OUT | |||
| : SCSI_IOCTL_DATA_UNSPECIFIED)); | |||
| s.spt.DataTransferLength = srb->SRB_BufLen; | |||
| s.spt.TimeOutValue = 5; | |||
| s.spt.DataBuffer = srb->SRB_BufPointer; | |||
| s.spt.SenseInfoOffset = offsetof (SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, ucSenseBuf); | |||
| if (error != ERROR_INVALID_HANDLE) | |||
| CloseHandle (deviceHandle); | |||
| memcpy (s.spt.Cdb, srb->CDBByte, srb->SRB_CDBLen); | |||
| deviceHandle = createSCSIDeviceHandle (driveLetter); | |||
| srb->SRB_Status = SS_ERR; | |||
| srb->SRB_TargStat = 0x0004; | |||
| DWORD bytesReturned = 0; | |||
| if (DeviceIoControl (deviceHandle, IOCTL_SCSI_PASS_THROUGH_DIRECT, | |||
| &s, sizeof (s), &s, sizeof (s), &bytesReturned, 0) != 0) | |||
| { | |||
| srb->SRB_Status = SS_COMP; | |||
| } | |||
| else if (retryOnFailure) | |||
| { | |||
| const DWORD error = GetLastError(); | |||
| if ((error == ERROR_MEDIA_CHANGED) || (error == ERROR_INVALID_HANDLE)) | |||
| { | |||
| if (error != ERROR_INVALID_HANDLE) | |||
| CloseHandle (deviceHandle); | |||
| deviceHandle = createSCSIDeviceHandle (driveLetter); | |||
| return performScsiPassThroughCommand (srb, driveLetter, deviceHandle, false); | |||
| } | |||
| return performScsiPassThroughCommand (srb, driveLetter, deviceHandle, false); | |||
| } | |||
| return srb->SRB_Status; | |||
| } | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CDDeviceManager); | |||
| }; | |||
| return srb->SRB_Status; | |||
| } | |||
| //============================================================================== | |||
| @@ -794,7 +575,7 @@ public: | |||
| if (rb.numFrames * 2352 > rb.bufferSize) | |||
| return false; | |||
| if (!initialised) | |||
| if (! initialised) | |||
| { | |||
| setPaused (false); | |||
| initialised = true; | |||
| @@ -899,7 +680,7 @@ void CDController::perform (SRB_ExecSCSICmd& s) | |||
| { | |||
| s.SRB_PostProc = CreateEvent (0, TRUE, FALSE, 0); | |||
| CDDeviceManager::getInstance()->perform (s.SRB_PostProc, s, deviceInfo->info.scsiDriveLetter, deviceInfo->scsiHandle); | |||
| deviceInfo->performScsiCommand (s.SRB_PostProc, s); | |||
| } | |||
| void CDController::setPaused (bool paused) | |||
| @@ -1033,7 +814,7 @@ bool CDDeviceHandle::readTOC (TOC* lpToc) | |||
| s.SRB_Lun = info.lun; | |||
| s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; | |||
| s.SRB_BufLen = 0x324; | |||
| s.SRB_BufPointer = (BYTE*)lpToc; | |||
| s.SRB_BufPointer = (BYTE*) lpToc; | |||
| s.SRB_SenseLen = 0x0E; | |||
| s.SRB_CDBLen = 0x0A; | |||
| s.SRB_PostProc = CreateEvent (0, TRUE, FALSE, 0); | |||
| @@ -1042,10 +823,21 @@ bool CDDeviceHandle::readTOC (TOC* lpToc) | |||
| s.CDBByte[7] = 0x03; | |||
| s.CDBByte[8] = 0x24; | |||
| CDDeviceManager::getInstance()->perform (s.SRB_PostProc, s, info.scsiDriveLetter, scsiHandle); | |||
| performScsiCommand (s.SRB_PostProc, s); | |||
| return (s.SRB_Status == SS_COMP); | |||
| } | |||
| void CDDeviceHandle::performScsiCommand (HANDLE event, SRB_ExecSCSICmd& s) | |||
| { | |||
| ResetEvent (event); | |||
| DWORD status = performScsiPassThroughCommand ((SRB_ExecSCSICmd*) &s, info.scsiDriveLetter, scsiHandle, true); | |||
| if (status == SS_PENDING) | |||
| WaitForSingleObject (event, 4000); | |||
| CloseHandle (event); | |||
| } | |||
| bool CDDeviceHandle::readAudio (CDReadBuffer& buffer, CDReadBuffer* overlapBuffer) | |||
| { | |||
| if (controller == 0) | |||
| @@ -1105,7 +897,7 @@ void CDDeviceHandle::openDrawer (bool shouldBeOpen) | |||
| s.CDBByte[4] = (BYTE) (shouldBeOpen ? 2 : 3); | |||
| s.SRB_PostProc = CreateEvent (0, TRUE, FALSE, 0); | |||
| CDDeviceManager::getInstance()->perform (s.SRB_PostProc, s, info.scsiDriveLetter, scsiHandle); | |||
| performScsiCommand (s.SRB_PostProc, s); | |||
| } | |||
| bool CDDeviceHandle::testController (const int type, CDController* const newController, CDReadBuffer& rb) | |||
| @@ -1156,13 +948,13 @@ bool CDDeviceHandle::testController (const int type, CDController* const newCont | |||
| //============================================================================== | |||
| struct CDDeviceWrapper | |||
| { | |||
| CDDeviceWrapper (CDDeviceHandle* handle) | |||
| : cdH (handle), overlapBuffer (3), jitter (false) | |||
| CDDeviceWrapper (const CDDeviceDescription& device, HANDLE scsiHandle) | |||
| : deviceHandle (device, scsiHandle), overlapBuffer (3), jitter (false) | |||
| { | |||
| // xxx jitter never seemed to actually be enabled (??) | |||
| } | |||
| ScopedPointer<CDDeviceHandle> cdH; | |||
| CDDeviceHandle deviceHandle; | |||
| CDReadBuffer overlapBuffer; | |||
| bool jitter; | |||
| }; | |||
| @@ -1186,24 +978,17 @@ const StringArray AudioCDReader::getAvailableCDNames() | |||
| using namespace CDReaderHelpers; | |||
| StringArray results; | |||
| CDDeviceManager* manager = CDDeviceManager::getInstance(); | |||
| Array<CDDeviceDescription> list; | |||
| findCDDevices (list); | |||
| if (manager != 0) | |||
| for (int i = 0; i < list.size(); ++i) | |||
| { | |||
| manager->retain(); | |||
| Array<CDDeviceInfo> list; | |||
| manager->findCDDevices (list); | |||
| manager->release(); | |||
| for (int i = 0; i < list.size(); ++i) | |||
| { | |||
| String s; | |||
| if (list[i].scsiDriveLetter > 0) | |||
| s << String::charToString (list[i].scsiDriveLetter).toUpperCase() << ": "; | |||
| String s; | |||
| if (list[i].scsiDriveLetter > 0) | |||
| s << String::charToString (list[i].scsiDriveLetter).toUpperCase() << ": "; | |||
| s << list[i].description; | |||
| results.add (s); | |||
| } | |||
| s << list[i].description; | |||
| results.add (s); | |||
| } | |||
| return results; | |||
| @@ -1212,23 +997,16 @@ const StringArray AudioCDReader::getAvailableCDNames() | |||
| AudioCDReader* AudioCDReader::createReaderForCD (const int deviceIndex) | |||
| { | |||
| using namespace CDReaderHelpers; | |||
| CDDeviceManager* manager = CDDeviceManager::getInstance(); | |||
| if (manager != 0) | |||
| { | |||
| manager->retain(); | |||
| Array<CDDeviceInfo> list; | |||
| manager->findCDDevices (list); | |||
| if (isPositiveAndBelow (deviceIndex, list.size())) | |||
| { | |||
| CDDeviceHandle* const handle = manager->openHandle (list [deviceIndex]); | |||
| Array<CDDeviceDescription> list; | |||
| findCDDevices (list); | |||
| if (handle != 0) | |||
| return new AudioCDReader (new CDDeviceWrapper (handle)); | |||
| } | |||
| if (isPositiveAndBelow (deviceIndex, list.size())) | |||
| { | |||
| HANDLE h = createSCSIDeviceHandle (list [deviceIndex].scsiDriveLetter); | |||
| manager->release(); | |||
| if (h != INVALID_HANDLE_VALUE) | |||
| return new AudioCDReader (new CDDeviceWrapper (list [deviceIndex], h)); | |||
| } | |||
| return 0; | |||
| @@ -1260,8 +1038,6 @@ AudioCDReader::~AudioCDReader() | |||
| using namespace CDReaderHelpers; | |||
| CDDeviceWrapper* const device = static_cast <CDDeviceWrapper*> (handle); | |||
| delete device; | |||
| CDDeviceManager::getInstance()->release(); | |||
| } | |||
| bool AudioCDReader::readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, | |||
| @@ -1324,7 +1100,7 @@ bool AudioCDReader::readSamples (int** destSamples, int numDestChannels, int sta | |||
| readBuffer.startFrame = frameNeeded; | |||
| readBuffer.numFrames = framesInBuffer; | |||
| if (device->cdH->readAudio (readBuffer, device->jitter ? &device->overlapBuffer : 0)) | |||
| if (device->deviceHandle.readAudio (readBuffer, device->jitter ? &device->overlapBuffer : 0)) | |||
| break; | |||
| else | |||
| device->overlapBuffer.dataLength = 0; | |||
| @@ -1366,7 +1142,7 @@ bool AudioCDReader::isCDStillPresent() const | |||
| TOC toc; | |||
| zerostruct (toc); | |||
| return static_cast <CDDeviceWrapper*> (handle)->cdH->readTOC (&toc); | |||
| return static_cast <CDDeviceWrapper*> (handle)->deviceHandle.readTOC (&toc); | |||
| } | |||
| void AudioCDReader::refreshTrackLengths() | |||
| @@ -1378,7 +1154,7 @@ void AudioCDReader::refreshTrackLengths() | |||
| TOC toc; | |||
| zerostruct (toc); | |||
| if (static_cast <CDDeviceWrapper*> (handle)->cdH->readTOC (&toc)) | |||
| if (static_cast <CDDeviceWrapper*> (handle)->deviceHandle.readTOC (&toc)) | |||
| { | |||
| int numTracks = 1 + toc.lastTrack - toc.firstTrack; | |||
| @@ -1431,7 +1207,7 @@ int AudioCDReader::getIndexAt (int samplePos) | |||
| readBuffer.startFrame = frameNeeded; | |||
| readBuffer.numFrames = framesPerIndexRead; | |||
| if (device->cdH->readAudio (readBuffer, 0)) | |||
| if (device->deviceHandle.readAudio (readBuffer)) | |||
| break; | |||
| } | |||
| @@ -1516,7 +1292,7 @@ const Array <int> AudioCDReader::findIndexesInTrack (const int trackNumber) | |||
| readBuffer.startFrame = frameNeeded; | |||
| readBuffer.numFrames = framesPerIndexRead; | |||
| if (device->cdH->readAudio (readBuffer, 0)) | |||
| if (device->deviceHandle.readAudio (readBuffer)) | |||
| break; | |||
| } | |||
| @@ -1541,7 +1317,7 @@ const Array <int> AudioCDReader::findIndexesInTrack (const int trackNumber) | |||
| void AudioCDReader::ejectDisk() | |||
| { | |||
| using namespace CDReaderHelpers; | |||
| static_cast <CDDeviceWrapper*> (handle)->cdH->openDrawer (true); | |||
| static_cast <CDDeviceWrapper*> (handle)->deviceHandle.openDrawer (true); | |||
| } | |||
| #endif | |||
| @@ -222,44 +222,17 @@ namespace | |||
| DSOUND_FUNCTION_LOAD (DirectSoundCaptureEnumerateW) | |||
| } | |||
| } | |||
| } | |||
| //============================================================================== | |||
| class DSoundInternalOutChannel | |||
| { | |||
| String name; | |||
| LPGUID guid; | |||
| int sampleRate, bufferSizeSamples; | |||
| float* leftBuffer; | |||
| float* rightBuffer; | |||
| IDirectSound* pDirectSound; | |||
| IDirectSoundBuffer* pOutputBuffer; | |||
| DWORD writeOffset; | |||
| int totalBytesPerBuffer; | |||
| int bytesPerBuffer; | |||
| unsigned int lastPlayCursor; | |||
| public: | |||
| int bitDepth; | |||
| bool doneFlag; | |||
| DSoundInternalOutChannel (const String& name_, | |||
| LPGUID guid_, | |||
| int rate, | |||
| int bufferSize, | |||
| float* left, | |||
| float* right) | |||
| : name (name_), | |||
| guid (guid_), | |||
| sampleRate (rate), | |||
| bufferSizeSamples (bufferSize), | |||
| leftBuffer (left), | |||
| rightBuffer (right), | |||
| pDirectSound (0), | |||
| pOutputBuffer (0), | |||
| bitDepth (16) | |||
| DSoundInternalOutChannel (const String& name_, LPGUID guid_, int rate, | |||
| int bufferSize, float* left, float* right) | |||
| : bitDepth (16), name (name_), guid (guid_), sampleRate (rate), | |||
| bufferSizeSamples (bufferSize), leftBuffer (left), rightBuffer (right), | |||
| pDirectSound (0), pOutputBuffer (0) | |||
| { | |||
| } | |||
| @@ -274,34 +247,20 @@ public: | |||
| if (pOutputBuffer != 0) | |||
| { | |||
| JUCE_TRY | |||
| { | |||
| log ("closing dsound out: " + name); | |||
| hr = pOutputBuffer->Stop(); | |||
| logError (hr); | |||
| } | |||
| CATCH | |||
| JUCE_TRY | |||
| { | |||
| hr = pOutputBuffer->Release(); | |||
| logError (hr); | |||
| } | |||
| CATCH | |||
| log ("closing dsound out: " + name); | |||
| hr = pOutputBuffer->Stop(); | |||
| logError (hr); | |||
| hr = pOutputBuffer->Release(); | |||
| pOutputBuffer = 0; | |||
| logError (hr); | |||
| } | |||
| if (pDirectSound != 0) | |||
| { | |||
| JUCE_TRY | |||
| { | |||
| hr = pDirectSound->Release(); | |||
| logError (hr); | |||
| } | |||
| CATCH | |||
| hr = pDirectSound->Release(); | |||
| pDirectSound = 0; | |||
| logError (hr); | |||
| } | |||
| } | |||
| @@ -470,8 +429,7 @@ public: | |||
| DWORD dwSize1 = 0; | |||
| DWORD dwSize2 = 0; | |||
| HRESULT hr = pOutputBuffer->Lock (writeOffset, | |||
| bytesPerBuffer, | |||
| HRESULT hr = pOutputBuffer->Lock (writeOffset, bytesPerBuffer, | |||
| &lpbuf1, &dwSize1, | |||
| &lpbuf2, &dwSize2, 0); | |||
| @@ -479,8 +437,7 @@ public: | |||
| { | |||
| pOutputBuffer->Restore(); | |||
| hr = pOutputBuffer->Lock (writeOffset, | |||
| bytesPerBuffer, | |||
| hr = pOutputBuffer->Lock (writeOffset, bytesPerBuffer, | |||
| &lpbuf1, &dwSize1, | |||
| &lpbuf2, &dwSize2, 0); | |||
| } | |||
| @@ -489,9 +446,6 @@ public: | |||
| { | |||
| if (bitDepth == 16) | |||
| { | |||
| const float gainL = 32767.0f; | |||
| const float gainR = 32767.0f; | |||
| int* dest = static_cast<int*> (lpbuf1); | |||
| const float* left = leftBuffer; | |||
| const float* right = rightBuffer; | |||
| @@ -501,107 +455,39 @@ public: | |||
| if (left == 0) | |||
| { | |||
| while (--samples1 >= 0) | |||
| { | |||
| int r = roundToInt (gainR * *right++); | |||
| if (r < -32768) | |||
| r = -32768; | |||
| else if (r > 32767) | |||
| r = 32767; | |||
| *dest++ = (r << 16); | |||
| } | |||
| *dest++ = (convertInputValue (*right++) << 16); | |||
| dest = static_cast<int*> (lpbuf2); | |||
| while (--samples2 >= 0) | |||
| { | |||
| int r = roundToInt (gainR * *right++); | |||
| if (r < -32768) | |||
| r = -32768; | |||
| else if (r > 32767) | |||
| r = 32767; | |||
| *dest++ = (r << 16); | |||
| } | |||
| *dest++ = (convertInputValue (*right++) << 16); | |||
| } | |||
| else if (right == 0) | |||
| { | |||
| while (--samples1 >= 0) | |||
| { | |||
| int l = roundToInt (gainL * *left++); | |||
| if (l < -32768) | |||
| l = -32768; | |||
| else if (l > 32767) | |||
| l = 32767; | |||
| l &= 0xffff; | |||
| *dest++ = l; | |||
| } | |||
| *dest++ = (0xffff & convertInputValue (*left++)); | |||
| dest = static_cast<int*> (lpbuf2); | |||
| while (--samples2 >= 0) | |||
| { | |||
| int l = roundToInt (gainL * *left++); | |||
| if (l < -32768) | |||
| l = -32768; | |||
| else if (l > 32767) | |||
| l = 32767; | |||
| l &= 0xffff; | |||
| *dest++ = l; | |||
| } | |||
| *dest++ = (0xffff & convertInputValue (*left++)); | |||
| } | |||
| else | |||
| { | |||
| while (--samples1 >= 0) | |||
| { | |||
| int l = roundToInt (gainL * *left++); | |||
| if (l < -32768) | |||
| l = -32768; | |||
| else if (l > 32767) | |||
| l = 32767; | |||
| l &= 0xffff; | |||
| int r = roundToInt (gainR * *right++); | |||
| if (r < -32768) | |||
| r = -32768; | |||
| else if (r > 32767) | |||
| r = 32767; | |||
| *dest++ = (r << 16) | l; | |||
| const int l = convertInputValue (*left++); | |||
| const int r = convertInputValue (*right++); | |||
| *dest++ = (r << 16) | (0xffff & l); | |||
| } | |||
| dest = static_cast<int*> (lpbuf2); | |||
| while (--samples2 >= 0) | |||
| { | |||
| int l = roundToInt (gainL * *left++); | |||
| if (l < -32768) | |||
| l = -32768; | |||
| else if (l > 32767) | |||
| l = 32767; | |||
| l &= 0xffff; | |||
| int r = roundToInt (gainR * *right++); | |||
| if (r < -32768) | |||
| r = -32768; | |||
| else if (r > 32767) | |||
| r = 32767; | |||
| *dest++ = (r << 16) | l; | |||
| const int l = convertInputValue (*left++); | |||
| const int r = convertInputValue (*right++); | |||
| *dest++ = (r << 16) | (0xffff & l); | |||
| } | |||
| } | |||
| } | |||
| @@ -621,7 +507,6 @@ public: | |||
| } | |||
| bytesEmpty -= bytesPerBuffer; | |||
| return true; | |||
| } | |||
| else | |||
| @@ -629,11 +514,11 @@ public: | |||
| return false; | |||
| } | |||
| } | |||
| }; | |||
| //============================================================================== | |||
| struct DSoundInternalInChannel | |||
| { | |||
| int bitDepth; | |||
| bool doneFlag; | |||
| private: | |||
| String name; | |||
| LPGUID guid; | |||
| int sampleRate, bufferSizeSamples; | |||
| @@ -641,31 +526,28 @@ struct DSoundInternalInChannel | |||
| float* rightBuffer; | |||
| IDirectSound* pDirectSound; | |||
| IDirectSoundCapture* pDirectSoundCapture; | |||
| IDirectSoundCaptureBuffer* pInputBuffer; | |||
| IDirectSoundBuffer* pOutputBuffer; | |||
| DWORD writeOffset; | |||
| int totalBytesPerBuffer, bytesPerBuffer; | |||
| unsigned int lastPlayCursor; | |||
| public: | |||
| unsigned int readOffset; | |||
| int bytesPerBuffer, totalBytesPerBuffer; | |||
| int bitDepth; | |||
| bool doneFlag; | |||
| static inline int convertInputValue (const float v) throw() | |||
| { | |||
| return jlimit (-32768, 32767, roundToInt (32767.0f * v)); | |||
| } | |||
| JUCE_DECLARE_NON_COPYABLE (DSoundInternalOutChannel); | |||
| }; | |||
| DSoundInternalInChannel (const String& name_, | |||
| LPGUID guid_, | |||
| int rate, | |||
| int bufferSize, | |||
| float* left, | |||
| float* right) | |||
| : name (name_), | |||
| guid (guid_), | |||
| sampleRate (rate), | |||
| bufferSizeSamples (bufferSize), | |||
| leftBuffer (left), | |||
| rightBuffer (right), | |||
| pDirectSound (0), | |||
| pDirectSoundCapture (0), | |||
| pInputBuffer (0), | |||
| bitDepth (16) | |||
| //============================================================================== | |||
| struct DSoundInternalInChannel | |||
| { | |||
| public: | |||
| DSoundInternalInChannel (const String& name_, LPGUID guid_, int rate, | |||
| int bufferSize, float* left, float* right) | |||
| : bitDepth (16), name (name_), guid (guid_), sampleRate (rate), | |||
| bufferSizeSamples (bufferSize), leftBuffer (left), rightBuffer (right), | |||
| pDirectSound (0), pDirectSoundCapture (0), pInputBuffer (0) | |||
| { | |||
| } | |||
| @@ -680,53 +562,34 @@ public: | |||
| if (pInputBuffer != 0) | |||
| { | |||
| JUCE_TRY | |||
| { | |||
| log ("closing dsound in: " + name); | |||
| hr = pInputBuffer->Stop(); | |||
| logError (hr); | |||
| } | |||
| CATCH | |||
| JUCE_TRY | |||
| { | |||
| hr = pInputBuffer->Release(); | |||
| logError (hr); | |||
| } | |||
| CATCH | |||
| log ("closing dsound in: " + name); | |||
| hr = pInputBuffer->Stop(); | |||
| logError (hr); | |||
| hr = pInputBuffer->Release(); | |||
| pInputBuffer = 0; | |||
| logError (hr); | |||
| } | |||
| if (pDirectSoundCapture != 0) | |||
| { | |||
| JUCE_TRY | |||
| { | |||
| hr = pDirectSoundCapture->Release(); | |||
| logError (hr); | |||
| } | |||
| CATCH | |||
| hr = pDirectSoundCapture->Release(); | |||
| pDirectSoundCapture = 0; | |||
| logError (hr); | |||
| } | |||
| if (pDirectSound != 0) | |||
| { | |||
| JUCE_TRY | |||
| { | |||
| hr = pDirectSound->Release(); | |||
| logError (hr); | |||
| } | |||
| CATCH | |||
| hr = pDirectSound->Release(); | |||
| pDirectSound = 0; | |||
| logError (hr); | |||
| } | |||
| } | |||
| const String open() | |||
| { | |||
| log ("opening dsound in device: " + name | |||
| + " rate=" + String (sampleRate) + " bits=" + String (bitDepth) + " buf=" + String (bufferSizeSamples)); | |||
| + " rate=" + String (sampleRate) + " bits=" + String (bitDepth) + " buf=" + String (bufferSizeSamples)); | |||
| pDirectSound = 0; | |||
| pDirectSoundCapture = 0; | |||
| @@ -818,8 +681,7 @@ public: | |||
| DWORD dwsize1 = 0; | |||
| DWORD dwsize2 = 0; | |||
| HRESULT hr = pInputBuffer->Lock (readOffset, | |||
| bytesPerBuffer, | |||
| HRESULT hr = pInputBuffer->Lock (readOffset, bytesPerBuffer, | |||
| (void**) &lpbuf1, &dwsize1, | |||
| (void**) &lpbuf2, &dwsize2, 0); | |||
| @@ -909,6 +771,24 @@ public: | |||
| return false; | |||
| } | |||
| } | |||
| unsigned int readOffset; | |||
| int bytesPerBuffer, totalBytesPerBuffer; | |||
| int bitDepth; | |||
| bool doneFlag; | |||
| private: | |||
| String name; | |||
| LPGUID guid; | |||
| int sampleRate, bufferSizeSamples; | |||
| float* leftBuffer; | |||
| float* rightBuffer; | |||
| IDirectSound* pDirectSound; | |||
| IDirectSoundCapture* pDirectSoundCapture; | |||
| IDirectSoundCaptureBuffer* pInputBuffer; | |||
| JUCE_DECLARE_NON_COPYABLE (DSoundInternalInChannel); | |||
| }; | |||
| //============================================================================== | |||
| @@ -950,53 +830,9 @@ public: | |||
| close(); | |||
| } | |||
| const StringArray getOutputChannelNames() | |||
| { | |||
| return outChannels; | |||
| } | |||
| const StringArray getInputChannelNames() | |||
| { | |||
| return inChannels; | |||
| } | |||
| int getNumSampleRates() | |||
| { | |||
| return 4; | |||
| } | |||
| double getSampleRate (int index) | |||
| { | |||
| const double samps[] = { 44100.0, 48000.0, 88200.0, 96000.0 }; | |||
| return samps [jlimit (0, 3, index)]; | |||
| } | |||
| int getNumBufferSizesAvailable() | |||
| { | |||
| return 50; | |||
| } | |||
| int getBufferSizeSamples (int index) | |||
| { | |||
| int n = 64; | |||
| for (int i = 0; i < index; ++i) | |||
| n += (n < 512) ? 32 | |||
| : ((n < 1024) ? 64 | |||
| : ((n < 2048) ? 128 : 256)); | |||
| return n; | |||
| } | |||
| int getDefaultBufferSize() | |||
| { | |||
| return 2560; | |||
| } | |||
| const String open (const BigInteger& inputChannels, | |||
| const BigInteger& outputChannels, | |||
| double sampleRate, | |||
| int bufferSizeSamples) | |||
| double sampleRate, int bufferSizeSamples) | |||
| { | |||
| lastError = openDevice (inputChannels, outputChannels, sampleRate, bufferSizeSamples); | |||
| isOpen_ = lastError.isEmpty(); | |||
| @@ -1015,19 +851,35 @@ public: | |||
| } | |||
| } | |||
| bool isOpen() | |||
| { | |||
| return isOpen_ && isThreadRunning(); | |||
| } | |||
| bool isOpen() { return isOpen_ && isThreadRunning(); } | |||
| int getCurrentBufferSizeSamples() { return bufferSizeSamples; } | |||
| double getCurrentSampleRate() { return sampleRate; } | |||
| const BigInteger getActiveOutputChannels() const { return enabledOutputs; } | |||
| const BigInteger getActiveInputChannels() const { return enabledInputs; } | |||
| int getOutputLatencyInSamples() { return (int) (getCurrentBufferSizeSamples() * 1.5); } | |||
| int getInputLatencyInSamples() { return getOutputLatencyInSamples(); } | |||
| const StringArray getOutputChannelNames() { return outChannels; } | |||
| const StringArray getInputChannelNames() { return inChannels; } | |||
| int getCurrentBufferSizeSamples() | |||
| int getNumSampleRates() { return 4; } | |||
| int getDefaultBufferSize() { return 2560; } | |||
| int getNumBufferSizesAvailable() { return 50; } | |||
| double getSampleRate (int index) | |||
| { | |||
| return bufferSizeSamples; | |||
| const double samps[] = { 44100.0, 48000.0, 88200.0, 96000.0 }; | |||
| return samps [jlimit (0, 3, index)]; | |||
| } | |||
| double getCurrentSampleRate() | |||
| int getBufferSizeSamples (int index) | |||
| { | |||
| return sampleRate; | |||
| int n = 64; | |||
| for (int i = 0; i < index; ++i) | |||
| n += (n < 512) ? 32 | |||
| : ((n < 1024) ? 64 | |||
| : ((n < 2048) ? 128 : 256)); | |||
| return n; | |||
| } | |||
| int getCurrentBitDepth() | |||
| @@ -1046,26 +898,6 @@ public: | |||
| return bits; | |||
| } | |||
| const BigInteger getActiveOutputChannels() const | |||
| { | |||
| return enabledOutputs; | |||
| } | |||
| const BigInteger getActiveInputChannels() const | |||
| { | |||
| return enabledInputs; | |||
| } | |||
| int getOutputLatencyInSamples() | |||
| { | |||
| return (int) (getCurrentBufferSizeSamples() * 1.5); | |||
| } | |||
| int getInputLatencyInSamples() | |||
| { | |||
| return getOutputLatencyInSamples(); | |||
| } | |||
| void start (AudioIODeviceCallback* call) | |||
| { | |||
| if (isOpen_ && call != 0 && ! isStarted) | |||
| @@ -1101,15 +933,8 @@ public: | |||
| } | |||
| } | |||
| bool isPlaying() | |||
| { | |||
| return isStarted && isOpen_ && isThreadRunning(); | |||
| } | |||
| const String getLastError() | |||
| { | |||
| return lastError; | |||
| } | |||
| bool isPlaying() { return isStarted && isOpen_ && isThreadRunning(); } | |||
| const String getLastError() { return lastError; } | |||
| //============================================================================== | |||
| StringArray inChannels, outChannels; | |||
| @@ -1129,7 +954,6 @@ private: | |||
| int64 volatile lastBlockTime; | |||
| double sampleRate; | |||
| BigInteger enabledInputs, enabledOutputs; | |||
| AudioSampleBuffer inputBuffers, outputBuffers; | |||
| AudioIODeviceCallback* callback; | |||
| @@ -1137,8 +961,7 @@ private: | |||
| const String openDevice (const BigInteger& inputChannels, | |||
| const BigInteger& outputChannels, | |||
| double sampleRate_, | |||
| int bufferSizeSamples_); | |||
| double sampleRate_, int bufferSizeSamples_); | |||
| void closeDevice() | |||
| { | |||
| @@ -1289,10 +1112,6 @@ public: | |||
| initialiseDSoundFunctions(); | |||
| } | |||
| ~DSoundAudioIODeviceType() | |||
| { | |||
| } | |||
| //============================================================================== | |||
| void scanForDevices() | |||
| { | |||
| @@ -1315,7 +1134,7 @@ public: | |||
| jassert (hasScanned); // need to call scanForDevices() before doing this | |||
| return wantInputNames ? inputDeviceNames | |||
| : outputDeviceNames; | |||
| : outputDeviceNames; | |||
| } | |||
| int getDefaultDeviceIndex (bool /*forInput*/) const | |||
| @@ -1355,11 +1174,8 @@ public: | |||
| } | |||
| //============================================================================== | |||
| StringArray outputDeviceNames; | |||
| OwnedArray <GUID> outputGuids; | |||
| StringArray inputDeviceNames; | |||
| OwnedArray <GUID> inputGuids; | |||
| StringArray outputDeviceNames, inputDeviceNames; | |||
| OwnedArray <GUID> outputGuids, inputGuids; | |||
| private: | |||
| bool hasScanned; | |||
| @@ -1443,8 +1259,7 @@ private: | |||
| //============================================================================== | |||
| const String DSoundAudioIODevice::openDevice (const BigInteger& inputChannels, | |||
| const BigInteger& outputChannels, | |||
| double sampleRate_, | |||
| int bufferSizeSamples_) | |||
| double sampleRate_, int bufferSizeSamples_) | |||
| { | |||
| closeDevice(); | |||
| totalSamplesOut = 0; | |||
| @@ -1576,7 +1391,6 @@ AudioIODeviceType* juce_createAudioIODeviceType_DirectSound() | |||
| return new DSoundAudioIODeviceType(); | |||
| } | |||
| #undef log | |||
| #endif | |||