31 #if defined(_CARBON_) || defined(__APPLE__) 
   32 # if defined (__GNUC__) && (__GNUC__ >= 4) 
   33 #  include <sys/disk.h> 
   35 #  include <dev/disk.h> 
   38 #include <sys/types.h> 
   41 #if defined(_CARBON_) || defined(__APPLE__) 
   43 #include <sys/ioctl.h> 
   44 #include <sys/param.h> 
   45 #include <IOKit/IOKitLib.h> 
   46 #include <IOKit/IOBSD.h> 
   47 #include <IOKit/storage/IOMediaBSDClient.h> 
   48 #include <IOKit/storage/IOMedia.h> 
   49 #include <IOKit/storage/IOCDMedia.h> 
   50 #include <IOKit/storage/IOCDTypes.h> 
   51 #include <CoreFoundation/CoreFoundation.h> 
   54 #if defined(_CARBON_) || defined(__APPLE__) 
   66 #define MSF_TO_LBA(msf)                \ 
   67      (((((msf).minute * 60UL) + (msf).second) * 75UL) + (msf).frame - 150) 
   74     struct _CDMSF address;
 
   83     struct _CDTOC_Desc trackdesc[1];
 
   93 static kern_return_t FindEjectableCDMedia(io_iterator_t *mediaIterator) {
 
   94     kern_return_t kernResult;
 
   95     CFMutableDictionaryRef classesToMatch;
 
   98     classesToMatch = IOServiceMatching(kIOCDMediaClass);
 
   99     if (classesToMatch == NULL) {
 
  100         printf(
"IOServiceMatching returned a NULL dictionary.\n");
 
  102         CFDictionarySetValue(classesToMatch, CFSTR(kIOMediaEjectableKey), kCFBooleanTrue);
 
  107     kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, classesToMatch, mediaIterator);
 
  114 static kern_return_t GetBSDPath(io_iterator_t mediaIterator, 
char *bsdPath, CFIndex maxPathSize) {
 
  115     io_object_t nextMedia;
 
  116     kern_return_t kernResult = KERN_FAILURE;
 
  120     nextMedia = IOIteratorNext(mediaIterator);
 
  122         CFTypeRef bsdPathAsCFString;
 
  124         bsdPathAsCFString = IORegistryEntryCreateCFProperty(nextMedia,
 
  125                                                             CFSTR(kIOBSDNameKey),
 
  128         if (bsdPathAsCFString) {
 
  129             strlcpy(bsdPath, _PATH_DEV, maxPathSize);
 
  135             strlcat(bsdPath, 
"r", maxPathSize);
 
  137             size_t devPathLength = strlen(bsdPath);
 
  139             if (CFStringGetCString((CFStringRef)bsdPathAsCFString,
 
  140                                    bsdPath + devPathLength,
 
  141                                    maxPathSize - devPathLength,
 
  142                                    kCFStringEncodingUTF8)) {
 
  143                 printf(
"BSD path: %s\n", bsdPath);
 
  144                 kernResult = KERN_SUCCESS;
 
  147             CFRelease(bsdPathAsCFString);
 
  150         IOObjectRelease(nextMedia);
 
  215 static struct _CDTOC * ReadTOC(
const char *devpath) {
 
  216     struct _CDTOC * toc_p = NULL;
 
  217     io_iterator_t iterator = 0;
 
  218     io_registry_entry_t service = 0;
 
  219     CFDictionaryRef properties = 0;
 
  221     mach_port_t port = 0;
 
  224     if ((devname = strrchr(devpath, 
'/')) != NULL) {
 
  227         devname = (
char *) devpath;
 
  230     if (IOMasterPort(bootstrap_port, &port) != KERN_SUCCESS) {
 
  231         fprintf(stderr, 
"IOMasterPort failed\n");
 
  235     if (IOServiceGetMatchingServices(port, IOBSDNameMatching(port, 0, devname),
 
  236                                      &iterator) != KERN_SUCCESS) {
 
  237         fprintf(stderr, 
"IOServiceGetMatchingServices failed\n");
 
  241     service = IOIteratorNext(iterator);
 
  243     IOObjectRelease(iterator);
 
  247     while (service && !IOObjectConformsTo(service, 
"IOCDMedia")) {
 
  248         if (IORegistryEntryGetParentIterator(service, kIOServicePlane,
 
  249                                              &iterator) != KERN_SUCCESS)
 
  251             fprintf(stderr, 
"IORegistryEntryGetParentIterator failed\n");
 
  255         IOObjectRelease(service);
 
  256         service = IOIteratorNext(iterator);
 
  257         IOObjectRelease(iterator);
 
  261         fprintf(stderr, 
"CD media not found\n");
 
  265     if (IORegistryEntryCreateCFProperties(service, (__CFDictionary **) &properties,
 
  267                                           kNilOptions) != KERN_SUCCESS)
 
  269         fprintf(stderr, 
"IORegistryEntryGetParentIterator failed\n");
 
  273     data = (CFDataRef) CFDictionaryGetValue(properties, CFSTR(kIOCDMediaTOCKey));
 
  275         fprintf(stderr, 
"CFDictionaryGetValue failed\n");
 
  281         buflen = CFDataGetLength(data) + 1;
 
  282         range = CFRangeMake(0, buflen);
 
  283         toc_p = (
struct _CDTOC *) malloc(buflen);
 
  285             fprintf(stderr, 
"Out of memory\n");
 
  288             CFDataGetBytes(data, range, (
unsigned char *) toc_p);
 
  296         CFRelease(properties);
 
  302         IOObjectRelease(service);
 
  312 AkaiSample::AkaiSample(
DiskImage* pDisk, 
AkaiVolume* pParent, 
const AkaiDirEntry& DirEntry)
 
  313   : AkaiDiskElement(pDisk->GetPos())
 
  317   mDirEntry = DirEntry;
 
  326 AkaiSample::~AkaiSample()
 
  332 AkaiDirEntry AkaiSample::GetDirEntry()
 
  337 bool AkaiSample::LoadSampleData()
 
  344   mpDisk->SetPos(mImageOffset);
 
  345   mpSamples = (int16_t*) malloc(mNumberOfSamples * 
sizeof(int16_t));
 
  349   mpDisk->ReadInt16((uint16_t*)mpSamples, mNumberOfSamples);
 
  353 void AkaiSample::ReleaseSampleData()
 
  361 int AkaiSample::SetPos(
int Where, akai_stream_whence_t Whence)
 
  363   if (!mHeaderOK) 
return -1;
 
  367   case akai_stream_start:
 
  372   case akai_stream_curpos:
 
  375   case akai_stream_end:
 
  376     mPos = mNumberOfSamples - w;
 
  379   if (mPos > mNumberOfSamples) mPos = mNumberOfSamples;
 
  380   if (mPos < 0) mPos = 0;
 
  384 int AkaiSample::Read(
void* pBuffer, uint SampleCount)
 
  386   if (!mHeaderOK) 
return 0;
 
  388   if (mPos + SampleCount > mNumberOfSamples) SampleCount = mNumberOfSamples - mPos;
 
  390   mpDisk->SetPos(mImageOffset + mPos * 2); 
 
  391   mpDisk->ReadInt16((uint16_t*)pBuffer, SampleCount);
 
  395 bool AkaiSample::LoadHeader()
 
  400   mpDisk->SetPos(mpParent->GetParent()->GetOffset() + mDirEntry.mStart * AKAI_BLOCK_SIZE );
 
  405   if (mpDisk->ReadInt8() != AKAI_SAMPLE_ID)
 
  410   mMidiRootNote = mpDisk->ReadInt8();
 
  413   mpDisk->Read(buffer, 12, 1);
 
  414   AkaiToAscii(buffer, 12);
 
  420   mActiveLoops = mpDisk->ReadInt8();
 
  422   mFirstActiveLoop = mpDisk->ReadInt8();
 
  427   mLoopMode = mpDisk->ReadInt8();
 
  429   mTuneCents = mpDisk->ReadInt8();
 
  431   mTuneSemitones = mpDisk->ReadInt8();
 
  439   mNumberOfSamples = mpDisk->ReadInt32();
 
  441   mStartMarker = mpDisk->ReadInt32();
 
  443   mEndMarker = mpDisk->ReadInt32();
 
  454     mLoops[i].Load(mpDisk);
 
  458   mSamplingFrequency = mpDisk->ReadInt16();
 
  460   mLoopTuneOffset = mpDisk->ReadInt8();
 
  462   mImageOffset = mpParent->GetParent()->GetOffset() + mDirEntry.mStart * AKAI_BLOCK_SIZE + 150; 
 
  465   return (mHeaderOK = 
true);
 
  468 bool AkaiSampleLoop::Load(
DiskImage* pDisk)
 
  471   mMarker = pDisk->ReadInt32();
 
  473   mFineLength = pDisk->ReadInt16();
 
  475   mCoarseLength = pDisk->ReadInt32();
 
  477   mTime = pDisk->ReadInt16();
 
  483 AkaiProgram::AkaiProgram(
DiskImage* pDisk, 
AkaiVolume* pParent, 
const AkaiDirEntry& DirEntry)
 
  484   : AkaiDiskElement(pDisk->GetPos())
 
  488   mDirEntry = DirEntry;
 
  493 AkaiProgram::~AkaiProgram()
 
  496     delete[] mpKeygroups;
 
  499 AkaiDirEntry AkaiProgram::GetDirEntry()
 
  504 bool AkaiProgram::Load()
 
  507   uint temppos = mpDisk->GetPos();
 
  508   mpDisk->SetPos(mpParent->GetParent()->GetOffset() + mDirEntry.mStart * AKAI_BLOCK_SIZE );
 
  512   uint8_t ProgID = mpDisk->ReadInt8();
 
  513   if (ProgID != AKAI_PROGRAM_ID)
 
  515     mpDisk->SetPos(temppos);
 
  522   mpDisk->
Read(buffer, 12, 1);
 
  523   AkaiToAscii(buffer, 12);
 
  526   mMidiProgramNumber = mpDisk->ReadInt8();
 
  528   mMidiChannel = mpDisk->ReadInt8();
 
  530   mPolyphony = mpDisk->ReadInt8();
 
  532   mPriority = mpDisk->ReadInt8();
 
  534   mLowKey = mpDisk->ReadInt8();
 
  536   mHighKey = mpDisk->ReadInt8();
 
  538   mOctaveShift = mpDisk->ReadInt8();
 
  540   mAuxOutputSelect = mpDisk->ReadInt8();
 
  542   mMixOutputSelect = mpDisk->ReadInt8();
 
  544   mMixPan = mpDisk->ReadInt8();
 
  546   mVolume = mpDisk->ReadInt8();
 
  548   mVelocityToVolume = mpDisk->ReadInt8();
 
  550   mKeyToVolume = mpDisk->ReadInt8();
 
  552   mPressureToVolume = mpDisk->ReadInt8();
 
  554   mPanLFORate = mpDisk->ReadInt8();
 
  556   mPanLFODepth = mpDisk->ReadInt8();
 
  558   mPanLFODelay = mpDisk->ReadInt8();
 
  560   mKeyToPan = mpDisk->ReadInt8();
 
  562   mLFORate = mpDisk->ReadInt8();
 
  564   mLFODepth = mpDisk->ReadInt8();
 
  566   mLFODelay = mpDisk->ReadInt8();
 
  568   mModulationToLFODepth = mpDisk->ReadInt8();
 
  570   mPressureToLFODepth = mpDisk->ReadInt8();
 
  572   mVelocityToLFODepth = mpDisk->ReadInt8();
 
  574   mBendToPitch = mpDisk->ReadInt8();
 
  576   mPressureToPitch = mpDisk->ReadInt8();
 
  578   mKeygroupCrossfade = mpDisk->ReadInt8()?
true:
false;
 
  580   mNumberOfKeygroups = mpDisk->ReadInt8();
 
  585   for (i = 0; i<11; i++)
 
  586     mKeyTemperament[i] =  mpDisk->ReadInt8();
 
  588   mFXOutput = mpDisk->ReadInt8()?
true:
false;
 
  590   mModulationToPan = mpDisk->ReadInt8();
 
  592   mStereoCoherence = mpDisk->ReadInt8()?
true:
false;
 
  594   mLFODesync = mpDisk->ReadInt8()?
true:
false;
 
  596   mPitchLaw = mpDisk->ReadInt8();
 
  598   mVoiceReassign = mpDisk->ReadInt8();
 
  600   mSoftpedToVolume = mpDisk->ReadInt8();
 
  602   mSoftpedToAttack = mpDisk->ReadInt8();
 
  604   mSoftpedToFilter = mpDisk->ReadInt8();
 
  606   mSoftpedToTuneCents = mpDisk->ReadInt8();
 
  608   mSoftpedToTuneSemitones = mpDisk->ReadInt8();
 
  610   mKeyToLFORate = mpDisk->ReadInt8();
 
  612   mKeyToLFODepth = mpDisk->ReadInt8();
 
  614   mKeyToLFODelay = mpDisk->ReadInt8();
 
  616   mVoiceOutputScale = mpDisk->ReadInt8();
 
  618   mStereoOutputScale = mpDisk->ReadInt8();
 
  623     delete[] mpKeygroups;
 
  624   mpKeygroups = 
new AkaiKeygroup[mNumberOfKeygroups];
 
  625   for (i = 0; i < mNumberOfKeygroups; i++)
 
  628     mpDisk->SetPos(mpParent->GetParent()->GetOffset() + mDirEntry.mStart * AKAI_BLOCK_SIZE + 150 * (i+1));
 
  629     if (!mpKeygroups[i].Load(mpDisk))
 
  631       mpDisk->SetPos(temppos);
 
  636   mpDisk->SetPos(temppos);
 
  640 uint AkaiProgram::ListSamples(std::list<String>& )
 
  645 AkaiSample* AkaiProgram::GetSample(uint )
 
  650 AkaiSample* AkaiProgram::GetSample(
const String& )
 
  656 bool AkaiKeygroup::Load(
DiskImage* pDisk)
 
  662   if (pDisk->ReadInt8() != AKAI_KEYGROUP_ID)
 
  667   mLowKey = pDisk->ReadInt8();
 
  669   mHighKey = pDisk->ReadInt8();
 
  671   mTuneCents = pDisk->ReadInt8();
 
  673   mTuneSemitones = pDisk->ReadInt8();
 
  675   mFilter = pDisk->ReadInt8();
 
  677   mKeyToFilter = pDisk->ReadInt8();
 
  679   mVelocityToFilter = pDisk->ReadInt8();
 
  681   mPressureToFilter = pDisk->ReadInt8();
 
  683   mEnveloppe2ToFilter = pDisk->ReadInt8();
 
  702     mEnveloppes[i].Load(pDisk);
 
  705   mVelocityToEnveloppe2ToFilter = pDisk->ReadInt8();
 
  707   mEnveloppe2ToPitch = pDisk->ReadInt8();
 
  709   mVelocityZoneCrossfade = pDisk->ReadInt8()?
true:
false;
 
  711   mVelocityZoneUsed = pDisk->ReadInt8();
 
  740     mSamples[i].Load(pDisk);
 
  743   mBeatDetune = pDisk->ReadInt8();
 
  745   mHoldAttackUntilLoop = pDisk->ReadInt8()?
true:
false;
 
  748     mSampleKeyTracking[i] = pDisk->ReadInt8()?
true:
false;
 
  751     mSampleAuxOutOffset[i] = pDisk->ReadInt8();
 
  754     mVelocityToSampleStart[i] = pDisk->ReadInt8();
 
  757     mVelocityToVolumeOffset[i] = pDisk->ReadInt8();
 
  763 bool AkaiEnveloppe::Load(
DiskImage* pDisk)
 
  766   mAttack = pDisk->ReadInt8();
 
  768   mDecay = pDisk->ReadInt8();
 
  770   mSustain = pDisk->ReadInt8();
 
  772   mRelease = pDisk->ReadInt8();
 
  774   mVelocityToAttack = pDisk->ReadInt8();
 
  776   mVelocityToRelease = pDisk->ReadInt8();
 
  778   mOffVelocityToRelease = pDisk->ReadInt8();
 
  780   mKeyToDecayAndRelease = pDisk->ReadInt8();
 
  784 bool AkaiKeygroupSample::Load(
DiskImage* pDisk)
 
  788   pDisk->
Read(buffer, 12, 1);
 
  789   AkaiToAscii(buffer, 12);
 
  793   mLowLevel = pDisk->ReadInt8();
 
  828   mDirEntry = DirEntry;
 
  830   if (mDirEntry.mType != AKAI_TYPE_DIR_S1000 && mDirEntry.mType != AKAI_TYPE_DIR_S3000)
 
  832     printf(
"Creating Unknown Volume type! %d\n",mDirEntry.mType);
 
  834     OutputDebugString(
"Creating Unknown Volume type!\n");
 
  839 AkaiVolume::~AkaiVolume()
 
  842     std::list<AkaiProgram*>::iterator it;
 
  843     std::list<AkaiProgram*>::iterator end = mpPrograms.end();
 
  844     for (it = mpPrograms.begin(); it != end; it++)
 
  850     std::list<AkaiSample*>::iterator it;
 
  851     std::list<AkaiSample*>::iterator end = mpSamples.end();
 
  852     for (it = mpSamples.begin(); it != end; it++)
 
  858 uint AkaiVolume::ReadDir()
 
  861   if (mpPrograms.empty())
 
  863     uint maxfiles = ReadFAT(mpDisk, mpParent,mDirEntry.mStart) ? AKAI_MAX_FILE_ENTRIES_S1000 : AKAI_MAX_FILE_ENTRIES_S3000;
 
  864     for (i = 0; i < maxfiles; i++) 
 
  866       AkaiDirEntry DirEntry;
 
  867       ReadDirEntry(mpDisk, mpParent, DirEntry, mDirEntry.mStart, i); 
 
  869       if (DirEntry.mType == 
'p') 
 
  873         mpPrograms.push_back(pProgram);
 
  875       else if (DirEntry.mType == 
's') 
 
  877         AkaiSample* pSample = 
new AkaiSample(mpDisk, 
this, DirEntry);
 
  879         mpSamples.push_back(pSample);
 
  883   return (uint)(mpPrograms.size() + mpSamples.size());
 
  886 uint AkaiVolume::ListPrograms(std::list<AkaiDirEntry>& rPrograms)
 
  891   std::list<AkaiProgram*>::iterator it;
 
  892   std::list<AkaiProgram*>::iterator end = mpPrograms.end();
 
  893   for (it = mpPrograms.begin(); it != end; it++)
 
  895       rPrograms.push_back((*it)->GetDirEntry());
 
  896   return (uint)rPrograms.size();
 
  903   if (mpPrograms.empty())
 
  905     std::list<AkaiDirEntry> dummy;
 
  909   std::list<AkaiProgram*>::iterator it;
 
  910   std::list<AkaiProgram*>::iterator end = mpPrograms.end();
 
  911   for (it = mpPrograms.begin(); it != end; it++)
 
  913     if (*it && i == Index)
 
  923 AkaiProgram* AkaiVolume::GetProgram(
const String& rName)
 
  925   if (mpPrograms.empty())
 
  927     std::list<AkaiDirEntry> dummy;
 
  931   std::list<AkaiProgram*>::iterator it;
 
  932   std::list<AkaiProgram*>::iterator end = mpPrograms.end();
 
  933   for (it = mpPrograms.begin(); it != end; it++)
 
  935     if (*it && rName == (*it)->GetDirEntry().mName)
 
  944 uint AkaiVolume::ListSamples(std::list<AkaiDirEntry>& rSamples)
 
  949   std::list<AkaiSample*>::iterator it;
 
  950   std::list<AkaiSample*>::iterator end = mpSamples.end();
 
  951   for (it = mpSamples.begin(); it != end; it++)
 
  953       rSamples.push_back((*it)->GetDirEntry());
 
  954   return (uint)rSamples.size();
 
  957 AkaiSample* AkaiVolume::GetSample(uint Index)
 
  961   if (mpSamples.empty())
 
  963     std::list<AkaiDirEntry> dummy;
 
  967   std::list<AkaiSample*>::iterator it;
 
  968   std::list<AkaiSample*>::iterator end = mpSamples.end();
 
  969   for (it = mpSamples.begin(); it != end; it++)
 
  971     if (*it && i == Index)
 
  981 AkaiSample* AkaiVolume::GetSample(
const String& rName)
 
  983   if (mpSamples.empty())
 
  985     std::list<AkaiDirEntry> dummy;
 
  989   std::list<AkaiSample*>::iterator it;
 
  990   std::list<AkaiSample*>::iterator end = mpSamples.end();
 
  991   for (it = mpSamples.begin(); it != end; it++)
 
  993     if (*it && rName == (*it)->GetDirEntry().mName)
 
 1002 AkaiDirEntry AkaiVolume::GetDirEntry()
 
 1007 bool AkaiVolume::IsEmpty()
 
 1009   return ReadDir() == 0;
 
 1021 AkaiPartition::~AkaiPartition()
 
 1023   std::list<AkaiVolume*>::iterator it;
 
 1024   std::list<AkaiVolume*>::iterator end = mpVolumes.end();
 
 1025   for (it = mpVolumes.begin(); it != end; it++)
 
 1030 uint AkaiPartition::ListVolumes(std::list<AkaiDirEntry>& rVolumes)
 
 1034   if (mpVolumes.empty())
 
 1036     for (i = 0; i < AKAI_MAX_DIR_ENTRIES; i++)
 
 1038       AkaiDirEntry DirEntry;
 
 1039       ReadDirEntry(mpDisk, 
this, DirEntry, AKAI_ROOT_ENTRY_OFFSET, i);
 
 1040       DirEntry.mIndex = i;
 
 1041       if (DirEntry.mType == AKAI_TYPE_DIR_S1000 || DirEntry.mType == AKAI_TYPE_DIR_S3000)
 
 1045         if (!pVolume->IsEmpty())
 
 1047           mpVolumes.push_back(pVolume);
 
 1048           rVolumes.push_back(DirEntry);
 
 1057     std::list<AkaiVolume*>::iterator it;
 
 1058     std::list<AkaiVolume*>::iterator end = mpVolumes.end();
 
 1059     for (it = mpVolumes.begin(); it != end; it++)
 
 1061         rVolumes.push_back((*it)->GetDirEntry());
 
 1063   return (uint)rVolumes.size();
 
 1066 AkaiVolume* AkaiPartition::GetVolume(uint Index)
 
 1070   if (mpVolumes.empty())
 
 1072     std::list<AkaiDirEntry> dummy;
 
 1076   std::list<AkaiVolume*>::iterator it;
 
 1077   std::list<AkaiVolume*>::iterator end = mpVolumes.end();
 
 1078   for (it = mpVolumes.begin(); it != end; it++)
 
 1080     if (*it && i == Index)
 
 1090 AkaiVolume* AkaiPartition::GetVolume(
const String& rName)
 
 1092   if (mpVolumes.empty())
 
 1094     std::list<AkaiDirEntry> dummy;
 
 1098   std::list<AkaiVolume*>::iterator it;
 
 1099   std::list<AkaiVolume*>::iterator end = mpVolumes.end();
 
 1100   for (it = mpVolumes.begin(); it != end; it++)
 
 1102     if (*it && rName == (*it)->GetDirEntry().mName)
 
 1111 bool AkaiPartition::IsEmpty()
 
 1113   std::list<AkaiDirEntry> Volumes;
 
 1114   return ListVolumes(Volumes) == 0;
 
 1125 AkaiDisk::~AkaiDisk()
 
 1127   std::list<AkaiPartition*>::iterator it;
 
 1128   std::list<AkaiPartition*>::iterator end = mpPartitions.end();
 
 1129   for (it = mpPartitions.begin(); it != end ; it++)
 
 1134 uint AkaiDisk::GetPartitionCount()
 
 1136   if (!mpPartitions.empty())
 
 1137     return (uint)mpPartitions.size();
 
 1141   while (size != AKAI_PARTITION_END_MARK && size != 0x0fff && size != 0xffff
 
 1142          && size<30720 && mpPartitions.size()<9)
 
 1146     pPartition->Acquire();
 
 1147     pPartition->SetOffset(offset);
 
 1149     if (!pPartition->IsEmpty())
 
 1151       mpPartitions.push_back(pPartition); 
 
 1154     mpDisk->SetPos(offset);
 
 1155     if (!mpDisk->ReadInt16(&size))
 
 1156       return (uint)mpPartitions.size();
 
 1158     offset +=  AKAI_BLOCK_SIZE * t;
 
 1162   return (uint)mpPartitions.size();
 
 1167   std::list<AkaiPartition*>::iterator it;
 
 1168   std::list<AkaiPartition*>::iterator end = mpPartitions.end();
 
 1170   for (i = 0, it = mpPartitions.begin(); it != end && i != count; i++) it++;
 
 1172   if (i != count || it == end)
 
 1185   pDisk->SetPos(pPartition->GetOffset()+AKAI_FAT_OFFSET + block*2); 
 
 1186   pDisk->
Read(&value, 2,1); 
 
 1191 bool AkaiDiskElement::ReadDirEntry(
DiskImage* pDisk, 
AkaiPartition* pPartition, AkaiDirEntry& rEntry, 
int block, 
int pos)
 
 1195   if (block == AKAI_ROOT_ENTRY_OFFSET)
 
 1197     pDisk->SetPos(pPartition->GetOffset()+AKAI_DIR_ENTRY_OFFSET + pos * AKAI_DIR_ENTRY_SIZE);
 
 1198     pDisk->
Read(buffer, 12, 1);
 
 1199     AkaiToAscii(buffer, 12);
 
 1200     rEntry.mName = buffer;
 
 1202     pDisk->ReadInt16(&rEntry.mType);
 
 1203     pDisk->ReadInt16(&rEntry.mStart);
 
 1211       pDisk->SetPos(block * AKAI_BLOCK_SIZE + pos * AKAI_FILE_ENTRY_SIZE + pPartition->GetOffset());
 
 1216       temp = ReadFAT(pDisk, pPartition, block);
 
 1217       pDisk->SetPos(pPartition->GetOffset()+temp * AKAI_BLOCK_SIZE + (pos - 341) * AKAI_FILE_ENTRY_SIZE);
 
 1220     pDisk->
Read(buffer, 12, 1);
 
 1221     AkaiToAscii(buffer, 12);
 
 1222     rEntry.mName = buffer; 
 
 1225     pDisk->SetPos(4,akai_stream_curpos);
 
 1226     pDisk->
Read(&t1, 1,1);
 
 1229     pDisk->
Read(&t1, 1,1);
 
 1230     pDisk->
Read(&t2, 1,1);
 
 1231     pDisk->
Read(&t3, 1,1);
 
 1232     rEntry.mSize = (
unsigned char)t1 | ((
unsigned char)t2 <<8) | ((
unsigned char)t3<<16); 
 
 1234     pDisk->ReadInt16(&rEntry.mStart,1);
 
 1239 void AkaiDiskElement::AkaiToAscii(
char * buffer, 
int length) 
 
 1243   for (i = 0; i < length; i++)
 
 1245     if (buffer[i]>=0 && buffer[i]<=9)
 
 1247     else if (buffer[i]==10)
 
 1249     else if (buffer[i]>=11 && buffer[i]<=36)
 
 1250       buffer[i] = 64+(buffer[i]-10);
 
 1254   buffer[length] = 
'\0';
 
 1255   while (length-- > 0 && buffer[length] == 32)
 
 1259   buffer[length+1] = 
'\0';
 
 1273 kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
 
 1275   kern_return_t  kernResult;
 
 1276   mach_port_t   masterPort;
 
 1277   CFMutableDictionaryRef classesToMatch;
 
 1279   kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
 
 1280   if ( KERN_SUCCESS != kernResult )
 
 1282     printf( 
"IOMasterPort returned %d\n", kernResult );
 
 1285   classesToMatch = IOServiceMatching( kIOCDMediaClass );
 
 1286   if ( classesToMatch == NULL )
 
 1288       printf( 
"IOServiceMatching returned a NULL dictionary.\n" );
 
 1292     CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue );
 
 1295   kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator );
 
 1296   if ( KERN_SUCCESS != kernResult )
 
 1298       printf( 
"IOServiceGetMatchingServices returned %d\n", kernResult );
 
 1304 kern_return_t GetBSDPath( io_iterator_t mediaIterator, 
char *bsdPath, CFIndex maxPathSize )
 
 1306   io_object_t  nextMedia;
 
 1307   kern_return_t kernResult = KERN_FAILURE;
 
 1311   nextMedia = IOIteratorNext( mediaIterator );
 
 1314     CFTypeRef bsdPathAsCFString;
 
 1316     bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia,
 
 1317                                                          CFSTR( kIOBSDNameKey ), 
 
 1318                                                          kCFAllocatorDefault,
 
 1320     if ( bsdPathAsCFString )
 
 1322       size_t devPathLength;
 
 1324       strcpy( bsdPath, _PATH_DEV );
 
 1325       strcat( bsdPath, 
"r" );
 
 1327       devPathLength = strlen( bsdPath );
 
 1329       if ( CFStringGetCString( (__CFString*)bsdPathAsCFString,
 
 1330                                bsdPath + devPathLength,
 
 1331                                maxPathSize - devPathLength,
 
 1332                                kCFStringEncodingASCII ) )
 
 1334           printf( 
"BSD path: %s\n", bsdPath );
 
 1335           kernResult = KERN_SUCCESS;
 
 1338       CFRelease( bsdPathAsCFString );
 
 1340     IOObjectRelease( nextMedia );
 
 1354 #define MSF_TO_LBA(msf) (((((msf).minute * 60UL) + (msf).second) * 75UL) + (msf).frame - 150) 
 1362   struct _CDMSF  address;
 
 1370   u_char             first_session;
 
 1371   u_char             last_session;
 
 1372   struct _CDTOC_Desc  trackdesc[1];
 
 1375 static struct _CDTOC * ReadTOC (
const char * devpath )
 
 1377   struct _CDTOC * toc_p = NULL;
 
 1378   io_iterator_t iterator = 0;
 
 1379   io_registry_entry_t service = 0;
 
 1380   CFDictionaryRef properties = 0;
 
 1382   mach_port_t port = 0; 
 
 1384   if (( devname = strrchr( devpath, 
'/' )) != NULL ) 
 
 1390     devname = ( 
char *) devpath;
 
 1393   if ( IOMasterPort(bootstrap_port, &port ) != KERN_SUCCESS )
 
 1395     printf(  
"IOMasterPort failed\n" ); 
goto Exit ;
 
 1397   if ( IOServiceGetMatchingServices( port, IOBSDNameMatching( port, 0, devname ),
 
 1398                                      &iterator ) != KERN_SUCCESS ) 
 
 1400     printf( 
"IOServiceGetMatchingServices failed\n" ); 
goto Exit ;
 
 1404     IOObjectGetClass(iterator,buffer);
 
 1405     printf(
"Service: %s\n",buffer);
 
 1408   IOIteratorReset (iterator);
 
 1409   service = IOIteratorNext( iterator );
 
 1411   IOObjectRelease( iterator );
 
 1414   while ( service && !IOObjectConformsTo( service, 
"IOCDMedia" ))
 
 1417     IOObjectGetClass(service,buffer);
 
 1418     printf(
"Service: %s\n",buffer);
 
 1420     if ( IORegistryEntryGetParentIterator( service, kIOServicePlane, &iterator ) != KERN_SUCCESS ) 
 
 1422       printf( 
"IORegistryEntryGetParentIterator failed\n" );
 
 1426     IOObjectRelease( service );
 
 1427     service = IOIteratorNext( iterator );
 
 1428     IOObjectRelease( iterator );
 
 1431   if ( service == NULL ) 
 
 1433     printf(  
"CD media not found\n" ); 
goto Exit ;
 
 1435   if ( IORegistryEntryCreateCFProperties( service, (__CFDictionary **) &properties,
 
 1436                                           kCFAllocatorDefault,
 
 1437                                           kNilOptions ) != KERN_SUCCESS ) 
 
 1439     printf( 
"IORegistryEntryGetParentIterator failed\n" ); 
goto Exit ;
 
 1442   data = (CFDataRef) CFDictionaryGetValue( properties, CFSTR( 
"TOC" ) ); 
 
 1445     printf(  
"CFDictionaryGetValue failed\n" ); 
goto Exit ;
 
 1453     buflen = CFDataGetLength( data ) + 1;
 
 1454     range = CFRangeMake( 0, buflen );
 
 1455     toc_p = ( 
struct _CDTOC *) malloc( buflen );
 
 1456     if ( toc_p == NULL )
 
 1458       printf( 
"Out of memory\n" ); 
goto Exit ;
 
 1462       CFDataGetBytes( data, range, ( 
unsigned char *) toc_p );
 
 1470     CFRelease( properties );
 
 1476     IOObjectRelease( service );
 
 1488   sprintf(buffer,
"%c:\\",
'A'+disk);
 
 1489   mSize = GetFileSize(buffer,NULL);
 
 1491   sprintf(buffer,
"\\\\.\\%c:",
'a'+disk);
 
 1492   mFile = CreateFile(buffer, GENERIC_READ,0,NULL,OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS,NULL);
 
 1496   DISK_GEOMETRY* pdg = &dg;
 
 1497   BOOL res = DeviceIoControl(mFile,
 
 1498     IOCTL_DISK_GET_DRIVE_GEOMETRY,
 
 1506     mSize = dg.BytesPerSector * dg.SectorsPerTrack * dg.TracksPerCylinder * dg.Cylinders.LowPart;
 
 1507     mClusterSize = dg.BytesPerSector;
 
 1509 #elif defined(_CARBON_) || defined(__APPLE__) 
 1510   kern_return_t  kernResult;
 
 1511   io_iterator_t mediaIterator;
 
 1512   char  bsdPath[ MAXPATHLEN ];
 
 1513   kernResult = FindEjectableCDMedia( &mediaIterator );
 
 1514   kernResult = GetBSDPath( mediaIterator, bsdPath, 
sizeof( bsdPath ) );
 
 1515   if ( bsdPath[ 0 ] != 
'\0' )
 
 1517         strcpy(bsdPath,
"/dev/rdisk1s0");
 
 1519       struct _CDTOC * toc = ReadTOC( bsdPath );
 
 1522         size_t toc_entries = ( toc->length - 2 ) / 
sizeof (
struct _CDTOC_Desc );
 
 1524         int start_sector = -1;
 
 1525         int data_track = -1;
 
 1530         for (ssize_t i=toc_entries - 1; i>=0; i-- )
 
 1532           if ( start_sector != -1 )
 
 1534             start_sector = MSF_TO_LBA(toc->trackdesc[i].p) - start_sector;
 
 1538           if (( toc->trackdesc[i].ctrl_adr >> 4) != 1 )
 
 1540           if ( toc->trackdesc[i].ctrl_adr & 0x04 )
 
 1542             data_track = toc->trackdesc[i].point;
 
 1543             start_sector = MSF_TO_LBA(toc->trackdesc[i].p);
 
 1548         if ( start_sector == -1 )
 
 1557     mFile = open(bsdPath,O_RDONLY);
 
 1559       printf(
"Error while opening file: %s\n",bsdPath);
 
 1562       printf(
"opened file: %s\n",bsdPath);
 
 1564             mSize = (int) lseek(mFile,1000000000,SEEK_SET);
 
 1565             printf(
"size %d\n",mSize);
 
 1566             lseek(mFile,0,SEEK_SET);
 
 1568             mSize = 700 * 1024 * 1024;
 
 1572   if ( mediaIterator )
 
 1574     IOObjectRelease( mediaIterator );
 
 1577   OpenStream(
"/dev/cdrom");
 
 1581 void DiskImage::Init()
 
 1585   mCluster     = (uint)-1;
 
 1589   mpCache = (
char*) VirtualAlloc(NULL,mClusterSize,MEM_COMMIT,PAGE_READWRITE);
 
 1595 DiskImage::~DiskImage()
 
 1598   if (mFile != INVALID_HANDLE_VALUE)
 
 1602 #elif defined _CARBON_ || defined(__APPLE__) || LINUX 
 1611     VirtualFree(mpCache, 0, MEM_RELEASE);
 
 1612 #elif defined(_CARBON_) || defined(__APPLE__) || LINUX 
 1618 akai_stream_state_t DiskImage::GetState()
 const 
 1620   if (!mFile)       
return akai_stream_closed;
 
 1621   if (mPos > mSize) 
return akai_stream_end_reached;
 
 1622   return akai_stream_ready;
 
 1625 int DiskImage::GetPos()
 const 
 1630 int DiskImage::SetPos(
int Where, akai_stream_whence_t Whence)
 
 1636   case akai_stream_start:
 
 1641   case akai_stream_curpos:
 
 1644   case akai_stream_end:
 
 1655 int DiskImage::Available (uint WordSize)
 
 1657   return (mSize-mPos)/WordSize;
 
 1663   int sizetoread = WordCount * WordSize;
 
 1665   while (sizetoread > 0) {
 
 1666     if (mSize <= mPos) 
return readbytes / WordSize;
 
 1667     int requestedCluster = (mRegularFile) ? mPos / mClusterSize
 
 1668                                           : mPos / mClusterSize + mStartFrame;
 
 1669     if (mCluster != requestedCluster) { 
 
 1670       mCluster = requestedCluster;
 
 1672       if (mCluster * mClusterSize != SetFilePointer(mFile, mCluster * mClusterSize, NULL, FILE_BEGIN)) {
 
 1673         printf(
"ERROR: couldn't seek device!\n");
 
 1675         if ((readbytes > 0) && (mEndian != eEndianNative)) {
 
 1677             case 2: bswap_16_s ((uint16*)pData, readbytes); 
break;
 
 1678             case 4: bswap_32_s ((uint32*)pData, readbytes); 
break;
 
 1679             case 8: bswap_64_s ((uint64*)pData, readbytes); 
break;
 
 1683         return readbytes / WordSize;
 
 1686       ReadFile(mFile, mpCache, mClusterSize, &size, NULL);
 
 1687 #elif defined(_CARBON_) || defined(__APPLE__) || LINUX 
 1688       if (mCluster * mClusterSize != lseek(mFile, mCluster * mClusterSize, SEEK_SET))
 
 1689         return readbytes / WordSize;
 
 1691        read(mFile, mpCache, mClusterSize);
 
 1697     int currentReadSize = sizetoread;
 
 1698     int posInCluster = mPos % mClusterSize;
 
 1699     if (currentReadSize > mClusterSize - posInCluster) 
 
 1700       currentReadSize = mClusterSize - posInCluster;
 
 1702     memcpy((uint8_t*)pData + readbytes, mpCache + posInCluster, currentReadSize);
 
 1704     mPos       += currentReadSize;
 
 1705     readbytes  += currentReadSize;
 
 1706     sizetoread -= currentReadSize;
 
 1711   if ((readbytes > 0) && (mEndian != eEndianNative))
 
 1714       case 2: bswap_16_s ((uint16_t*)pData, readbytes); 
break;
 
 1715       case 4: bswap_32_s ((uint32_t*)pData, readbytes); 
break;
 
 1716       case 8: bswap_64_s ((uint64_t*)pData, readbytes); 
break;
 
 1720   return readbytes / WordSize;
 
 1723 void DiskImage::ReadInt8(uint8_t* pData, uint WordCount) {
 
 1724   Read(pData, WordCount, 1);
 
 1727 void DiskImage::ReadInt16(uint16_t* pData, uint WordCount) {
 
 1729   for (i = 0; i < WordCount; i++) {
 
 1730     *(pData + i) = ReadInt16();
 
 1734 void DiskImage::ReadInt32(uint32_t* pData, uint WordCount) {
 
 1736   for (i = 0; i < WordCount; i++) {
 
 1737     *(pData + i) = ReadInt32();
 
 1741 int DiskImage::ReadInt8(uint8_t* pData) {
 
 1742   return Read(pData, 1, 1);
 
 1745 int DiskImage::ReadInt16(uint16_t* pData) {
 
 1746   int result = 
Read(pData, 1, 2);
 
 1748   swapBytes_16(pData);
 
 1753 int DiskImage::ReadInt32(uint32_t* pData) {
 
 1754   int result = 
Read(pData, 1, 4);
 
 1756   swapBytes_32(pData);
 
 1761 uint8_t DiskImage::ReadInt8()
 
 1768 uint16_t DiskImage::ReadInt16()
 
 1773   swapBytes_16(&word);
 
 1778 uint32_t DiskImage::ReadInt32()
 
 1783   swapBytes_32(&word);
 
 1788 void DiskImage::OpenStream(
const char* path) {
 
 1790   mFile = CreateFile(path, GENERIC_READ,0,NULL,OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS,NULL);
 
 1791   BY_HANDLE_FILE_INFORMATION FileInfo;
 
 1792   GetFileInformationByHandle(mFile,&FileInfo);
 
 1793   mSize = FileInfo.nFileSizeLow;
 
 1794 #elif defined(_CARBON_) || defined(__APPLE__) || LINUX 
 1795   struct stat filestat;
 
 1796   stat(path,&filestat);
 
 1797   mFile = open(path, O_RDONLY | O_NONBLOCK);
 
 1799     printf(
"Can't open %s\n", path);
 
 1804   if (S_ISREG(filestat.st_mode)) { 
 
 1805     printf(
"Using regular Akai image file.\n");
 
 1806     mRegularFile = 
true;
 
 1807     mSize        = (int) filestat.st_size;
 
 1808     mClusterSize = DISK_CLUSTER_SIZE;
 
 1809     mpCache = (
char*) malloc(mClusterSize);
 
 1811 #if defined(_CARBON_) || defined(__APPLE__) 
 1812     printf(
"Can't open %s: not a regular file\n", path);
 
 1814     mRegularFile = 
false;
 
 1815     mClusterSize = CD_FRAMESIZE;
 
 1816     mpCache = (
char*) malloc(mClusterSize);
 
 1818     struct cdrom_tochdr   tochdr;
 
 1819     struct cdrom_tocentry tocentry;
 
 1821     if (ioctl(mFile, CDROMREADTOCHDR, (
unsigned long)&tochdr) < 0) {
 
 1822       printf(
"Trying to read TOC of %s failed\n", path);
 
 1827     printf(
"Total tracks: %d\n", tochdr.cdth_trk1);
 
 1830     tocentry.cdte_format = CDROM_LBA;
 
 1832     int firstDataTrack = -1;
 
 1833     int start, end, length;
 
 1836     for (
int t = tochdr.cdth_trk1; t >= 0; t--) {
 
 1837       tocentry.cdte_track = (t == tochdr.cdth_trk1) ? CDROM_LEADOUT : t + 1;
 
 1838       if (ioctl(mFile, CDROMREADTOCENTRY, (
unsigned long)&tocentry) < 0){
 
 1839         printf(
"Failed to read TOC entry for track %d\n", tocentry.cdte_track);
 
 1844       if (tocentry.cdte_track == CDROM_LEADOUT) {
 
 1845           printf(
"Lead Out: Start(LBA)=%d\n", tocentry.cdte_addr.lba);
 
 1848         printf(
"Track %d: Start(LBA)=%d End(LBA)=%d Length(Blocks)=%d ",
 
 1849                tocentry.cdte_track, tocentry.cdte_addr.lba, prev_addr - 1, prev_addr - tocentry.cdte_addr.lba);
 
 1850         if (tocentry.cdte_ctrl & CDROM_DATA_TRACK) {
 
 1851           printf(
"Type: Data\n");
 
 1852           firstDataTrack = tocentry.cdte_track;
 
 1853           start  = tocentry.cdte_addr.lba;
 
 1854           end    = prev_addr - 1;
 
 1855           length = prev_addr - tocentry.cdte_addr.lba;
 
 1857         else printf(
"Type: Audio\n");
 
 1859       prev_addr = tocentry.cdte_addr.lba;
 
 1862     if (firstDataTrack == -1) {
 
 1863       printf(
"Sorry, no data track found on %s\n", path);
 
 1869     printf(
"Ok, I'll pick track %d\n", firstDataTrack);
 
 1870     mStartFrame = start;
 
 1872     mSize       = length * CD_FRAMESIZE;
 
 1880 #if defined(_CARBON_) || defined(__APPLE__) || LINUX 
 1881   const uint bufferSize = 524288; 
 
 1882   int fOut = open(path, O_WRONLY | O_NONBLOCK | O_CREAT | O_TRUNC,
 
 1883                   S_IRUSR | S_IWUSR | S_IRGRP);
 
 1885     printf(
"Can't open output file %s\n", path);
 
 1888   uint8_t* pBuffer = 
new uint8_t[bufferSize];
 
 1890   while (Available() > 0) {
 
 1891     int readBytes = 
Read(pBuffer,bufferSize,1);
 
 1892     if (readBytes > 0) write(fOut,pBuffer,readBytes);
 
 1901 inline void DiskImage::swapBytes_16(
void* Word) {
 
 1903   byteCache = *((uint8_t*) Word);
 
 1904   *((uint8_t*) Word)     = *((uint8_t*) Word + 1);
 
 1905   *((uint8_t*) Word + 1) = byteCache;
 
 1908 inline void DiskImage::swapBytes_32(
void* Word) {
 
 1910   byteCache = *((uint8_t*) Word);
 
 1911   *((uint8_t*) Word)     = *((uint8_t*) Word + 3);
 
 1912   *((uint8_t*) Word + 3) = byteCache;
 
 1913   byteCache = *((uint8_t*) Word + 1);
 
 1914   *((uint8_t*) Word + 1) = *((uint8_t*) Word + 2);
 
 1915   *((uint8_t*) Word + 2) = byteCache;
 
Toplevel AKAI image interpreter.
Encapsulates one disk partition of an AKAI disk.
AKAI instrument definition.
Subdivision of an AKAI disk partition.
Accessing AKAI image either from file or a drive (i.e.
bool WriteImage(const char *path)
Extract Akai data track and write it into a regular file.
virtual int Read(void *pData, uint WordCount, uint WordSize)
Returns number of successfully read words.
DiskImage(const char *path)
Open an image from a file.