/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id: mpeg.c,v 1.168 2002/11/24 00:23:48 linusnielsen Exp $
*
* Copyright (C) 2002 by Linus Nielsen Feltzing
*
* All files in this archive are subject to the GNU General Public License.
* See the file COPYING in the source tree root for full license agreement.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include <stdbool.h>
#include "config.h"
#include "debug.h"
#include "panic.h"
#include "id3.h"
#include "mpeg.h"
#include "ata.h"
#include "string.h"
#ifndef SIMULATOR
#include "i2c.h"
#include "mas.h"
#include "dac.h"
#include "system.h"
#include "kernel.h"
#include "thread.h"
#include "usb.h"
#include "file.h"
#include "hwcompat.h"
#endif
extern void bitswap(unsigned char *data, int length);
#ifdef HAVE_MAS3587F
static void init_recording(void);
static void init_playback(void);
static void start_recording(void);
#endif
#ifndef SIMULATOR
static int get_unplayed_space(void);
static int get_unswapped_space(void);
#endif
#define MPEG_PLAY 1
#define MPEG_STOP 2
#define MPEG_PAUSE 3
#define MPEG_RESUME 4
#define MPEG_NEXT 5
#define MPEG_PREV 6
#define MPEG_FF_REWIND 7
#define MPEG_FLUSH_RELOAD 8
#define MPEG_RECORD 9
#define MPEG_INIT_RECORDING 10
#define MPEG_INIT_PLAYBACK 11
#define MPEG_NEED_DATA 100
#define MPEG_TRACK_CHANGE 101
#define MPEG_SAVE_DATA 102
#define MPEG_STOP_DONE 103
enum
{
MPEG_DECODER,
MPEG_ENCODER
} mpeg_mode;
extern char* playlist_peek(int steps);
extern int playlist_next(int steps);
extern int playlist_amount(void);
extern void update_file_pos( int id, int pos );
static char *units[] =
{
"%", /* Volume */
"dB", /* Bass */
"dB", /* Treble */
"%", /* Balance */
"dB", /* Loudness */
"%", /* Bass boost */
"", /* AVC */
"", /* Channels */
"dB", /* Left gain */
"dB", /* Right gain */
"dB", /* Mic gain */
};
static int numdecimals[] =
{
0, /* Volume */
0, /* Bass */
0, /* Treble */
0, /* Balance */
0, /* Loudness */
0, /* Bass boost */
0, /* AVC */
0, /* Channels */
1, /* Left gain */
1, /* Right gain */
1, /* Mic gain */
};
static int minval[] =
{
0, /* Volume */
0, /* Bass */
0, /* Treble */
-50, /* Balance */
0, /* Loudness */
0, /* Bass boost */
-1, /* AVC */
0, /* Channels */
0, /* Left gain */
0, /* Right gain */
0, /* Mic gain */
};
static int maxval[] =
{
100, /* Volume */
#ifdef HAVE_MAS3587F
24, /* Bass */
24, /* Treble */
#else
30, /* Bass */
30, /* Treble */
#endif
50, /* Balance */
17, /* Loudness */
10, /* Bass boost */
3, /* AVC */
3, /* Channels */
15, /* Left gain */
15, /* Right gain */
15, /* Mic gain */
};
static int defaultval[] =
{
70, /* Volume */
#ifdef HAVE_MAS3587F
12+6, /* Bass */
12+6, /* Treble */
#else
15+7, /* Bass */
15+7, /* Treble */
#endif
0, /* Balance */
0, /* Loudness */
0, /* Bass boost */
0, /* AVC */
0, /* Channels */
8, /* Left gain */
2, /* Right gain */
2, /* Mic gain */
};
char *mpeg_sound_unit(int setting)
{
return units[setting];
}
int mpeg_sound_numdecimals(int setting)
{
return numdecimals[setting];
}
int mpeg_sound_min(int setting)
{
return minval[setting];
}
int mpeg_sound_max(int setting)
{
return maxval[setting];
}
int mpeg_sound_default(int setting)
{
return defaultval[setting];
}
/* list of tracks in memory */
#define MAX_ID3_TAGS (1<<4) /* Must be power of 2 */
#define MAX_ID3_TAGS_MASK (MAX_ID3_TAGS - 1)
struct id3tag
{
struct mp3entry id3;
int mempos;
bool used;
};
static struct id3tag *id3tags[MAX_ID3_TAGS];
static struct id3tag _id3tags[MAX_ID3_TAGS];
static unsigned int current_track_counter = 0;
static unsigned int last_track_counter = 0;
#ifndef SIMULATOR
static bool mpeg_is_initialized = false;
static int tag_read_idx = 0;
static int tag_write_idx = 0;
static int num_tracks_in_memory(void)
{
return (tag_write_idx - tag_read_idx) & MAX_ID3_TAGS_MASK;
}
#endif
#ifndef SIMULATOR
static void debug_tags(void)
{
#ifdef DEBUG_TAGS
int i;
for(i = 0;i < MAX_ID3_TAGS;i++)
{
DEBUGF("id3tags[%d]: %08x", i, id3tags[i]);
if(id3tags[i])
DEBUGF(" - %s", id3tags[i]->id3.path);
DEBUGF("\n");
}
DEBUGF("read: %d, write :%d\n", tag_read_idx, tag_write_idx);
DEBUGF("num_tracks_in_memory: %d\n", num_tracks_in_memory());
#endif
}
static bool append_tag(struct id3tag *tag)
{
if(num_tracks_in_memory() < MAX_ID3_TAGS - 1)
{
id3tags[tag_write_idx] = tag;
tag_write_idx = (tag_write_idx+1) & MAX_ID3_TAGS_MASK;
debug_tags();
return true;
}
else
{
DEBUGF("Tag memory is full\n");
return false;
}
}
static void remove_current_tag(void)
{
int oldidx = tag_read_idx;
if(num_tracks_in_memory() > 0)
{
/* First move the index, so nobody tries to access the tag */
tag_read_idx = (tag_read_idx+1) & MAX_ID3_TAGS_MASK;
/* Now delete it */
id3tags[oldidx]->used = false;
id3tags[oldidx] = NULL;
debug_tags();
}
}
static void remove_all_non_current_tags(void)
{
int i = (tag_read_idx+1) & MAX_ID3_TAGS_MASK;
while (i != tag_write_idx)
{
id3tags[i]->used = false;
id3tags[i] = NULL;
i = (i+1) & MAX_ID3_TAGS_MASK;
}
tag_write_idx = (tag_read_idx+1) & MAX_ID3_TAGS_MASK;
debug_tags();
}
static void remove_all_tags(void)
{
int i;
for(i = 0;i < MAX_ID3_TAGS;i++)
remove_current_tag();
debug_tags();
}
#endif
static void set_elapsed(struct mp3entry* id3)
{
if ( id3->vbr ) {
if ( id3->vbrflags & VBR_TOC_FLAG ) {
/* calculate elapsed time using TOC */
int i;
unsigned int remainder, plen, relpos, nextpos;
/* find wich percent we're at */
for (i=0; i<100; i++ )
{
if ( id3->offset < (int)(id3->toc[i] * (id3->filesize / 256)) )
{
break;
}
}
i--;
if (i < 0)
i = 0;
relpos = id3->toc[i];
if (i < 99)
{
nextpos = id3->toc[i+1];
}
else
{
nextpos = 256;
}
remainder = id3->offset - (relpos * (id3->filesize / 256));
/* set time for this percent */
id3->elapsed = i * id3->length / 100;
/* calculate remainder time */
plen = (nextpos - relpos) * (id3->filesize / 256);
id3->elapsed += (((remainder * 100) / plen) * id3->length) / 10000;
}
else {
/* no TOC exists. set a rough estimate using average bitrate */
int tpk = (id3->filesize / 1024) / id3->length;
id3->elapsed = id3->offset * tpk / 1024;
}
}
else
/* constant bitrate == simple frame calculation */
id3->elapsed = id3->offset / id3->bpf * id3->tpf;
}
static bool paused; /* playback is paused */
#ifdef SIMULATOR
static bool is_