root/lang/c/sonydb/sonydb.cpp

Revision 18890, 92.8 kB (checked in by mattn, 3 months ago)

デフォルトで検知するデバイス(WALKMANマウント先)を指定出来る様修正

Line 
1/*
2 ** SonyDB.cpp
3 **
4 ** Made by (julien)
5 */
6
7#include <stdio.h>
8#include <fstream>
9#include "sonydb.h"
10
11using namespace std;
12
13#ifndef _WIN32
14#define strnicmp(x, y, z) strncasecmp(x, y, z)
15#define stricmp(x, y) strcasecmp(x, y)
16#endif
17
18//SORT function for song vectors
19#define SKIP_THE_AND_WHITESPACE(x) { while (!isalnum(*x) && *x) x++; if (!strnicmp(x,"the ",4)) x+=4; while (*x == ' ') x++; }
20static int STRCMP_NULLOK(const char *pa, const char *pb)
21{
22        if (!pa) pa="";
23        else SKIP_THE_AND_WHITESPACE(pa)
24
25                if (!pb) pb="";
26                else SKIP_THE_AND_WHITESPACE(pb)
27                        return stricmp(pa,pb);
28}
29
30static int STRCMP2_NULLOK(const char *pa, const char *pb)
31{
32        if (!pa) pa="";
33        if (!pb) pb="";
34        return stricmp(pa,pb);
35}
36
37static int STRNCMP_NULLOK(const char *pa, const char *pb, int size)
38{
39        if (!pa) pa=""; 
40        if (!pb) pb="";
41        return strnicmp(pa, pb, size);
42}
43
44
45
46SonyDb::SonyDb()
47{
48        this->driveLetter = 0;
49        this->deviceName = (char*)calloc(sizeof(char), 256);
50        this->trackListLoaded = false;
51        this->nbTrackToAdd = 0;
52        this->nbTrackToDel = 0;
53        this->lastTrackIndex = 1;
54        this->codeType = ENCODING_USE_NONE;
55        this->copying = false;
56        this->copyIndex = 0;
57        this->copyPercent = 0;
58        this->addTrackTotalByte = 0;
59        this->delTrackTotalByte = 0;
60        this->freeSpaceDisk = 0;
61        this->neededSpace = 0;
62        this->totalDiskSpaceValue = 0;
63        this->useAllTags = false;
64
65
66        totalDiskSpace = (char*)calloc(sizeof(char), 64);
67        freeDiskSpaceAfterApply = (char*)calloc(sizeof(char), 64);
68        totalUsedSpaceAfterApply = (char*)calloc(sizeof(char), 64);
69        delTrackTotalByteString = (char*)calloc(sizeof(char), 64);
70        addTrackTotalByteString = (char*)calloc(sizeof(char), 64);
71        neededSpace = (char*)calloc(sizeof(char), 64);
72
73        //debug
74        //fp = fopen("c:/Debug_ml_sony.log", "ab");
75        //fprintf(fp,"+++++++++++++\n");
76        //fflush(fp);
77        fp = stderr;
78}
79
80//clean the song list before living
81SonyDb::~SonyDb()
82{
83        //free track list
84        freeAllTracks();
85
86        //free device Name
87        free(this->deviceName);
88
89        //free disk space info
90        free(totalDiskSpace);
91        free(totalUsedSpaceAfterApply);
92        free(freeDiskSpaceAfterApply);
93        free(delTrackTotalByteString);
94        free(addTrackTotalByteString);
95        free(neededSpace);
96
97        //debug
98        //fclose(fp);
99
100        if (driveLetter) free(driveLetter);
101}
102
103//free track list
104void SonyDb::freeAllTracks()
105{
106        for (vector<Song>::iterator i = songs.begin(); i != songs.end(); i++)
107        {
108                if ((*i).album) free((*i).album);
109                if ((*i).artist) free((*i).artist);
110                if ((*i).title) free((*i).title);
111                if ((*i).genre) free((*i).genre);
112                if ((*i).filename) free((*i).filename);
113        }
114        while (songs.size() > 0)
115                songs.pop_back();
116}
117
118//free playlist
119void SonyDb::freeAllPlaylist()
120{
121        vector<Song *> plSongs;
122
123        for (vector<Playlist>::iterator pl = playlist.begin(); pl != playlist.end(); pl++)
124        {
125                plSongs = (*pl).songs;
126                for (vector<Song*>::iterator i = plSongs.begin(); i != plSongs.end(); i++)
127                {
128                        if ((*i)->statusOfSong == MODIFIED)
129                        {
130                                free((*i)->filename);
131                                free((*i)->artist);
132                                free((*i)->album);
133                                free((*i)->genre);
134                                free((*i)->title);
135                        }
136                }
137        }
138        while (playlist.size() > 0)
139                playlist.pop_back();
140}
141
142int  SonyDb::getId()
143{
144        return (this->id);
145}
146
147void SonyDb::setId(int newId)
148{
149        this->id = newId;
150}
151
152void SonyDb::setUseAllTags(bool value)
153{
154        useAllTags = value;
155}
156
157bool SonyDb::getUseAllTags()
158{
159        return (useAllTags);
160}
161
162vector<Playlist*> SonyDb::getPlaylist()
163{   
164        vector<Playlist*> ret;
165        for (vector<Playlist>::iterator pl = playlist_temporary.begin(); pl != playlist_temporary.end(); pl++)
166                ret.push_back(&(*pl));
167        for (vector<Playlist>::iterator pl2 = playlist.begin(); pl2 != playlist.end(); pl2++)
168                ret.push_back(&(*pl2));
169        return (ret);
170}
171
172vector<Song*> SonyDb::getSongsInPlaylist(int source)
173{
174        vector<Song*> ret;
175        Song *p;
176        vector<Song *> plSongs;
177        vector<Playlist>::iterator playlistBegin;
178        vector<Playlist>::iterator playlistEnd;
179
180        if (this->copying)
181        {
182                playlistBegin = playlist_temporary.begin();
183                playlistEnd = playlist_temporary.end();
184        }
185        else
186        {
187                playlistBegin = playlist.begin();
188                playlistEnd = playlist.end();
189        }
190
191        for (vector<Playlist>::iterator pl = playlistBegin; pl != playlistEnd; pl++)
192        {
193                if (pl->index  == source)
194                {
195                        plSongs = pl->songs;
196                        for (vector<Song*>::iterator i = plSongs.begin(); i != plSongs.end(); i++)
197                        {
198                                if ((*i)->statusOfSong != EMPTYTRACK)
199                                {
200                                        //new song
201                                        p = (Song *)calloc(sizeof(Song),1);
202                                        p->filename = strdup((*i)->filename);
203                                        p->artist = strdup((*i)->artist);
204                                        p->album = strdup((*i)->album);
205                                        p->genre = strdup((*i)->genre);
206                                        p->title = strdup((*i)->title);
207
208                                        p->track_nr = (*i)->track_nr;
209                                        p->songlen = (*i)->songlen;
210                                        p->year = (*i)->year;
211                                        p->statusOfSong = (*i)->statusOfSong;
212                                        p->sonyDbOrder = (*i)->sonyDbOrder;
213                                        ret.push_back(p);
214                                }
215                        }
216                        return (ret);
217                }
218        }
219
220        //not found in temporary playlists so try in other playlist
221        playlistBegin = playlist.begin();
222        playlistEnd = playlist.end();
223
224        for (vector<Playlist>::iterator pl2 = playlistBegin; pl2 != playlistEnd; pl2++)
225        {
226                if (pl2->index  == source)
227                {
228                        plSongs = pl2->songs;
229                        for (vector<Song*>::iterator i = plSongs.begin(); i != plSongs.end(); i++)
230                        {
231                                if ((*i)->statusOfSong != EMPTYTRACK)
232                                {
233                                        //new song
234                                        p = (Song *)calloc(sizeof(Song),1);
235                                        p->filename = strdup((*i)->filename);
236                                        p->artist = strdup((*i)->artist);
237                                        p->album = strdup((*i)->album);
238                                        p->genre = strdup((*i)->genre);
239                                        p->title = strdup((*i)->title);
240
241                                        p->track_nr = (*i)->track_nr;
242                                        p->songlen = (*i)->songlen;
243                                        p->year = (*i)->year;
244                                        p->statusOfSong = (*i)->statusOfSong;
245                                        p->sonyDbOrder = (*i)->sonyDbOrder;
246                                        ret.push_back(p);
247                                }
248                        }
249                        return (ret);
250                }
251        }
252
253        return (ret);
254}
255
256bool SonyDb::deletePlaylist(int source, bool removeSongs)
257{
258        vector<Song *> plSongs;
259
260        for (vector<Playlist>::iterator pl = playlist.begin(); pl != playlist.end(); pl++)
261        {
262                if (pl->index  == source)
263                {
264                        plSongs = pl->songs;
265                        if (removeSongs)
266                        {
267                                for (vector<Song*>::iterator song = plSongs.begin(); song != plSongs.end(); song++)
268                                {
269                                        delSong(*song);
270                                }
271                        }
272                        pl->songs.clear();
273                        playlist.erase(pl);
274                        return (true);
275                }
276        }
277        return (false);
278
279}
280
281vector<Song*> SonyDb::getSongs()
282{
283        vector<Song*> ret;
284        Song *p;
285
286        if (this->copying)
287        {
288                for (vector<Song>::iterator i = songs_temporary.begin(); i != songs_temporary.end(); i++)
289                {
290                        if ((*i).statusOfSong != EMPTYTRACK)
291                        {
292                                //new song
293                                p = (Song *)calloc(sizeof(Song),1);
294                                p->filename = strdup((*i).filename);
295                                p->artist = strdup((*i).artist);
296                                p->album = strdup((*i).album);
297                                p->genre = strdup((*i).genre);
298                                p->title = strdup((*i).title);
299
300                                p->track_nr = (*i).track_nr;
301                                p->songlen = (*i).songlen;
302                                p->year = (*i).year;
303                                p->statusOfSong = (*i).statusOfSong;
304                                p->sonyDbOrder = (*i).sonyDbOrder;
305                                ret.push_back(p);
306                        }
307                }
308        }
309        else
310        {
311                for (vector<Song>::iterator i = songs.begin(); i != songs.end(); i++)
312                {
313                        if ((*i).statusOfSong != EMPTYTRACK)
314                        {
315                                //new song
316                                p = (Song *)calloc(sizeof(Song),1);
317                                p->filename = strdup((*i).filename);
318                                p->artist = strdup((*i).artist);
319                                p->album = strdup((*i).album);
320                                p->genre = strdup((*i).genre);
321                                p->title = strdup((*i).title);
322
323                                p->track_nr = (*i).track_nr;
324                                p->songlen = (*i).songlen;
325                                p->year = (*i).year;
326                                p->statusOfSong = (*i).statusOfSong;
327                                p->sonyDbOrder = (*i).sonyDbOrder;
328                                ret.push_back(p);
329                        }
330                }
331        }
332        return (ret);
333}
334
335
336int SonyDb::progressIndex()
337{
338        return (this->copyIndex);
339}
340
341
342int SonyDb::isTrackListLoaded()
343{
344        return (this->trackListLoaded);
345}
346
347int SonyDb::getNbTrackToDel()
348{
349        return (this->nbTrackToDel);
350}
351
352int SonyDb::getNbTrackToAdd()
353{
354        return (this->nbTrackToAdd);
355}
356
357bool SonyDb::updSong(Song *songToUpd)
358{
359        if (this->copying)
360        {
361                for (vector<Song>::iterator song = songs_temporary.begin(); song != songs_temporary.end(); song++)
362                {
363                        //song is the same
364                        if (song->sonyDbOrder == songToUpd->sonyDbOrder)
365                        {
366                                if (song->statusOfSong != REMOVE_FROM_DEVICE &&
367                                        song->statusOfSong != EMPTYTRACK)
368                                {
369                                        song->artist = strdup(songToUpd->artist);
370                                        song->album = strdup(songToUpd->album);
371                                        song->genre = strdup(songToUpd->genre);
372                                        song->title = strdup(songToUpd->title);
373
374                                        song->track_nr = songToUpd->track_nr;
375                                        song->songlen = songToUpd->songlen;
376                                        song->year = songToUpd->year;
377                                        return (true);
378                                }
379                                return (false);
380                        }
381                }
382        }
383        else
384        {
385                for (vector<Song>::iterator song = songs.begin(); song != songs.end(); song++)
386                {
387                        //song is the same
388                        if (song->sonyDbOrder == songToUpd->sonyDbOrder)
389                        {
390                                if (song->statusOfSong != REMOVE_FROM_DEVICE &&
391                                        song->statusOfSong != EMPTYTRACK)
392                                {
393                                        song->artist = strdup(songToUpd->artist);
394                                        song->album = strdup(songToUpd->album);
395                                        song->genre = strdup(songToUpd->genre);
396                                        song->title = strdup(songToUpd->title);
397
398                                        song->track_nr = songToUpd->track_nr;
399                                        song->songlen = songToUpd->songlen;
400                                        song->year = songToUpd->year;
401                                        return (true);
402                                }
403                                return (false);
404                        }
405                }
406        }
407        return (0);
408}
409
410int SonyDb::delSong(Song *songToDel)
411{
412        if (this->copying)
413        {
414                for (vector<Song>::iterator song = songs_temporary.begin(); song != songs_temporary.end(); song++)
415                {
416                        //song is the same
417                        if ((STRCMP2_NULLOK((*song).album, (songToDel)->album) == 0) &&
418                                        (STRCMP2_NULLOK((*song).artist, (songToDel)->artist) == 0) &&
419                                        (STRCMP2_NULLOK((*song).title, (songToDel)->title) == 0))
420                        {
421                                if ((*song).statusOfSong == ADD_TO_DEVICE) //song is not yet on the device
422                                {
423                                        //remove it from the list
424                                        songs_temporary.erase(song);
425                                        nbTrackToAdd--;
426                                        //size of the song
427                                        struct stat results;
428                                        if (stat((*songToDel).filename, &results) == 0)
429                                                addTrackTotalByte -= results.st_size;
430                                        return (2);
431                                }
432                        }
433                }
434        }
435        else
436        {
437                for (vector<Song>::iterator song = songs.begin(); song != songs.end(); song++)
438                {
439                        //song is the same
440                        if ((STRCMP2_NULLOK((*song).album, (songToDel)->album) == 0) &&
441                                        (STRCMP2_NULLOK((*song).artist, (songToDel)->artist) == 0) &&
442                                        (STRCMP2_NULLOK((*song).title, (songToDel)->title) == 0))
443                        {
444                                if ((*song).statusOfSong == ADD_TO_DEVICE) //song is not yet on the device
445                                {
446                                        //remove it from the list
447                                        songs.erase(song);
448                                        nbTrackToAdd--;
449                                        //size of the song
450                                        struct stat results;
451                                        if (stat((*songToDel).filename, &results) == 0)
452                                                addTrackTotalByte -= results.st_size;
453                                        return (2);
454                                }
455                                if ((*song).statusOfSong == ON_DEVICE)
456                                {
457                                        (*song).statusOfSong = REMOVE_FROM_DEVICE;
458                                        nbTrackToDel++;
459                                        //size of the song
460                                        struct stat results;
461                                        if (stat((*songToDel).filename, &results) == 0)
462                                                delTrackTotalByte += results.st_size;
463                                        return (1);
464                                }
465                        }
466                }
467        }
468        return (0);
469}
470
471int SonyDb::getNbPlaylist()
472{
473        return(this->playlist.size());
474}
475
476bool SonyDb::addPlaylist(Playlist *p)
477{
478        if (this->copying)
479                playlist_temporary.push_back(*p);
480        else
481                playlist.push_back(*p);
482        return (true);
483}
484
485bool SonyDb::addSong(Song *songToAdd)
486{
487        //check how much space is needed
488        struct stat results;
489        if (stat((*songToAdd).filename, &results) == 0)
490                addTrackTotalByte += results.st_size;
491
492        if (this->copying)
493        {
494                //add the song to the temporary list
495                songToAdd->sonyDbOrder = 0;
496                songs_temporary.push_back(*songToAdd);
497                nbTrackToAdd++;
498        }
499        else
500        {
501                //check if song is already present on device
502                for (vector<Song>::iterator song = songs.begin(); song != songs.end(); song++)
503                {
504                        //song is the same
505                        if ((STRCMP2_NULLOK((*song).album, (songToAdd)->album) == 0) &&
506                                        (STRCMP2_NULLOK((*song).artist, (songToAdd)->artist) == 0) &&
507                                        (STRCMP2_NULLOK((*song).title, (songToAdd)->title) == 0))
508                        {
509                                if ((*song).statusOfSong != ADD_TO_DEVICE)
510                                        (*song).statusOfSong = ON_DEVICE;
511                                free(songToAdd->filename);
512                                songToAdd->filename = strdup((*song).filename);
513                                return (false);
514                        }
515                }
516
517                //add the song
518                nbTrackToAdd++;
519                songToAdd->sonyDbOrder = 0; //changed when copied to the device in writeTracks
520                songs.push_back(*songToAdd);
521        }
522
523        return (true);
524}
525
526
527
528
529/*****************************************************************************************/
530/** read/write functions (common header) */
531
532bool SonyDb::getHeader(sonyFileHeader *header, FILE *f)
533{
534        //read header file
535        if ( fread(header, sizeof(sonyFileHeader), 1, f ) != 1)
536        {
537                fprintf(fp, "error could not read file header (fileheader)\n");
538                fflush(fp);
539                return false;
540        }
541        /*  else
542                {
543                fprintf(fp, "header\n: magic:%08x, cte: %08x ,count:%08x \n", header->magic, header->cte, header->count);
544
545                }
546                */
547
548        return true;
549}
550
551bool SonyDb::getObjectPointer(sonyObjectPointer *Opointer, FILE *f)
552{
553        //read object pointer
554        if ( fread(Opointer, sizeof(sonyObjectPointer), 1, f ) != 1 )
555        {
556                fprintf(fp, "error could not read file header (filePointer)\n");
557                fflush(fp);
558                return false;
559        }
560        else
561        {
562                //fprintf(fp, "objectPointer: magic:%x length:%x, offset:%x\n", Opointer->magic, Opointer->length, Opointer->offset);
563                //get values from big endian
564                Opointer->length = UINT32_SWAP_BE_LE(Opointer->length);
565                Opointer->offset = UINT32_SWAP_BE_LE(Opointer->offset);
566                //fprintf(fp, "sizeof: %i, objectPointer\n: magic:%s length:%08x, offset:%08x\n",sizeof(sonyObjectPointer), Opointer->magic, Opointer->length, Opointer->offset);
567        }
568        return true;
569}
570
571bool SonyDb::getObject(sonyObject *obj, FILE *f)
572{
573        //read object
574        if ( fread(obj, sizeof(sonyObject), 1, f ) !=1 )
575        {
576                fprintf(fp, "error could not read file header (object)\n");
577                fflush(fp);
578                return false;
579        }
580        else
581        {
582                //fprintf(fp, "object: magic:%x size :%x, count:%x \n", obj->magic, obj->size, obj->count);
583                //get values from big endian
584                obj->size = UINT16_SWAP_BE_LE(obj->size);
585                obj->count = UINT16_SWAP_BE_LE(obj->count);
586                //fprintf(fp, "sizeof: %i, object\n: magic:%s size :%08x, count:%08x \n", sizeof(sonyObject), obj->magic, obj->size, obj->count);
587        }   
588        return true;
589}
590
591// write a file header
592bool SonyDb::writeHeader(sonyFileHeader *h, FILE *f)
593{
594        return(writeHeader(h, f, 1));
595}
596
597// write a file header specifying the object pointer count
598bool SonyDb::writeHeader(sonyFileHeader *h, FILE *f, int count)
599{
600        h->cte[0] = 0x01;
601        h->cte[1] = 0x01;
602        h->cte[2] = 0x00;
603        h->cte[3] = 0x00;
604        h->count = count;
605        for (int i = 0; i < 7; i++)
606                h->padding[i]= 0x00;
607
608        if (fwrite(h, sizeof(sonyFileHeader), 1, f) == 1)
609                return (true);
610        else
611                return (false);
612}
613
614// write an object pointer header
615bool SonyDb::writeObjectPointer(sonyObjectPointer *p, FILE *f)
616{
617        p->padding = 0x00000000;
618
619        if (fwrite(p, sizeof(sonyFileHeader), 1, f) == 1)
620                return (true);
621        else
622                return (false);
623        return (true);
624}
625
626//internal write an object header
627bool SonyDb::writeObject(sonyObject *obj, FILE *f)
628{
629        if (fwrite(obj, sizeof(sonyFileHeader), 1, f) == 1)
630                return (true);
631        else
632                return (false);
633}
634
635
636/*****************************************************************************************/
637
638//internal write a track header
639bool SonyDb::writeTrackHeader(sonyTrack *t, FILE *f)
640{
641        if (fwrite(t, sizeof(sonyTrack), 1, f) != 1)
642        {
643                fprintf(fp, "error could not write file header (object)\n");
644                fflush(fp);
645                return false;
646        }
647        return (true);
648}
649
650//internal write a track tag
651bool SonyDb::writeTrackTag(sonyTrackTag *tt, char *input, FILE *f)
652
653        //init
654        int size = TAGSIZE;
655        utf16char *tagRecord;
656
657        //to utf16
658        tagRecord = ansi_to_utf16(input, (size - 6), true);
659
660        //write tracktag (tagtype + encoding)
661        if (fwrite(tt, sizeof(sonyTrackTag), 1, f) != 1) return (false);
662
663        //write tag (data itself)
664        if (fwrite(tagRecord, (size - 6), 1, f) != 1) return (false);
665        free(tagRecord);
666
667        return (true);
668}
669
670void SonyDb::setTable(char *TableFileName, int type)
671{
672        this->decodeTableFilename = strdup(TableFileName);
673        this->codeType = type;
674
675        if (type == ENCODING_USE_KEY)
676        {
677                FILE *t = fopen(decodeTableFilename, "rb");
678                fseek(t, 0x0a, SEEK_SET);
679                fread(&(this->DvId), sizeof(uint32), 1, t);
680                this->DvId = UINT32_SWAP_BE_LE(this->DvId);
681                fclose(t);
682        }
683}
684
685
686
687//ported from gym
688bool SonyDb::loadCodeTable(int id)
689{
690        FILE *t;
691        uint8 *header1 = (uint8*)malloc(sizeof(uint8) * 134); //deserialize manually ...
692        uint8 *header2 = (uint8*)malloc(sizeof(uint8) * 10);
693        uint8 *tmp = (uint8*)malloc(sizeof(uint8) * 256);
694
695        t = fopen(decodeTableFilename, "rb");
696        // place cursor in place...
697        fseek(t, 0x4B0 * id, SEEK_SET);
698        fread(header1, sizeof(uint8), 134, t);
699
700        for (int i = 0; i < 4; i++)
701        {
702                fread(tmp, sizeof(uint8), 256, t);
703                for (int j = 0; j < 256; j++)
704                        codeTable[(i*256) + j] = tmp[j];
705                fread(header2, sizeof(uint8), 10, t);
706        }
707
708        free(header1);
709        free(header2);
710        free(tmp);
711        fclose(t);
712        return true;
713}
714
715//add mp3 file to device
716bool SonyDb::addOMA(Song *s, int destination)
717{
718        uint32    key = 0xFFFFFFFF;
719        bool      isVBR = false;
720
721        this->copyPercent = 0;
722        if (s->statusOfSong != ADD_TO_DEVICE)
723                return false;
724
725        char *filename = GetOMAFilename(destination);
726
727        fprintf(fp, "sending %s to %s\n", s->filename, filename);
728        fflush(fp);
729
730        //createDirectory if necessary
731        createDir(destination);
732
733        //load decode table for this track
734        if (this->codeType == ENCODING_USE_TABLE)
735                this->loadCodeTable(destination - 1);
736
737        //or use key
738        if (this->codeType == ENCODING_USE_KEY)
739                key = ( 0x2465 + destination * 0x5296E435 ) ^ this->DvId;
740
741
742        FILE *fout = fopen(filename, "wb");
743        if (fout == NULL)
744        {
745                fprintf(fp, "error can't open file %s\n", filename);
746                fflush(fp);
747                return false;
748        }
749
750        FILE *fin = fopen(s->filename, "rb");
751        float finSize = 0;
752        if (fin == NULL)
753        {
754                fprintf(fp, "error can't open file %s\n", s->filename);
755                fflush(fp);
756                fclose(fout);
757                return false;
758        }
759
760        //get input file size
761        struct stat results;
762        if (stat(s->filename, &results) == 0)
763                finSize = results.st_size;
764
765        uint8       *header = (uint8*)malloc(sizeof(uint8) * 11);
766        utf16char           *tagRecord;
767        char        *tmpTag = (char*)malloc(sizeof(char) * 256);
768        int         tagLength;
769        int         headerLength = 0;
770        long        startPoint = 0;
771        int         nbFrames = 0; // estimated number of frames
772
773        memset(header, 0, 11);
774        if (fread(header, 1, 10, fin) != 10)
775                return false;
776        if (STRNCMP_NULLOK((char*)header, "ID3", 3) == 0)
777        {
778                //skip Idv2 tags
779                startPoint = ((header[6] << 21) + (header[7] << 14) + (header[8] << 7) + header[9]) + 10;
780
781        }
782        else
783        {
784                //no idv2 tag found
785                startPoint = 0;
786        }
787
788        //go to the first frame
789        fseek(fin, startPoint, SEEK_SET);
790
791        memset(header, 0, 11);
792        //skip zeros
793        while (header[0] == 0)
794        {
795                if(fread(header, sizeof(uint8), 1, fin) != 1)
796                {
797                        fclose(fout);
798                        fclose(fin);
799                        return false;
800                }
801        }
802
803        if (header[0] == 0xFF)
804        {
805                if (fread(header, sizeof(uint8), 3, fin) != 3)
806                {
807                        fclose(fout);
808                        fclose(fin);
809                        return false;
810                }
811
812                //get mpeg type, layer type and bitrate
813                if ((header[0] & 0xE0) == 0xE0) //we found the first frame
814                {
815                        //encoding =  mpeg version(2bits), layer version(2bits), bitrate(4bits)
816                        s->encoding = ( ((header[0] & 0x1E) << 3) + ((header[1] & 0xF0) >> 4) );
817
818                        // 00 - MPEG Version 2.5 (unofficial extension of MPEG 2)
819                        // 01 - reserved
820                        // 10 - MPEG Version 2 (ISO/IEC 13818-3)
821                        // 11 - MPEG Version 1 (ISO/IEC 11172-3)
822                        uint8 mpegVersion = (header[0] & 0x18) >> 3;
823
824                        //00 - reserved
825                        //01 - Layer III
826                        //10 - Layer II
827                        //11 - Layer I
828                        uint8 layerVersion = (header[0] & 0x06) >> 1;
829
830                        uint8 samplingRateIndex = (header[1] & 0xC) >> 2;
831
832                        if (((mpegVersion * 3) + samplingRateIndex >= 12) || ((mpegVersion * 3) + layerVersion >= 16))
833                        {
834                                //header is invalid
835                                nbFrames = 0;
836                        }
837                        else
838                        {
839                                int  SAMPLING_RATES[] = {11025, 12000, 8000, 0, 0, 0, 22050, 24000, 16000, 44100, 48000, 32000};
840                                int  SAMPLE_PER_FRAME[] = {0,576,1152,384,0,0,0,0,0,576,1152,384,0,1152,1152,384};
841
842                                //sample per frame 0=reserved
843                                //          MPG2.5 res        MPG2   MPG1
844                                //reserved  0      0          0      0
845                                //Layer III 576    0          576    1152       
846                                //Layer II  1152   0          1152   1152       
847                                //Layer I   384    0          384    384
848
849                                int samplingRate = SAMPLING_RATES[(mpegVersion * 3) + samplingRateIndex];
850                                int samplePerFrame = SAMPLE_PER_FRAME[(mpegVersion * 4) + layerVersion];
851                                nbFrames = (s->songlen * samplingRate) / samplePerFrame;
852                        }
853
854                        //skip the the frame header
855                        fseek(fin, sizeof(uint8) * 32, SEEK_CUR);
856
857                        //check if first is "XING" for VBR files
858                        memset(header, 0, 11);
859                        if (fread(header, sizeof(uint8), 4, fin) != 4)
860                        {
861                                fclose(fout);
862                                fclose(fin);
863                                return false;
864                        }
865
866                        if (STRNCMP_NULLOK((char*)header, "XING", 4) == 0)
867                                isVBR = true;
868                }
869                else
870                {
871                        fprintf(fp, "File format invalid, could not find first frame%s\n", s->filename);
872                        fflush(fp);
873                        //return false;
874                }
875        }
876        else
877        {
878                fprintf(fp, "File format invalid, could not find first frame%s\n", s->filename);
879                fflush(fp);
880                //return false;
881        }
882
883
884
885        //go back to the start of mp3 data
886        fseek(fin, startPoint, SEEK_SET);
887
888        //write the OMA headers :
889        //format is :
890        //"ea3"0x03 (4bytes), sizeOfTotaltags (6bytes)
891        //TIT2(4bytes) sizeOfTag(4bytes) 2flags (2bytes) 0x02(=utf16be format?) titleOftheSong
892        //...
893        //not all size are coded in synchsafe format
894
895
896        //idv2 header
897        memset(header, 0, 11);
898        header[0] = 'e';
899        header[1] = 'a';
900        header[2] = '3';
901        header[3] = 0x03;
902        //...zeros
903        header[8] = 0x17;
904        header[9] = 0x76; //size of tag header in Synchsafe format (=3072 bytes - 10 of header)
905        if (fwrite(header, sizeof(uint8), 10, fout) != 10)
906        {
907                fclose(fout);
908                fclose(fin);
909                return false;
910        }
911
912        //title tag
913        memset(header, 0, 11);
914        memcpy(header, "TIT2", 4);
915        tagLength = strlen(s->title);
916        tagRecord = ansi_to_utf16(s->title, tagLength + 1, true);
917        tagLength = (tagLength * 2) + 1;
918        header[4] = NOT_SYNCHSAFE_B1(tagLength);//size of the title
919        header[5] = NOT_SYNCHSAFE_B2(tagLength);
920        header[6] = NOT_SYNCHSAFE_B3(tagLength);
921        header[7] = NOT_SYNCHSAFE_B4(tagLength);
922        header[8] = 0;   //flag 1
923        header[9] = 0;  //flag 2
924        header[10] = 0x02;  //
925        tagLength = (tagLength - 1 )/ 2;
926        if (fwrite(header, sizeof(uint8), 11, fout) != 11)
927        {
928                fclose(fout);
929                fclose(fin);
930                return false;
931        }
932        headerLength += (11 * sizeof(uint8));
933        if (fwrite(tagRecord, sizeof(utf16char), tagLength, fout) != tagLength)
934        {
935                fclose(fout);
936                fclose(fin);
937                return false;
938        }
939        headerLength += (tagLength * sizeof(utf16char));
940        free(tagRecord);
941
942
943        //artist tag
944        memset(header, 0, 11);
945        memcpy(header, "TPE1", 4);
946        tagLength = strlen(s->artist);
947        tagRecord = ansi_to_utf16(s->artist, tagLength + 1, true);
948        tagLength = (tagLength * 2) + 1;
949        header[4] = NOT_SYNCHSAFE_B1(tagLength);//size of the title
950        header[5] = NOT_SYNCHSAFE_B2(tagLength);
951        header[6] = NOT_SYNCHSAFE_B3(tagLength);
952        header[7] = NOT_SYNCHSAFE_B4(tagLength);
953        header[8] = 0;   //flag 1
954        header[9] = 0;  //flag 2
955        header[10] = 0x02;  //
956        tagLength = (tagLength - 1 )/ 2;
957        if (fwrite(header, sizeof(uint8), 11, fout) != 11)
958        {
959                fclose(fout);
960                fclose(fin);
961                return false;
962        }
963        headerLength += (11 * sizeof(uint8));
964        if (fwrite(tagRecord, sizeof(utf16char), tagLength, fout) != tagLength)
965        {
966                fclose(fout);
967                fclose(fin);
968                return false;
969        }
970        headerLength += (tagLength * sizeof(utf16char));
971        free(tagRecord);
972
973        //album tag
974        memset(header, 0, 11);
975        memcpy(header, "TALB", 4);
976        tagLength = strlen(s->album);
977        tagRecord = ansi_to_utf16(s->album, tagLength + 1, true);
978        tagLength = (tagLength * 2) + 1;
979        header[4] = NOT_SYNCHSAFE_B1(tagLength);//size of the title
980        header[5] = NOT_SYNCHSAFE_B2(tagLength);
981        header[6] = NOT_SYNCHSAFE_B3(tagLength);
982        header[7] = NOT_SYNCHSAFE_B4(tagLength);
983        header[8] = 0;  //flag 1
984        header[9] = 0;  //flag 2
985        header[10] = 0x02;  //
986        tagLength = (tagLength - 1 )/ 2;
987        if (fwrite(header, sizeof(uint8), 11, fout) != 11)
988        {
989                fclose(fout);
990                fclose(fin);
991                return false;
992        }
993        headerLength += (11 * sizeof(uint8));
994        if (fwrite(tagRecord, sizeof(utf16char), tagLength, fout) != tagLength)
995        {
996                fclose(fout);
997                fclose(fin);
998                return false;
999        }
1000        headerLength += (tagLength * sizeof(utf16char));
1001        free(tagRecord);
1002
1003        //genre tag
1004        memset(header, 0, 11);
1005        memcpy(header, "TCON", 4);
1006        tagLength = strlen(s->genre);
1007        tagRecord = ansi_to_utf16(s->genre, tagLength + 1, true);
1008        tagLength = (tagLength * 2) + 1;
1009        header[4] = NOT_SYNCHSAFE_B1(tagLength);//size of the title
1010        header[5] = NOT_SYNCHSAFE_B2(tagLength);
1011        header[6] = NOT_SYNCHSAFE_B3(tagLength);
1012        header[7] = NOT_SYNCHSAFE_B4(tagLength);
1013        header[8] = 0;   //flag 1
1014        header[9] = 0;  //flag 2
1015        header[10] = 0x02;  //
1016        tagLength = (tagLength - 1 )/ 2;
1017        if (fwrite(header, sizeof(uint8), 11, fout) != 11)
1018        {
1019                fclose(fout);
1020                fclose(fin);
1021                return false;
1022        }
1023        headerLength += (11 * sizeof(uint8));
1024        if (fwrite(tagRecord, sizeof(utf16char), tagLength, fout) != tagLength)
1025        {
1026                fclose(fout);
1027                fclose(fin);
1028                return false;
1029        }
1030        headerLength += (tagLength * sizeof(utf16char));
1031        free(tagRecord);
1032
1033        //track number tag //space are suppose to be replaced by 0x00 not 0x20
1034        sprintf(tmpTag, "OMG_TRACK %02i", s->track_nr);
1035        memset(header, 0, 11);
1036        memcpy(header, "TXXX", 4);
1037        tagLength = strlen(tmpTag);
1038        tagRecord = ansi_to_utf16(tmpTag, tagLength + 1, true);
1039        tagLength = (tagLength * 2) + 1;
1040        header[4] = NOT_SYNCHSAFE_B1(tagLength);//size of the title
1041        header[5] = NOT_SYNCHSAFE_B2(tagLength);
1042        header[6] = NOT_SYNCHSAFE_B3(tagLength);
1043        header[7] = NOT_SYNCHSAFE_B4(tagLength);
1044        header[8] = 0;   //flag 1
1045        header[9] = 0;  //flag 2
1046        header[10] = 0x02;  //
1047        tagLength = (tagLength - 1 )/ 2;
1048        if (fwrite(header, sizeof(uint8), 11, fout) != 11)
1049        {
1050                fclose(fout);
1051                fclose(fin);
1052                return false;
1053        }
1054        headerLength += (11 * sizeof(uint8));
1055        if (fwrite(tagRecord, sizeof(utf16char), tagLength, fout) != tagLength)
1056        {
1057                fclose(fout);
1058                fclose(fin);
1059                return false;
1060        }
1061        headerLength += (tagLength * sizeof(utf16char));
1062        free(tagRecord);
1063
1064        //fixme date of transfert? tag //space are suppose to be replaced by 0x00 not 0x20
1065        sprintf(tmpTag, "OMG_TRLDA 2001/01/01 00:00:00");
1066        memset(header, 0, 11);
1067        memcpy(header, "TXXX", 4);
1068        tagLength = strlen(tmpTag);
1069        tagRecord = ansi_to_utf16(tmpTag, tagLength + 1, true);
1070        tagLength = (tagLength * 2) + 1;
1071        tagLength = (strlen(tmpTag) + 1) * 2;
1072        header[4] = NOT_SYNCHSAFE_B1(tagLength);//size of the title
1073        header[5] = NOT_SYNCHSAFE_B2(tagLength);
1074        header[6] = NOT_SYNCHSAFE_B3(tagLength);
1075        header[7] = NOT_SYNCHSAFE_B4(tagLength);
1076        header[8] = 0;   //flag 1
1077        header[9] = 0;  //flag 2
1078        header[10] = 0x02;  //
1079        tagLength = (tagLength - 1 )/ 2;
1080        if (fwrite(header, sizeof(uint8), 11, fout) != 11)
1081        {
1082                fclose(fout);
1083                fclose(fin);
1084                return false;
1085        }
1086        headerLength += (11 * sizeof(uint8));
1087        if (fwrite(tagRecord, sizeof(utf16char), tagLength, fout) != tagLength)
1088        {
1089                fclose(fout);
1090                fclose(fin);
1091                return false;
1092        }
1093        headerLength += (tagLength * sizeof(utf16char));
1094        free(tagRecord);
1095
1096        //track length tag
1097        sprintf(tmpTag, "%i", s->songlen * 1000);
1098        memset(header, 0, 11);
1099        memcpy(header, "TLEN", 4);
1100        tagLength = strlen(tmpTag);
1101        tagRecord = ansi_to_utf16(tmpTag, tagLength + 1, true);
1102        tagLength = (tagLength * 2) + 1;
1103        header[4] = NOT_SYNCHSAFE_B1(tagLength);//size of the title
1104        header[5] = NOT_SYNCHSAFE_B2(tagLength);
1105        header[6] = NOT_SYNCHSAFE_B3(tagLength);
1106        header[7] = NOT_SYNCHSAFE_B4(tagLength);
1107        header[8] = 0;   //flag 1
1108        header[9] = 0;  //flag 2
1109        header[10] = 0x02;  //
1110        tagLength = (tagLength - 1 )/ 2;
1111        if (fwrite(header, sizeof(uint8), 11, fout) != 11)
1112        {
1113                fclose(fout);
1114                fclose(fin);
1115                return false;
1116        }
1117        headerLength += (11 * sizeof(uint8));
1118        if (fwrite(tagRecord, sizeof(utf16char), tagLength, fout) != tagLength)
1119        {
1120                fclose(fout);
1121                fclose(fin);
1122                return false;
1123        }
1124        headerLength += (tagLength * sizeof(utf16char));
1125        free(tagRecord);
1126
1127        memset(header, 0, 11);
1128        //fill the rest with 0
1129        while (headerLength < 3062)
1130        {
1131                headerLength += sizeof(uint8);
1132                if (fwrite(header, sizeof(uint8), 1, fout) != 1)
1133                {
1134                        fclose(fout);
1135                        fclose(fin);
1136                        return false;
1137                }
1138        }
1139
1140        //write second header fixme (some stuff are missing here... important?)
1141        uint8 *header2 = (uint8*)malloc(sizeof(uint8) * 16);
1142        headerLength = 0;
1143        memset(header2, 0, 16);
1144        //first line
1145        memcpy(header2, "EA3", 3);
1146        header2[3] = 0x02;
1147        header2[4] = 0;   //size of 2nd header
1148        header2[5] = 0x60;//size of 2nd header
1149        header2[6] = 0xff;// + same value as in 05CIDLST.DAT
1150        if (this->codeType == ENCODING_USE_NONE)
1151        {
1152                header2[7] = 0xff;// cp or sonicstage? or encoded not encoded? 505 =e  1000 =f
1153        }
1154        else
1155        {
1156                header2[7] = 0xfe;// cp or sonicstage? or encoded not encoded? 505 =e  1000 =f
1157        }
1158        header2[12] = 0x01;
1159        header2[13] = 0x0F;
1160        header2[14] = 0x50;
1161        header2[15] = 0x00;// - same value as in 05CIDLST.DAT
1162        if (fwrite(header2, sizeof(uint8), 16, fout) != 16)
1163        {
1164                fclose(fout);
1165                fclose(fin);
1166                return false;
1167        }
1168        headerLength += (16 * sizeof(uint8));
1169
1170        //second line
1171        memset(header2, 0, 16);
1172        header2[1] = 0x04;// + same value as in 05CIDLST.DAT fixme
1173        //zeros...   
1174        header2[5] = 0x01; //fixme 01
1175        header2[6] = 0x02; //fixme 02
1176        header2[7] = 0x03; //fixme 03
1177        header2[8] = 0xc8;
1178        header2[9] = 0xd8;
1179        header2[10] = 0x36;
1180        header2[11] = 0xd8;
1181        header2[12] = 0x11; //fixme 11
1182        header2[13] = 0x22; //fixme 22
1183        header2[14] = 0x33; //fixme 33
1184        header2[15] = 0x44;// - same value as in 05CIDLST.DAT
1185        if (fwrite(header2, sizeof(uint8), 16, fout) != 16)
1186        {
1187                fclose(fout);
1188                fclose(fin);
1189                return false;
1190        }
1191        headerLength += (16 * sizeof(uint8));
1192
1193        //third line
1194        memset(header2, 0, 16);
1195
1196        header2[0] = 0x03;// 3 = MP3
1197        header2[1] =(isVBR) ? 0x90 : 0x80 ;// VBR = 90, CBR = 80
1198        header2[2] = s->encoding;// mpeg version(2bits), layer version(2bits), bitrate(4bits)
1199        header2[3] = 0x10;//?? fixme
1200
1201        //tracklength
1202        uint32 trackLengh = s->songlen * 1000;
1203        header2[4] = (uint8) (((trackLengh) & (uint32) 0xff000000U) >> 24);
1204        header2[5] = (uint8) (((trackLengh) & (uint32) 0x00ff0000U) >> 16);
1205        header2[6] = (uint8) (((trackLengh) & (uint32) 0x0000ff00U) >>  8);
1206        header2[7] = (uint8) ((trackLengh) & (uint32)  0x000000ffU);
1207
1208        //number of frames