/[svn]/libgig/trunk/src/Akai.cpp
ViewVC logotype

Diff of /libgig/trunk/src/Akai.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 2572 by schoenebeck, Thu May 22 12:14:04 2014 UTC revision 2573 by schoenebeck, Thu May 22 15:17:09 2014 UTC
# Line 27  Line 27 
27  #include <unistd.h>  #include <unistd.h>
28  #include <fcntl.h>  #include <fcntl.h>
29  #include <sys/ioctl.h>  #include <sys/ioctl.h>
30    #if defined (__GNUC__) && (__GNUC__ >= 4)
31    #include <sys/disk.h>
32    #else
33    #include <dev/disk.h>
34    #endif
35  #include <sys/types.h>  #include <sys/types.h>
36  #include <sys/stat.h>  #include <sys/stat.h>
37  #include <errno.h>  #include <errno.h>
38  #include <paths.h>  #include <paths.h>
39  #ifdef _CARBON_  #if defined(_CARBON_) || defined(__APPLE__)
40  #include <sys/param.h>  #include <sys/param.h>
41  #include <IOKit/IOKitLib.h>  #include <IOKit/IOKitLib.h>
42  #include <IOKit/IOBSD.h>  #include <IOKit/IOBSD.h>
# Line 42  Line 47 
47  #include <CoreFoundation/CoreFoundation.h>  #include <CoreFoundation/CoreFoundation.h>
48  #endif  #endif
49    
50    #if defined(_CARBON_) || defined(__APPLE__)
51    
52    // These definitions were taken from mount_cd9660.c
53    // There are some similar definitions in IOCDTypes.h
54    // however there seems to be some dissagreement in
55    // the definition of CDTOC.length
56    struct _CDMSF {
57        u_char   minute;
58        u_char   second;
59        u_char   frame;
60    };
61    
62    #define MSF_TO_LBA(msf)                \
63         (((((msf).minute * 60UL) + (msf).second) * 75UL) + (msf).frame - 150)
64    
65    struct _CDTOC_Desc {
66        u_char        session;
67        u_char        ctrl_adr;  /* typed to be machine and compiler independent */
68        u_char        tno;
69        u_char        point;
70        struct _CDMSF address;
71        u_char        zero;
72        struct _CDMSF p;
73    };
74    
75    struct _CDTOC {
76        u_short            length;  /* in native cpu endian */
77        u_char             first_session;
78        u_char             last_session;
79        struct _CDTOC_Desc trackdesc[1];
80    };
81    
82    // Most of the following Mac CDROM IO functions were taken from Apple's IOKit
83    // examples (BSD style license). ReadTOC() function was taken from the Bochs x86
84    // Emulator (LGPL). Most probably they have taken it however also from some
85    // other BSD style licensed example code as well ...
86    
87    // Returns an iterator across all CD media (class IOCDMedia). Caller is responsible for releasing
88    // the iterator when iteration is complete.
89    static kern_return_t FindEjectableCDMedia(io_iterator_t *mediaIterator) {
90        kern_return_t kernResult;
91        CFMutableDictionaryRef classesToMatch;
92    
93        // CD media are instances of class kIOCDMediaClass
94        classesToMatch = IOServiceMatching(kIOCDMediaClass);
95        if (classesToMatch == NULL) {
96            printf("IOServiceMatching returned a NULL dictionary.\n");
97        } else {
98            CFDictionarySetValue(classesToMatch, CFSTR(kIOMediaEjectableKey), kCFBooleanTrue);
99            // Each IOMedia object has a property with key kIOMediaEjectableKey which is true if the
100            // media is indeed ejectable. So add this property to the CFDictionary we're matching on.
101        }
102    
103        kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, classesToMatch, mediaIterator);
104        
105        return kernResult;
106    }
107    
108    // Given an iterator across a set of CD media, return the BSD path to the
109    // next one. If no CD media was found the path name is set to an empty string.
110    static kern_return_t GetBSDPath(io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize) {
111        io_object_t nextMedia;
112        kern_return_t kernResult = KERN_FAILURE;
113        
114        *bsdPath = '\0';
115        
116        nextMedia = IOIteratorNext(mediaIterator);
117        if (nextMedia) {
118            CFTypeRef bsdPathAsCFString;
119            
120            bsdPathAsCFString = IORegistryEntryCreateCFProperty(nextMedia,
121                                                                CFSTR(kIOBSDNameKey),
122                                                                kCFAllocatorDefault,
123                                                                0);
124            if (bsdPathAsCFString) {
125                strlcpy(bsdPath, _PATH_DEV, maxPathSize);
126                
127                // Add "r" before the BSD node name from the I/O Registry to specify the raw disk
128                // node. The raw disk nodes receive I/O requests directly and do not go through
129                // the buffer cache.
130                
131                strlcat(bsdPath, "r", maxPathSize);
132                
133                size_t devPathLength = strlen(bsdPath);
134                
135                if (CFStringGetCString((CFStringRef)bsdPathAsCFString,
136                                       bsdPath + devPathLength,
137                                       maxPathSize - devPathLength,
138                                       kCFStringEncodingUTF8)) {
139                    printf("BSD path: %s\n", bsdPath);
140                    kernResult = KERN_SUCCESS;
141                }
142                
143                CFRelease(bsdPathAsCFString);
144            }
145        
146            IOObjectRelease(nextMedia);
147        }
148        
149        return kernResult;
150    }
151    
152    // Given the path to a CD drive, open the drive.
153    // Return the file descriptor associated with the device.
154    static int OpenDrive(const char *bsdPath) {
155        int fileDescriptor;
156        
157        // This open() call will fail with a permissions error if the sample has been changed to
158        // look for non-removable media. This is because device nodes for fixed-media devices are
159        // owned by root instead of the current console user.
160    
161        fileDescriptor = open(bsdPath, O_RDONLY);
162        
163        if (fileDescriptor == -1) {
164            printf("Error opening device %s: ", bsdPath);
165            perror(NULL);
166        }
167        
168        return fileDescriptor;
169    }
170    
171    // Given the file descriptor for a whole-media CD device, read a sector from the drive.
172    // Return true if successful, otherwise false.
173    static Boolean ReadSector(int fileDescriptor) {
174        char *buffer;
175        ssize_t numBytes;
176        u_int32_t blockSize;
177        
178        // This ioctl call retrieves the preferred block size for the media. It is functionally
179        // equivalent to getting the value of the whole media object's "Preferred Block Size"
180        // property from the IORegistry.
181        if (ioctl(fileDescriptor, DKIOCGETBLOCKSIZE, &blockSize)) {
182            perror("Error getting preferred block size");
183            
184            // Set a reasonable default if we can't get the actual preferred block size. A real
185            // app would probably want to bail at this point.
186            blockSize = kCDSectorSizeCDDA;
187        }
188        
189        printf("Media has block size of %d bytes.\n", blockSize);
190        
191        // Allocate a buffer of the preferred block size. In a real application, performance
192        // can be improved by reading as many blocks at once as you can.
193        buffer = (char*) malloc(blockSize);
194        
195        // Do the read. Note that we use read() here, not fread(), since this is a raw device
196        // node.
197        numBytes = read(fileDescriptor, buffer, blockSize);
198            
199        // Free our buffer. Of course, a real app would do something useful with the data first.
200        free(buffer);
201        
202        return numBytes == blockSize ? true : false;
203    }
204    
205    // Given the file descriptor for a device, close that device.
206    static void CloseDrive(int fileDescriptor) {
207        close(fileDescriptor);
208    }
209    
210    // path is the BSD path to a raw device such as /dev/rdisk1
211    static struct _CDTOC * ReadTOC(const char *devpath) {
212        struct _CDTOC * toc_p = NULL;
213        io_iterator_t iterator = 0;
214        io_registry_entry_t service = 0;
215        CFDictionaryRef properties = 0;
216        CFDataRef data = 0;
217        mach_port_t port = 0;
218        char *devname;
219    
220        if ((devname = strrchr(devpath, '/')) != NULL) {
221            ++devname;
222        } else {
223            devname = (char *) devpath;
224        }
225    
226        if (IOMasterPort(bootstrap_port, &port) != KERN_SUCCESS) {
227            fprintf(stderr, "IOMasterPort failed\n");
228            goto Exit;
229        }
230    
231        if (IOServiceGetMatchingServices(port, IOBSDNameMatching(port, 0, devname),
232                                         &iterator) != KERN_SUCCESS) {
233            fprintf(stderr, "IOServiceGetMatchingServices failed\n");
234            goto Exit;
235        }
236    
237        service = IOIteratorNext(iterator);
238    
239        IOObjectRelease(iterator);
240    
241        iterator = 0;
242    
243        while (service && !IOObjectConformsTo(service, "IOCDMedia")) {
244            if (IORegistryEntryGetParentIterator(service, kIOServicePlane,
245                                                 &iterator) != KERN_SUCCESS)
246            {
247                fprintf(stderr, "IORegistryEntryGetParentIterator failed\n");
248                goto Exit;
249            }
250    
251            IOObjectRelease(service);
252            service = IOIteratorNext(iterator);
253            IOObjectRelease(iterator);
254        }
255    
256        if (!service) {
257            fprintf(stderr, "CD media not found\n");
258            goto Exit;
259        }
260    
261        if (IORegistryEntryCreateCFProperties(service, (__CFDictionary **) &properties,
262                                              kCFAllocatorDefault,
263                                              kNilOptions) != KERN_SUCCESS)
264        {
265            fprintf(stderr, "IORegistryEntryGetParentIterator failed\n");
266            goto Exit;
267        }
268    
269        data = (CFDataRef) CFDictionaryGetValue(properties, CFSTR(kIOCDMediaTOCKey));
270        if (data == NULL) {
271            fprintf(stderr, "CFDictionaryGetValue failed\n");
272            goto Exit;
273        } else {
274            CFRange range;
275            CFIndex buflen;
276    
277            buflen = CFDataGetLength(data) + 1;
278            range = CFRangeMake(0, buflen);
279            toc_p = (struct _CDTOC *) malloc(buflen);
280            if (toc_p == NULL) {
281                fprintf(stderr, "Out of memory\n");
282                goto Exit;
283            } else {
284                CFDataGetBytes(data, range, (unsigned char *) toc_p);
285            }
286    
287           /*
288            fprintf(stderr, "Table of contents\n length %d first %d last %d\n",
289                    toc_p->length, toc_p->first_session, toc_p->last_session);
290            */
291    
292            CFRelease(properties);
293        }
294    
295        Exit:
296    
297        if (service) {
298            IOObjectRelease(service);
299        }
300    
301        return toc_p;
302    }
303    
304    #endif // defined(_CARBON_) || defined(__APPLE__)
305    
306  //////////////////////////////////  //////////////////////////////////
307  // AkaiSample:  // AkaiSample:
308  AkaiSample::AkaiSample(DiskImage* pDisk, AkaiVolume* pParent, const AkaiDirEntry& DirEntry)  AkaiSample::AkaiSample(DiskImage* pDisk, AkaiVolume* pParent, const AkaiDirEntry& DirEntry)
# Line 565  AkaiVolume::AkaiVolume(DiskImage* pDisk, Line 826  AkaiVolume::AkaiVolume(DiskImage* pDisk,
826    if (mDirEntry.mType != AKAI_TYPE_DIR_S1000 && mDirEntry.mType != AKAI_TYPE_DIR_S3000)    if (mDirEntry.mType != AKAI_TYPE_DIR_S1000 && mDirEntry.mType != AKAI_TYPE_DIR_S3000)
827    {    {
828      printf("Creating Unknown Volume type! %d\n",mDirEntry.mType);      printf("Creating Unknown Volume type! %d\n",mDirEntry.mType);
829  #ifdef _WIN32_  #ifdef WIN32
830      OutputDebugString("Creating Unknown Volume type!\n");      OutputDebugString("Creating Unknown Volume type!\n");
831  #endif  #endif
832    }    }
# Line 1241  DiskImage::DiskImage(int disk) Line 1502  DiskImage::DiskImage(int disk)
1502      mSize = dg.BytesPerSector * dg.SectorsPerTrack * dg.TracksPerCylinder * dg.Cylinders.LowPart;      mSize = dg.BytesPerSector * dg.SectorsPerTrack * dg.TracksPerCylinder * dg.Cylinders.LowPart;
1503      mClusterSize = dg.BytesPerSector;      mClusterSize = dg.BytesPerSector;
1504    }    }
1505  #elif defined _CARBON_  #elif defined(_CARBON_) || defined(__APPLE__)
1506    kern_return_t  kernResult;    kern_return_t  kernResult;
1507    io_iterator_t mediaIterator;    io_iterator_t mediaIterator;
1508    char  bsdPath[ MAXPATHLEN ];    char  bsdPath[ MAXPATHLEN ];
# Line 1320  void DiskImage::Init() Line 1581  void DiskImage::Init()
1581    mCluster     = (uint)-1;    mCluster     = (uint)-1;
1582    mStartFrame  = -1;    mStartFrame  = -1;
1583    mEndFrame    = -1;    mEndFrame    = -1;
1584  #ifdef _WIN32_  #ifdef WIN32
1585    mpCache = (char*) VirtualAlloc(NULL,mClusterSize,MEM_COMMIT,PAGE_READWRITE);    mpCache = (char*) VirtualAlloc(NULL,mClusterSize,MEM_COMMIT,PAGE_READWRITE);
1586  #else  #else
1587    mpCache = NULL; // we allocate the cache later when we know what type of media we access    mpCache = NULL; // we allocate the cache later when we know what type of media we access
# Line 1329  void DiskImage::Init() Line 1590  void DiskImage::Init()
1590    
1591  DiskImage::~DiskImage()  DiskImage::~DiskImage()
1592  {  {
1593  #ifdef _WIN32_  #ifdef WIN32
1594    if (mFile != INVALID_HANDLE_VALUE)    if (mFile != INVALID_HANDLE_VALUE)
1595    {    {
1596      CloseHandle(mFile);      CloseHandle(mFile);
1597    }    }
1598  #elif defined _CARBON_ || LINUX  #elif defined _CARBON_ || defined(__APPLE__) || LINUX
1599    if (mFile)    if (mFile)
1600    {    {
1601      close(mFile);      close(mFile);
# Line 1342  DiskImage::~DiskImage() Line 1603  DiskImage::~DiskImage()
1603  #endif  #endif
1604    if (mpCache)    if (mpCache)
1605    {    {
1606  #ifdef _WIN32_  #ifdef WIN32
1607      VirtualFree(mpCache, 0, MEM_RELEASE);      VirtualFree(mpCache, 0, MEM_RELEASE);
1608  #elif defined _CARBON_ || LINUX  #elif defined(_CARBON_) || defined(__APPLE__) || LINUX
1609      free(mpCache);      free(mpCache);
1610  #endif  #endif
1611    }    }
# Line 1403  int DiskImage::Read(void* pData, uint Wo Line 1664  int DiskImage::Read(void* pData, uint Wo
1664                                            : mPos / mClusterSize + mStartFrame;                                            : mPos / mClusterSize + mStartFrame;
1665      if (mCluster != requestedCluster) { // read the requested cluster into cache      if (mCluster != requestedCluster) { // read the requested cluster into cache
1666        mCluster = requestedCluster;        mCluster = requestedCluster;
1667  #ifdef _WIN32_  #ifdef WIN32
1668        if (mCluster * mClusterSize != SetFilePointer(mFile, mCluster * mClusterSize, NULL, FILE_BEGIN)) {        if (mCluster * mClusterSize != SetFilePointer(mFile, mCluster * mClusterSize, NULL, FILE_BEGIN)) {
1669          printf("ERROR: couldn't seek device!\n");          printf("ERROR: couldn't seek device!\n");
1670          if ((readbytes > 0) && (mEndian != eEndianNative)) {          if ((readbytes > 0) && (mEndian != eEndianNative)) {
# Line 1417  int DiskImage::Read(void* pData, uint Wo Line 1678  int DiskImage::Read(void* pData, uint Wo
1678        }        }
1679        DWORD size;        DWORD size;
1680        ReadFile(mFile, mpCache, mClusterSize, &size, NULL);        ReadFile(mFile, mpCache, mClusterSize, &size, NULL);
1681  #elif defined _CARBON_ || LINUX  #elif defined(_CARBON_) || defined(__APPLE__) || LINUX
1682        if (mCluster * mClusterSize != lseek(mFile, mCluster * mClusterSize, SEEK_SET))        if (mCluster * mClusterSize != lseek(mFile, mCluster * mClusterSize, SEEK_SET))
1683          return readbytes / WordSize;          return readbytes / WordSize;
1684  //          printf("trying to read %d bytes from device!\n",mClusterSize);  //          printf("trying to read %d bytes from device!\n",mClusterSize);
# Line 1519  uint32_t DiskImage::ReadInt32() Line 1780  uint32_t DiskImage::ReadInt32()
1780  }  }
1781    
1782  void DiskImage::OpenStream(const char* path) {  void DiskImage::OpenStream(const char* path) {
1783  #ifdef _WIN32_  #ifdef WIN32
1784    mFile = CreateFile(path, GENERIC_READ,0,NULL,OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS,NULL);    mFile = CreateFile(path, GENERIC_READ,0,NULL,OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS,NULL);
1785    BY_HANDLE_FILE_INFORMATION FileInfo;    BY_HANDLE_FILE_INFORMATION FileInfo;
1786    GetFileInformationByHandle(mFile,&FileInfo);    GetFileInformationByHandle(mFile,&FileInfo);
1787    mSize = FileInfo.nFileSizeLow;    mSize = FileInfo.nFileSizeLow;
1788  #elif _CARBON_ || LINUX  #elif defined(_CARBON_) || defined(__APPLE__) || LINUX
1789    struct stat filestat;    struct stat filestat;
1790    stat(path,&filestat);    stat(path,&filestat);
1791    mFile = open(path, O_RDONLY | O_NONBLOCK);    mFile = open(path, O_RDONLY | O_NONBLOCK);
# Line 1540  void DiskImage::OpenStream(const char* p Line 1801  void DiskImage::OpenStream(const char* p
1801      mSize        = filestat.st_size;      mSize        = filestat.st_size;
1802      mClusterSize = DISK_CLUSTER_SIZE;      mClusterSize = DISK_CLUSTER_SIZE;
1803      mpCache = (char*) malloc(mClusterSize);      mpCache = (char*) malloc(mClusterSize);
1804    }    } else { // CDROM
1805    else { // CDROM  #if defined(_CARBON_) || defined(__APPLE__)
1806        printf("Can't open %s: not a regular file\n", path);
1807    #else // Linux ...
1808      mRegularFile = false;      mRegularFile = false;
1809      mClusterSize = CD_FRAMESIZE;      mClusterSize = CD_FRAMESIZE;
1810      mpCache = (char*) malloc(mClusterSize);      mpCache = (char*) malloc(mClusterSize);
# Line 1601  void DiskImage::OpenStream(const char* p Line 1864  void DiskImage::OpenStream(const char* p
1864      mStartFrame = start;      mStartFrame = start;
1865      mEndFrame   = end;      mEndFrame   = end;
1866      mSize       = length * CD_FRAMESIZE;      mSize       = length * CD_FRAMESIZE;
1867    #endif
1868    } // CDROM    } // CDROM
1869  #endif  #endif
1870  }  }
1871    
1872  bool DiskImage::WriteImage(const char* path)  bool DiskImage::WriteImage(const char* path)
1873  {  {
1874  #if _CARBON_ || LINUX  #if defined(_CARBON_) || defined(__APPLE__) || LINUX
1875    const uint bufferSize = 524288; // 512 kB    const uint bufferSize = 524288; // 512 kB
1876    int fOut = open(path, O_WRONLY | O_NONBLOCK | O_CREAT | O_TRUNC);    int fOut = open(path, O_WRONLY | O_NONBLOCK | O_CREAT | O_TRUNC);
1877    if (mFile <= 0) {    if (mFile <= 0) {

Legend:
Removed from v.2572  
changed lines
  Added in v.2573

  ViewVC Help
Powered by ViewVC