#include "GSLDatei.h" #ifdef WIN32 #include "Sound.h" #else #include "Sound.h" #endif using namespace GSL; // Inhalt der GSLDatei Klasse aus GSLDatei.h // Konstruktor GSLDatei::GSLDatei() : ReferenceCounter() { sounds = new Array< SoundKopf >(); pfad = new Text(); } // Destruktor GSLDatei::~GSLDatei() { sounds->release(); pfad->release(); } // Datei open void GSLDatei::setDatei( Framework::Text *txt ) { cs.lock(); pfad->setText( txt ); cs.unlock(); } void GSLDatei::setDatei( char *txt ) { cs.lock(); pfad->setText( txt ); cs.unlock(); } bool GSLDatei::leseDaten() { cs.lock(); sounds->leeren(); Datei d; d.setDatei( *pfad ); if( !d.getSize() ) { cs.unlock(); return 1; } if( !d.open( Datei::Style::lesen ) ) { cs.unlock(); return 0; } unsigned char sAnz = 0; d.lese( (char *)&sAnz, 1 ); // Datei Sound - Köpfe einlesen for( int i = 0; i < sAnz; i++ ) { SoundKopf kpf; bool bit = 0; char len = 0; // Namenslänge lesen for( int i = 0; i < 4; i++ ) { d.getNextBit( bit ); len = (char)( len | ( ( (char)bit << ( 3 - i ) ) & ( 1 << ( 3 - i ) ) ) ); } len &= 15; // Name lesen for( int i = 0; i < len; i++ ) { char zeichen = 0; for( int j = 0; j < 5; j++ ) { d.getNextBit( bit ); zeichen = (char)( zeichen | ( ( (char)bit << ( 4 - j ) ) & ( 1 << ( 4 - j ) ) ) ); } zeichen &= 31; if( zeichen == 27 ) zeichen = 'ü'; if( zeichen == 28 ) zeichen = 'ö'; if( zeichen == 29 ) zeichen = 'ä'; if( zeichen == 30 ) zeichen = 'ß'; if( zeichen == 31 ) zeichen = '.'; if( zeichen < 27 ) zeichen = (char)( zeichen + 'a' ); kpf.name.append( &zeichen, 1 ); } // Chanel Anzahl lesen d.getNextBit( bit ); kpf.channels = (char)( bit + 1 ); // Sample Rate lesen d.lese( (char *)&kpf.sampleRate, 4 ); // Position des Sounds in der Datei lesen d.lese( (char *)&kpf.datPos, 8 ); // Länge des Sounds lesen int sLen = 0; d.lese( (char *)&sLen, 4 ); kpf.datEnd = kpf.datPos + sLen; kpf.pfad = pfad->getText(); sounds->add( kpf ); } d.close(); cs.unlock(); return 1; } int GSLDatei::getSoundAnzahl() { return sounds->getEintragAnzahl(); } Text *GSLDatei::getSoundName( int num ) { if( !sounds->hat( num ) ) return 0; return new Text( sounds->get( num ).name ); } // Laden GSLSoundV *GSLDatei::getSound( Framework::Text *name ) { GSLSoundV *ret = getSound( *name ); name->release(); return ret; } GSLSoundV *GSLDatei::getSound( char *name ) { cs.lock(); int anz = sounds->getEintragAnzahl(); for( int i = 0; i < anz; i++ ) { if( sounds->get( i ).name.istGleich( name ) ) { cs.unlock(); return new GSLSound( sounds->get( i ) ); } } cs.unlock(); return 0; } // Speichern bool GSLDatei::speicherSound( GSLSoundV *zSound, Framework::Text *name ) { bool ret = speicherSound( zSound, *name ); name->release(); return ret; } bool GSLDatei::speicherSound( GSLSoundV *zSound, char *name ) { Text kName; for( char *c = name; *c; ++c ) { if( *c >= 'A' && *c <= 'Z' ) kName.append( (char)( *c + 32 ) ); if( *c >= 'a' && *c <= 'z' ) kName.append( *c ); if( *c == 'Ü' || *c == 'ü' ) kName.append( 'ü' ); if( *c == 'Ö' || *c == 'ö' ) kName.append( 'ö' ); if( *c == 'Ä' || *c == 'ä' ) kName.append( 'ä' ); if( *c == 'ß' ) kName.append( 'ß' ); if( *c == '.' ) kName.append( '.' ); if( kName.getLength() == 15 ) break; } name = kName; cs.lock(); // Prüfen ob bereits vorhanden int anz = sounds->getEintragAnzahl(); for( int i = 0; i < anz; i++ ) { if( sounds->get( i ).name.istGleich( name ) ) { cs.unlock(); return 0; } } Text tmpPf = pfad->getText(); tmpPf += "_"; GetFreePfad( &tmpPf ); Datei tmp; tmp.setDatei( tmpPf ); tmp.erstellen(); if( !tmp.open( Datei::Style::schreiben ) ) { cs.unlock(); return 0; } char *buffer = new char[ 0x4000 ]; // Neuen Sound in Temporäre Datei schreiben zSound->open(); while( 1 ) { int len = 0; if( ( len = zSound->getDaten( buffer, 0x4000 ) ) < 0 ) break; tmp.schreibe( buffer, len ); } zSound->close(); delete[] buffer; tmp.close(); int hLen = 1; unsigned char sAnz = (unsigned char)sounds->getEintragAnzahl(); // Sound Kopf Länge errechnen for( int i = 0; i < sAnz; i++ ) { SoundKopf kpf = sounds->get( i ); hLen += ( 140 + 5 * kpf.name.getLength() ) / 8; } Datei alt; alt.setDatei( *pfad ); // Sound Kopf Erstellen SoundKopf kpf; kpf.channels = (char)( !zSound->istMono() + 1 ); kpf.name = name; kpf.pfad = pfad->getText(); kpf.sampleRate = zSound->getSampleRate(); kpf.datPos = ( alt.getSize() <= 0 ? 1 : alt.getSize() ); kpf.datEnd = tmp.getSize() + kpf.datPos; sounds->add( kpf ); Text neuPf = pfad->getText(); neuPf += "_"; GetFreePfad( &neuPf ); Datei neu; neu.setDatei( neuPf ); neu.erstellen(); if( !neu.open( Datei::Style::schreiben ) ) { sounds->remove( sAnz ); tmp.remove(); cs.unlock(); return 0; } sAnz = (unsigned char)sounds->getEintragAnzahl(); neu.schreibe( (char *)&sAnz, 1 ); // Sound Köpfe speichern for( int i = 0; i < sAnz; i++ ) { SoundKopf k = sounds->get( i ); k.datPos += ( 140 + 5 * kpf.name.getLength() ) / 8; k.datEnd += ( 140 + 5 * kpf.name.getLength() ) / 8; int l = k.name.getLength(); // Namenslänge speichern neu.setNextBit( ( l & 8 ) != 0 ); neu.setNextBit( ( l & 4 ) != 0 ); neu.setNextBit( ( l & 2 ) != 0 ); neu.setNextBit( ( l & 1 ) != 0 ); for( int j = 0; j < l; j++ ) { // Name speichern char c = k.name.getText()[ j ]; if( c == 'ü' ) c = 27; if( c == 'ö' ) c = 28; if( c == 'ä' ) c = 29; if( c == 'ß' ) c = 30; if( c == '.' ) c = 31; if( c >= 'a' && c <= 'z' ) c = (char)( c - 'a' ); neu.setNextBit( ( c & 16 ) != 0 ); neu.setNextBit( ( c & 8 ) != 0 ); neu.setNextBit( ( c & 4 ) != 0 ); neu.setNextBit( ( c & 2 ) != 0 ); neu.setNextBit( ( c & 1 ) != 0 ); } // Chanels speichern neu.setNextBit( ( k.channels - 1 ) == 1 ); // Sample Rate speichern neu.schreibe( (char *)&k.sampleRate, 4 ); // Datei Position schreiben neu.schreibe( (char *)&k.datPos, 8 ); // Länge des Sounds Speichern int sLen = (int)( k.datEnd - k.datPos ); neu.schreibe( (char *)&sLen, 4 ); } // alte Sounds kopieren char *byte = new char[ 2048 ]; if( sAnz > 1 ) { if( !alt.open( Datei::Style::lesen ) ) { tmp.remove(); neu.close(); neu.remove(); sounds->remove( sAnz ); cs.unlock(); return 0; } alt.setLPosition( hLen, 0 ); for( __int64 i = hLen; i < alt.getSize(); ) { int l = 2048; if( l > alt.getSize() - i ) l = (int)( alt.getSize() - i ); alt.lese( byte, l ); neu.schreibe( byte, l ); i += l; } alt.close(); } // Neuen Sound kopieren if( !tmp.open( Datei::Style::lesen ) ) { tmp.remove(); neu.close(); neu.remove(); sounds->remove( sAnz ); cs.unlock(); return 0; } for( int i = 0; i < (int)tmp.getSize(); ) { int l = 2048; if( l > tmp.getSize() - i ) l = (int)( tmp.getSize() - i ); tmp.lese( byte, l ); neu.schreibe( byte, l ); i += l; } delete[] byte; tmp.close(); neu.close(); // Dateien Umbenennen und remove tmp.remove(); alt.remove(); neu.umbenennen( *pfad ); leseDaten(); cs.unlock(); return 1; } // Löschen bool GSLDatei::removeSound( Framework::Text *name ) { bool ret = removeSound( *name ); name->release(); return ret; } bool GSLDatei::removeSound( char *name ) { cs.lock(); // Prüfen ob vorhanden int anz = sounds->getEintragAnzahl(); int num = -1; for( int i = 0; i < anz; i++ ) { if( sounds->get( i ).name.istGleich( name ) ) { num = i; break; } } if( num < 0 ) { cs.unlock(); return 1; } Text neuPf = pfad->getText(); neuPf += "_"; GetFreePfad( &neuPf ); Datei neu; neu.setDatei( neuPf ); neu.erstellen(); if( !neu.open( Datei::Style::schreiben ) ) { cs.unlock(); return 0; } SoundKopf kpf = sounds->get( num ); unsigned char sAnz = (unsigned char)( anz - 1 ); neu.schreibe( (char *)&sAnz, 1 ); // Sound Köpfe speichern for( int i = 0; i <= sAnz; i++ ) { if( i == num ) continue; SoundKopf k = sounds->get( i ); k.datPos -= ( 140 + 5 * kpf.name.getLength() ) / 8; k.datEnd -= ( 140 + 5 * kpf.name.getLength() ) / 8; if( i > num ) { k.datPos -= kpf.datEnd - kpf.datPos; k.datEnd -= kpf.datEnd - kpf.datPos; } int l = k.name.getLength(); // Namenslänge speichern neu.setNextBit( ( l & 8 ) != 0 ); neu.setNextBit( ( l & 4 ) != 0 ); neu.setNextBit( ( l & 2 ) != 0 ); neu.setNextBit( ( l & 1 ) != 0 ); for( int j = 0; j < l; j++ ) { // Name speichern char c = k.name.getText()[ j ]; if( c == 'ü' ) c = 27; if( c == 'ö' ) c = 28; if( c == 'ä' ) c = 29; if( c == 'ß' ) c = 30; if( c == '.' ) c = 31; if( c >= 'a' && c <= 'z' ) c = (char)( c - 'a' ); neu.setNextBit( ( c & 16 ) != 0 ); neu.setNextBit( ( c & 8 ) != 0 ); neu.setNextBit( ( c & 4 ) != 0 ); neu.setNextBit( ( c & 2 ) != 0 ); neu.setNextBit( ( c & 1 ) != 0 ); } // Chanels speichern neu.setNextBit( ( k.channels - 1 ) == 1 ); // Sample Rate speichern neu.schreibe( (char *)&k.sampleRate, 4 ); // Datei Position schreiben neu.schreibe( (char *)&k.datPos, 8 ); // Länge des Sounds Speichern int sLen = (int)( k.datEnd - k.datPos ); neu.schreibe( (char *)&sLen, 4 ); } // Alte Sounds kopieren Datei alt; alt.setDatei( *pfad ); if( sAnz ) { if( !alt.open( Datei::Style::lesen ) ) { neu.close(); neu.remove(); cs.unlock(); return 0; } alt.setLPosition( neu.getSPosition() + ( 140 + 5 * kpf.name.getLength() ) / 8, 0 ); char *byte = new char[ 2048 ]; for( __int64 i = alt.getLPosition(); i < kpf.datPos; ) { int l = 2048; if( l > kpf.datPos - i ) l = (int)( kpf.datPos - i ); alt.lese( byte, l ); neu.schreibe( byte, l ); i += l; } alt.setLPosition( kpf.datEnd, 0 ); for( __int64 i = alt.getLPosition(); i < alt.getSize(); ) { int l = 2048; if( l > alt.getSize() - i ) l = (int)( alt.getSize() - i ); alt.lese( byte, l ); neu.schreibe( byte, l ); i += l; } delete[] byte; alt.close(); } neu.close(); // Dateien Umbenennen und remove alt.remove(); neu.umbenennen( *pfad ); leseDaten(); cs.unlock(); return 1; }