|
|
||||
|
vbAccelerator - Contents of code file: cCDToc.clsThis file is part of the download VB5 CD Ripper, which is described in the article CD Ripping in VB Part 1. VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "cToc"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit
' ------------------------------------------------------------
' Name: cToc
' Author: Steve McMahon (steve@vbaccelerator.com)
' Date: 2004-05-06
' Description:
' Wrapper around the CDRip.DLL API describing the table
' of contents of a CD. Includes CDDB ID generation function.
'
' See http://vbaccelerator.com/
' ------------------------------------------------------------
Private Type CDTEXTPACK_TAG ' packed = 18 bytes
packType As Byte
TrackNumber As Byte
sequenceNumber As Byte
positionInfo As Byte
'BYTE characterPosition:4; // character position
'BYTE block :3; // block number 0..7
'BYTE bDBC :1; // double byte character
data(0 To 11) As Byte
crc0 As Byte
crc1 As Byte
End Type
'// Read CD Text entry
Private Declare Function CR_ReadCDText Lib "cdrip.dll" (pbtBuffer As Any, ByVal
nBufferSize As Long, pnCDTextSize As Integer) As Long
Private Type tTOCENTRY
dwStartSector As Long '// Start sector of the track
btFlag As Byte '// Track flags (i.e. data or audio track)
btTrackNumber As Byte '// Track number
End Type
'// Read the table of contents
Private Declare Function CR_ReadToc Lib "cdrip.dll" () As Long
'// Get the number of TOC entries, including the lead out
Private Declare Function CR_GetNumTocEntries Lib "cdrip.dll" () As Long
'// Get the TOC entry
Private Declare Function CR_GetTocEntry Lib "cdrip.dll" (ByVal nTocEntry As
Long) As Currency ' ptr to TOC entry?
Private Declare Sub CR_SetActiveCDROM Lib "cdrip.dll" (ByVal nActiveDrive As
Long)
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
lpvDest As Any, lpvSource As Any, ByVal cbCopy As Long)
Private m_count As Long
Private m_cEntries As Collection
Private m_index As Long
Private m_lLeadOutOffset As Long
Private m_iCDDBID As Long
Private m_lPower2(0 To 31) As Long
Friend Sub fInit(ByVal nIndex As Long)
Set m_cEntries = New Collection
m_index = nIndex
CDRipErrHandler "cCDToc.fInit", CR_ReadToc(), True
m_count = CR_GetNumTocEntries()
If (m_count > 0) Then
Dim i As Long
Dim lTocValue As Currency
' Last entry is the leadout
Dim tTOC() As tTOCENTRY
ReDim tTOC(0 To m_count) As tTOCENTRY
Dim cToc As cTocEntry
Dim lOffset As Long
For i = 0 To m_count
lTocValue = CR_GetTocEntry(i)
CopyMemory tTOC(i).dwStartSector, lTocValue, 6
CopyMemory tTOC(i).btTrackNumber, ByVal (VarPtr(lTocValue) + 5), 1
CopyMemory tTOC(i).btFlag, ByVal (VarPtr(lTocValue) + 4), 1
Next i
For i = 0 To m_count - 1
Set cToc = New cTocEntry
cToc.fInit _
m_index, _
tTOC(i).dwStartSector, _
tTOC(i).btFlag, tTOC(i).btTrackNumber, _
tTOC(i + 1).dwStartSector
m_cEntries.Add cToc, "T" & (i + 1)
Next i
m_lLeadOutOffset = tTOC(m_count).dwStartSector + 150
getCDDBID
End If
End Sub
Public Property Get TotalLengthSeconds()
TotalLengthSeconds = m_lLeadOutOffset \ 75
End Property
Public Property Get TotalLengthSectors()
TotalLengthSectors = m_lLeadOutOffset
End Property
Public Property Get CDDBId() As Long
CDDBId = m_iCDDBID
End Property
Public Property Get CDDBQuery() As String
Dim sQuery As String
sQuery = "cddb query"
sQuery = sQuery & " " & Hex$(m_iCDDBID)
sQuery = sQuery & " " & m_count
Dim i As Long
Dim cToc As cTocEntry
For i = 1 To m_count
Set cToc = m_cEntries("T" & i)
sQuery = sQuery & " " & cToc.Offset
Next i
sQuery = sQuery & " " & TotalLengthSeconds
CDDBQuery = LCase(sQuery)
End Property
Public Sub Refresh()
CR_SetActiveCDROM m_index
fInit m_index
End Sub
Public Property Get Count() As Long
Count = m_count
End Property
Public Property Get Entry(ByVal nIndex As Long) As cTocEntry
Set Entry = m_cEntries("T" & nIndex)
End Property
' Read CD Text not implemented yet as I don't have a suitable disc
' Dim buffer() As Byte
' Dim nBufferSize As Long
' nBufferSize = 4 + 8 + 18 * 256
' ReDim buffer(0 To nBufferSize - 1) As Byte
' Dim cdTextSize As Integer
'
' l = CR_ReadCDText(buffer(0), nBufferSize, cdTextSize)
' errHandler "Command1_Click", l, True
' Debug.Print
'
' If (cdTextSize < 4) Then
' errHandler "Command1_Click", CDEX_ERROR, True
' Else
' Dim numPacks As Long
' numPacks = (cdTextSize - 4) / 18
' Debug.Print numPacks
' End If
Private Sub getCDDBID()
Dim i As Long
Dim numTracks As Long
Dim cToc As cTocEntry
Dim n As Long
Dim t As Long
Dim Res As Long
Dim leadOutMinutes As Long
Dim leadOutSeconds As Long
For i = 1 To m_count
Set cToc = m_cEntries("T" & i)
n = UnsignedAdd(n, CDDBSum(60 * cToc.StartTimeMinutes +
cToc.StartTimeSeconds))
Next i
leadOutMinutes = Int(m_lLeadOutOffset / (75 * 60))
leadOutSeconds = (Int(m_lLeadOutOffset / 75)) Mod 60
t = 60 * leadOutMinutes + leadOutSeconds
Set cToc = m_cEntries("T1")
t = t - (60 * cToc.StartTimeMinutes + cToc.StartTimeSeconds)
m_iCDDBID = RShift((n Mod &HFF), 24) Or RShift(t, 8) Or m_count
Debug.Print Hex(m_iCDDBID)
End Sub
Private Function CDDBSum(ByVal n As Long) As Long
Dim retVal As Long
Do While (n > 0)
retVal = UnsignedAdd(retVal, (n Mod 10))
n = n \ 10
Loop
CDDBSum = retVal
End Function
Private Function UnsignedAdd(Start As Long, Incr As Long) As Long
' This function is useful when doing pointer arithmetic,
' but note it only works for positive values of Incr
If Start And &H80000000 Then 'Start < 0
UnsignedAdd = Start + Incr
ElseIf (Start Or &H80000000) < -Incr Then
UnsignedAdd = Start + Incr
Else
UnsignedAdd = (Start + &H80000000) + (Incr + &H80000000)
End If
End Function
Private Function RShift(ByVal lThis As Long, ByVal lBits As Long) As Long
If (lBits <= 0) Then
RShift = lThis
ElseIf (lBits > 63) Then
' .. error ...
ElseIf (lBits > 31) Then
RShift = 0
Else
If (lThis And m_lPower2(31 - lBits)) = m_lPower2(31 - lBits) Then
RShift = (lThis And (m_lPower2(31 - lBits) - 1)) * m_lPower2(lBits) Or
m_lPower2(31)
Else
RShift = (lThis And (m_lPower2(31 - lBits) - 1)) * m_lPower2(lBits)
End If
End If
End Function
Private Function LShift(ByVal lThis As Long, ByVal lBits As Long) As Long
If (lBits <= 0) Then
LShift = lThis
ElseIf (lBits > 63) Then
' ... error ...
ElseIf (lBits > 31) Then
LShift = 0
Else
If (lThis And m_lPower2(31)) = m_lPower2(31) Then
LShift = (lThis And &H7FFFFFFF) \ m_lPower2(lBits) Or m_lPower2(31 -
lBits)
Else
LShift = lThis \ m_lPower2(lBits)
End If
End If
End Function
Private Sub Init()
m_lPower2(0) = &H1&
m_lPower2(1) = &H2&
m_lPower2(2) = &H4&
m_lPower2(3) = &H8&
m_lPower2(4) = &H10&
m_lPower2(5) = &H20&
m_lPower2(6) = &H40&
m_lPower2(7) = &H80&
m_lPower2(8) = &H100&
m_lPower2(9) = &H200&
m_lPower2(10) = &H400&
m_lPower2(11) = &H800&
m_lPower2(12) = &H1000&
m_lPower2(13) = &H2000&
m_lPower2(14) = &H4000&
m_lPower2(15) = &H8000&
m_lPower2(16) = &H10000
m_lPower2(17) = &H20000
m_lPower2(18) = &H40000
m_lPower2(19) = &H80000
m_lPower2(20) = &H100000
m_lPower2(21) = &H200000
m_lPower2(22) = &H400000
m_lPower2(23) = &H800000
m_lPower2(24) = &H1000000
m_lPower2(25) = &H2000000
m_lPower2(26) = &H4000000
m_lPower2(27) = &H8000000
m_lPower2(28) = &H10000000
m_lPower2(29) = &H20000000
m_lPower2(30) = &H40000000
m_lPower2(31) = &H80000000
End Sub
Private Sub Class_Initialize()
Init
End Sub
|
|||
|
|
||||