29 #if defined(_CARBON_) || defined(__APPLE__) 30 # if defined (__GNUC__) && (__GNUC__ >= 4) 31 # include <sys/disk.h> 33 # include <dev/disk.h> 36 #include <sys/types.h> 39 #if defined(_CARBON_) || defined(__APPLE__) 41 #include <sys/ioctl.h> 42 #include <sys/param.h> 43 #include <IOKit/IOKitLib.h> 44 #include <IOKit/IOBSD.h> 45 #include <IOKit/storage/IOMediaBSDClient.h> 46 #include <IOKit/storage/IOMedia.h> 47 #include <IOKit/storage/IOCDMedia.h> 48 #include <IOKit/storage/IOCDTypes.h> 49 #include <CoreFoundation/CoreFoundation.h> 52 #if defined(_CARBON_) || defined(__APPLE__) 64 #define MSF_TO_LBA(msf) \ 65 (((((msf).minute * 60UL) + (msf).second) * 75UL) + (msf).frame - 150) 72 struct _CDMSF address;
81 struct _CDTOC_Desc trackdesc[1];
91 static kern_return_t FindEjectableCDMedia(io_iterator_t *mediaIterator) {
92 kern_return_t kernResult;
93 CFMutableDictionaryRef classesToMatch;
96 classesToMatch = IOServiceMatching(kIOCDMediaClass);
97 if (classesToMatch == NULL) {
98 printf(
"IOServiceMatching returned a NULL dictionary.\n");
100 CFDictionarySetValue(classesToMatch, CFSTR(kIOMediaEjectableKey), kCFBooleanTrue);
105 kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, classesToMatch, mediaIterator);
112 static kern_return_t GetBSDPath(io_iterator_t mediaIterator,
char *bsdPath, CFIndex maxPathSize) {
113 io_object_t nextMedia;
114 kern_return_t kernResult = KERN_FAILURE;
118 nextMedia = IOIteratorNext(mediaIterator);
120 CFTypeRef bsdPathAsCFString;
122 bsdPathAsCFString = IORegistryEntryCreateCFProperty(nextMedia,
123 CFSTR(kIOBSDNameKey),
126 if (bsdPathAsCFString) {
127 strlcpy(bsdPath, _PATH_DEV, maxPathSize);
133 strlcat(bsdPath,
"r", maxPathSize);
135 size_t devPathLength = strlen(bsdPath);
137 if (CFStringGetCString((CFStringRef)bsdPathAsCFString,
138 bsdPath + devPathLength,
139 maxPathSize - devPathLength,
140 kCFStringEncodingUTF8)) {
141 printf(
"BSD path: %s\n", bsdPath);
142 kernResult = KERN_SUCCESS;
145 CFRelease(bsdPathAsCFString);
148 IOObjectRelease(nextMedia);
213 static struct _CDTOC * ReadTOC(
const char *devpath) {
214 struct _CDTOC * toc_p = NULL;
215 io_iterator_t iterator = 0;
216 io_registry_entry_t service = 0;
217 CFDictionaryRef properties = 0;
219 mach_port_t port = 0;
222 if ((devname = strrchr(devpath,
'/')) != NULL) {
225 devname = (
char *) devpath;
228 if (IOMasterPort(bootstrap_port, &port) != KERN_SUCCESS) {
229 fprintf(stderr,
"IOMasterPort failed\n");
233 if (IOServiceGetMatchingServices(port, IOBSDNameMatching(port, 0, devname),
234 &iterator) != KERN_SUCCESS) {
235 fprintf(stderr,
"IOServiceGetMatchingServices failed\n");
239 service = IOIteratorNext(iterator);
241 IOObjectRelease(iterator);
245 while (service && !IOObjectConformsTo(service,
"IOCDMedia")) {
246 if (IORegistryEntryGetParentIterator(service, kIOServicePlane,
247 &iterator) != KERN_SUCCESS)
249 fprintf(stderr,
"IORegistryEntryGetParentIterator failed\n");
253 IOObjectRelease(service);
254 service = IOIteratorNext(iterator);
255 IOObjectRelease(iterator);
259 fprintf(stderr,
"CD media not found\n");
263 if (IORegistryEntryCreateCFProperties(service, (__CFDictionary **) &properties,
265 kNilOptions) != KERN_SUCCESS)
267 fprintf(stderr,
"IORegistryEntryGetParentIterator failed\n");
271 data = (CFDataRef) CFDictionaryGetValue(properties, CFSTR(kIOCDMediaTOCKey));
273 fprintf(stderr,
"CFDictionaryGetValue failed\n");
279 buflen = CFDataGetLength(data) + 1;
280 range = CFRangeMake(0, buflen);
281 toc_p = (
struct _CDTOC *) malloc(buflen);
283 fprintf(stderr,
"Out of memory\n");
286 CFDataGetBytes(data, range, (
unsigned char *) toc_p);
294 CFRelease(properties);
300 IOObjectRelease(service);
306 #endif // defined(_CARBON_) || defined(__APPLE__) 310 AkaiSample::AkaiSample(
DiskImage* pDisk,
AkaiVolume* pParent,
const AkaiDirEntry& DirEntry)
311 : AkaiDiskElement(pDisk->GetPos())
315 mDirEntry = DirEntry;
324 AkaiSample::~AkaiSample()
330 AkaiDirEntry AkaiSample::GetDirEntry()
335 bool AkaiSample::LoadSampleData()
342 mpDisk->SetPos(mImageOffset);
343 mpSamples = (int16_t*) malloc(mNumberOfSamples *
sizeof(int16_t));
347 mpDisk->ReadInt16((uint16_t*)mpSamples, mNumberOfSamples);
351 void AkaiSample::ReleaseSampleData()
359 int AkaiSample::SetPos(
int Where, akai_stream_whence_t Whence)
361 if (!mHeaderOK)
return -1;
365 case akai_stream_start:
370 case akai_stream_curpos:
373 case akai_stream_end:
374 mPos = mNumberOfSamples - w;
377 if (mPos > mNumberOfSamples) mPos = mNumberOfSamples;
378 if (mPos < 0) mPos = 0;
382 int AkaiSample::Read(
void* pBuffer, uint SampleCount)
384 if (!mHeaderOK)
return 0;
386 if (mPos + SampleCount > mNumberOfSamples) SampleCount = mNumberOfSamples - mPos;
388 mpDisk->SetPos(mImageOffset + mPos * 2);
389 mpDisk->ReadInt16((uint16_t*)pBuffer, SampleCount);
393 bool AkaiSample::LoadHeader()
398 mpDisk->SetPos(mpParent->GetParent()->GetOffset() + mDirEntry.mStart * AKAI_BLOCK_SIZE );
403 if (mpDisk->ReadInt8() != AKAI_SAMPLE_ID)
408 mMidiRootNote = mpDisk->ReadInt8();
411 mpDisk->Read(buffer, 12, 1);
412 AkaiToAscii(buffer, 12);
418 mActiveLoops = mpDisk->ReadInt8();
420 mFirstActiveLoop = mpDisk->ReadInt8();
425 mLoopMode = mpDisk->ReadInt8();
427 mTuneCents = mpDisk->ReadInt8();
429 mTuneSemitones = mpDisk->ReadInt8();
437 mNumberOfSamples = mpDisk->ReadInt32();
439 mStartMarker = mpDisk->ReadInt32();
441 mEndMarker = mpDisk->ReadInt32();
452 mLoops[i].Load(mpDisk);
456 mSamplingFrequency = mpDisk->ReadInt16();
458 mLoopTuneOffset = mpDisk->ReadInt8();
460 mImageOffset = mpParent->GetParent()->GetOffset() + mDirEntry.mStart * AKAI_BLOCK_SIZE + 150;
463 return (mHeaderOK =
true);
466 bool AkaiSampleLoop::Load(
DiskImage* pDisk)
469 mMarker = pDisk->ReadInt32();
471 mFineLength = pDisk->ReadInt16();
473 mCoarseLength = pDisk->ReadInt32();
475 mTime = pDisk->ReadInt16();
481 AkaiProgram::AkaiProgram(
DiskImage* pDisk,
AkaiVolume* pParent,
const AkaiDirEntry& DirEntry)
482 : AkaiDiskElement(pDisk->GetPos())
486 mDirEntry = DirEntry;
491 AkaiProgram::~AkaiProgram()
494 delete[] mpKeygroups;
497 AkaiDirEntry AkaiProgram::GetDirEntry()
502 bool AkaiProgram::Load()
505 uint temppos = mpDisk->GetPos();
506 mpDisk->SetPos(mpParent->GetParent()->GetOffset() + mDirEntry.mStart * AKAI_BLOCK_SIZE );
510 uint8_t ProgID = mpDisk->ReadInt8();
511 if (ProgID != AKAI_PROGRAM_ID)
513 mpDisk->SetPos(temppos);
520 mpDisk->
Read(buffer, 12, 1);
521 AkaiToAscii(buffer, 12);
524 mMidiProgramNumber = mpDisk->ReadInt8();
526 mMidiChannel = mpDisk->ReadInt8();
528 mPolyphony = mpDisk->ReadInt8();
530 mPriority = mpDisk->ReadInt8();
532 mLowKey = mpDisk->ReadInt8();
534 mHighKey = mpDisk->ReadInt8();
536 mOctaveShift = mpDisk->ReadInt8();
538 mAuxOutputSelect = mpDisk->ReadInt8();
540 mMixOutputSelect = mpDisk->ReadInt8();
542 mMixPan = mpDisk->ReadInt8();
544 mVolume = mpDisk->ReadInt8();
546 mVelocityToVolume = mpDisk->ReadInt8();
548 mKeyToVolume = mpDisk->ReadInt8();
550 mPressureToVolume = mpDisk->ReadInt8();
552 mPanLFORate = mpDisk->ReadInt8();
554 mPanLFODepth = mpDisk->ReadInt8();
556 mPanLFODelay = mpDisk->ReadInt8();
558 mKeyToPan = mpDisk->ReadInt8();
560 mLFORate = mpDisk->ReadInt8();
562 mLFODepth = mpDisk->ReadInt8();
564 mLFODelay = mpDisk->ReadInt8();
566 mModulationToLFODepth = mpDisk->ReadInt8();
568 mPressureToLFODepth = mpDisk->ReadInt8();
570 mVelocityToLFODepth = mpDisk->ReadInt8();
572 mBendToPitch = mpDisk->ReadInt8();
574 mPressureToPitch = mpDisk->ReadInt8();
576 mKeygroupCrossfade = mpDisk->ReadInt8()?
true:
false;
578 mNumberOfKeygroups = mpDisk->ReadInt8();
583 for (i = 0; i<11; i++)
584 mKeyTemperament[i] = mpDisk->ReadInt8();
586 mFXOutput = mpDisk->ReadInt8()?
true:
false;
588 mModulationToPan = mpDisk->ReadInt8();
590 mStereoCoherence = mpDisk->ReadInt8()?
true:
false;
592 mLFODesync = mpDisk->ReadInt8()?
true:
false;
594 mPitchLaw = mpDisk->ReadInt8();
596 mVoiceReassign = mpDisk->ReadInt8();
598 mSoftpedToVolume = mpDisk->ReadInt8();
600 mSoftpedToAttack = mpDisk->ReadInt8();
602 mSoftpedToFilter = mpDisk->ReadInt8();
604 mSoftpedToTuneCents = mpDisk->ReadInt8();
606 mSoftpedToTuneSemitones = mpDisk->ReadInt8();
608 mKeyToLFORate = mpDisk->ReadInt8();
610 mKeyToLFODepth = mpDisk->ReadInt8();
612 mKeyToLFODelay = mpDisk->ReadInt8();
614 mVoiceOutputScale = mpDisk->ReadInt8();
616 mStereoOutputScale = mpDisk->ReadInt8();
621 delete[] mpKeygroups;
622 mpKeygroups =
new AkaiKeygroup[mNumberOfKeygroups];
623 for (i = 0; i < mNumberOfKeygroups; i++)
626 mpDisk->SetPos(mpParent->GetParent()->GetOffset() + mDirEntry.mStart * AKAI_BLOCK_SIZE + 150 * (i+1));
627 if (!mpKeygroups[i].Load(mpDisk))
629 mpDisk->SetPos(temppos);
634 mpDisk->SetPos(temppos);
638 uint AkaiProgram::ListSamples(std::list<String>& rSamples)
643 AkaiSample* AkaiProgram::GetSample(uint Index)
648 AkaiSample* AkaiProgram::GetSample(
const String& rName)
654 bool AkaiKeygroup::Load(
DiskImage* pDisk)
660 if (pDisk->ReadInt8() != AKAI_KEYGROUP_ID)
665 mLowKey = pDisk->ReadInt8();
667 mHighKey = pDisk->ReadInt8();
669 mTuneCents = pDisk->ReadInt8();
671 mTuneSemitones = pDisk->ReadInt8();
673 mFilter = pDisk->ReadInt8();
675 mKeyToFilter = pDisk->ReadInt8();
677 mVelocityToFilter = pDisk->ReadInt8();
679 mPressureToFilter = pDisk->ReadInt8();
681 mEnveloppe2ToFilter = pDisk->ReadInt8();
700 mEnveloppes[i].Load(pDisk);
703 mVelocityToEnveloppe2ToFilter = pDisk->ReadInt8();
705 mEnveloppe2ToPitch = pDisk->ReadInt8();
707 mVelocityZoneCrossfade = pDisk->ReadInt8()?
true:
false;
709 mVelocityZoneUsed = pDisk->ReadInt8();
738 mSamples[i].Load(pDisk);
741 mBeatDetune = pDisk->ReadInt8();
743 mHoldAttackUntilLoop = pDisk->ReadInt8()?
true:
false;
746 mSampleKeyTracking[i] = pDisk->ReadInt8()?
true:
false;
749 mSampleAuxOutOffset[i] = pDisk->ReadInt8();
752 mVelocityToSampleStart[i] = pDisk->ReadInt8();
755 mVelocityToVolumeOffset[i] = pDisk->ReadInt8();
761 bool AkaiEnveloppe::Load(
DiskImage* pDisk)
764 mAttack = pDisk->ReadInt8();
766 mDecay = pDisk->ReadInt8();
768 mSustain = pDisk->ReadInt8();
770 mRelease = pDisk->ReadInt8();
772 mVelocityToAttack = pDisk->ReadInt8();
774 mVelocityToRelease = pDisk->ReadInt8();
776 mOffVelocityToRelease = pDisk->ReadInt8();
778 mKeyToDecayAndRelease = pDisk->ReadInt8();
782 bool AkaiKeygroupSample::Load(
DiskImage* pDisk)
786 pDisk->
Read(buffer, 12, 1);
787 AkaiToAscii(buffer, 12);
791 mLowLevel = pDisk->ReadInt8();
826 mDirEntry = DirEntry;
828 if (mDirEntry.mType != AKAI_TYPE_DIR_S1000 && mDirEntry.mType != AKAI_TYPE_DIR_S3000)
830 printf(
"Creating Unknown Volume type! %d\n",mDirEntry.mType);
832 OutputDebugString(
"Creating Unknown Volume type!\n");
837 AkaiVolume::~AkaiVolume()
840 std::list<AkaiProgram*>::iterator it;
841 std::list<AkaiProgram*>::iterator end = mpPrograms.end();
842 for (it = mpPrograms.begin(); it != end; it++)
848 std::list<AkaiSample*>::iterator it;
849 std::list<AkaiSample*>::iterator end = mpSamples.end();
850 for (it = mpSamples.begin(); it != end; it++)
856 uint AkaiVolume::ReadDir()
859 if (mpPrograms.empty())
861 uint maxfiles = ReadFAT(mpDisk, mpParent,mDirEntry.mStart) ? AKAI_MAX_FILE_ENTRIES_S1000 : AKAI_MAX_FILE_ENTRIES_S3000;
862 for (i = 0; i < maxfiles; i++)
864 AkaiDirEntry DirEntry;
865 ReadDirEntry(mpDisk, mpParent, DirEntry, mDirEntry.mStart, i);
867 if (DirEntry.mType ==
'p')
871 mpPrograms.push_back(pProgram);
873 else if (DirEntry.mType ==
's')
875 AkaiSample* pSample =
new AkaiSample(mpDisk,
this, DirEntry);
877 mpSamples.push_back(pSample);
881 return (uint)(mpPrograms.size() + mpSamples.size());
884 uint AkaiVolume::ListPrograms(std::list<AkaiDirEntry>& rPrograms)
889 std::list<AkaiProgram*>::iterator it;
890 std::list<AkaiProgram*>::iterator end = mpPrograms.end();
891 for (it = mpPrograms.begin(); it != end; it++)
893 rPrograms.push_back((*it)->GetDirEntry());
894 return (uint)rPrograms.size();
901 if (mpPrograms.empty())
903 std::list<AkaiDirEntry> dummy;
907 std::list<AkaiProgram*>::iterator it;
908 std::list<AkaiProgram*>::iterator end = mpPrograms.end();
909 for (it = mpPrograms.begin(); it != end; it++)
911 if (*it && i == Index)
921 AkaiProgram* AkaiVolume::GetProgram(
const String& rName)
923 if (mpPrograms.empty())
925 std::list<AkaiDirEntry> dummy;
929 std::list<AkaiProgram*>::iterator it;
930 std::list<AkaiProgram*>::iterator end = mpPrograms.end();
931 for (it = mpPrograms.begin(); it != end; it++)
933 if (*it && rName == (*it)->GetDirEntry().mName)
942 uint AkaiVolume::ListSamples(std::list<AkaiDirEntry>& rSamples)
947 std::list<AkaiSample*>::iterator it;
948 std::list<AkaiSample*>::iterator end = mpSamples.end();
949 for (it = mpSamples.begin(); it != end; it++)
951 rSamples.push_back((*it)->GetDirEntry());
952 return (uint)rSamples.size();
955 AkaiSample* AkaiVolume::GetSample(uint Index)
959 if (mpSamples.empty())
961 std::list<AkaiDirEntry> dummy;
965 std::list<AkaiSample*>::iterator it;
966 std::list<AkaiSample*>::iterator end = mpSamples.end();
967 for (it = mpSamples.begin(); it != end; it++)
969 if (*it && i == Index)
979 AkaiSample* AkaiVolume::GetSample(
const String& rName)
981 if (mpSamples.empty())
983 std::list<AkaiDirEntry> dummy;
987 std::list<AkaiSample*>::iterator it;
988 std::list<AkaiSample*>::iterator end = mpSamples.end();
989 for (it = mpSamples.begin(); it != end; it++)
991 if (*it && rName == (*it)->GetDirEntry().mName)
1000 AkaiDirEntry AkaiVolume::GetDirEntry()
1005 bool AkaiVolume::IsEmpty()
1007 return ReadDir() == 0;
1019 AkaiPartition::~AkaiPartition()
1021 std::list<AkaiVolume*>::iterator it;
1022 std::list<AkaiVolume*>::iterator end = mpVolumes.end();
1023 for (it = mpVolumes.begin(); it != end; it++)
1028 uint AkaiPartition::ListVolumes(std::list<AkaiDirEntry>& rVolumes)
1032 if (mpVolumes.empty())
1034 for (i = 0; i < AKAI_MAX_DIR_ENTRIES; i++)
1036 AkaiDirEntry DirEntry;
1037 ReadDirEntry(mpDisk,
this, DirEntry, AKAI_ROOT_ENTRY_OFFSET, i);
1038 DirEntry.mIndex = i;
1039 if (DirEntry.mType == AKAI_TYPE_DIR_S1000 || DirEntry.mType == AKAI_TYPE_DIR_S3000)
1043 if (!pVolume->IsEmpty())
1045 mpVolumes.push_back(pVolume);
1046 rVolumes.push_back(DirEntry);
1055 std::list<AkaiVolume*>::iterator it;
1056 std::list<AkaiVolume*>::iterator end = mpVolumes.end();
1057 for (it = mpVolumes.begin(); it != end; it++)
1059 rVolumes.push_back((*it)->GetDirEntry());
1061 return (uint)rVolumes.size();
1064 AkaiVolume* AkaiPartition::GetVolume(uint Index)
1068 if (mpVolumes.empty())
1070 std::list<AkaiDirEntry> dummy;
1074 std::list<AkaiVolume*>::iterator it;
1075 std::list<AkaiVolume*>::iterator end = mpVolumes.end();
1076 for (it = mpVolumes.begin(); it != end; it++)
1078 if (*it && i == Index)
1088 AkaiVolume* AkaiPartition::GetVolume(
const String& rName)
1090 if (mpVolumes.empty())
1092 std::list<AkaiDirEntry> dummy;
1096 std::list<AkaiVolume*>::iterator it;
1097 std::list<AkaiVolume*>::iterator end = mpVolumes.end();
1098 for (it = mpVolumes.begin(); it != end; it++)
1100 if (*it && rName == (*it)->GetDirEntry().mName)
1109 bool AkaiPartition::IsEmpty()
1111 std::list<AkaiDirEntry> Volumes;
1112 return ListVolumes(Volumes) == 0;
1123 AkaiDisk::~AkaiDisk()
1125 std::list<AkaiPartition*>::iterator it;
1126 std::list<AkaiPartition*>::iterator end = mpPartitions.end();
1127 for (it = mpPartitions.begin(); it != end ; it++)
1132 uint AkaiDisk::GetPartitionCount()
1134 if (!mpPartitions.empty())
1135 return (uint)mpPartitions.size();
1139 while (size != AKAI_PARTITION_END_MARK && size != 0x0fff && size != 0xffff
1140 && size<30720 && mpPartitions.size()<9)
1144 pPartition->Acquire();
1145 pPartition->SetOffset(offset);
1147 if (!pPartition->IsEmpty())
1149 mpPartitions.push_back(pPartition);
1152 mpDisk->SetPos(offset);
1153 if (!mpDisk->ReadInt16(&size))
1154 return (uint)mpPartitions.size();
1156 offset += AKAI_BLOCK_SIZE * t;
1160 return (uint)mpPartitions.size();
1165 std::list<AkaiPartition*>::iterator it;
1166 std::list<AkaiPartition*>::iterator end = mpPartitions.end();
1168 for (i = 0, it = mpPartitions.begin(); it != end && i != count; i++) it++;
1170 if (i != count || it == end)
1183 pDisk->SetPos(pPartition->GetOffset()+AKAI_FAT_OFFSET + block*2);
1184 pDisk->
Read(&value, 2,1);
1189 bool AkaiDiskElement::ReadDirEntry(
DiskImage* pDisk,
AkaiPartition* pPartition, AkaiDirEntry& rEntry,
int block,
int pos)
1193 if (block == AKAI_ROOT_ENTRY_OFFSET)
1195 pDisk->SetPos(pPartition->GetOffset()+AKAI_DIR_ENTRY_OFFSET + pos * AKAI_DIR_ENTRY_SIZE);
1196 pDisk->
Read(buffer, 12, 1);
1197 AkaiToAscii(buffer, 12);
1198 rEntry.mName = buffer;
1200 pDisk->ReadInt16(&rEntry.mType);
1201 pDisk->ReadInt16(&rEntry.mStart);
1209 pDisk->SetPos(block * AKAI_BLOCK_SIZE + pos * AKAI_FILE_ENTRY_SIZE + pPartition->GetOffset());
1214 temp = ReadFAT(pDisk, pPartition, block);
1215 pDisk->SetPos(pPartition->GetOffset()+temp * AKAI_BLOCK_SIZE + (pos - 341) * AKAI_FILE_ENTRY_SIZE);
1218 pDisk->
Read(buffer, 12, 1);
1219 AkaiToAscii(buffer, 12);
1220 rEntry.mName = buffer;
1223 pDisk->SetPos(4,akai_stream_curpos);
1224 pDisk->
Read(&t1, 1,1);
1227 pDisk->
Read(&t1, 1,1);
1228 pDisk->
Read(&t2, 1,1);
1229 pDisk->
Read(&t3, 1,1);
1230 rEntry.mSize = (
unsigned char)t1 | ((
unsigned char)t2 <<8) | ((
unsigned char)t3<<16);
1232 pDisk->ReadInt16(&rEntry.mStart,1);
1237 void AkaiDiskElement::AkaiToAscii(
char * buffer,
int length)
1241 for (i = 0; i < length; i++)
1243 if (buffer[i]>=0 && buffer[i]<=9)
1245 else if (buffer[i]==10)
1247 else if (buffer[i]>=11 && buffer[i]<=36)
1248 buffer[i] = 64+(buffer[i]-10);
1252 buffer[length] =
'\0';
1253 while (length-- > 0 && buffer[length] == 32)
1257 buffer[length+1] =
'\0';
1271 kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
1273 kern_return_t kernResult;
1274 mach_port_t masterPort;
1275 CFMutableDictionaryRef classesToMatch;
1277 kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
1278 if ( KERN_SUCCESS != kernResult )
1280 printf(
"IOMasterPort returned %d\n", kernResult );
1283 classesToMatch = IOServiceMatching( kIOCDMediaClass );
1284 if ( classesToMatch == NULL )
1286 printf(
"IOServiceMatching returned a NULL dictionary.\n" );
1290 CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue );
1293 kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator );
1294 if ( KERN_SUCCESS != kernResult )
1296 printf(
"IOServiceGetMatchingServices returned %d\n", kernResult );
1302 kern_return_t GetBSDPath( io_iterator_t mediaIterator,
char *bsdPath, CFIndex maxPathSize )
1304 io_object_t nextMedia;
1305 kern_return_t kernResult = KERN_FAILURE;
1309 nextMedia = IOIteratorNext( mediaIterator );
1312 CFTypeRef bsdPathAsCFString;
1314 bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia,
1315 CFSTR( kIOBSDNameKey ),
1316 kCFAllocatorDefault,
1318 if ( bsdPathAsCFString )
1320 size_t devPathLength;
1322 strcpy( bsdPath, _PATH_DEV );
1323 strcat( bsdPath,
"r" );
1325 devPathLength = strlen( bsdPath );
1327 if ( CFStringGetCString( (__CFString*)bsdPathAsCFString,
1328 bsdPath + devPathLength,
1329 maxPathSize - devPathLength,
1330 kCFStringEncodingASCII ) )
1332 printf(
"BSD path: %s\n", bsdPath );
1333 kernResult = KERN_SUCCESS;
1336 CFRelease( bsdPathAsCFString );
1338 IOObjectRelease( nextMedia );
1352 #define MSF_TO_LBA(msf) (((((msf).minute * 60UL) + (msf).second) * 75UL) + (msf).frame - 150) 1360 struct _CDMSF address;
1368 u_char first_session;
1369 u_char last_session;
1370 struct _CDTOC_Desc trackdesc[1];
1373 static struct _CDTOC * ReadTOC (
const char * devpath )
1375 struct _CDTOC * toc_p = NULL;
1376 io_iterator_t iterator = 0;
1377 io_registry_entry_t service = 0;
1378 CFDictionaryRef properties = 0;
1380 mach_port_t port = 0;
1382 if (( devname = strrchr( devpath,
'/' )) != NULL )
1388 devname = (
char *) devpath;
1391 if ( IOMasterPort(bootstrap_port, &port ) != KERN_SUCCESS )
1393 printf(
"IOMasterPort failed\n" );
goto Exit ;
1395 if ( IOServiceGetMatchingServices( port, IOBSDNameMatching( port, 0, devname ),
1396 &iterator ) != KERN_SUCCESS )
1398 printf(
"IOServiceGetMatchingServices failed\n" );
goto Exit ;
1402 IOObjectGetClass(iterator,buffer);
1403 printf(
"Service: %s\n",buffer);
1406 IOIteratorReset (iterator);
1407 service = IOIteratorNext( iterator );
1409 IOObjectRelease( iterator );
1412 while ( service && !IOObjectConformsTo( service,
"IOCDMedia" ))
1415 IOObjectGetClass(service,buffer);
1416 printf(
"Service: %s\n",buffer);
1418 if ( IORegistryEntryGetParentIterator( service, kIOServicePlane, &iterator ) != KERN_SUCCESS )
1420 printf(
"IORegistryEntryGetParentIterator failed\n" );
1424 IOObjectRelease( service );
1425 service = IOIteratorNext( iterator );
1426 IOObjectRelease( iterator );
1429 if ( service == NULL )
1431 printf(
"CD media not found\n" );
goto Exit ;
1433 if ( IORegistryEntryCreateCFProperties( service, (__CFDictionary **) &properties,
1434 kCFAllocatorDefault,
1435 kNilOptions ) != KERN_SUCCESS )
1437 printf(
"IORegistryEntryGetParentIterator failed\n" );
goto Exit ;
1440 data = (CFDataRef) CFDictionaryGetValue( properties, CFSTR(
"TOC" ) );
1443 printf(
"CFDictionaryGetValue failed\n" );
goto Exit ;
1451 buflen = CFDataGetLength( data ) + 1;
1452 range = CFRangeMake( 0, buflen );
1453 toc_p = (
struct _CDTOC *) malloc( buflen );
1454 if ( toc_p == NULL )
1456 printf(
"Out of memory\n" );
goto Exit ;
1460 CFDataGetBytes( data, range, (
unsigned char *) toc_p );
1468 CFRelease( properties );
1474 IOObjectRelease( service );
1486 sprintf(buffer,
"%c:\\",
'A'+disk);
1487 mSize = GetFileSize(buffer,NULL);
1489 sprintf(buffer,
"\\\\.\\%c:",
'a'+disk);
1490 mFile = CreateFile(buffer, GENERIC_READ,0,NULL,OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS,NULL);
1494 DISK_GEOMETRY* pdg = &dg;
1495 BOOL res = DeviceIoControl(mFile,
1496 IOCTL_DISK_GET_DRIVE_GEOMETRY,
1504 mSize = dg.BytesPerSector * dg.SectorsPerTrack * dg.TracksPerCylinder * dg.Cylinders.LowPart;
1505 mClusterSize = dg.BytesPerSector;
1507 #elif defined(_CARBON_) || defined(__APPLE__) 1508 kern_return_t kernResult;
1509 io_iterator_t mediaIterator;
1510 char bsdPath[ MAXPATHLEN ];
1511 kernResult = FindEjectableCDMedia( &mediaIterator );
1512 kernResult = GetBSDPath( mediaIterator, bsdPath,
sizeof( bsdPath ) );
1513 if ( bsdPath[ 0 ] !=
'\0' )
1515 strcpy(bsdPath,
"/dev/rdisk1s0");
1517 struct _CDTOC * toc = ReadTOC( bsdPath );
1520 size_t toc_entries = ( toc->length - 2 ) /
sizeof (
struct _CDTOC_Desc );
1522 int start_sector = -1;
1523 int data_track = -1;
1528 for (ssize_t i=toc_entries - 1; i>=0; i-- )
1530 if ( start_sector != -1 )
1532 start_sector = MSF_TO_LBA(toc->trackdesc[i].p) - start_sector;
1536 if (( toc->trackdesc[i].ctrl_adr >> 4) != 1 )
1538 if ( toc->trackdesc[i].ctrl_adr & 0x04 )
1540 data_track = toc->trackdesc[i].point;
1541 start_sector = MSF_TO_LBA(toc->trackdesc[i].p);
1546 if ( start_sector == -1 )
1555 mFile = open(bsdPath,O_RDONLY);
1557 printf(
"Error while opening file: %s\n",bsdPath);
1560 printf(
"opened file: %s\n",bsdPath);
1562 mSize = (int) lseek(mFile,1000000000,SEEK_SET);
1563 printf(
"size %d\n",mSize);
1564 lseek(mFile,0,SEEK_SET);
1566 mSize = 700 * 1024 * 1024;
1570 if ( mediaIterator )
1572 IOObjectRelease( mediaIterator );
1575 OpenStream(
"/dev/cdrom");
1579 void DiskImage::Init()
1583 mCluster = (uint)-1;
1587 mpCache = (
char*) VirtualAlloc(NULL,mClusterSize,MEM_COMMIT,PAGE_READWRITE);
1593 DiskImage::~DiskImage()
1596 if (mFile != INVALID_HANDLE_VALUE)
1600 #elif defined _CARBON_ || defined(__APPLE__) || LINUX 1609 VirtualFree(mpCache, 0, MEM_RELEASE);
1610 #elif defined(_CARBON_) || defined(__APPLE__) || LINUX 1616 akai_stream_state_t DiskImage::GetState()
const 1618 if (!mFile)
return akai_stream_closed;
1619 if (mPos > mSize)
return akai_stream_end_reached;
1620 return akai_stream_ready;
1623 int DiskImage::GetPos()
const 1628 int DiskImage::SetPos(
int Where, akai_stream_whence_t Whence)
1634 case akai_stream_start:
1639 case akai_stream_curpos:
1642 case akai_stream_end:
1653 int DiskImage::Available (uint WordSize)
1655 return (mSize-mPos)/WordSize;
1661 int sizetoread = WordCount * WordSize;
1663 while (sizetoread > 0) {
1664 if (mSize <= mPos)
return readbytes / WordSize;
1665 int requestedCluster = (mRegularFile) ? mPos / mClusterSize
1666 : mPos / mClusterSize + mStartFrame;
1667 if (mCluster != requestedCluster) {
1668 mCluster = requestedCluster;
1670 if (mCluster * mClusterSize != SetFilePointer(mFile, mCluster * mClusterSize, NULL, FILE_BEGIN)) {
1671 printf(
"ERROR: couldn't seek device!\n");
1672 #if 0 // FIXME: endian correction is missing correct detection 1673 if ((readbytes > 0) && (mEndian != eEndianNative)) {
1675 case 2: bswap_16_s ((uint16*)pData, readbytes);
break;
1676 case 4: bswap_32_s ((uint32*)pData, readbytes);
break;
1677 case 8: bswap_64_s ((uint64*)pData, readbytes);
break;
1681 return readbytes / WordSize;
1684 ReadFile(mFile, mpCache, mClusterSize, &size, NULL);
1685 #elif defined(_CARBON_) || defined(__APPLE__) || LINUX 1686 if (mCluster * mClusterSize != lseek(mFile, mCluster * mClusterSize, SEEK_SET))
1687 return readbytes / WordSize;
1689 read(mFile, mpCache, mClusterSize);
1695 int currentReadSize = sizetoread;
1696 int posInCluster = mPos % mClusterSize;
1697 if (currentReadSize > mClusterSize - posInCluster)
1698 currentReadSize = mClusterSize - posInCluster;
1700 memcpy((uint8_t*)pData + readbytes, mpCache + posInCluster, currentReadSize);
1702 mPos += currentReadSize;
1703 readbytes += currentReadSize;
1704 sizetoread -= currentReadSize;
1708 #if 0 // FIXME: endian correction is missing correct detection 1709 if ((readbytes > 0) && (mEndian != eEndianNative))
1712 case 2: bswap_16_s ((uint16_t*)pData, readbytes);
break;
1713 case 4: bswap_32_s ((uint32_t*)pData, readbytes);
break;
1714 case 8: bswap_64_s ((uint64_t*)pData, readbytes);
break;
1718 return readbytes / WordSize;
1721 void DiskImage::ReadInt8(uint8_t* pData, uint WordCount) {
1722 Read(pData, WordCount, 1);
1725 void DiskImage::ReadInt16(uint16_t* pData, uint WordCount) {
1727 for (i = 0; i < WordCount; i++) {
1728 *(pData + i) = ReadInt16();
1732 void DiskImage::ReadInt32(uint32_t* pData, uint WordCount) {
1734 for (i = 0; i < WordCount; i++) {
1735 *(pData + i) = ReadInt32();
1739 int DiskImage::ReadInt8(uint8_t* pData) {
1740 return Read(pData, 1, 1);
1743 int DiskImage::ReadInt16(uint16_t* pData) {
1744 int result = Read(pData, 1, 2);
1746 swapBytes_16(pData);
1751 int DiskImage::ReadInt32(uint32_t* pData) {
1752 int result = Read(pData, 1, 4);
1754 swapBytes_32(pData);
1759 uint8_t DiskImage::ReadInt8()
1766 uint16_t DiskImage::ReadInt16()
1771 swapBytes_16(&word);
1776 uint32_t DiskImage::ReadInt32()
1781 swapBytes_32(&word);
1786 void DiskImage::OpenStream(
const char* path) {
1788 mFile = CreateFile(path, GENERIC_READ,0,NULL,OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS,NULL);
1789 BY_HANDLE_FILE_INFORMATION FileInfo;
1790 GetFileInformationByHandle(mFile,&FileInfo);
1791 mSize = FileInfo.nFileSizeLow;
1792 #elif defined(_CARBON_) || defined(__APPLE__) || LINUX 1793 struct stat filestat;
1794 stat(path,&filestat);
1795 mFile = open(path, O_RDONLY | O_NONBLOCK);
1797 printf(
"Can't open %s\n", path);
1802 if (S_ISREG(filestat.st_mode)) {
1803 printf(
"Using regular Akai image file.\n");
1804 mRegularFile =
true;
1805 mSize = (int) filestat.st_size;
1806 mClusterSize = DISK_CLUSTER_SIZE;
1807 mpCache = (
char*) malloc(mClusterSize);
1809 #if defined(_CARBON_) || defined(__APPLE__) 1810 printf(
"Can't open %s: not a regular file\n", path);
1812 mRegularFile =
false;
1813 mClusterSize = CD_FRAMESIZE;
1814 mpCache = (
char*) malloc(mClusterSize);
1816 struct cdrom_tochdr tochdr;
1817 struct cdrom_tocentry tocentry;
1819 if (ioctl(mFile, CDROMREADTOCHDR, (
unsigned long)&tochdr) < 0) {
1820 printf(
"Trying to read TOC of %s failed\n", path);
1825 printf(
"Total tracks: %d\n", tochdr.cdth_trk1);
1828 tocentry.cdte_format = CDROM_LBA;
1830 int firstDataTrack = -1;
1831 int start, end, length;
1834 for (
int t = tochdr.cdth_trk1; t >= 0; t--) {
1835 tocentry.cdte_track = (t == tochdr.cdth_trk1) ? CDROM_LEADOUT : t + 1;
1836 if (ioctl(mFile, CDROMREADTOCENTRY, (
unsigned long)&tocentry) < 0){
1837 printf(
"Failed to read TOC entry for track %d\n", tocentry.cdte_track);
1842 if (tocentry.cdte_track == CDROM_LEADOUT) {
1843 printf(
"Lead Out: Start(LBA)=%d\n", tocentry.cdte_addr.lba);
1846 printf(
"Track %d: Start(LBA)=%d End(LBA)=%d Length(Blocks)=%d ",
1847 tocentry.cdte_track, tocentry.cdte_addr.lba, prev_addr - 1, prev_addr - tocentry.cdte_addr.lba);
1848 if (tocentry.cdte_ctrl & CDROM_DATA_TRACK) {
1849 printf(
"Type: Data\n");
1850 firstDataTrack = tocentry.cdte_track;
1851 start = tocentry.cdte_addr.lba;
1852 end = prev_addr - 1;
1853 length = prev_addr - tocentry.cdte_addr.lba;
1855 else printf(
"Type: Audio\n");
1857 prev_addr = tocentry.cdte_addr.lba;
1860 if (firstDataTrack == -1) {
1861 printf(
"Sorry, no data track found on %s\n", path);
1867 printf(
"Ok, I'll pick track %d\n", firstDataTrack);
1868 mStartFrame = start;
1870 mSize = length * CD_FRAMESIZE;
1878 #if defined(_CARBON_) || defined(__APPLE__) || LINUX 1879 const uint bufferSize = 524288;
1880 int fOut = open(path, O_WRONLY | O_NONBLOCK | O_CREAT | O_TRUNC,
1881 S_IRUSR | S_IWUSR | S_IRGRP);
1883 printf(
"Can't open output file %s\n", path);
1886 uint8_t* pBuffer =
new uint8_t[bufferSize];
1888 while (Available() > 0) {
1889 int readBytes = Read(pBuffer,bufferSize,1);
1890 if (readBytes > 0) write(fOut,pBuffer,readBytes);
1895 #endif // _CARBON_ || LINUX 1899 inline void DiskImage::swapBytes_16(
void* Word) {
1901 byteCache = *((uint8_t*) Word);
1902 *((uint8_t*) Word) = *((uint8_t*) Word + 1);
1903 *((uint8_t*) Word + 1) = byteCache;
1906 inline void DiskImage::swapBytes_32(
void* Word) {
1908 byteCache = *((uint8_t*) Word);
1909 *((uint8_t*) Word) = *((uint8_t*) Word + 3);
1910 *((uint8_t*) Word + 3) = byteCache;
1911 byteCache = *((uint8_t*) Word + 1);
1912 *((uint8_t*) Word + 1) = *((uint8_t*) Word + 2);
1913 *((uint8_t*) Word + 2) = byteCache;
bool WriteImage(const char *path)
Extract Akai data track and write it into a regular file.
Encapsulates one disk partition of an AKAI disk.
DiskImage(const char *path)
Open an image from a file.
Toplevel AKAI image interpreter.
Accessing AKAI image either from file or a drive (i.e.
AKAI instrument definition.
Subdivision of an AKAI disk partition.
virtual int Read(void *pData, uint WordCount, uint WordSize)
Returns number of successfully read words.