diff --git a/extras/audio plugins/wrapper/AU/juce_AU_Wrapper.mm b/extras/audio plugins/wrapper/AU/juce_AU_Wrapper.mm index 95dafdfc95..28b293d101 100644 --- a/extras/audio plugins/wrapper/AU/juce_AU_Wrapper.mm +++ b/extras/audio plugins/wrapper/AU/juce_AU_Wrapper.mm @@ -794,7 +794,7 @@ public: while (i.getNextEvent (midiEventData, midiEventSize, midiEventPosition)) { - jassert (isPositiveAndBelow (midiEventPosition, numSamples)); + jassert (isPositiveAndBelow (midiEventPosition, (int) numSamples)); diff --git a/src/audio/audio_file_formats/juce_AudioThumbnail.h b/src/audio/audio_file_formats/juce_AudioThumbnail.h index 5e3aa1e8cf..8b680bc2e9 100644 --- a/src/audio/audio_file_formats/juce_AudioThumbnail.h +++ b/src/audio/audio_file_formats/juce_AudioThumbnail.h @@ -99,7 +99,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); diff --git a/src/gui/components/juce_Desktop.cpp b/src/gui/components/juce_Desktop.cpp index 552caf69f2..e9df31d739 100644 --- a/src/gui/components/juce_Desktop.cpp +++ b/src/gui/components/juce_Desktop.cpp @@ -207,12 +207,17 @@ void Desktop::componentBroughtToFront (Component* const c) } //============================================================================== -const Point Desktop::getLastMouseDownPosition() throw() +const Point Desktop::getMousePosition() +{ + return getInstance().getMainMouseSource().getScreenPosition(); +} + +const Point Desktop::getLastMouseDownPosition() { return getInstance().getMainMouseSource().getLastMouseDownPosition(); } -int Desktop::getMouseButtonClickCounter() throw() +int Desktop::getMouseButtonClickCounter() { return getInstance().mouseClickCounter; } @@ -288,7 +293,7 @@ void Desktop::removeGlobalMouseListener (MouseListener* const listener) void Desktop::timerCallback() { - if (lastFakeMouseMove != getMousePosition()) + if (lastFakeMouseMove != getRawMousePosition()) sendMouseMove(); } @@ -298,7 +303,7 @@ void Desktop::sendMouseMove() { startTimer (20); - lastFakeMouseMove = getMousePosition(); + lastFakeMouseMove = getRawMousePosition(); Component* const target = findComponentAt (lastFakeMouseMove); @@ -326,7 +331,7 @@ void Desktop::resetTimer() else startTimer (100); - lastFakeMouseMove = getMousePosition(); + lastFakeMouseMove = getRawMousePosition(); } //============================================================================== diff --git a/src/gui/components/juce_Desktop.h b/src/gui/components/juce_Desktop.h index 9c423af95d..11bfc0f481 100644 --- a/src/gui/components/juce_Desktop.h +++ b/src/gui/components/juce_Desktop.h @@ -104,6 +104,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 getMousePosition(); @@ -114,15 +118,20 @@ public: static void setMousePosition (const Point& 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 getLastMouseDownPosition() throw(); + static const Point 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. @@ -345,6 +354,8 @@ private: ComponentAnimator animator; + static const Point getRawMousePosition(); + void timerCallback(); void resetTimer(); diff --git a/src/native/linux/juce_linux_Windowing.cpp b/src/native/linux/juce_linux_Windowing.cpp index b7eb6fb434..ee3247b304 100644 --- a/src/native/linux/juce_linux_Windowing.cpp +++ b/src/native/linux/juce_linux_Windowing.cpp @@ -1432,7 +1432,7 @@ public: void handleMotionNotifyEvent (const XPointerMovedEvent* const movedEvent) { updateKeyModifiers (movedEvent->state); - const Point mousePos (Desktop::getMousePosition()); + const Point mousePos (movedEvent->x_root, movedEvent->y_root); if (lastMousePos != mousePos) { @@ -2806,7 +2806,7 @@ bool Desktop::canUseSemiTransparentWindows() throw() && (matchedDepth == desiredDepth); } -const Point Desktop::getMousePosition() +const Point Desktop::getRawMousePosition() { Window root, child; int x, y, winx, winy; diff --git a/src/native/mac/juce_iphone_UIViewComponentPeer.mm b/src/native/mac/juce_iphone_UIViewComponentPeer.mm index f937ce9ff0..61a9cb5537 100644 --- a/src/native/mac/juce_iphone_UIViewComponentPeer.mm +++ b/src/native/mac/juce_iphone_UIViewComponentPeer.mm @@ -978,7 +978,7 @@ bool Desktop::canUseSemiTransparentWindows() throw() return true; } -const Point Desktop::getMousePosition() +const Point Desktop::getRawMousePosition() { return juce_lastMousePos; } diff --git a/src/native/mac/juce_mac_MiscUtilities.mm b/src/native/mac/juce_mac_MiscUtilities.mm index 85b3b32166..755352fbe5 100644 --- a/src/native/mac/juce_mac_MiscUtilities.mm +++ b/src/native/mac/juce_mac_MiscUtilities.mm @@ -143,7 +143,7 @@ bool Desktop::canUseSemiTransparentWindows() throw() return true; } -const Point Desktop::getMousePosition() +const Point Desktop::getRawMousePosition() { const ScopedAutoReleasePool pool; const NSPoint p ([NSEvent mouseLocation]); diff --git a/src/native/windows/juce_win32_AudioCDReader.cpp b/src/native/windows/juce_win32_AudioCDReader.cpp index a159d97b98..30a17ffb14 100644 --- a/src/native/windows/juce_win32_AudioCDReader.cpp +++ b/src/native/windows/juce_win32_AudioCDReader.cpp @@ -32,549 +32,168 @@ namespace CDReaderHelpers { -//*************************************************************************** -// %%% TARGET STATUS VALUES %%% -//*************************************************************************** -#define STATUS_GOOD 0x00 // Status Good -#define STATUS_CHKCOND 0x02 // Check Condition -#define STATUS_CONDMET 0x04 // Condition Met -#define STATUS_BUSY 0x08 // Busy -#define STATUS_INTERM 0x10 // Intermediate -#define STATUS_INTCDMET 0x14 // Intermediate-condition met -#define STATUS_RESCONF 0x18 // Reservation conflict -#define STATUS_COMTERM 0x22 // Command Terminated -#define STATUS_QFULL 0x28 // Queue full - -//*************************************************************************** -// %%% SCSI MISCELLANEOUS EQUATES %%% -//*************************************************************************** -#define MAXLUN 7 // Maximum Logical Unit Id -#define MAXTARG 7 // Maximum Target Id -#define MAX_SCSI_LUNS 64 // Maximum Number of SCSI LUNs -#define MAX_NUM_HA 8 // Maximum Number of SCSI HA's - -//*************************************************************************** -// %%% Commands for all Device Types %%% -//*************************************************************************** -#define SCSI_CHANGE_DEF 0x40 // Change Definition (Optional) -#define SCSI_COMPARE 0x39 // Compare (O) -#define SCSI_COPY 0x18 // Copy (O) -#define SCSI_COP_VERIFY 0x3A // Copy and Verify (O) -#define SCSI_INQUIRY 0x12 // Inquiry (MANDATORY) -#define SCSI_LOG_SELECT 0x4C // Log Select (O) -#define SCSI_LOG_SENSE 0x4D // Log Sense (O) -#define SCSI_MODE_SEL6 0x15 // Mode Select 6-byte (Device Specific) -#define SCSI_MODE_SEL10 0x55 // Mode Select 10-byte (Device Specific) -#define SCSI_MODE_SEN6 0x1A // Mode Sense 6-byte (Device Specific) -#define SCSI_MODE_SEN10 0x5A // Mode Sense 10-byte (Device Specific) -#define SCSI_READ_BUFF 0x3C // Read Buffer (O) -#define SCSI_REQ_SENSE 0x03 // Request Sense (MANDATORY) -#define SCSI_SEND_DIAG 0x1D // Send Diagnostic (O) -#define SCSI_TST_U_RDY 0x00 // Test Unit Ready (MANDATORY) -#define SCSI_WRITE_BUFF 0x3B // Write Buffer (O) - -//*************************************************************************** -// %%% Commands Unique to Direct Access Devices %%% -//*************************************************************************** -#define SCSI_COMPARE 0x39 // Compare (O) -#define SCSI_FORMAT 0x04 // Format Unit (MANDATORY) -#define SCSI_LCK_UN_CAC 0x36 // Lock Unlock Cache (O) -#define SCSI_PREFETCH 0x34 // Prefetch (O) -#define SCSI_MED_REMOVL 0x1E // Prevent/Allow medium Removal (O) -#define SCSI_READ6 0x08 // Read 6-byte (MANDATORY) -#define SCSI_READ10 0x28 // Read 10-byte (MANDATORY) -#define SCSI_RD_CAPAC 0x25 // Read Capacity (MANDATORY) -#define SCSI_RD_DEFECT 0x37 // Read Defect Data (O) -#define SCSI_READ_LONG 0x3E // Read Long (O) -#define SCSI_REASS_BLK 0x07 // Reassign Blocks (O) -#define SCSI_RCV_DIAG 0x1C // Receive Diagnostic Results (O) -#define SCSI_RELEASE 0x17 // Release Unit (MANDATORY) -#define SCSI_REZERO 0x01 // Rezero Unit (O) -#define SCSI_SRCH_DAT_E 0x31 // Search Data Equal (O) -#define SCSI_SRCH_DAT_H 0x30 // Search Data High (O) -#define SCSI_SRCH_DAT_L 0x32 // Search Data Low (O) -#define SCSI_SEEK6 0x0B // Seek 6-Byte (O) -#define SCSI_SEEK10 0x2B // Seek 10-Byte (O) -#define SCSI_SEND_DIAG 0x1D // Send Diagnostics (MANDATORY) -#define SCSI_SET_LIMIT 0x33 // Set Limits (O) -#define SCSI_START_STP 0x1B // Start/Stop Unit (O) -#define SCSI_SYNC_CACHE 0x35 // Synchronize Cache (O) -#define SCSI_VERIFY 0x2F // Verify (O) -#define SCSI_WRITE6 0x0A // Write 6-Byte (MANDATORY) -#define SCSI_WRITE10 0x2A // Write 10-Byte (MANDATORY) -#define SCSI_WRT_VERIFY 0x2E // Write and Verify (O) -#define SCSI_WRITE_LONG 0x3F // Write Long (O) -#define SCSI_WRITE_SAME 0x41 // Write Same (O) - -//*************************************************************************** -// %%% Commands Unique to Sequential Access Devices %%% -//*************************************************************************** -#define SCSI_ERASE 0x19 // Erase (MANDATORY) -#define SCSI_LOAD_UN 0x1b // Load/Unload (O) -#define SCSI_LOCATE 0x2B // Locate (O) -#define SCSI_RD_BLK_LIM 0x05 // Read Block Limits (MANDATORY) -#define SCSI_READ_POS 0x34 // Read Position (O) -#define SCSI_READ_REV 0x0F // Read Reverse (O) -#define SCSI_REC_BF_DAT 0x14 // Recover Buffer Data (O) -#define SCSI_RESERVE 0x16 // Reserve Unit (MANDATORY) -#define SCSI_REWIND 0x01 // Rewind (MANDATORY) -#define SCSI_SPACE 0x11 // Space (MANDATORY) -#define SCSI_VERIFY_T 0x13 // Verify (Tape) (O) -#define SCSI_WRT_FILE 0x10 // Write Filemarks (MANDATORY) - -//*************************************************************************** -// %%% Commands Unique to Printer Devices %%% -//*************************************************************************** -#define SCSI_PRINT 0x0A // Print (MANDATORY) -#define SCSI_SLEW_PNT 0x0B // Slew and Print (O) -#define SCSI_STOP_PNT 0x1B // Stop Print (O) -#define SCSI_SYNC_BUFF 0x10 // Synchronize Buffer (O) - -//*************************************************************************** -// %%% Commands Unique to Processor Devices %%% -//*************************************************************************** -#define SCSI_RECEIVE 0x08 // Receive (O) -#define SCSI_SEND 0x0A // Send (O) - -//*************************************************************************** -// %%% Commands Unique to Write-Once Devices %%% -//*************************************************************************** -#define SCSI_MEDIUM_SCN 0x38 // Medium Scan (O) -#define SCSI_SRCHDATE10 0x31 // Search Data Equal 10-Byte (O) -#define SCSI_SRCHDATE12 0xB1 // Search Data Equal 12-Byte (O) -#define SCSI_SRCHDATH10 0x30 // Search Data High 10-Byte (O) -#define SCSI_SRCHDATH12 0xB0 // Search Data High 12-Byte (O) -#define SCSI_SRCHDATL10 0x32 // Search Data Low 10-Byte (O) -#define SCSI_SRCHDATL12 0xB2 // Search Data Low 12-Byte (O) -#define SCSI_SET_LIM_10 0x33 // Set Limits 10-Byte (O) -#define SCSI_SET_LIM_12 0xB3 // Set Limits 10-Byte (O) -#define SCSI_VERIFY10 0x2F // Verify 10-Byte (O) -#define SCSI_VERIFY12 0xAF // Verify 12-Byte (O) -#define SCSI_WRITE12 0xAA // Write 12-Byte (O) -#define SCSI_WRT_VER10 0x2E // Write and Verify 10-Byte (O) -#define SCSI_WRT_VER12 0xAE // Write and Verify 12-Byte (O) - -//*************************************************************************** -// %%% Commands Unique to CD-ROM Devices %%% -//*************************************************************************** -#define SCSI_PLAYAUD_10 0x45 // Play Audio 10-Byte (O) -#define SCSI_PLAYAUD_12 0xA5 // Play Audio 12-Byte 12-Byte (O) -#define SCSI_PLAYAUDMSF 0x47 // Play Audio MSF (O) -#define SCSI_PLAYA_TKIN 0x48 // Play Audio Track/Index (O) -#define SCSI_PLYTKREL10 0x49 // Play Track Relative 10-Byte (O) -#define SCSI_PLYTKREL12 0xA9 // Play Track Relative 12-Byte (O) -#define SCSI_READCDCAP 0x25 // Read CD-ROM Capacity (MANDATORY) -#define SCSI_READHEADER 0x44 // Read Header (O) -#define SCSI_SUBCHANNEL 0x42 // Read Subchannel (O) -#define SCSI_READ_TOC 0x43 // Read TOC (O) - -//*************************************************************************** -// %%% Commands Unique to Scanner Devices %%% -//*************************************************************************** -#define SCSI_GETDBSTAT 0x34 // Get Data Buffer Status (O) -#define SCSI_GETWINDOW 0x25 // Get Window (O) -#define SCSI_OBJECTPOS 0x31 // Object Postion (O) -#define SCSI_SCAN 0x1B // Scan (O) -#define SCSI_SETWINDOW 0x24 // Set Window (MANDATORY) - -//*************************************************************************** -// %%% Commands Unique to Optical Memory Devices %%% -//*************************************************************************** -#define SCSI_UpdateBlk 0x3D // Update Block (O) - -//*************************************************************************** -// %%% Commands Unique to Medium Changer Devices %%% -//*************************************************************************** -#define SCSI_EXCHMEDIUM 0xA6 // Exchange Medium (O) -#define SCSI_INITELSTAT 0x07 // Initialize Element Status (O) -#define SCSI_POSTOELEM 0x2B // Position to Element (O) -#define SCSI_REQ_VE_ADD 0xB5 // Request Volume Element Address (O) -#define SCSI_SENDVOLTAG 0xB6 // Send Volume Tag (O) - -//*************************************************************************** -// %%% Commands Unique to Communication Devices %%% -//*************************************************************************** -#define SCSI_GET_MSG_6 0x08 // Get Message 6-Byte (MANDATORY) -#define SCSI_GET_MSG_10 0x28 // Get Message 10-Byte (O) -#define SCSI_GET_MSG_12 0xA8 // Get Message 12-Byte (O) -#define SCSI_SND_MSG_6 0x0A // Send Message 6-Byte (MANDATORY) -#define SCSI_SND_MSG_10 0x2A // Send Message 10-Byte (O) -#define SCSI_SND_MSG_12 0xAA // Send Message 12-Byte (O) - - -//*************************************************************************** -// %%% Request Sense Data Format %%% -//*************************************************************************** -typedef struct { - BYTE ErrorCode; // Error Code (70H or 71H) - BYTE SegmentNum; // Number of current segment descriptor - BYTE SenseKey; // Sense Key(See bit definitions too) - BYTE InfoByte0; // Information MSB - BYTE InfoByte1; // Information MID - BYTE InfoByte2; // Information MID - BYTE InfoByte3; // Information LSB - BYTE AddSenLen; // Additional Sense Length - BYTE ComSpecInf0; // Command Specific Information MSB - BYTE ComSpecInf1; // Command Specific Information MID - BYTE ComSpecInf2; // Command Specific Information MID - BYTE ComSpecInf3; // Command Specific Information LSB - BYTE AddSenseCode; // Additional Sense Code - BYTE AddSenQual; // Additional Sense Code Qualifier - BYTE FieldRepUCode; // Field Replaceable Unit Code - BYTE SenKeySpec15; // Sense Key Specific 15th byte - BYTE SenKeySpec16; // Sense Key Specific 16th byte - BYTE SenKeySpec17; // Sense Key Specific 17th byte - BYTE AddSenseBytes; // Additional Sense Bytes -} SENSE_DATA_FMT; - -//*************************************************************************** -// %%% REQUEST SENSE ERROR CODE %%% -//*************************************************************************** -#define SERROR_CURRENT 0x70 // Current Errors -#define SERROR_DEFERED 0x71 // Deferred Errors - -//*************************************************************************** -// %%% REQUEST SENSE BIT DEFINITIONS %%% -//*************************************************************************** -#define SENSE_VALID 0x80 // Byte 0 Bit 7 -#define SENSE_FILEMRK 0x80 // Byte 2 Bit 7 -#define SENSE_EOM 0x40 // Byte 2 Bit 6 -#define SENSE_ILI 0x20 // Byte 2 Bit 5 - -//*************************************************************************** -// %%% REQUEST SENSE SENSE KEY DEFINITIONS %%% -//*************************************************************************** -#define KEY_NOSENSE 0x00 // No Sense -#define KEY_RECERROR 0x01 // Recovered Error -#define KEY_NOTREADY 0x02 // Not Ready -#define KEY_MEDIUMERR 0x03 // Medium Error -#define KEY_HARDERROR 0x04 // Hardware Error -#define KEY_ILLGLREQ 0x05 // Illegal Request -#define KEY_UNITATT 0x06 // Unit Attention -#define KEY_DATAPROT 0x07 // Data Protect -#define KEY_BLANKCHK 0x08 // Blank Check -#define KEY_VENDSPEC 0x09 // Vendor Specific -#define KEY_COPYABORT 0x0A // Copy Abort -#define KEY_EQUAL 0x0C // Equal (Search) -#define KEY_VOLOVRFLW 0x0D // Volume Overflow -#define KEY_MISCOMP 0x0E // Miscompare (Search) -#define KEY_RESERVED 0x0F // Reserved - -//*************************************************************************** -// %%% PERIPHERAL DEVICE TYPE DEFINITIONS %%% -//*************************************************************************** -#define DTYPE_DASD 0x00 // Disk Device -#define DTYPE_SEQD 0x01 // Tape Device -#define DTYPE_PRNT 0x02 // Printer -#define DTYPE_PROC 0x03 // Processor -#define DTYPE_WORM 0x04 // Write-once read-multiple -#define DTYPE_CROM 0x05 // CD-ROM device -#define DTYPE_SCAN 0x06 // Scanner device -#define DTYPE_OPTI 0x07 // Optical memory device -#define DTYPE_JUKE 0x08 // Medium Changer device -#define DTYPE_COMM 0x09 // Communications device -#define DTYPE_RESL 0x0A // Reserved (low) -#define DTYPE_RESH 0x1E // Reserved (high) -#define DTYPE_UNKNOWN 0x1F // Unknown or no device type - -//*************************************************************************** -// %%% ANSI APPROVED VERSION DEFINITIONS %%% -//*************************************************************************** -#define ANSI_MAYBE 0x0 // Device may or may not be ANSI approved stand -#define ANSI_SCSI1 0x1 // Device complies to ANSI X3.131-1986 (SCSI-1) -#define ANSI_SCSI2 0x2 // Device complies to SCSI-2 -#define ANSI_RESLO 0x3 // Reserved (low) -#define ANSI_RESHI 0x7 // Reserved (high) - - -typedef struct -{ - USHORT Length; - UCHAR ScsiStatus; - UCHAR PathId; - UCHAR TargetId; - UCHAR Lun; - UCHAR CdbLength; - UCHAR SenseInfoLength; - UCHAR DataIn; - ULONG DataTransferLength; - ULONG TimeOutValue; - ULONG DataBufferOffset; - ULONG SenseInfoOffset; - UCHAR Cdb[16]; -} SCSI_PASS_THROUGH, *PSCSI_PASS_THROUGH; - -typedef struct -{ - USHORT Length; - UCHAR ScsiStatus; - UCHAR PathId; - UCHAR TargetId; - UCHAR Lun; - UCHAR CdbLength; - UCHAR SenseInfoLength; - UCHAR DataIn; - ULONG DataTransferLength; - ULONG TimeOutValue; - PVOID DataBuffer; - ULONG SenseInfoOffset; - UCHAR Cdb[16]; -} SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT; - -typedef struct -{ - SCSI_PASS_THROUGH_DIRECT spt; - ULONG Filler; - UCHAR ucSenseBuf[32]; -} SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, *PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER; - -typedef struct -{ - ULONG Length; - UCHAR PortNumber; - UCHAR PathId; - UCHAR TargetId; - UCHAR Lun; -} SCSI_ADDRESS, *PSCSI_ADDRESS; - - -#define METHOD_BUFFERED 0 -#define METHOD_IN_DIRECT 1 -#define METHOD_OUT_DIRECT 2 -#define METHOD_NEITHER 3 - -#define FILE_ANY_ACCESS 0 +#define FILE_ANY_ACCESS 0 #ifndef FILE_READ_ACCESS -#define FILE_READ_ACCESS (0x0001) + #define FILE_READ_ACCESS 1 #endif #ifndef FILE_WRITE_ACCESS -#define FILE_WRITE_ACCESS (0x0002) + #define FILE_WRITE_ACCESS 2 #endif -#define IOCTL_SCSI_BASE 0x00000004 +#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 +#define SCSI_IOCTL_DATA_IN 1 +#define SCSI_IOCTL_DATA_UNSPECIFIED 2 -#define SCSI_IOCTL_DATA_OUT 0 -#define SCSI_IOCTL_DATA_IN 1 -#define SCSI_IOCTL_DATA_UNSPECIFIED 2 - -#define CTL_CODE2( DevType, Function, Method, Access ) ( \ - ((DevType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \ -) - -#define IOCTL_SCSI_PASS_THROUGH CTL_CODE2( IOCTL_SCSI_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS ) -#define IOCTL_SCSI_GET_CAPABILITIES CTL_CODE2( IOCTL_SCSI_BASE, 0x0404, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define CTL_CODE2(DevType, Function, Method, Access) (((DevType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method)) #define IOCTL_SCSI_PASS_THROUGH_DIRECT CTL_CODE2( IOCTL_SCSI_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS ) #define IOCTL_SCSI_GET_ADDRESS CTL_CODE2( IOCTL_SCSI_BASE, 0x0406, METHOD_BUFFERED, FILE_ANY_ACCESS ) - -#define SENSE_LEN 14 -#define SRB_DIR_SCSI 0x00 -#define SRB_POSTING 0x01 +#define SENSE_LEN 14 #define SRB_ENABLE_RESIDUAL_COUNT 0x04 -#define SRB_DIR_IN 0x08 -#define SRB_DIR_OUT 0x10 -#define SRB_EVENT_NOTIFY 0x40 -#define RESIDUAL_COUNT_SUPPORTED 0x02 -#define MAX_SRB_TIMEOUT 1080001u -#define DEFAULT_SRB_TIMEOUT 1080001u +#define SRB_DIR_IN 0x08 +#define SRB_DIR_OUT 0x10 +#define SRB_EVENT_NOTIFY 0x40 +#define SC_HA_INQUIRY 0x00 +#define SC_GET_DEV_TYPE 0x01 +#define SC_EXEC_SCSI_CMD 0x02 +#define SS_PENDING 0x00 +#define SS_COMP 0x01 +#define SS_ERR 0x04 +#define SS_NO_ADAPTERS 0xE8 -#define SC_HA_INQUIRY 0x00 -#define SC_GET_DEV_TYPE 0x01 -#define SC_EXEC_SCSI_CMD 0x02 -#define SC_ABORT_SRB 0x03 -#define SC_RESET_DEV 0x04 -#define SC_SET_HA_PARMS 0x05 -#define SC_GET_DISK_INFO 0x06 -#define SC_RESCAN_SCSI_BUS 0x07 -#define SC_GETSET_TIMEOUTS 0x08 +enum +{ + READTYPE_ANY = 0, + READTYPE_ATAPI1 = 1, + READTYPE_ATAPI2 = 2, + READTYPE_READ6 = 3, + READTYPE_READ10 = 4, + READTYPE_READ_D8 = 5, + READTYPE_READ_D4 = 6, + READTYPE_READ_D4_1 = 7, + READTYPE_READ10_2 = 8 +}; -#define SS_PENDING 0x00 -#define SS_COMP 0x01 -#define SS_ABORTED 0x02 -#define SS_ABORT_FAIL 0x03 -#define SS_ERR 0x04 -#define SS_INVALID_CMD 0x80 -#define SS_INVALID_HA 0x81 -#define SS_NO_DEVICE 0x82 -#define SS_INVALID_SRB 0xE0 -#define SS_OLD_MANAGER 0xE1 -#define SS_BUFFER_ALIGN 0xE1 -#define SS_ILLEGAL_MODE 0xE2 -#define SS_NO_ASPI 0xE3 -#define SS_FAILED_INIT 0xE4 -#define SS_ASPI_IS_BUSY 0xE5 -#define SS_BUFFER_TO_BIG 0xE6 -#define SS_BUFFER_TOO_BIG 0xE6 -#define SS_MISMATCHED_COMPONENTS 0xE7 -#define SS_NO_ADAPTERS 0xE8 -#define SS_INSUFFICIENT_RESOURCES 0xE9 -#define SS_ASPI_IS_SHUTDOWN 0xEA -#define SS_BAD_INSTALL 0xEB +struct SCSI_PASS_THROUGH +{ + USHORT Length; + UCHAR ScsiStatus; + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; + UCHAR CdbLength; + UCHAR SenseInfoLength; + UCHAR DataIn; + ULONG DataTransferLength; + ULONG TimeOutValue; + ULONG DataBufferOffset; + ULONG SenseInfoOffset; + UCHAR Cdb[16]; +}; -#define HASTAT_OK 0x00 -#define HASTAT_SEL_TO 0x11 -#define HASTAT_DO_DU 0x12 -#define HASTAT_BUS_FREE 0x13 -#define HASTAT_PHASE_ERR 0x14 -#define HASTAT_TIMEOUT 0x09 -#define HASTAT_COMMAND_TIMEOUT 0x0B -#define HASTAT_MESSAGE_REJECT 0x0D -#define HASTAT_BUS_RESET 0x0E -#define HASTAT_PARITY_ERROR 0x0F -#define HASTAT_REQUEST_SENSE_FAILED 0x10 +struct SCSI_PASS_THROUGH_DIRECT +{ + USHORT Length; + UCHAR ScsiStatus; + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; + UCHAR CdbLength; + UCHAR SenseInfoLength; + UCHAR DataIn; + ULONG DataTransferLength; + ULONG TimeOutValue; + PVOID DataBuffer; + ULONG SenseInfoOffset; + UCHAR Cdb[16]; +}; + +struct SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER +{ + SCSI_PASS_THROUGH_DIRECT spt; + ULONG Filler; + UCHAR ucSenseBuf[32]; +}; + +struct SCSI_ADDRESS +{ + ULONG Length; + UCHAR PortNumber; + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; +}; -#define PACKED #pragma pack(1) -typedef struct +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]; -} PACKED SRB_HAInquiry, *PSRB_HAInquiry, FAR *LPSRB_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]; +}; - -typedef struct +struct SRB_GDEVBlock { - BYTE SRB_Cmd; - BYTE SRB_Status; - BYTE SRB_HaID; - BYTE SRB_Flags; - DWORD SRB_Hdr_Rsvd; - BYTE SRB_Target; - BYTE SRB_Lun; - BYTE SRB_DeviceType; - BYTE SRB_Rsvd1; - BYTE pad[68]; -} PACKED SRB_GDEVBlock, *PSRB_GDEVBlock, FAR *LPSRB_GDEVBlock; - - -typedef struct -{ - BYTE SRB_Cmd; - BYTE SRB_Status; - BYTE SRB_HaID; - BYTE SRB_Flags; - DWORD SRB_Hdr_Rsvd; - BYTE SRB_Target; - BYTE SRB_Lun; - WORD SRB_Rsvd1; - DWORD SRB_BufLen; - BYTE FAR *SRB_BufPointer; - BYTE SRB_SenseLen; - BYTE SRB_CDBLen; - BYTE SRB_HaStat; - BYTE SRB_TargStat; - VOID FAR *SRB_PostProc; - BYTE SRB_Rsvd2[20]; - BYTE CDBByte[16]; - BYTE SenseArea[SENSE_LEN+2]; -} PACKED SRB_ExecSCSICmd, *PSRB_ExecSCSICmd, FAR *LPSRB_ExecSCSICmd; - - -typedef struct -{ - BYTE SRB_Cmd; - BYTE SRB_Status; - BYTE SRB_HaId; - BYTE SRB_Flags; - DWORD SRB_Hdr_Rsvd; -} PACKED SRB, *PSRB, FAR *LPSRB; - -#pragma pack() - - -//============================================================================== -struct CDDeviceInfo -{ - char vendor[9]; - char productId[17]; - char rev[5]; - char vendorSpec[21]; - - BYTE ha; - BYTE tgt; - BYTE lun; - char scsiDriveLetter; // will be 0 if not using scsi + BYTE SRB_Cmd; + BYTE SRB_Status; + BYTE SRB_HaID; + BYTE SRB_Flags; + DWORD SRB_Hdr_Rsvd; + BYTE SRB_Target; + BYTE SRB_Lun; + BYTE SRB_DeviceType; + BYTE SRB_Rsvd1; + BYTE pad[68]; }; -//============================================================================== -class CDReadBuffer +struct SRB_ExecSCSICmd { -public: - int startFrame; - int numFrames; - int dataStartOffset; - int dataLength; - int bufferSize; - HeapBlock buffer; - int index; - bool wantsIndex; - - //============================================================================== - CDReadBuffer (const int numberOfFrames) - : startFrame (0), - numFrames (0), - dataStartOffset (0), - dataLength (0), - bufferSize (2352 * numberOfFrames), - buffer (bufferSize), - index (0), - wantsIndex (false) - { - } - - bool isZero() const throw() - { - BYTE* p = buffer + dataStartOffset; - - for (int i = dataLength; --i >= 0;) - if (*p++ != 0) - return false; - - return true; - } + BYTE SRB_Cmd; + BYTE SRB_Status; + BYTE SRB_HaID; + BYTE SRB_Flags; + DWORD SRB_Hdr_Rsvd; + BYTE SRB_Target; + BYTE SRB_Lun; + WORD SRB_Rsvd1; + DWORD SRB_BufLen; + BYTE *SRB_BufPointer; + BYTE SRB_SenseLen; + BYTE SRB_CDBLen; + BYTE SRB_HaStat; + BYTE SRB_TargStat; + VOID *SRB_PostProc; + BYTE SRB_Rsvd2[20]; + BYTE CDBByte[16]; + BYTE SenseArea[SENSE_LEN + 2]; }; -class CDDeviceHandle; - -class CDController +struct SRB { -public: - CDController(); - virtual ~CDController(); - - virtual bool read (CDReadBuffer* t) = 0; - virtual void shutDown(); - - bool readAudio (CDReadBuffer* t, CDReadBuffer* overlapBuffer = 0); - int getLastIndex(); - -public: - bool initialised; - - CDDeviceHandle* deviceInfo; - int framesToCheck, framesOverlap; - - void prepare (SRB_ExecSCSICmd& s); - void perform (SRB_ExecSCSICmd& s); - void setPaused (bool paused); + BYTE SRB_Cmd; + BYTE SRB_Status; + BYTE SRB_HaId; + BYTE SRB_Flags; + DWORD SRB_Hdr_Rsvd; }; - -//============================================================================== -#pragma pack(1) - struct TOCTRACK { BYTE rsvd; @@ -594,17 +213,74 @@ struct TOC #pragma pack() -enum +//============================================================================== +struct CDDeviceInfo { - READTYPE_ANY = 0, - READTYPE_ATAPI1 = 1, - READTYPE_ATAPI2 = 2, - READTYPE_READ6 = 3, - READTYPE_READ10 = 4, - READTYPE_READ_D8 = 5, - READTYPE_READ_D4 = 6, - READTYPE_READ_D4_1 = 7, - READTYPE_READ10_2 = 8 + CDDeviceInfo() : ha (0), tgt (0), lun (0), scsiDriveLetter (0) + { + } + + void createDescription (const char* data) + { + description << String (data + 8, 8).trim() // vendor + << ' ' << String (data + 16, 16).trim() // product id + << ' ' << String (data + 32, 4).trim(); // rev + } + + String description; + BYTE ha, tgt, lun; + char scsiDriveLetter; // will be 0 if not using scsi +}; + +//============================================================================== +class CDReadBuffer +{ +public: + CDReadBuffer (const int numberOfFrames) + : startFrame (0), numFrames (0), dataStartOffset (0), + dataLength (0), bufferSize (2352 * numberOfFrames), index (0), + buffer (bufferSize), wantsIndex (false) + { + } + + bool isZero() const throw() + { + for (int i = 0; i < dataLength; ++i) + if (buffer [dataStartOffset + i] != 0) + return false; + + return true; + } + + int startFrame, numFrames, dataStartOffset; + int dataLength, bufferSize, index; + HeapBlock buffer; + bool wantsIndex; +}; + +class CDDeviceHandle; + +//============================================================================== +class CDController +{ +public: + CDController() : initialised (false) {} + virtual ~CDController() {} + + virtual bool read (CDReadBuffer&) = 0; + virtual void shutDown() {} + + bool readAudio (CDReadBuffer& rb, CDReadBuffer* overlapBuffer = 0); + int getLastIndex(); + +public: + CDDeviceHandle* deviceInfo; + int framesToCheck, framesOverlap; + bool initialised; + + void prepare (SRB_ExecSCSICmd& s); + void perform (SRB_ExecSCSICmd& s); + void setPaused (bool paused); }; @@ -612,12 +288,9 @@ enum class CDDeviceHandle { public: - CDDeviceHandle (const CDDeviceInfo* const device) - : scsiHandle (0), - readType (READTYPE_ANY), - controller (0) + CDDeviceHandle (const CDDeviceInfo& device, HANDLE scsiHandle_) + : info (device), scsiHandle (scsiHandle_), readType (READTYPE_ANY) { - memcpy (&info, device, sizeof (info)); } ~CDDeviceHandle() @@ -633,7 +306,7 @@ public: } bool readTOC (TOC* lpToc); - bool readAudio (CDReadBuffer* buffer, CDReadBuffer* overlapBuffer = 0); + bool readAudio (CDReadBuffer& buffer, CDReadBuffer* overlapBuffer = 0); void openDrawer (bool shouldBeOpen); CDDeviceInfo info; @@ -643,47 +316,25 @@ public: private: ScopedPointer controller; - bool testController (const int readType, - CDController* const newController, - CDReadBuffer* const bufferToUse); + bool testController (int readType, CDController* newController, CDReadBuffer& bufferToUse); }; - //============================================================================== -DWORD (*fGetASPI32SupportInfo)(void); -DWORD (*fSendASPI32Command)(LPSRB); - -//============================================================================== -static HINSTANCE winAspiLib = 0; -static bool usingScsi = false; -static bool initialised = false; - - -bool InitialiseCDRipper() +class CDDeviceManager : public Timer, + public DeletedAtShutdown { - if (! initialised) +private: + CDDeviceManager() + : fGetASPI32SupportInfo (0), fSendASPI32Command (0), userCount (0), + usingScsi (SystemStats::getOperatingSystemType() >= SystemStats::Win2000) { - initialised = true; - - OSVERSIONINFO info; - info.dwOSVersionInfoSize = sizeof (info); - GetVersionEx (&info); - - usingScsi = (info.dwPlatformId == VER_PLATFORM_WIN32_NT) && (info.dwMajorVersion > 4); - if (! usingScsi) { - fGetASPI32SupportInfo = 0; - fSendASPI32Command = 0; - winAspiLib = LoadLibrary (_T("WNASPI32.DLL")); - - if (winAspiLib != 0) + // xxx can the winaspi stuff be ditched? Seems like it's only needed in win98.. + if (winAspiLib.load ("WNASPI32.DLL")) { - fGetASPI32SupportInfo = (DWORD(*)(void)) GetProcAddress (winAspiLib, "GetASPI32SupportInfo"); - fSendASPI32Command = (DWORD(*)(LPSRB)) GetProcAddress (winAspiLib, "SendASPI32Command"); - - if (fGetASPI32SupportInfo == 0 || fSendASPI32Command == 0) - return false; + fGetASPI32SupportInfo = (DWORD (*) (void)) winAspiLib.findProcAddress ("GetASPI32SupportInfo"); + fSendASPI32Command = (DWORD (*) (SRB*)) winAspiLib.findProcAddress ("SendASPI32Command"); } else { @@ -692,98 +343,305 @@ bool InitialiseCDRipper() } } - return true; -} - -void DeinitialiseCDRipper() -{ - if (winAspiLib != 0) +public: + static CDDeviceManager* getInstance() { - fGetASPI32SupportInfo = 0; - fSendASPI32Command = 0; - FreeLibrary (winAspiLib); - winAspiLib = 0; - } + static CDDeviceManager* manager = 0; - initialised = false; -} - -//============================================================================== -HANDLE CreateSCSIDeviceHandle (char driveLetter) -{ - TCHAR devicePath[] = { '\\', '\\', '.', '\\', driveLetter, ':', 0, 0 }; - - OSVERSIONINFO info; - info.dwOSVersionInfoSize = sizeof (info); - GetVersionEx (&info); - - DWORD flags = GENERIC_READ; - - if ((info.dwPlatformId == VER_PLATFORM_WIN32_NT) && (info.dwMajorVersion > 4)) - 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) - { - flags ^= GENERIC_WRITE; - h = CreateFile (devicePath, flags, FILE_SHARE_WRITE | FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); - } - - return h; -} - -DWORD performScsiPassThroughCommand (const LPSRB_ExecSCSICmd 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); - - memcpy (s.spt.Cdb, srb->CDBByte, srb->SRB_CDBLen); - - 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 (manager == 0) { - if (error != ERROR_INVALID_HANDLE) - CloseHandle (deviceHandle); + ScopedPointer newOne (new CDDeviceManager()); + if (newOne->ok()) + manager = newOne.release(); + } - deviceHandle = CreateSCSIDeviceHandle (driveLetter); + return manager; + } - return performScsiPassThroughCommand (srb, driveLetter, deviceHandle, false); + void retain() + { + ++userCount; + } + + void release() + { + --userCount; + startTimer (4000); + } + + void findCDDevices (Array& list) + { + if (usingScsi) + { + for (char driveLetter = 'b'; driveLetter <= 'z'; ++driveLetter) + { + TCHAR drivePath[] = { driveLetter, ':', '\\', 0, 0 }; + + if (GetDriveType (drivePath) == DRIVE_CDROM) + { + HANDLE h = createSCSIDeviceHandle (driveLetter); + + 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 + { + const DWORD d = fGetASPI32SupportInfo(); + BYTE status = HIBYTE (LOWORD (d)); + + if (status != SS_COMP || status == SS_NO_ADAPTERS) + return; + + const int numAdapters = LOBYTE (LOWORD (d)); + + for (BYTE ha = 0; ha < numAdapters; ++ha) + { + SRB_HAInquiry s; + zerostruct (s); + s.SRB_Cmd = SC_HA_INQUIRY; + s.SRB_HaID = ha; + + fSendASPI32Command ((SRB*) &s); + + if (s.SRB_Status == SS_COMP) + { + int maxItems = (int) s.HA_Unique[3]; + if (maxItems == 0) + maxItems = 8; + + for (BYTE tgt = 0; tgt < maxItems; ++tgt) + { + 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); + } + } + } + } + } } } - return srb->SRB_Status; -} + 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); + } + + 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); + + if (status == SS_PENDING) + WaitForSingleObject (event, 4000); + + CloseHandle (event); + } + + void timerCallback() + { + stopTimer(); + + if (userCount == 0) + delete this; + } + +private: + DynamicLibraryLoader winAspiLib; + DWORD (*fGetASPI32SupportInfo) (void); + DWORD (*fSendASPI32Command) (SRB*); + int userCount; + bool usingScsi; + + bool ok() const { return usingScsi || (fGetASPI32SupportInfo != 0 && fSendASPI32Command != 0); } + + void getAspiDeviceInfo (CDDeviceInfo& dev) + { + 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); + } + + HANDLE createSCSIDeviceHandle (char driveLetter) + { + TCHAR devicePath[] = { '\\', '\\', '.', '\\', driveLetter, ':', 0, 0 }; + + DWORD flags = GENERIC_READ; + + 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) + { + 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); + + memcpy (s.spt.Cdb, srb->CDBByte, srb->SRB_CDBLen); + + 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 srb->SRB_Status; + } + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CDDeviceManager); +}; //============================================================================== @@ -793,43 +651,40 @@ class ControllerType1 : public CDController { public: ControllerType1() {} - ~ControllerType1() {} - bool read (CDReadBuffer* rb) + bool read (CDReadBuffer& rb) { - if (rb->numFrames * 2352 > rb->bufferSize) + if (rb.numFrames * 2352 > rb.bufferSize) return false; SRB_ExecSCSICmd s; prepare (s); s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; - s.SRB_BufLen = rb->bufferSize; - s.SRB_BufPointer = rb->buffer; + s.SRB_BufLen = rb.bufferSize; + s.SRB_BufPointer = rb.buffer; s.SRB_CDBLen = 12; s.CDBByte[0] = 0xBE; - s.CDBByte[3] = (BYTE)((rb->startFrame >> 16) & 0xFF); - s.CDBByte[4] = (BYTE)((rb->startFrame >> 8) & 0xFF); - s.CDBByte[5] = (BYTE)(rb->startFrame & 0xFF); - s.CDBByte[8] = (BYTE)(rb->numFrames & 0xFF); - s.CDBByte[9] = (BYTE)((deviceInfo->readType == READTYPE_ATAPI1) ? 0x10 : 0xF0); + s.CDBByte[3] = (BYTE) ((rb.startFrame >> 16) & 0xFF); + s.CDBByte[4] = (BYTE) ((rb.startFrame >> 8) & 0xFF); + s.CDBByte[5] = (BYTE) (rb.startFrame & 0xFF); + s.CDBByte[8] = (BYTE) (rb.numFrames & 0xFF); + s.CDBByte[9] = (BYTE) (deviceInfo->readType == READTYPE_ATAPI1 ? 0x10 : 0xF0); perform (s); if (s.SRB_Status != SS_COMP) return false; - rb->dataLength = rb->numFrames * 2352; - rb->dataStartOffset = 0; + rb.dataLength = rb.numFrames * 2352; + rb.dataStartOffset = 0; return true; } }; - //============================================================================== class ControllerType2 : public CDController { public: ControllerType2() {} - ~ControllerType2() {} void shutDown() { @@ -892,54 +747,51 @@ public: return s.SRB_Status == SS_COMP; } - bool read (CDReadBuffer* rb) + bool read (CDReadBuffer& rb) { - if (rb->numFrames * 2352 > rb->bufferSize) + if (rb.numFrames * 2352 > rb.bufferSize) return false; - if (!initialised) + if (! initialised) { initialised = init(); - if (!initialised) + if (! initialised) return false; } SRB_ExecSCSICmd s; prepare (s); s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; - s.SRB_BufLen = rb->bufferSize; - s.SRB_BufPointer = rb->buffer; + s.SRB_BufLen = rb.bufferSize; + s.SRB_BufPointer = rb.buffer; s.SRB_CDBLen = 10; s.CDBByte[0] = 0x28; - s.CDBByte[1] = (BYTE)(deviceInfo->info.lun << 5); - s.CDBByte[3] = (BYTE)((rb->startFrame >> 16) & 0xFF); - s.CDBByte[4] = (BYTE)((rb->startFrame >> 8) & 0xFF); - s.CDBByte[5] = (BYTE)(rb->startFrame & 0xFF); - s.CDBByte[8] = (BYTE)(rb->numFrames & 0xFF); + s.CDBByte[1] = (BYTE) (deviceInfo->info.lun << 5); + s.CDBByte[3] = (BYTE) ((rb.startFrame >> 16) & 0xFF); + s.CDBByte[4] = (BYTE) ((rb.startFrame >> 8) & 0xFF); + s.CDBByte[5] = (BYTE) (rb.startFrame & 0xFF); + s.CDBByte[8] = (BYTE) (rb.numFrames & 0xFF); perform (s); if (s.SRB_Status != SS_COMP) return false; - rb->dataLength = rb->numFrames * 2352; - rb->dataStartOffset = 0; - + rb.dataLength = rb.numFrames * 2352; + rb.dataStartOffset = 0; return true; } }; - //============================================================================== class ControllerType3 : public CDController { public: ControllerType3() {} - ~ControllerType3() {} - bool read (CDReadBuffer* rb) + bool read (CDReadBuffer& rb) { - if (rb->numFrames * 2352 > rb->bufferSize) + if (rb.numFrames * 2352 > rb.bufferSize) return false; if (!initialised) @@ -951,33 +803,30 @@ public: SRB_ExecSCSICmd s; prepare (s); s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; - s.SRB_BufLen = rb->numFrames * 2352; - s.SRB_BufPointer = rb->buffer; + s.SRB_BufLen = rb.numFrames * 2352; + s.SRB_BufPointer = rb.buffer; s.SRB_CDBLen = 12; s.CDBByte[0] = 0xD8; - s.CDBByte[3] = (BYTE)((rb->startFrame >> 16) & 0xFF); - s.CDBByte[4] = (BYTE)((rb->startFrame >> 8) & 0xFF); - s.CDBByte[5] = (BYTE)(rb->startFrame & 0xFF); - s.CDBByte[9] = (BYTE)(rb->numFrames & 0xFF); + s.CDBByte[3] = (BYTE) ((rb.startFrame >> 16) & 0xFF); + s.CDBByte[4] = (BYTE) ((rb.startFrame >> 8) & 0xFF); + s.CDBByte[5] = (BYTE) (rb.startFrame & 0xFF); + s.CDBByte[9] = (BYTE) (rb.numFrames & 0xFF); perform (s); if (s.SRB_Status != SS_COMP) return false; - rb->dataLength = rb->numFrames * 2352; - rb->dataStartOffset = 0; - + rb.dataLength = rb.numFrames * 2352; + rb.dataStartOffset = 0; return true; } }; - //============================================================================== class ControllerType4 : public CDController { public: ControllerType4() {} - ~ControllerType4() {} bool selectD4Mode() { @@ -997,12 +846,12 @@ public: return s.SRB_Status == SS_COMP; } - bool read (CDReadBuffer* rb) + bool read (CDReadBuffer& rb) { - if (rb->numFrames * 2352 > rb->bufferSize) + if (rb.numFrames * 2352 > rb.bufferSize) return false; - if (!initialised) + if (! initialised) { setPaused (true); @@ -1015,40 +864,30 @@ public: SRB_ExecSCSICmd s; prepare (s); s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; - s.SRB_BufLen = rb->bufferSize; - s.SRB_BufPointer = rb->buffer; + s.SRB_BufLen = rb.bufferSize; + s.SRB_BufPointer = rb.buffer; s.SRB_CDBLen = 10; s.CDBByte[0] = 0xD4; - s.CDBByte[3] = (BYTE)((rb->startFrame >> 16) & 0xFF); - s.CDBByte[4] = (BYTE)((rb->startFrame >> 8) & 0xFF); - s.CDBByte[5] = (BYTE)(rb->startFrame & 0xFF); - s.CDBByte[8] = (BYTE)(rb->numFrames & 0xFF); + s.CDBByte[3] = (BYTE) ((rb.startFrame >> 16) & 0xFF); + s.CDBByte[4] = (BYTE) ((rb.startFrame >> 8) & 0xFF); + s.CDBByte[5] = (BYTE) (rb.startFrame & 0xFF); + s.CDBByte[8] = (BYTE) (rb.numFrames & 0xFF); perform (s); if (s.SRB_Status != SS_COMP) return false; - rb->dataLength = rb->numFrames * 2352; - rb->dataStartOffset = 0; - + rb.dataLength = rb.numFrames * 2352; + rb.dataStartOffset = 0; return true; } }; //============================================================================== -CDController::CDController() : initialised (false) -{ -} - -CDController::~CDController() -{ -} - void CDController::prepare (SRB_ExecSCSICmd& s) { zerostruct (s); - s.SRB_Cmd = SC_EXEC_SCSI_CMD; s.SRB_HaID = deviceInfo->info.ha; s.SRB_Target = deviceInfo->info.tgt; @@ -1058,20 +897,9 @@ void CDController::prepare (SRB_ExecSCSICmd& s) void CDController::perform (SRB_ExecSCSICmd& s) { - HANDLE event = CreateEvent (0, TRUE, FALSE, 0); - s.SRB_PostProc = event; + s.SRB_PostProc = CreateEvent (0, TRUE, FALSE, 0); - ResetEvent (event); - - DWORD status = (usingScsi) ? performScsiPassThroughCommand ((LPSRB_ExecSCSICmd)&s, - deviceInfo->info.scsiDriveLetter, - deviceInfo->scsiHandle) - : fSendASPI32Command ((LPSRB)&s); - - if (status == SS_PENDING) - WaitForSingleObject (event, 4000); - - CloseHandle (event); + CDDeviceManager::getInstance()->perform (s.SRB_PostProc, s, deviceInfo->info.scsiDriveLetter, deviceInfo->scsiHandle); } void CDController::setPaused (bool paused) @@ -1085,11 +913,7 @@ void CDController::setPaused (bool paused) perform (s); } -void CDController::shutDown() -{ -} - -bool CDController::readAudio (CDReadBuffer* rb, CDReadBuffer* overlapBuffer) +bool CDController::readAudio (CDReadBuffer& rb, CDReadBuffer* overlapBuffer) { if (overlapBuffer != 0) { @@ -1101,15 +925,15 @@ bool CDController::readAudio (CDReadBuffer* rb, CDReadBuffer* overlapBuffer) && overlapBuffer->numFrames > 0 && overlapBuffer->dataLength > 0) { - const int numFrames = rb->numFrames; + const int numFrames = rb.numFrames; - if (overlapBuffer->startFrame == (rb->startFrame - framesToCheck)) + if (overlapBuffer->startFrame == (rb.startFrame - framesToCheck)) { - rb->startFrame -= framesOverlap; + rb.startFrame -= framesOverlap; if (framesToCheck < framesOverlap - && numFrames + framesOverlap <= rb->bufferSize / 2352) - rb->numFrames += framesOverlap; + && numFrames + framesOverlap <= rb.bufferSize / 2352) + rb.numFrames += framesOverlap; } else { @@ -1125,7 +949,7 @@ bool CDController::readAudio (CDReadBuffer* rb, CDReadBuffer* overlapBuffer) if (doJitter) { const int checkLen = framesToCheck * 2352; - const int maxToCheck = rb->dataLength - checkLen; + const int maxToCheck = rb.dataLength - checkLen; if (overlapBuffer->dataLength == 0 || overlapBuffer->isZero()) return true; @@ -1135,31 +959,31 @@ bool CDController::readAudio (CDReadBuffer* rb, CDReadBuffer* overlapBuffer) for (int i = 0; i < maxToCheck; ++i) { - if (memcmp (p, rb->buffer + i, checkLen) == 0) + if (memcmp (p, rb.buffer + i, checkLen) == 0) { i += checkLen; - rb->dataStartOffset = i; - rb->dataLength -= i; - rb->startFrame = overlapBuffer->startFrame + framesToCheck; + rb.dataStartOffset = i; + rb.dataLength -= i; + rb.startFrame = overlapBuffer->startFrame + framesToCheck; found = true; break; } } - rb->numFrames = rb->dataLength / 2352; - rb->dataLength = 2352 * rb->numFrames; + rb.numFrames = rb.dataLength / 2352; + rb.dataLength = 2352 * rb.numFrames; - if (!found) + if (! found) return false; } if (canDoJitter) { memcpy (overlapBuffer->buffer, - rb->buffer + rb->dataStartOffset + 2352 * (rb->numFrames - framesToCheck), + rb.buffer + rb.dataStartOffset + 2352 * (rb.numFrames - framesToCheck), 2352 * framesToCheck); - overlapBuffer->startFrame = rb->startFrame + rb->numFrames - framesToCheck; + overlapBuffer->startFrame = rb.startFrame + rb.numFrames - framesToCheck; overlapBuffer->numFrames = framesToCheck; overlapBuffer->dataLength = 2352 * framesToCheck; overlapBuffer->dataStartOffset = 0; @@ -1173,10 +997,8 @@ bool CDController::readAudio (CDReadBuffer* rb, CDReadBuffer* overlapBuffer) return true; } - else - { - return read (rb); - } + + return read (rb); } int CDController::getLastIndex() @@ -1187,30 +1009,24 @@ int CDController::getLastIndex() prepare (s); s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; s.SRB_BufLen = sizeof (qdata); - s.SRB_BufPointer = (BYTE*)qdata; + s.SRB_BufPointer = (BYTE*) qdata; s.SRB_CDBLen = 12; s.CDBByte[0] = 0x42; - s.CDBByte[1] = (BYTE)(deviceInfo->info.lun << 5); + s.CDBByte[1] = (BYTE) (deviceInfo->info.lun << 5); s.CDBByte[2] = 64; s.CDBByte[3] = 1; // get current position s.CDBByte[7] = 0; - s.CDBByte[8] = (BYTE)sizeof (qdata); + s.CDBByte[8] = (BYTE) sizeof (qdata); perform (s); - if (s.SRB_Status == SS_COMP) - return qdata[7]; - - return 0; + return s.SRB_Status == SS_COMP ? qdata[7] : 0; } //============================================================================== bool CDDeviceHandle::readTOC (TOC* lpToc) { - HANDLE event = CreateEvent (0, TRUE, FALSE, 0); - SRB_ExecSCSICmd s; zerostruct (s); - s.SRB_Cmd = SC_EXEC_SCSI_CMD; s.SRB_HaID = info.ha; s.SRB_Target = info.tgt; @@ -1220,25 +1036,17 @@ bool CDDeviceHandle::readTOC (TOC* lpToc) s.SRB_BufPointer = (BYTE*)lpToc; s.SRB_SenseLen = 0x0E; s.SRB_CDBLen = 0x0A; - s.SRB_PostProc = event; + s.SRB_PostProc = CreateEvent (0, TRUE, FALSE, 0); s.CDBByte[0] = 0x43; s.CDBByte[1] = 0x00; s.CDBByte[7] = 0x03; s.CDBByte[8] = 0x24; - ResetEvent (event); - DWORD status = (usingScsi) ? performScsiPassThroughCommand ((LPSRB_ExecSCSICmd)&s, info.scsiDriveLetter, scsiHandle) - : fSendASPI32Command ((LPSRB)&s); - - if (status == SS_PENDING) - WaitForSingleObject (event, 4000); - - CloseHandle (event); + CDDeviceManager::getInstance()->perform (s.SRB_PostProc, s, info.scsiDriveLetter, scsiHandle); return (s.SRB_Status == SS_COMP); } -bool CDDeviceHandle::readAudio (CDReadBuffer* const buffer, - CDReadBuffer* const overlapBuffer) +bool CDDeviceHandle::readAudio (CDReadBuffer& buffer, CDReadBuffer* overlapBuffer) { if (controller == 0) { @@ -1251,13 +1059,12 @@ bool CDDeviceHandle::readAudio (CDReadBuffer* const buffer, || testController (READTYPE_READ_D4_1, new ControllerType4(), buffer); } - buffer->index = 0; + buffer.index = 0; - if ((controller != 0) - && controller->readAudio (buffer, overlapBuffer)) + if (controller != 0 && controller->readAudio (buffer, overlapBuffer)) { - if (buffer->wantsIndex) - buffer->index = controller->getLastIndex(); + if (buffer.wantsIndex) + buffer.index = controller->getLastIndex(); return true; } @@ -1284,7 +1091,6 @@ void CDDeviceHandle::openDrawer (bool shouldBeOpen) SRB_ExecSCSICmd s; zerostruct (s); - s.SRB_Cmd = SC_EXEC_SCSI_CMD; s.SRB_HaID = info.ha; s.SRB_Target = info.tgt; @@ -1295,45 +1101,32 @@ void CDDeviceHandle::openDrawer (bool shouldBeOpen) s.SRB_BufPointer = 0; s.SRB_CDBLen = 12; s.CDBByte[0] = 0x1b; - s.CDBByte[1] = (BYTE)(info.lun << 5); - s.CDBByte[4] = (BYTE)((shouldBeOpen) ? 2 : 3); + s.CDBByte[1] = (BYTE) (info.lun << 5); + s.CDBByte[4] = (BYTE) (shouldBeOpen ? 2 : 3); + s.SRB_PostProc = CreateEvent (0, TRUE, FALSE, 0); - HANDLE event = CreateEvent (0, TRUE, FALSE, 0); - s.SRB_PostProc = event; - - ResetEvent (event); - - DWORD status = (usingScsi) ? performScsiPassThroughCommand ((LPSRB_ExecSCSICmd)&s, info.scsiDriveLetter, scsiHandle) - : fSendASPI32Command ((LPSRB)&s); - - if (status == SS_PENDING) - WaitForSingleObject (event, 4000); - - CloseHandle (event); + CDDeviceManager::getInstance()->perform (s.SRB_PostProc, s, info.scsiDriveLetter, scsiHandle); } -bool CDDeviceHandle::testController (const int type, - CDController* const newController, - CDReadBuffer* const rb) +bool CDDeviceHandle::testController (const int type, CDController* const newController, CDReadBuffer& rb) { controller = newController; - readType = (BYTE)type; + readType = (BYTE) type; controller->deviceInfo = this; controller->framesToCheck = 1; controller->framesOverlap = 3; bool passed = false; - - memset (rb->buffer, 0xcd, rb->bufferSize); + memset (rb.buffer, 0xcd, rb.bufferSize); if (controller->read (rb)) { passed = true; - int* p = (int*) (rb->buffer + rb->dataStartOffset); + int* p = (int*) (rb.buffer + rb.dataStartOffset); int wrong = 0; - for (int i = rb->dataLength / 4; --i >= 0;) + for (int i = rb.dataLength / 4; --i >= 0;) { if (*p++ == (int) 0xcdcdcdcd) { @@ -1360,272 +1153,30 @@ bool CDDeviceHandle::testController (const int type, } -//============================================================================== -void GetAspiDeviceInfo (CDDeviceInfo* dev, BYTE ha, BYTE tgt, BYTE lun) -{ - HANDLE event = CreateEvent (0, TRUE, FALSE, 0); - - const int bufSize = 128; - BYTE buffer[bufSize]; - zeromem (buffer, bufSize); - - SRB_ExecSCSICmd s; - zerostruct (s); - - s.SRB_Cmd = SC_EXEC_SCSI_CMD; - s.SRB_HaID = ha; - s.SRB_Target = tgt; - s.SRB_Lun = lun; - s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; - s.SRB_BufLen = bufSize; - s.SRB_BufPointer = 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 ((LPSRB)&s) == SS_PENDING) - WaitForSingleObject (event, 4000); - - CloseHandle (event); - - if (s.SRB_Status == SS_COMP) - { - memcpy (dev->vendor, &buffer[8], 8); - memcpy (dev->productId, &buffer[16], 16); - memcpy (dev->rev, &buffer[32], 4); - memcpy (dev->vendorSpec, &buffer[36], 20); - } -} - -int FindCDDevices (CDDeviceInfo* const list, int maxItems) -{ - int count = 0; - - if (usingScsi) - { - for (char driveLetter = 'b'; driveLetter <= 'z'; ++driveLetter) - { - TCHAR drivePath[8]; - drivePath[0] = driveLetter; - drivePath[1] = ':'; - drivePath[2] = '\\'; - drivePath[3] = 0; - - if (GetDriveType (drivePath) == DRIVE_CDROM) - { - HANDLE h = CreateSCSIDeviceHandle (driveLetter); - - if (h != INVALID_HANDLE_VALUE) - { - BYTE buffer[100], passThroughStruct[1024]; - zeromem (buffer, sizeof (buffer)); - zeromem (passThroughStruct, sizeof (passThroughStruct)); - - PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER p = (PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER)passThroughStruct; - - 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 = 100; - 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 (SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER), - p, sizeof (SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER), - &bytesReturned, 0) != 0) - { - zeromem (&list[count], sizeof (CDDeviceInfo)); - - list[count].scsiDriveLetter = driveLetter; - - memcpy (list[count].vendor, &buffer[8], 8); - memcpy (list[count].productId, &buffer[16], 16); - memcpy (list[count].rev, &buffer[32], 4); - memcpy (list[count].vendorSpec, &buffer[36], 20); - - zeromem (passThroughStruct, sizeof (passThroughStruct)); - PSCSI_ADDRESS scsiAddr = (PSCSI_ADDRESS)passThroughStruct; - - scsiAddr->Length = sizeof (SCSI_ADDRESS); - - if (DeviceIoControl (h, IOCTL_SCSI_GET_ADDRESS, - 0, 0, scsiAddr, sizeof (SCSI_ADDRESS), - &bytesReturned, 0) != 0) - { - list[count].ha = scsiAddr->PortNumber; - list[count].tgt = scsiAddr->TargetId; - list[count].lun = scsiAddr->Lun; - ++count; - } - } - - CloseHandle (h); - } - } - } - } - else - { - const DWORD d = fGetASPI32SupportInfo(); - BYTE status = HIBYTE (LOWORD (d)); - - if (status != SS_COMP || status == SS_NO_ADAPTERS) - return 0; - - const int numAdapters = LOBYTE (LOWORD (d)); - - for (BYTE ha = 0; ha < numAdapters; ++ha) - { - SRB_HAInquiry s; - zerostruct (s); - - s.SRB_Cmd = SC_HA_INQUIRY; - s.SRB_HaID = ha; - fSendASPI32Command ((LPSRB)&s); - - if (s.SRB_Status == SS_COMP) - { - maxItems = (int)s.HA_Unique[3]; - - if (maxItems == 0) - maxItems = 8; - - for (BYTE tgt = 0; tgt < maxItems; ++tgt) - { - 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 ((LPSRB) &sb); - - if (sb.SRB_Status == SS_COMP - && sb.SRB_DeviceType == DTYPE_CROM) - { - zeromem (&list[count], sizeof (CDDeviceInfo)); - - list[count].ha = ha; - list[count].tgt = tgt; - list[count].lun = lun; - - GetAspiDeviceInfo (&(list[count]), ha, tgt, lun); - - ++count; - } - } - } - } - } - } - - return count; -} - - -//============================================================================== -static int ripperUsers = 0; -static bool initialisedOk = false; - -class DeinitialiseTimer : private Timer, - private DeletedAtShutdown -{ -public: - DeinitialiseTimer() - { - startTimer (4000); - } - - ~DeinitialiseTimer() - { - if (--ripperUsers == 0) - DeinitialiseCDRipper(); - } - - void timerCallback() - { - delete this; - } - -private: - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DeinitialiseTimer); -}; - -static void incUserCount() -{ - if (ripperUsers++ == 0) - initialisedOk = InitialiseCDRipper(); -} - -static void decUserCount() -{ - new DeinitialiseTimer(); -} - //============================================================================== struct CDDeviceWrapper { + CDDeviceWrapper (CDDeviceHandle* handle) + : cdH (handle), overlapBuffer (3), jitter (false) + { + // xxx jitter never seemed to actually be enabled (??) + } + ScopedPointer cdH; - ScopedPointer overlapBuffer; + CDReadBuffer overlapBuffer; bool jitter; }; //============================================================================== -int getAddressOf (const TOCTRACK* const t) +int getAddressOfTrack (const TOCTRACK& t) throw() { - return (((DWORD)t->addr[0]) << 24) + (((DWORD)t->addr[1]) << 16) + - (((DWORD)t->addr[2]) << 8) + ((DWORD)t->addr[3]); + return (((DWORD) t.addr[0]) << 24) + (((DWORD) t.addr[1]) << 16) + + (((DWORD) t.addr[2]) << 8) + ((DWORD) t.addr[3]); } -static const int samplesPerFrame = 44100 / 75; -static const int bytesPerFrame = samplesPerFrame * 4; - -CDDeviceHandle* openHandle (const CDDeviceInfo* const 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) - { - CDDeviceHandle* cdh = new CDDeviceHandle (device); - cdh->scsiHandle = h; - return cdh; - } - } - else - { - if (fSendASPI32Command ((LPSRB)&s) == SS_COMP - && s.SRB_DeviceType == DTYPE_CROM) - { - return new CDDeviceHandle (device); - } - } - - return 0; -} +const int samplesPerFrame = 44100 / 75; +const int bytesPerFrame = samplesPerFrame * 4; +const int framesPerIndexRead = 4; } @@ -1634,26 +1185,23 @@ const StringArray AudioCDReader::getAvailableCDNames() { using namespace CDReaderHelpers; StringArray results; - incUserCount(); - if (initialisedOk) + CDDeviceManager* manager = CDDeviceManager::getInstance(); + + if (manager != 0) { - CDDeviceInfo list[8]; - const int num = FindCDDevices (list, 8); + manager->retain(); + Array list; + manager->findCDDevices (list); + manager->release(); - decUserCount(); - - for (int i = 0; i < num; ++i) + for (int i = 0; i < list.size(); ++i) { String s; - if (list[i].scsiDriveLetter > 0) s << String::charToString (list[i].scsiDriveLetter).toUpperCase() << ": "; - s << String (list[i].vendor).trim() - << ' ' << String (list[i].productId).trim() - << ' ' << String (list[i].rev).trim(); - + s << list[i].description; results.add (s); } } @@ -1664,29 +1212,25 @@ const StringArray AudioCDReader::getAvailableCDNames() AudioCDReader* AudioCDReader::createReaderForCD (const int deviceIndex) { using namespace CDReaderHelpers; - incUserCount(); + CDDeviceManager* manager = CDDeviceManager::getInstance(); - if (initialisedOk) + if (manager != 0) { - CDDeviceInfo list[8]; - const int num = FindCDDevices (list, 8); + manager->retain(); + Array list; + manager->findCDDevices (list); - if (isPositiveAndBelow (deviceIndex, num)) + if (isPositiveAndBelow (deviceIndex, list.size())) { - CDDeviceHandle* const handle = openHandle (&(list[deviceIndex])); + CDDeviceHandle* const handle = manager->openHandle (list [deviceIndex]); if (handle != 0) - { - CDDeviceWrapper* const d = new CDDeviceWrapper(); - d->cdH = handle; - d->overlapBuffer = new CDReadBuffer(3); - - return new AudioCDReader (d); - } + return new AudioCDReader (new CDDeviceWrapper (handle)); } + + manager->release(); } - decUserCount(); return 0; } @@ -1714,17 +1258,17 @@ AudioCDReader::AudioCDReader (void* handle_) AudioCDReader::~AudioCDReader() { using namespace CDReaderHelpers; - CDDeviceWrapper* const device = (CDDeviceWrapper*) handle; + CDDeviceWrapper* const device = static_cast (handle); delete device; - decUserCount(); + CDDeviceManager::getInstance()->release(); } bool AudioCDReader::readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, int64 startSampleInFile, int numSamples) { using namespace CDReaderHelpers; - CDDeviceWrapper* const device = (CDDeviceWrapper*) handle; + CDDeviceWrapper* const device = static_cast (handle); bool ok = true; @@ -1762,9 +1306,9 @@ bool AudioCDReader::readSamples (int** destSamples, int numDestChannels, int sta if (firstFrameInBuffer + framesInBuffer != frameNeeded) { - device->overlapBuffer->dataLength = 0; - device->overlapBuffer->startFrame = 0; - device->overlapBuffer->numFrames = 0; + device->overlapBuffer.dataLength = 0; + device->overlapBuffer.startFrame = 0; + device->overlapBuffer.numFrames = 0; device->jitter = false; } @@ -1780,18 +1324,15 @@ 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->cdH->readAudio (readBuffer, device->jitter ? &device->overlapBuffer : 0)) break; else - device->overlapBuffer->dataLength = 0; + device->overlapBuffer.dataLength = 0; } if (i >= 0) { - memcpy ((char*) buffer.getData(), - readBuffer.buffer + readBuffer.dataStartOffset, - readBuffer.dataLength); - + buffer.copyFrom (readBuffer.buffer + readBuffer.dataStartOffset, 0, readBuffer.dataLength); samplesInBuffer = readBuffer.dataLength >> 2; lastIndex = readBuffer.index; } @@ -1825,7 +1366,7 @@ bool AudioCDReader::isCDStillPresent() const TOC toc; zerostruct (toc); - return ((CDDeviceWrapper*) handle)->cdH->readTOC (&toc); + return static_cast (handle)->cdH->readTOC (&toc); } void AudioCDReader::refreshTrackLengths() @@ -1837,13 +1378,13 @@ void AudioCDReader::refreshTrackLengths() TOC toc; zerostruct (toc); - if (((CDDeviceWrapper*)handle)->cdH->readTOC (&toc)) + if (static_cast (handle)->cdH->readTOC (&toc)) { int numTracks = 1 + toc.lastTrack - toc.firstTrack; for (int i = 0; i <= numTracks; ++i) { - trackStartSamples.add (samplesPerFrame * getAddressOf (&toc.tracks [i])); + trackStartSamples.add (samplesPerFrame * getAddressOfTrack (toc.tracks [i])); audioTracks [i] = ((toc.tracks[i].ADR & 4) == 0); } } @@ -1866,18 +1407,16 @@ int AudioCDReader::getLastIndex() const return lastIndex; } -const int framesPerIndexRead = 4; - int AudioCDReader::getIndexAt (int samplePos) { using namespace CDReaderHelpers; - CDDeviceWrapper* const device = (CDDeviceWrapper*) handle; + CDDeviceWrapper* const device = static_cast (handle); const int frameNeeded = samplePos / samplesPerFrame; - device->overlapBuffer->dataLength = 0; - device->overlapBuffer->startFrame = 0; - device->overlapBuffer->numFrames = 0; + device->overlapBuffer.dataLength = 0; + device->overlapBuffer.startFrame = 0; + device->overlapBuffer.numFrames = 0; device->jitter = false; firstFrameInBuffer = 0; @@ -1892,7 +1431,7 @@ int AudioCDReader::getIndexAt (int samplePos) readBuffer.startFrame = frameNeeded; readBuffer.numFrames = framesPerIndexRead; - if (device->cdH->readAudio (&readBuffer, (false) ? device->overlapBuffer : 0)) + if (device->cdH->readAudio (readBuffer, 0)) break; } @@ -1952,7 +1491,7 @@ const Array AudioCDReader::findIndexesInTrack (const int trackNumber) if (needToScan) { - CDDeviceWrapper* const device = (CDDeviceWrapper*) handle; + CDDeviceWrapper* const device = static_cast (handle); int pos = trackStart; int last = -1; @@ -1961,9 +1500,9 @@ const Array AudioCDReader::findIndexesInTrack (const int trackNumber) { const int frameNeeded = pos / samplesPerFrame; - device->overlapBuffer->dataLength = 0; - device->overlapBuffer->startFrame = 0; - device->overlapBuffer->numFrames = 0; + device->overlapBuffer.dataLength = 0; + device->overlapBuffer.startFrame = 0; + device->overlapBuffer.numFrames = 0; device->jitter = false; firstFrameInBuffer = 0; @@ -1977,7 +1516,7 @@ const Array AudioCDReader::findIndexesInTrack (const int trackNumber) readBuffer.startFrame = frameNeeded; readBuffer.numFrames = framesPerIndexRead; - if (device->cdH->readAudio (&readBuffer, (false) ? device->overlapBuffer : 0)) + if (device->cdH->readAudio (readBuffer, 0)) break; } @@ -2002,7 +1541,7 @@ const Array AudioCDReader::findIndexesInTrack (const int trackNumber) void AudioCDReader::ejectDisk() { using namespace CDReaderHelpers; - ((CDDeviceWrapper*) handle)->cdH->openDrawer (true); + static_cast (handle)->cdH->openDrawer (true); } #endif diff --git a/src/native/windows/juce_win32_DynamicLibraryLoader.cpp b/src/native/windows/juce_win32_DynamicLibraryLoader.cpp index 965f337dbc..0a35a6d66b 100644 --- a/src/native/windows/juce_win32_DynamicLibraryLoader.cpp +++ b/src/native/windows/juce_win32_DynamicLibraryLoader.cpp @@ -29,16 +29,23 @@ #include "juce_win32_DynamicLibraryLoader.h" - //============================================================================== DynamicLibraryLoader::DynamicLibraryLoader (const String& name) + : libHandle (0) { - libHandle = LoadLibrary (name); + load (name); } DynamicLibraryLoader::~DynamicLibraryLoader() +{ + load (String::empty); +} + +bool DynamicLibraryLoader::load (const String& name) { FreeLibrary ((HMODULE) libHandle); + libHandle = name.isNotEmpty() ? LoadLibrary (name) : 0; + return libHandle != 0; } void* DynamicLibraryLoader::findProcAddress (const String& functionName) @@ -46,5 +53,4 @@ void* DynamicLibraryLoader::findProcAddress (const String& functionName) return (void*) GetProcAddress ((HMODULE) libHandle, functionName.toCString()); // (void* cast is required for mingw) } - #endif diff --git a/src/native/windows/juce_win32_DynamicLibraryLoader.h b/src/native/windows/juce_win32_DynamicLibraryLoader.h index 42f7976d52..dbd89469a7 100644 --- a/src/native/windows/juce_win32_DynamicLibraryLoader.h +++ b/src/native/windows/juce_win32_DynamicLibraryLoader.h @@ -48,9 +48,11 @@ class JUCE_API DynamicLibraryLoader { public: - DynamicLibraryLoader (const String& name); + DynamicLibraryLoader (const String& name = String::empty); ~DynamicLibraryLoader(); + bool load (const String& libraryName); + void* findProcAddress (const String& functionName); private: diff --git a/src/native/windows/juce_win32_Windowing.cpp b/src/native/windows/juce_win32_Windowing.cpp index 54378e26d7..765b7aff26 100644 --- a/src/native/windows/juce_win32_Windowing.cpp +++ b/src/native/windows/juce_win32_Windowing.cpp @@ -2439,7 +2439,7 @@ void Desktop::createMouseInputSources() mouseSources.add (new MouseInputSource (0, true)); } -const Point Desktop::getMousePosition() +const Point Desktop::getRawMousePosition() { POINT mousePos; GetCursorPos (&mousePos); diff --git a/src/threads/juce_Thread.cpp b/src/threads/juce_Thread.cpp index 33ff5ed1b8..9359568c4e 100644 --- a/src/threads/juce_Thread.cpp +++ b/src/threads/juce_Thread.cpp @@ -122,13 +122,13 @@ void Thread::threadEntryPoint() JUCE_TRY { - jassert (getCurrentThreadId() == threadId_); - if (threadName_.isNotEmpty()) setCurrentThreadName (threadName_); if (startSuspensionEvent_.wait (10000)) { + jassert (getCurrentThreadId() == threadId_); + if (affinityMask_ != 0) setCurrentThreadAffinityMask (affinityMask_);