vbAccelerator - Contents of code file: cCDTrackRipper.cls

This file is part of the download VB6 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 = "cCDTrackRipper"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit

' ------------------------------------------------------------
' Name:   cCDTrackRipper
' Author: Steve McMahon (steve@vbaccelerator.com)
' Date:   2004-05-06
' Description:
' Wrapper around the CDRip.DLL API for ripping tracks (or
' parts of CDs)
'
' See http://vbaccelerator.com/
' ------------------------------------------------------------

Private Const GMEM_FIXED = &H0
Private Const GMEM_ZEROINIT = &H40
Private Const GPTR = (GMEM_FIXED Or GMEM_ZEROINIT)
Private Declare Function LocalAlloc Lib "kernel32" (ByVal wFlags As Long, ByVal
 wBytes As Long) As Long
Private Declare Function LocalLock Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function LocalFree Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function LocalUnlock Lib "kernel32" (ByVal hMem As Long) As Long

Private Declare Sub CR_SetActiveCDROM Lib "cdrip.dll" (ByVal nActiveDrive As
 Long)

'// Start ripping section, output is fetched to WriteBufferFunc
'// Data is extracted from dwStartSector to dwEndSector
Private Declare Function CR_OpenRipper Lib "cdrip.dll" ( _
      ByRef plBufferSize As Long, _
      ByVal dwStartSector As Long, _
      ByVal dwEndSector As Long) As Long
'// Close the ripper, has to be called when the ripping process is completed
 (i.e 100%)
'// Or it can be called to abort the current ripping section
Private Declare Function CR_CloseRipper Lib "cdrip.dll" () As Long
'// Indicates how far the ripping process is right now
'// Returns 100% when the ripping is completed
Private Declare Function CR_GetPercentCompleted Lib "cdrip.dll" () As Long
'// Get number of Jitter Errors that have occured during the ripping
'// This function must be called before CloseRipper is called !
Private Declare Function CR_GetNumberOfJitterErrors Lib "cdrip.dll" () As Long
'// Get the jitter position of the extracted track
Private Declare Function CR_GetJitterPosition Lib "cdrip.dll" () As Long
'// Returns the peak value of the ripped section (0..2^15)
Private Declare Function CR_GetPeakValue Lib "cdrip.dll" () As Long
'// Rip a chunk from the CD, pbtStream contains the ripped data, pNumBytes the
'// number of bytes that have been ripped and corrected for jitter (if enabled)
Private Declare Function CR_RipChunk Lib "cdrip.dll" ( _
   pbtStream As Any, _
   ByRef pNumBytes As Long, _
   bAbort As Long) As Long
'// Normalize the stream (i.e. multiply by dScaleFactor)
Private Declare Sub CR_NormalizeChunk Lib "cdrip.dll" ( _
   pbsStream As Any, _
   ByVal nNumSamples As Long, _
   ByVal dScaleFactor As Double _
   )

Private m_cdIndex As Long
Private m_startSector As Long
Private m_endSector As Long
Private m_iJitterErrCount As Long
Private m_bRipperOpen As Boolean
Private m_lBufferSize As Long
Private m_lReadSize As Long
Private m_hMem As Long
Private m_lPtrMem As Long
Private m_lPercentComplete As Long

Public Sub CreateForTrack(cTrack As cTocEntry)
   If CloseRipper() Then
      m_startSector = cTrack.StartSector
      m_endSector = cTrack.EndSector
      m_cdIndex = cTrack.fCDIndex
   End If
End Sub

Public Sub CreateForSection(cD As cDrive, ByVal lStartSector As Long, ByVal
 lEndSector As Long)
   If CloseRipper() Then
      m_startSector = 0
      m_endSector = 0
      If (lStartSector >= 0) And (lStartSector < cD.TOC.TotalLengthSectors) Then
         CDRipErrHandler "CreateForSection", 3, False
      Else
         If (lEndSector > lStartSector) And (lEndSector <
          cD.TOC.TotalLengthSectors) Then
            CDRipErrHandler "CreateForSection", 3, False
         Else
            m_startSector = lStartSector
            m_endSector = lEndSector
            m_cdIndex = cD.fCDIndex
         End If
      End If
   End If
End Sub

Public Property Get JitterErrorCount() As Long
   JitterErrorCount = m_iJitterErrCount
End Property

Public Property Get PercentComplete() As Long
   PercentComplete = m_lPercentComplete
End Property


Public Function CloseRipper()
Dim eErr As ECDRipErrorCode
   If (m_bRipperOpen) Then
      m_bRipperOpen = False
      m_iJitterErrCount = CR_GetNumberOfJitterErrors()
      eErr = CR_CloseRipper()
      CDRipErrHandler "cCDTrackRipper.CloseRipper", eErr, True
      If (eErr = CDEX_OK) Then
         CloseRipper = True
      End If
   Else
      CloseRipper = True
   End If
End Function

Private Function CreateBuffer(ByVal lSize As Long) As Boolean
   
   If (lSize <= 1) Then
      ' inappropriate
      Debug.Print lSize
      Debug.Assert "" = "Inappropriate buffer size"
      Exit Function
   End If
   
   If Not (lSize = m_lBufferSize) Then
      DestroyBuffer
   End If
   
   If (m_lPtrMem = 0) Then
      m_hMem = LocalAlloc(GPTR, lSize)
      If (m_hMem = 0) Then
         ' failed
      Else
         m_lPtrMem = LocalLock(m_hMem)
         If (m_lPtrMem = 0) Then
            ' failed
            DestroyBuffer
         Else
            ' success
            m_lBufferSize = lSize
            CreateBuffer = True
         End If
      End If
   Else
      ' success
      CreateBuffer = True
   End If
   
End Function

Private Sub DestroyBuffer()
   If Not (m_lPtrMem = 0) Then
      LocalUnlock m_hMem
      m_lPtrMem = 0
   End If
   If Not (m_hMem = 0) Then
      LocalFree m_hMem
      m_hMem = 0
   End If
   m_lReadSize = 0
   m_lBufferSize = 0
End Sub

Public Function OpenRipper() As Boolean
Dim eErr As ECDRipErrorCode
Dim lStartSector As Long
Dim lEndSector As Long
Dim lBufferSize As Long

   If CloseRipper() Then

      CR_SetActiveCDROM m_cdIndex

      m_lPercentComplete = 0
      lStartSector = m_startSector
      lEndSector = m_endSector
   
      eErr = CR_OpenRipper(lBufferSize, lStartSector, lEndSector)
      CDRipErrHandler "cCDTrackRipper.OpenRipper", eErr, True
      If (eErr = CDEX_OK) Then
         If CreateBuffer(lBufferSize) Then
            m_bRipperOpen = True
   
            m_iJitterErrCount = 0
            OpenRipper = True
         Else
            CDRipErrHandler "cCDTrackRipper.CreateBuffer", 7, False
         End If
      End If
      
   End If
   
End Function

Public Function Read() As Boolean
Dim bAbort As Long
Dim lNumBytes As Long
Dim eErr As ECDRipErrorCode

   If (m_bRipperOpen) Then
   
      ' Try and read the next chunk
      eErr = CR_RipChunk(ByVal m_lPtrMem, lNumBytes, bAbort)
      m_lReadSize = lNumBytes
      m_lPercentComplete = CR_GetPercentCompleted()
      
      Select Case eErr
      Case CDEX_RIPPING_INPROGRESS, CDEX_OK
         Read = True
      
      Case CDEX_RIPPING_DONE
         ' Complete
         CloseRipper
         Read = True ' will be false next time
         
      Case CDEX_JITTER_ERROR
         ' TODO handle jitter error
         Read = True
         
      Case CDEX_FILEOPEN_ERROR
         ' Failed
         CloseRipper
         CDRipErrHandler "cCDTrackRipper.Read", eErr, True
         Read = False
         
      Case CDEX_ERROR
         ' Failed
         CloseRipper
         CDRipErrHandler "cCDTrackRipper.Read", eErr, True
         Read = False
                        
      End Select
   Else
      m_lReadSize = 0
      Read = False
   End If
   
End Function

Public Property Get ReadBufferPtr() As Long
   ReadBufferPtr = m_lPtrMem
End Property
Public Property Get ReadBufferSize() As Long
   ReadBufferSize = m_lReadSize
End Property

Private Sub Class_Terminate()
Dim bWasOpen As Boolean
   
   bWasOpen = m_bRipperOpen
   
   On Error Resume Next ' don't throw in terminate
   DestroyBuffer
   CloseRipper
   
   If (bWasOpen) Then
      Debug.Print "Warning: cCDTrackRipper instance terminated whilst ripper
       open"
      Debug.Assert Not (m_bRipperOpen)
   End If
   
End Sub