1
0
Fork 0
forked from len0rd/rockbox

Added FS#2939 Encoder Codec Interface + Codecs by Antonius Hellmann with additional FM Recording support and my modifications

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10789 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Michael Sevakis 2006-08-28 22:38:41 +00:00
parent 65c2c58b3a
commit 4fc717a4c1
36 changed files with 4803 additions and 860 deletions

View file

@ -40,6 +40,7 @@
#include "mpeg.h" #include "mpeg.h"
#include "buffer.h" #include "buffer.h"
#include "mp3_playback.h" #include "mp3_playback.h"
#include "playback.h"
#include "backlight.h" #include "backlight.h"
#include "ata.h" #include "ata.h"
#include "talk.h" #include "talk.h"
@ -208,11 +209,28 @@ struct codec_api ci = {
profile_func_exit, profile_func_exit,
#endif #endif
#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
false,
enc_get_inputs,
enc_set_parameters,
enc_alloc_chunk,
enc_free_chunk,
enc_wavbuf_near_empty,
enc_get_wav_data,
&enc_set_header_callback,
#endif
/* new stuff at the end, sort into place next time /* new stuff at the end, sort into place next time
the API gets incompatible */ the API gets incompatible */
}; };
void codec_get_full_path(char *path, const char *codec_fn)
{
/* Create full codec path */
snprintf(path, MAX_PATH-1, ROCKBOX_DIR CODECS_DIR "/%s", codec_fn);
}
int codec_load_ram(char* codecptr, int size, void* ptr2, int bufwrap, int codec_load_ram(char* codecptr, int size, void* ptr2, int bufwrap,
struct codec_api *api) struct codec_api *api)
{ {
@ -277,15 +295,18 @@ int codec_load_ram(char* codecptr, int size, void* ptr2, int bufwrap,
int codec_load_file(const char *plugin, struct codec_api *api) int codec_load_file(const char *plugin, struct codec_api *api)
{ {
char msgbuf[80]; char msgbuf[80];
char path[MAX_PATH];
int fd; int fd;
int rc; int rc;
codec_get_full_path(path, plugin);
/* zero out codec buffer to ensure a properly zeroed bss area */ /* zero out codec buffer to ensure a properly zeroed bss area */
memset(codecbuf, 0, CODEC_SIZE); memset(codecbuf, 0, CODEC_SIZE);
fd = open(plugin, O_RDONLY); fd = open(path, O_RDONLY);
if (fd < 0) { if (fd < 0) {
snprintf(msgbuf, sizeof(msgbuf)-1, "Couldn't load codec: %s", plugin); snprintf(msgbuf, sizeof(msgbuf)-1, "Couldn't load codec: %s", path);
logf("Codec load error:%d", fd); logf("Codec load error:%d", fd);
gui_syncsplash(HZ*2, true, msgbuf); gui_syncsplash(HZ*2, true, msgbuf);
return fd; return fd;

View file

@ -46,6 +46,9 @@
#include "profile.h" #include "profile.h"
#endif #endif
#if (CONFIG_CODEC == SWCODEC) #if (CONFIG_CODEC == SWCODEC)
#if !defined(SIMULATOR)
#include "pcm_record.h"
#endif
#include "dsp.h" #include "dsp.h"
#include "playback.h" #include "playback.h"
#endif #endif
@ -84,7 +87,7 @@
#define CODEC_MAGIC 0x52434F44 /* RCOD */ #define CODEC_MAGIC 0x52434F44 /* RCOD */
/* increase this every time the api struct changes */ /* increase this every time the api struct changes */
#define CODEC_API_VERSION 8 #define CODEC_API_VERSION 9
/* update this to latest version if a change to the api struct breaks /* update this to latest version if a change to the api struct breaks
backwards compatibility (and please take the opportunity to sort in any backwards compatibility (and please take the opportunity to sort in any
@ -285,6 +288,21 @@ struct codec_api {
void (*profile_func_exit)(void *this_fn, void *call_site); void (*profile_func_exit)(void *this_fn, void *call_site);
#endif #endif
#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
bool enc_codec_loaded;
void (*enc_get_inputs)(int *buffer_size,
int *channels, int *quality);
void (*enc_set_parameters)(int chunk_size, int num_chunks,
int samp_per_chunk, char *head_ptr, int head_size,
int enc_id);
unsigned int* (*enc_alloc_chunk)(void);
void (*enc_free_chunk)(void);
int (*enc_wavbuf_near_empty)(void);
char* (*enc_get_wav_data)(int size);
void (**enc_set_header_callback)(void *head_buffer,
int head_size, int num_samples, bool is_file_header);
#endif
/* new stuff at the end, sort into place next time /* new stuff at the end, sort into place next time
the API gets incompatible */ the API gets incompatible */
@ -317,6 +335,10 @@ extern unsigned char plugin_end_addr[];
#endif #endif
#endif #endif
/* create full codec path from filenames in audio_formats[]
assumes buffer size is MAX_PATH */
void codec_get_full_path(char *path, const char *codec_fn);
/* defined by the codec loader (codec.c) */ /* defined by the codec loader (codec.c) */
int codec_load_ram(char* codecptr, int size, void* ptr2, int bufwrap, int codec_load_ram(char* codecptr, int size, void* ptr2, int bufwrap,
struct codec_api *api); struct codec_api *api);

View file

@ -58,6 +58,9 @@ $(OBJDIR)/wavpack.elf : $(OBJDIR)/wavpack.o $(BUILDDIR)/libwavpack.a
$(OBJDIR)/alac.elf : $(OBJDIR)/alac.o $(BUILDDIR)/libalac.a $(BUILDDIR)/libm4a.a $(OBJDIR)/alac.elf : $(OBJDIR)/alac.o $(BUILDDIR)/libalac.a $(BUILDDIR)/libm4a.a
$(OBJDIR)/aac.elf : $(OBJDIR)/aac.o $(BUILDDIR)/libfaad.a $(BUILDDIR)/libm4a.a $(OBJDIR)/aac.elf : $(OBJDIR)/aac.o $(BUILDDIR)/libfaad.a $(BUILDDIR)/libm4a.a
$(OBJDIR)/shorten.elf : $(OBJDIR)/shorten.o $(BUILDDIR)/libffmpegFLAC.a $(OBJDIR)/shorten.elf : $(OBJDIR)/shorten.o $(BUILDDIR)/libffmpegFLAC.a
$(OBJDIR)/mp3_enc.elf: $(OBJDIR)/mp3_enc.o
$(OBJDIR)/wav_enc.elf: $(OBJDIR)/wav_enc.o
$(OBJDIR)/wavpack_enc.elf: $(OBJDIR)/wavpack_enc.o $(BUILDDIR)/libwavpack.a
$(OBJDIR)/%.elf : $(OBJDIR)/%.elf :
@echo "LD $(notdir $@)" @echo "LD $(notdir $@)"

View file

@ -1,4 +1,5 @@
#if CONFIG_CODEC == SWCODEC #if CONFIG_CODEC == SWCODEC
/* decoders */
vorbis.c vorbis.c
mpa.c mpa.c
flac.c flac.c
@ -13,4 +14,11 @@ aac.c
shorten.c shorten.c
aiff.c aiff.c
sid.c sid.c
#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
/* encoders */
mp3_enc.c
wav_enc.c
wavpack_enc.c
#endif #endif
#endif

2860
apps/codecs/mp3_enc.c Normal file

File diff suppressed because it is too large Load diff

172
apps/codecs/wav_enc.c Normal file
View file

@ -0,0 +1,172 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2006 Antonius Hellmann
*
* 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.
*
****************************************************************************/
#ifndef SIMULATOR
#include "codeclib.h"
CODEC_HEADER
static struct codec_api *ci;
static int enc_channels;
#define CHUNK_SIZE 8192
static unsigned char wav_header[44] =
{'R','I','F','F',0,0,0,0,'W','A','V','E','f','m','t',' ',16,
0,0,0,1,0,2,0,0x44,0xac,0,0,0x10,0xb1,2,0,4,0,16,0,'d','a','t','a',0,0,0,0};
static unsigned char wav_header_mono[44] =
{'R','I','F','F',0,0,0,0,'W','A','V','E','f','m','t',' ',16,
0,0,0,1,0,1,0,0x44,0xac,0,0,0x88,0x58,1,0,2,0,16,0,'d','a','t','a',0,0,0,0};
/* update file header info callback function (called by main application) */
void enc_set_header(void *head_buffer, /* ptr to the file header data */
int head_size, /* size of this header data */
int num_pcm_samples, /* amount of processed pcm samples */
bool is_file_header)
{
int num_file_bytes = num_pcm_samples * 2 * enc_channels;
if(is_file_header)
{
/* update file header before file closing */
if((int)sizeof(wav_header) < head_size)
{
/* update wave header size entries: special to WAV format */
*(long*)(head_buffer+ 4) = htole32(num_file_bytes + 36);
*(long*)(head_buffer+40) = htole32(num_file_bytes);
}
}
}
/* main codec entry point */
enum codec_status codec_start(struct codec_api* api)
{
int i;
long lr;
unsigned long t;
unsigned long *src;
unsigned long *dst;
int chunk_size, num_chunks, samp_per_chunk;
int enc_buffer_size;
int enc_quality;
bool cpu_boosted = true; /* start boosted */
ci = api; // copy to global api pointer
if(ci->enc_get_inputs == NULL ||
ci->enc_set_parameters == NULL ||
ci->enc_alloc_chunk == NULL ||
ci->enc_free_chunk == NULL ||
ci->enc_wavbuf_near_empty == NULL ||
ci->enc_get_wav_data == NULL ||
ci->enc_set_header_callback == NULL )
return CODEC_ERROR;
ci->cpu_boost(true);
*ci->enc_set_header_callback = enc_set_header;
ci->enc_get_inputs(&enc_buffer_size, &enc_channels, &enc_quality);
/* configure the buffer system */
chunk_size = sizeof(long) + CHUNK_SIZE * enc_channels / 2;
num_chunks = enc_buffer_size / chunk_size;
samp_per_chunk = CHUNK_SIZE / 4;
/* inform the main program about buffer dimensions and other params */
ci->enc_set_parameters(chunk_size, num_chunks, samp_per_chunk,
(enc_channels == 2) ? wav_header : wav_header_mono,
sizeof(wav_header), AFMT_PCM_WAV);
/* main application waits for this flag during encoder loading */
ci->enc_codec_loaded = true;
/* main encoding loop */
while(!ci->stop_codec)
{
while((src = (unsigned long*)ci->enc_get_wav_data(CHUNK_SIZE)) != NULL)
{
if(ci->stop_codec)
break;
if(ci->enc_wavbuf_near_empty() == 0)
{
if(!cpu_boosted)
{
ci->cpu_boost(true);
cpu_boosted = true;
}
}
dst = (unsigned long*)ci->enc_alloc_chunk();
*dst++ = CHUNK_SIZE * enc_channels / 2; /* set size info */
if(enc_channels == 2)
{
/* swap byte order & copy to destination */
for (i=0; i<CHUNK_SIZE/4; i++)
{
t = *src++;
*dst++ = ((t >> 8) & 0xff00ff) | ((t << 8) & 0xff00ff00);
}
}
else
{
/* mix left/right, swap byte order & copy to destination */
for (i=0; i<CHUNK_SIZE/8; i++)
{
lr = (long)*src++;
lr = (((lr<<16)>>16) + (lr>>16)) >> 1; /* left+right */
t = (lr << 16);
lr = (long)*src++;
lr = (((lr<<16)>>16) + (lr>>16)) >> 1; /* left+right */
t |= lr & 0xffff;
*dst++ = ((t >> 8) & 0xff00ff) | ((t << 8) & 0xff00ff00);
}
}
ci->enc_free_chunk();
ci->yield();
}
if(ci->enc_wavbuf_near_empty())
{
if(cpu_boosted)
{
ci->cpu_boost(false);
cpu_boosted = false;
}
}
ci->yield();
}
if(cpu_boosted) /* set initial boost state */
ci->cpu_boost(false);
/* reset parameters to initial state */
ci->enc_set_parameters(0, 0, 0, 0, 0, 0);
/* main application waits for this flag during encoder removing */
ci->enc_codec_loaded = false;
return CODEC_OK;
}
#endif

230
apps/codecs/wavpack_enc.c Normal file
View file

@ -0,0 +1,230 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2006 Antonius Hellmann
*
* 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.
*
****************************************************************************/
#ifndef SIMULATOR
#include "codeclib.h"
#include "libwavpack/wavpack.h"
CODEC_HEADER
typedef unsigned long uint32;
typedef unsigned short uint16;
typedef unsigned char uint8;
static unsigned char wav_header_ster [46] =
{33,22,'R','I','F','F',0,0,0,0,'W','A','V','E','f','m','t',' ',16,
0,0,0,1,0,2,0,0x44,0xac,0,0,0x10,0xb1,2,0,4,0,16,0,'d','a','t','a',0,0,0,0};
static unsigned char wav_header_mono [46] =
{33,22,'R','I','F','F',0,0,0,0,'W','A','V','E','f','m','t',' ',16,
0,0,0,1,0,1,0,0x44,0xac,0,0,0x88,0x58,1,0,2,0,16,0,'d','a','t','a',0,0,0,0};
static struct codec_api *ci;
static int enc_channels;
#define CHUNK_SIZE 20000
static long input_buffer[CHUNK_SIZE/2] IBSS_ATTR;
void *memset(void *s, int c, size_t n)
{
return(ci->memset(s,c,n));
}
void *memcpy(void *dest, const void *src, size_t n)
{
return(ci->memcpy(dest,src,n));
}
/* update file header info callback function */
void enc_set_header(void *head_buffer, /* ptr to the file header data */
int head_size, /* size of this header data */
int num_pcm_sampl, /* amount of processed pcm samples */
bool is_file_header) /* update file/chunk header */
{
if(is_file_header)
{
/* update file header before file closing */
if(sizeof(WavpackHeader) + sizeof(wav_header_mono) < (unsigned)head_size)
{
char* riff_header = (char*)head_buffer + sizeof(WavpackHeader);
char* wv_header = (char*)head_buffer + sizeof(wav_header_mono);
int num_file_bytes = num_pcm_sampl * 2 * enc_channels;
unsigned long ckSize;
/* RIFF header and WVPK header have to be swapped */
/* copy wavpack header to file start position */
ci->memcpy(head_buffer, wv_header, sizeof(WavpackHeader));
wv_header = head_buffer; /* recalc wavpack header position */
if(enc_channels == 2)
ci->memcpy(riff_header, wav_header_ster, sizeof(wav_header_ster));
else
ci->memcpy(riff_header, wav_header_mono, sizeof(wav_header_mono));
/* update the Wavpack header first chunk size & total frame count */
ckSize = htole32(((WavpackHeader*)wv_header)->ckSize)
+ sizeof(wav_header_mono);
((WavpackHeader*)wv_header)->total_samples = htole32(num_pcm_sampl);
((WavpackHeader*)wv_header)->ckSize = htole32(ckSize);
/* update the RIFF WAV header size entries */
*(long*)(riff_header+ 6) = htole32(num_file_bytes + 36);
*(long*)(riff_header+42) = htole32(num_file_bytes);
}
}
else
{
/* update timestamp (block_index) */
((WavpackHeader*)head_buffer)->block_index = htole32(num_pcm_sampl);
}
}
enum codec_status codec_start(struct codec_api* api)
{
int i;
long t;
uint32 *src;
uint32 *dst;
int chunk_size, num_chunks, samp_per_chunk;
int enc_buffer_size;
int enc_quality;
WavpackConfig config;
WavpackContext *wpc;
bool cpu_boosted = true; /* start boosted */
ci = api; // copy to global api pointer
if(ci->enc_get_inputs == NULL ||
ci->enc_set_parameters == NULL ||
ci->enc_alloc_chunk == NULL ||
ci->enc_free_chunk == NULL ||
ci->enc_wavbuf_near_empty == NULL ||
ci->enc_get_wav_data == NULL ||
ci->enc_set_header_callback == NULL )
return CODEC_ERROR;
ci->cpu_boost(true);
*ci->enc_set_header_callback = enc_set_header;
ci->enc_get_inputs(&enc_buffer_size, &enc_channels, &enc_quality);
/* configure the buffer system */
chunk_size = sizeof(long) + CHUNK_SIZE * enc_channels / 2;
num_chunks = enc_buffer_size / chunk_size;
samp_per_chunk = CHUNK_SIZE / 4;
/* inform the main program about buffer dimensions and other params */
/* add wav_header_mono as place holder to file start position */
/* wav header and wvpk header have to be reordered later */
ci->enc_set_parameters(chunk_size, num_chunks, samp_per_chunk,
wav_header_mono, sizeof(wav_header_mono),
AFMT_WAVPACK);
wpc = WavpackOpenFileOutput ();
memset (&config, 0, sizeof (config));
config.bits_per_sample = 16;
config.bytes_per_sample = 2;
config.sample_rate = 44100;
config.num_channels = enc_channels;
if (!WavpackSetConfiguration (wpc, &config, 1))
return CODEC_ERROR;
/* main application waits for this flag during encoder loading */
ci->enc_codec_loaded = true;
/* main encoding loop */
while(!ci->stop_codec)
{
while((src = (uint32*)ci->enc_get_wav_data(CHUNK_SIZE)) != NULL)
{
if(ci->stop_codec)
break;
if(ci->enc_wavbuf_near_empty() == 0)
{
if(!cpu_boosted)
{
ci->cpu_boost(true);
cpu_boosted = true;
}
}
dst = (uint32*)ci->enc_alloc_chunk() + 1;
WavpackStartBlock (wpc, (uint8*)dst, (uint8*)dst + CHUNK_SIZE);
if(enc_channels == 2)
{
for (i=0; i<CHUNK_SIZE/4; i++)
{
t = (long)*src++;
input_buffer[2*i + 0] = t >> 16;
input_buffer[2*i + 1] = (short)t;
}
}
else
{
for (i=0; i<CHUNK_SIZE/4; i++)
{
t = (long)*src++;
t = (((t<<16)>>16) + (t>>16)) >> 1; /* left+right */
input_buffer[i] = t;
}
}
if (!WavpackPackSamples (wpc, input_buffer, CHUNK_SIZE/4))
return CODEC_ERROR;
/* finish the chunk and store chunk size info */
dst[-1] = WavpackFinishBlock (wpc);
ci->enc_free_chunk();
ci->yield();
}
if(ci->enc_wavbuf_near_empty())
{
if(cpu_boosted)
{
ci->cpu_boost(false);
cpu_boosted = false;
}
}
ci->yield();
}
if(cpu_boosted) /* set initial boost state */
ci->cpu_boost(false);
/* reset parameters to initial state */
ci->enc_set_parameters(0, 0, 0, 0, 0, 0);
/* main application waits for this flag during encoder removing */
ci->enc_codec_loaded = false;
return CODEC_OK;
}
#endif

View file

@ -445,9 +445,8 @@ int ft_enter(struct tree_context* c)
{ {
set_file(buf, global_settings.fmr_file, MAX_FILENAME); set_file(buf, global_settings.fmr_file, MAX_FILENAME);
radio_load_presets(global_settings.fmr_file); radio_load_presets(global_settings.fmr_file);
if(get_radio_status() != FMRADIO_PLAYING && if(!in_radio_screen())
get_radio_status() != FMRADIO_PAUSED) radio_screen();
radio_screen();
} }
/* /*
* Preset outside default folder, we can choose such only * Preset outside default folder, we can choose such only

View file

@ -9661,6 +9661,22 @@
*: "Full Path" *: "Full Path"
</voice> </voice>
</phrase> </phrase>
<<<<<<< english.lang
<phrase>
id: VOICE_KBIT_PER_SEC
desc: spoken only, for file extension
user:
<source>
*: ""
</source>
<dest>
*: ""
</dest>
<voice>
*: "kilobits per second"
</voice>
</phrase>
=======
<phrase> <phrase>
id: LANG_RECORD_AGC_PRESET id: LANG_RECORD_AGC_PRESET
desc: automatic gain control in record settings desc: automatic gain control in record settings
@ -9778,3 +9794,4 @@
*: "AGC maximum gain" *: "AGC maximum gain"
</voice> </voice>
</phrase> </phrase>
>>>>>>> 1.267

View file

@ -285,9 +285,31 @@ static bool custom_theme_browse(void)
#ifdef HAVE_RECORDING #ifdef HAVE_RECORDING
static bool rec_menu_recording_screen(void)
{
return recording_screen(false);
}
static bool recording_settings(void) static bool recording_settings(void)
{ {
return recording_menu(false); bool ret;
#ifdef HAVE_FMRADIO_IN
int rec_source = global_settings.rec_source;
#endif
ret = recording_menu(false);
#ifdef HAVE_FMRADIO_IN
if (rec_source != global_settings.rec_source)
{
if (rec_source == AUDIO_SRC_FMRADIO)
radio_stop();
/* If AUDIO_SRC_FMRADIO was selected from something else,
the recording screen will start the radio */
}
#endif
return ret;
} }
bool rec_menu(void) bool rec_menu(void)
@ -297,7 +319,7 @@ bool rec_menu(void)
/* recording menu */ /* recording menu */
static const struct menu_item items[] = { static const struct menu_item items[] = {
{ ID2P(LANG_RECORDING_MENU), recording_screen }, { ID2P(LANG_RECORDING_MENU), rec_menu_recording_screen },
{ ID2P(LANG_RECORDING_SETTINGS), recording_settings}, { ID2P(LANG_RECORDING_SETTINGS), recording_settings},
}; };

View file

@ -74,29 +74,18 @@
#include "misc.h" #include "misc.h"
#include "sound.h" #include "sound.h"
#include "metadata.h" #include "metadata.h"
#include "talk.h"
#ifdef CONFIG_TUNER
#include "radio.h"
#endif
#include "splash.h" #include "splash.h"
#include "talk.h"
#ifdef HAVE_RECORDING
#include "recording.h"
#endif
static volatile bool audio_codec_loaded; static volatile bool audio_codec_loaded;
static volatile bool voice_codec_loaded; static volatile bool voice_codec_loaded;
static volatile bool playing; static volatile bool playing;
static volatile bool paused; static volatile bool paused;
#define CODEC_VORBIS "/.rockbox/codecs/vorbis.codec"
#define CODEC_MPA_L3 "/.rockbox/codecs/mpa.codec"
#define CODEC_FLAC "/.rockbox/codecs/flac.codec"
#define CODEC_WAV "/.rockbox/codecs/wav.codec"
#define CODEC_A52 "/.rockbox/codecs/a52.codec"
#define CODEC_MPC "/.rockbox/codecs/mpc.codec"
#define CODEC_WAVPACK "/.rockbox/codecs/wavpack.codec"
#define CODEC_ALAC "/.rockbox/codecs/alac.codec"
#define CODEC_AAC "/.rockbox/codecs/aac.codec"
#define CODEC_SHN "/.rockbox/codecs/shorten.codec"
#define CODEC_AIFF "/.rockbox/codecs/aiff.codec"
#define CODEC_SID "/.rockbox/codecs/sid.codec"
/* default point to start buffer refill */ /* default point to start buffer refill */
#define AUDIO_DEFAULT_WATERMARK (1024*512) #define AUDIO_DEFAULT_WATERMARK (1024*512)
@ -133,6 +122,11 @@ enum {
Q_CODEC_LOAD, Q_CODEC_LOAD,
Q_CODEC_LOAD_DISK, Q_CODEC_LOAD_DISK,
#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
Q_ENCODER_LOAD_DISK,
Q_ENCODER_RECORD,
#endif
}; };
/* As defined in plugins/lib/xxx2wav.h */ /* As defined in plugins/lib/xxx2wav.h */
@ -382,7 +376,7 @@ static bool voice_pcmbuf_insert_split_callback(
} }
return true; return true;
} } /* voice_pcmbuf_insert_split_callback */
static bool codec_pcmbuf_insert_split_callback( static bool codec_pcmbuf_insert_split_callback(
const void *ch1, const void *ch2, size_t length) const void *ch1, const void *ch2, size_t length)
@ -444,7 +438,7 @@ static bool codec_pcmbuf_insert_split_callback(
} }
return true; return true;
} } /* codec_pcmbuf_insert_split_callback */
static bool voice_pcmbuf_insert_callback(const char *buf, size_t length) static bool voice_pcmbuf_insert_callback(const char *buf, size_t length)
{ {
@ -649,7 +643,7 @@ static size_t codec_filebuf_callback(void *ptr, size_t size)
/* Return the actual amount of data copied to the buffer */ /* Return the actual amount of data copied to the buffer */
return copy_n; return copy_n;
} } /* codec_filebuf_callback */
static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize) static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize)
{ {
@ -664,7 +658,9 @@ static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize)
while (1) while (1)
{ {
if (voice_is_playing) if (voice_is_playing)
{
queue_wait_w_tmo(&voice_codec_queue, &ev, 0); queue_wait_w_tmo(&voice_codec_queue, &ev, 0);
}
else if (playing) else if (playing)
{ {
queue_wait_w_tmo(&voice_codec_queue, &ev, 0); queue_wait_w_tmo(&voice_codec_queue, &ev, 0);
@ -679,7 +675,11 @@ static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize)
if (playing) if (playing)
swap_codec(); swap_codec();
break; break;
#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
case Q_ENCODER_RECORD:
swap_codec();
break;
#endif
case Q_VOICE_STOP: case Q_VOICE_STOP:
if (voice_is_playing) if (voice_is_playing)
{ {
@ -743,7 +743,7 @@ voice_play_clip:
return NULL; return NULL;
return voicebuf; return voicebuf;
} } /* voice_request_buffer_callback */
static void* codec_request_buffer_callback(size_t *realsize, size_t reqsize) static void* codec_request_buffer_callback(size_t *realsize, size_t reqsize)
{ {
@ -794,7 +794,7 @@ static void* codec_request_buffer_callback(size_t *realsize, size_t reqsize)
*realsize = copy_n; *realsize = copy_n;
return (char *)&filebuf[buf_ridx]; return (char *)&filebuf[buf_ridx];
} } /* codec_request_buffer_callback */
static int get_codec_base_type(int type) static int get_codec_base_type(int type)
{ {
@ -1531,52 +1531,24 @@ static void codec_discard_codec_callback(void)
#endif #endif
} }
static const char *get_codec_path(int codectype) static const char * get_codec_filename(int enc_spec)
{ {
switch (codectype) { const char *fname;
case AFMT_OGG_VORBIS: int type = enc_spec & CODEC_TYPE_MASK;
logf("Codec: Vorbis"); int afmt = enc_spec & CODEC_AFMT_MASK;
return CODEC_VORBIS;
case AFMT_MPA_L1: if ((unsigned)afmt >= AFMT_NUM_CODECS)
case AFMT_MPA_L2: type = AFMT_UNKNOWN | (type & CODEC_TYPE_MASK);
case AFMT_MPA_L3:
logf("Codec: MPA L1/L2/L3"); fname = (type == CODEC_TYPE_DECODER) ?
return CODEC_MPA_L3; audio_formats[afmt].codec_fn : audio_formats[afmt].codec_enc_fn;
case AFMT_PCM_WAV:
logf("Codec: PCM WAV"); logf("%s: %d - %s",
return CODEC_WAV; (type == CODEC_TYPE_ENCODER) ? "Encoder" : "Decoder",
case AFMT_FLAC: afmt, fname ? fname : "<unknown>");
logf("Codec: FLAC");
return CODEC_FLAC; return fname;
case AFMT_A52: } /* get_codec_filename */
logf("Codec: A52");
return CODEC_A52;
case AFMT_MPC:
logf("Codec: Musepack");
return CODEC_MPC;
case AFMT_WAVPACK:
logf("Codec: WAVPACK");
return CODEC_WAVPACK;
case AFMT_ALAC:
logf("Codec: ALAC");
return CODEC_ALAC;
case AFMT_AAC:
logf("Codec: AAC");
return CODEC_AAC;
case AFMT_SHN:
logf("Codec: SHN");
return CODEC_SHN;
case AFMT_AIFF:
logf("Codec: PCM AIFF");
return CODEC_AIFF;
case AFMT_SID:
logf("Codec: SID");
return CODEC_SID;
default:
logf("Codec: Unsupported");
return NULL;
}
}
static bool loadcodec(bool start_play) static bool loadcodec(bool start_play)
{ {
@ -1585,9 +1557,10 @@ static bool loadcodec(bool start_play)
int rc; int rc;
size_t copy_n; size_t copy_n;
int prev_track; int prev_track;
char codec_path[MAX_PATH]; /* Full path to codec */
const char *codec_path = get_codec_path(tracks[track_widx].id3.codectype); const char * codec_fn = get_codec_filename(tracks[track_widx].id3.codectype);
if (codec_path == NULL) if (codec_fn == NULL)
return false; return false;
tracks[track_widx].has_codec = false; tracks[track_widx].has_codec = false;
@ -1603,7 +1576,7 @@ static bool loadcodec(bool start_play)
ci.taginfo_ready = &cur_ti->taginfo_ready; ci.taginfo_ready = &cur_ti->taginfo_ready;
ci.curpos = 0; ci.curpos = 0;
playing = true; playing = true;
queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (void *)codec_path); queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (void *)codec_fn);
return true; return true;
} }
else else
@ -1625,6 +1598,8 @@ static bool loadcodec(bool start_play)
} }
} }
codec_get_full_path(codec_path, codec_fn);
fd = open(codec_path, O_RDONLY); fd = open(codec_path, O_RDONLY);
if (fd < 0) if (fd < 0)
{ {
@ -1973,11 +1948,8 @@ static void audio_stop_playback(void)
(playlist_end && ci.stop_codec)?NULL:audio_current_track()); (playlist_end && ci.stop_codec)?NULL:audio_current_track());
} }
if (voice_is_playing) while (voice_is_playing && !queue_empty(&voice_codec_queue))
{ yield();
while (voice_is_playing && !queue_empty(&voice_codec_queue))
yield();
}
filebufused = 0; filebufused = 0;
playing = false; playing = false;
@ -1998,10 +1970,8 @@ static void audio_stop_playback(void)
static void audio_play_start(size_t offset) static void audio_play_start(size_t offset)
{ {
#ifdef CONFIG_TUNER #if defined(HAVE_RECORDING) || defined(CONFIG_TUNER)
/* check if radio is playing */ rec_set_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
if (get_radio_status() != FMRADIO_OFF)
radio_stop();
#endif #endif
/* Wait for any previously playing audio to flush - TODO: Not necessary? */ /* Wait for any previously playing audio to flush - TODO: Not necessary? */
@ -2483,6 +2453,20 @@ static void codec_thread(void)
mutex_unlock(&mutex_codecthread); mutex_unlock(&mutex_codecthread);
break ; break ;
#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
case Q_ENCODER_LOAD_DISK:
logf("Encoder load disk");
audio_codec_loaded = false;
if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
queue_post(&voice_codec_queue, Q_ENCODER_RECORD, NULL);
mutex_lock(&mutex_codecthread);
current_codec = CODEC_IDX_AUDIO;
ci.stop_codec = false;
status = codec_load_file((const char *)ev.data, &ci);
mutex_unlock(&mutex_codecthread);
break;
#endif
#ifndef SIMULATOR #ifndef SIMULATOR
case SYS_USB_CONNECTED: case SYS_USB_CONNECTED:
queue_clear(&codec_queue); queue_clear(&codec_queue);
@ -2511,8 +2495,6 @@ static void codec_thread(void)
case Q_CODEC_LOAD: case Q_CODEC_LOAD:
if (playing) if (playing)
{ {
const char *codec_path;
if (ci.new_track || status != CODEC_OK) if (ci.new_track || status != CODEC_OK)
{ {
if (!ci.new_track) if (!ci.new_track)
@ -2523,7 +2505,8 @@ static void codec_thread(void)
if (!load_next_track()) if (!load_next_track())
{ {
queue_post(&codec_queue, Q_AUDIO_STOP, 0); // queue_post(&codec_queue, Q_AUDIO_STOP, 0);
queue_post(&audio_queue, Q_AUDIO_STOP, 0);
break; break;
} }
} }
@ -2545,12 +2528,12 @@ static void codec_thread(void)
queue_post(&codec_queue, Q_CODEC_LOAD, 0); queue_post(&codec_queue, Q_CODEC_LOAD, 0);
else else
{ {
codec_path = get_codec_path(cur_ti->id3.codectype); const char *codec_fn = get_codec_filename(cur_ti->id3.codectype);
queue_post(&codec_queue, queue_post(&codec_queue, Q_CODEC_LOAD_DISK,
Q_CODEC_LOAD_DISK, (void *)codec_path); (void *)codec_fn);
} }
} }
} } /* end switch */
} }
} }
@ -2596,6 +2579,37 @@ static void reset_buffer(void)
filebuflen &= ~3; filebuflen &= ~3;
} }
void audio_load_encoder(int enc_id)
{
#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
const char *enc_fn = get_codec_filename(enc_id | CODEC_TYPE_ENCODER);
if (!enc_fn)
return;
audio_remove_encoder();
queue_post(&codec_queue, Q_ENCODER_LOAD_DISK, (void *)enc_fn);
while (!ci.enc_codec_loaded)
yield();
#endif
return;
(void)enc_id;
} /* audio_load_encoder */
void audio_remove_encoder(void)
{
#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
/* force encoder codec unload (if previously loaded) */
if (!ci.enc_codec_loaded)
return;
ci.stop_codec = true;
while (ci.enc_codec_loaded)
yield();
#endif
} /* audio_remove_encoder */
static void voice_codec_thread(void) static void voice_codec_thread(void)
{ {
while (1) while (1)
@ -2608,13 +2622,13 @@ static void voice_codec_thread(void)
voice_remaining = 0; voice_remaining = 0;
voice_getmore = NULL; voice_getmore = NULL;
codec_load_file(CODEC_MPA_L3, &ci_voice); codec_load_file(get_codec_filename(AFMT_MPA_L3), &ci_voice);
logf("Voice codec finished"); logf("Voice codec finished");
mutex_unlock(&mutex_codecthread);
voice_codec_loaded = false; voice_codec_loaded = false;
mutex_unlock(&mutex_codecthread);
} }
} } /* voice_codec_thread */
void voice_init(void) void voice_init(void)
{ {
@ -2642,7 +2656,20 @@ void voice_init(void)
while (!voice_codec_loaded) while (!voice_codec_loaded)
yield(); yield();
} } /* voice_init */
void voice_stop(void)
{
/* Messages should not be posted to voice codec queue unless it is the
current codec or deadlocks happen. This will be addressed globally soon.
-- jhMikeS */
if (current_codec != CODEC_IDX_VOICE)
return;
mp3_play_stop();
while (voice_is_playing && !queue_empty(&voice_codec_queue))
yield();
} /* voice_stop */
struct mp3entry* audio_current_track(void) struct mp3entry* audio_current_track(void)
{ {
@ -2803,9 +2830,19 @@ int audio_status(void)
if (paused) if (paused)
ret |= AUDIO_STATUS_PAUSE; ret |= AUDIO_STATUS_PAUSE;
#ifdef HAVE_RECORDING
/* Do this here for constitency with mpeg.c version */
ret |= pcm_rec_status();
#endif
return ret; return ret;
} }
bool audio_query_poweroff(void)
{
return !(playing && paused);
}
int audio_get_file_pos(void) int audio_get_file_pos(void)
{ {
return 0; return 0;

View file

@ -27,8 +27,8 @@
#include "id3.h" #include "id3.h"
#include "mp3data.h" #include "mp3data.h"
#define CODEC_IDX_AUDIO 0 #define CODEC_IDX_AUDIO 0
#define CODEC_IDX_VOICE 1 #define CODEC_IDX_VOICE 1
/* Not yet implemented. */ /* Not yet implemented. */
#define CODEC_SET_AUDIOBUF_WATERMARK 4 #define CODEC_SET_AUDIOBUF_WATERMARK 4
@ -66,6 +66,7 @@ void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3,
bool last_track)); bool last_track));
void audio_invalidate_tracks(void); void audio_invalidate_tracks(void);
void voice_init(void); void voice_init(void);
void voice_stop(void);
#if CONFIG_CODEC == SWCODEC /* This #ifdef is better here than gui/gwps.c */ #if CONFIG_CODEC == SWCODEC /* This #ifdef is better here than gui/gwps.c */
extern void audio_next_dir(void); extern void audio_next_dir(void);

View file

@ -24,7 +24,6 @@
#include "mas.h" #include "mas.h"
#include "settings.h" #include "settings.h"
#include "button.h" #include "button.h"
#include "fmradio.h"
#include "status.h" #include "status.h"
#include "kernel.h" #include "kernel.h"
#include "mpeg.h" #include "mpeg.h"
@ -63,17 +62,6 @@
#ifdef CONFIG_TUNER #ifdef CONFIG_TUNER
#if CONFIG_CODEC == SWCODEC
#ifdef HAVE_UDA1380
#include "uda1380.h"
#endif
#ifdef HAVE_TLV320
#include "tlv320.h"
#endif
#include "pcm_record.h"
#endif
#if CONFIG_KEYPAD == RECORDER_PAD #if CONFIG_KEYPAD == RECORDER_PAD
#define FM_MENU BUTTON_F1 #define FM_MENU BUTTON_F1
#define FM_PRESET BUTTON_F2 #define FM_PRESET BUTTON_F2
@ -165,6 +153,7 @@ static int curr_freq;
static int radio_mode = RADIO_SCAN_MODE; static int radio_mode = RADIO_SCAN_MODE;
static int radio_status = FMRADIO_OFF; static int radio_status = FMRADIO_OFF;
static bool in_screen = false;
#define MAX_PRESETS 64 #define MAX_PRESETS 64
static bool presets_loaded = false, presets_changed = false; static bool presets_loaded = false, presets_changed = false;
@ -239,22 +228,87 @@ int get_radio_status(void)
return radio_status; return radio_status;
} }
bool in_radio_screen(void)
{
return in_screen;
}
/* secret flag for starting paused - prevents unmute */
#define FMRADIO_START_PAUSED 0x8000
void radio_start(void)
{
bool start_paused;
int mute_timeout;
if(radio_status == FMRADIO_PLAYING)
return;
start_paused = radio_status & FMRADIO_START_PAUSED;
/* clear flag before any yielding */
radio_status &= ~FMRADIO_START_PAUSED;
if(radio_status == FMRADIO_OFF)
radio_power(true);
curr_freq = global_settings.last_frequency * FREQ_STEP + MIN_FREQ;
radio_set(RADIO_SLEEP, 0); /* wake up the tuner */
radio_set(RADIO_FREQUENCY, curr_freq);
if(radio_status == FMRADIO_OFF)
{
radio_set(RADIO_IF_MEASUREMENT, 0);
radio_set(RADIO_SENSITIVITY, 0);
radio_set(RADIO_FORCE_MONO, global_settings.fm_force_mono);
mute_timeout = current_tick + 1*HZ;
}
else
{
/* paused */
mute_timeout = current_tick + 2*HZ;
}
while(!radio_get(RADIO_STEREO) && !radio_get(RADIO_TUNED))
{
if(TIME_AFTER(current_tick, mute_timeout))
break;
yield();
}
/* keep radio from sounding initially */
if(!start_paused)
radio_set(RADIO_MUTE, 0);
radio_status = FMRADIO_PLAYING;
} /* radio_start */
void radio_pause(void)
{
if(radio_status == FMRADIO_PAUSED)
return;
if(radio_status == FMRADIO_OFF)
{
radio_status |= FMRADIO_START_PAUSED;
radio_start();
}
radio_set(RADIO_MUTE, 1);
radio_set(RADIO_SLEEP, 1);
radio_status = FMRADIO_PAUSED;
} /* radio_pause */
void radio_stop(void) void radio_stop(void)
{ {
if(radio_status == FMRADIO_OFF)
return;
radio_set(RADIO_MUTE, 1); radio_set(RADIO_MUTE, 1);
radio_set(RADIO_SLEEP, 1); /* low power mode, if available */ radio_set(RADIO_SLEEP, 1); /* low power mode, if available */
radio_status = FMRADIO_OFF; radio_status = FMRADIO_OFF;
radio_power(false); /* status update, power off if avail. */ radio_power(false); /* status update, power off if avail. */
} /* radio_stop */
#ifndef SIMULATOR /* SIMULATOR. Catch FMRADIO_OFF status for the sim. */
#if CONFIG_CODEC == SWCODEC
#ifdef HAVE_TLV320
tlv320_set_monitor(false);
#endif
pcm_rec_mux(0); /* Line In */
#endif
#endif /* SIMULATOR */
}
bool radio_hardware_present(void) bool radio_hardware_present(void)
{ {
@ -297,7 +351,7 @@ static int find_closest_preset(int freq)
return i; return i;
if(diff < 0) if(diff < 0)
diff = -diff; diff = -diff;
if(diff < min_diff) if(diff < min_diff)
{ {
preset = i; preset = i;
min_diff = diff; min_diff = diff;
@ -307,8 +361,6 @@ static int find_closest_preset(int freq)
return preset; return preset;
} }
static void remember_frequency(void) static void remember_frequency(void)
{ {
global_settings.last_frequency = (curr_freq - MIN_FREQ) / FREQ_STEP; global_settings.last_frequency = (curr_freq - MIN_FREQ) / FREQ_STEP;
@ -366,13 +418,15 @@ bool radio_screen(void)
#endif #endif
bool keep_playing = false; bool keep_playing = false;
bool statusbar = global_settings.statusbar; bool statusbar = global_settings.statusbar;
int mute_timeout = current_tick;
int button_timeout = current_tick + (2*HZ); int button_timeout = current_tick + (2*HZ);
#ifdef HAS_BUTTONBAR #ifdef HAS_BUTTONBAR
struct gui_buttonbar buttonbar; struct gui_buttonbar buttonbar;
gui_buttonbar_init(&buttonbar); gui_buttonbar_init(&buttonbar);
gui_buttonbar_set_display(&buttonbar, &(screens[SCREEN_MAIN]) ); gui_buttonbar_set_display(&buttonbar, &(screens[SCREEN_MAIN]) );
#endif #endif
/* change status to "in screen" */
in_screen = true;
/* always display status bar in radio screen for now */ /* always display status bar in radio screen for now */
global_settings.statusbar = true; global_settings.statusbar = true;
FOR_NB_SCREENS(i) FOR_NB_SCREENS(i)
@ -396,20 +450,13 @@ bool radio_screen(void)
} }
#ifndef SIMULATOR #ifndef SIMULATOR
#if CONFIG_CODEC != SWCODEC
if(rec_create_directory() > 0)
have_recorded = true;
#endif
if(radio_status == FMRADIO_PLAYING_OUT)
radio_status = FMRADIO_PLAYING;
else if(radio_status == FMRADIO_PAUSED_OUT)
radio_status = FMRADIO_PAUSED;
if(radio_status == FMRADIO_OFF) if(radio_status == FMRADIO_OFF)
audio_stop(); audio_stop();
#if CONFIG_CODEC != SWCODEC #if CONFIG_CODEC != SWCODEC
if(rec_create_directory() > 0)
have_recorded = true;
audio_init_recording(talk_get_bufsize()); audio_init_recording(talk_get_bufsize());
sound_settings_apply(); sound_settings_apply();
@ -418,58 +465,29 @@ bool radio_screen(void)
peak_meter_enabled = true; peak_meter_enabled = true;
if (global_settings.rec_prerecord_time) rec_set_recording_options(global_settings.rec_frequency,
talk_buffer_steal(); /* will use the mp3 buffer */ global_settings.rec_quality,
AUDIO_SRC_LINEIN, 0,
global_settings.rec_channels,
global_settings.rec_editable,
global_settings.rec_prerecord_time);
audio_set_recording_options(global_settings.rec_frequency,
global_settings.rec_quality,
1, /* Line In */
global_settings.rec_channels,
global_settings.rec_editable,
global_settings.rec_prerecord_time);
#else
peak_meter_enabled = false;
#ifdef HAVE_UDA1380
uda1380_enable_recording(false);
uda1380_set_monitor(true);
#elif defined(HAVE_TLV320)
//tlv320_enable_recording(false);
tlv320_set_recvol(23, 23, AUDIO_GAIN_LINEIN); /* 0dB */
tlv320_set_monitor(true);
#endif
/* Set the input multiplexer to FM */
pcm_rec_mux(1);
#endif
audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN), audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN),
sound_default(SOUND_RIGHT_GAIN), AUDIO_GAIN_LINEIN); sound_default(SOUND_RIGHT_GAIN), AUDIO_GAIN_LINEIN);
#endif /* CONFIG_CODEC != SWCODEC */
#endif /* ndef SIMULATOR */
/* turn on radio */
#if CONFIG_CODEC == SWCODEC
rec_set_source(AUDIO_SRC_FMRADIO, (radio_status == FMRADIO_PAUSED) ?
SRCF_FMRADIO_PAUSED : SRCF_FMRADIO_PLAYING);
#else
if (radio_status == FMRADIO_OFF)
radio_start();
#endif #endif
curr_freq = global_settings.last_frequency * FREQ_STEP + MIN_FREQ; /* I hate this thing with vehement passion (jhMikeS): */
if(radio_status == FMRADIO_OFF)
{
radio_power(true);
radio_set(RADIO_SLEEP, 0); /* wake up the tuner */
radio_set(RADIO_FREQUENCY, curr_freq);
radio_set(RADIO_IF_MEASUREMENT, 0);
radio_set(RADIO_SENSITIVITY, 0);
radio_set(RADIO_FORCE_MONO, global_settings.fm_force_mono);
mute_timeout = current_tick + (1*HZ);
while( !radio_get(RADIO_STEREO)
&&!radio_get(RADIO_TUNED) )
{
if(TIME_AFTER(current_tick, mute_timeout))
break;
yield();
}
radio_set(RADIO_MUTE, 0);
radio_status = FMRADIO_PLAYING;
}
if(num_presets == 0 && yesno_pop(str(LANG_FM_FIRST_AUTOSCAN))) if(num_presets == 0 && yesno_pop(str(LANG_FM_FIRST_AUTOSCAN)))
scan_presets(); scan_presets();
@ -478,8 +496,8 @@ bool radio_screen(void)
radio_mode = RADIO_PRESET_MODE; radio_mode = RADIO_PRESET_MODE;
#ifdef HAS_BUTTONBAR #ifdef HAS_BUTTONBAR
gui_buttonbar_set(&buttonbar, str(LANG_BUTTONBAR_MENU), str(LANG_FM_BUTTONBAR_PRESETS), gui_buttonbar_set(&buttonbar, str(LANG_BUTTONBAR_MENU),
str(LANG_FM_BUTTONBAR_RECORD)); str(LANG_FM_BUTTONBAR_PRESETS), str(LANG_FM_BUTTONBAR_RECORD));
#endif #endif
cpu_idle_mode(true); cpu_idle_mode(true);
@ -535,7 +553,7 @@ bool radio_screen(void)
if (lastbutton != FM_STOP_PRE) if (lastbutton != FM_STOP_PRE)
break; break;
#endif #endif
#ifndef SIMULATOR #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
if(audio_status() == AUDIO_STATUS_RECORD) if(audio_status() == AUDIO_STATUS_RECORD)
{ {
audio_stop(); audio_stop();
@ -548,7 +566,7 @@ bool radio_screen(void)
{ {
if(yesno_pop(str(LANG_FM_SAVE_CHANGES))) if(yesno_pop(str(LANG_FM_SAVE_CHANGES)))
{ {
if(filepreset[0] == '\0') if(filepreset[0] == '\0')
save_preset_list(); save_preset_list();
else else
radio_save_presets(); radio_save_presets();
@ -577,14 +595,13 @@ bool radio_screen(void)
#ifndef SIMULATOR #ifndef SIMULATOR
if(audio_status() == AUDIO_STATUS_RECORD) if(audio_status() == AUDIO_STATUS_RECORD)
{ {
audio_new_file(rec_create_filename(buf)); rec_new_file();
update_screen = true; update_screen = true;
} }
else else
{ {
have_recorded = true; have_recorded = true;
talk_buffer_steal(); /* we use the mp3 buffer */ rec_record();
audio_record(rec_create_filename(buf));
update_screen = true; update_screen = true;
} }
#endif #endif
@ -604,7 +621,7 @@ bool radio_screen(void)
) )
break; break;
#endif #endif
#ifndef SIMULATOR #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
if(audio_status() == AUDIO_STATUS_RECORD) if(audio_status() == AUDIO_STATUS_RECORD)
audio_stop(); audio_stop();
#endif #endif
@ -615,7 +632,7 @@ bool radio_screen(void)
{ {
if(yesno_pop(str(LANG_FM_SAVE_CHANGES))) if(yesno_pop(str(LANG_FM_SAVE_CHANGES)))
{ {
if(filepreset[0] == '\0') if(filepreset[0] == '\0')
save_preset_list(); save_preset_list();
else else
radio_save_presets(); radio_save_presets();
@ -734,27 +751,11 @@ bool radio_screen(void)
) )
break; break;
#endif #endif
if(radio_status != FMRADIO_PLAYING) if (radio_status == FMRADIO_PLAYING)
{ radio_pause();
radio_set(RADIO_SLEEP, 0);
radio_set(RADIO_FREQUENCY, curr_freq);
mute_timeout = current_tick + (2*HZ);
while( !radio_get(RADIO_STEREO)
&&!radio_get(RADIO_TUNED) )
{
if(TIME_AFTER(current_tick, mute_timeout))
break;
yield();
}
radio_set(RADIO_MUTE, 0);
radio_status = FMRADIO_PLAYING;
}
else else
{ radio_start();
radio_set(RADIO_MUTE, 1);
radio_set(RADIO_SLEEP, 1);
radio_status = FMRADIO_PAUSED;
}
update_screen = true; update_screen = true;
break; break;
#endif #endif
@ -918,12 +919,16 @@ bool radio_screen(void)
{ {
timeout = current_tick + HZ; timeout = current_tick + HZ;
stereo = radio_get(RADIO_STEREO) && /* keep "mono" from always being displayed when paused */
!global_settings.fm_force_mono; if (radio_status != FMRADIO_PAUSED)
if(stereo != last_stereo_status)
{ {
update_screen = true; stereo = radio_get(RADIO_STEREO) &&
last_stereo_status = stereo; !global_settings.fm_force_mono;
if(stereo != last_stereo_status)
{
update_screen = true;
last_stereo_status = stereo;
}
} }
} }
@ -952,9 +957,6 @@ bool radio_screen(void)
FOR_NB_SCREENS(i) FOR_NB_SCREENS(i)
screens[i].puts_scroll(0, top_of_screen + 1, buf); screens[i].puts_scroll(0, top_of_screen + 1, buf);
strcat(buf, stereo?str(LANG_CHANNEL_STEREO):
str(LANG_CHANNEL_MONO));
snprintf(buf, 128, stereo?str(LANG_CHANNEL_STEREO): snprintf(buf, 128, stereo?str(LANG_CHANNEL_STEREO):
str(LANG_CHANNEL_MONO)); str(LANG_CHANNEL_MONO));
FOR_NB_SCREENS(i) FOR_NB_SCREENS(i)
@ -1005,9 +1007,9 @@ bool radio_screen(void)
done = true; done = true;
} }
if (TIME_AFTER(current_tick, button_timeout)) if (TIME_AFTER(current_tick, button_timeout))
{ {
cpu_idle_mode(true); cpu_idle_mode(true);
} }
} /*while(!done)*/ } /*while(!done)*/
#ifndef SIMULATOR #ifndef SIMULATOR
@ -1033,28 +1035,26 @@ bool radio_screen(void)
sound_settings_apply(); sound_settings_apply();
#endif /* SIMULATOR */ #endif /* SIMULATOR */
if(keep_playing) if(keep_playing)
{ {
/* Catch FMRADIO_PLAYING_OUT status for the sim. */ /* Catch FMRADIO_PLAYING status for the sim. */
#ifndef SIMULATOR #ifndef SIMULATOR
#if CONFIG_CODEC != SWCODEC #if CONFIG_CODEC != SWCODEC
/* Enable the Left and right A/D Converter */ /* Enable the Left and right A/D Converter */
audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN), audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN),
sound_default(SOUND_RIGHT_GAIN), AUDIO_GAIN_LINEIN); sound_default(SOUND_RIGHT_GAIN),
AUDIO_GAIN_LINEIN);
mas_codec_writereg(6, 0x4000); mas_codec_writereg(6, 0x4000);
#endif #endif
#endif #endif
if(radio_status == FMRADIO_PAUSED)
radio_status = FMRADIO_PAUSED_OUT;
else
radio_status = FMRADIO_PLAYING_OUT;
} }
else else
{ {
radio_stop();
#if CONFIG_CODEC == SWCODEC #if CONFIG_CODEC == SWCODEC
peak_meter_enabled = true; rec_set_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
#else
radio_stop();
#endif #endif
} }
@ -1063,8 +1063,10 @@ bool radio_screen(void)
/* restore status bar settings */ /* restore status bar settings */
global_settings.statusbar = statusbar; global_settings.statusbar = statusbar;
in_screen = false;
return have_recorded; return have_recorded;
} } /* radio_screen */
void radio_save_presets(void) void radio_save_presets(void)
{ {
@ -1106,16 +1108,16 @@ void radio_load_presets(char *filename)
/* No Preset in configuration. */ /* No Preset in configuration. */
if(filename[0] == '\0') if(filename[0] == '\0')
{ {
filepreset[0] = '\0'; filepreset[0] = '\0';
return; return;
} }
/* Temporary preset, loaded until player shuts down. */ /* Temporary preset, loaded until player shuts down. */
else if(filename[0] == '/') else if(filename[0] == '/')
strncpy(filepreset, filename, sizeof(filepreset)); strncpy(filepreset, filename, sizeof(filepreset));
/* Preset from default directory. */ /* Preset from default directory. */
else else
snprintf(filepreset, sizeof(filepreset), "%s/%s.fmr", snprintf(filepreset, sizeof(filepreset), "%s/%s.fmr",
FMPRESET_PATH, filename); FMPRESET_PATH, filename);
fd = open(filepreset, O_RDONLY); fd = open(filepreset, O_RDONLY);
@ -1466,30 +1468,6 @@ bool handle_radio_presets(void)
return reload_dir; return reload_dir;
} }
#ifndef SIMULATOR
#if CONFIG_CODEC != SWCODEC
static bool fm_recording_settings(void)
{
bool ret;
ret = recording_menu(true);
if(!ret)
{
if (global_settings.rec_prerecord_time)
talk_buffer_steal(); /* will use the mp3 buffer */
audio_set_recording_options(global_settings.rec_frequency,
global_settings.rec_quality,
1, /* Line In */
global_settings.rec_channels,
global_settings.rec_editable,
global_settings.rec_prerecord_time);
}
return ret;
}
#endif
#endif
char monomode_menu_string[32]; char monomode_menu_string[32];
static void create_monomode_menu(void) static void create_monomode_menu(void)
@ -1628,6 +1606,55 @@ int radio_menu_cb(int key, int m)
return key; return key;
} }
#ifndef SIMULATOR
#if defined(HAVE_FMRADIO_IN) || CONFIG_CODEC != SWCODEC
static bool fm_recording_screen(void)
{
bool ret;
#ifdef HAVE_FMRADIO_IN
/* switch recording source to FMRADIO for the duration */
int rec_source = global_settings.rec_source;
global_settings.rec_source = AUDIO_SRC_FMRADIO;
/* clearing queue seems to cure a spontaneous abort during record */
while (button_get(false) != BUTTON_NONE);
#endif
ret = recording_screen(true);
#ifdef HAVE_FMRADIO_IN
/* safe to reset as changing sources is prohibited here */
global_settings.rec_source = rec_source;
#endif
return ret;
}
static bool fm_recording_settings(void)
{
bool ret = recording_menu(true);
if (!ret)
{
rec_set_recording_options(global_settings.rec_frequency,
global_settings.rec_quality,
#if CONFIG_CODEC == SWCODEC
AUDIO_SRC_FMRADIO, SRCF_FMRADIO_PLAYING,
#else
AUDIO_SRC_LINEIN, 0,
#endif
global_settings.rec_channels,
global_settings.rec_editable,
global_settings.rec_prerecord_time);
}
return ret;
}
#endif
#endif /* SIMULATOR */
/* main menu of the radio screen */ /* main menu of the radio screen */
bool radio_menu(void) bool radio_menu(void)
{ {
@ -1637,24 +1664,27 @@ bool radio_menu(void)
static const struct menu_item items[] = { static const struct menu_item items[] = {
/* Add functions not accessible via buttons */ /* Add functions not accessible via buttons */
#ifndef FM_PRESET #ifndef FM_PRESET
{ ID2P(LANG_FM_BUTTONBAR_PRESETS), handle_radio_presets }, { ID2P(LANG_FM_BUTTONBAR_PRESETS), handle_radio_presets },
#endif #endif
#ifndef FM_PRESET_ADD #ifndef FM_PRESET_ADD
{ ID2P(LANG_FM_ADD_PRESET) , radio_add_preset }, { ID2P(LANG_FM_ADD_PRESET) , radio_add_preset },
#endif #endif
{ ID2P(LANG_FM_PRESET_LOAD) , load_preset_list }, { ID2P(LANG_FM_PRESET_LOAD) , load_preset_list },
{ ID2P(LANG_FM_PRESET_SAVE) , save_preset_list }, { ID2P(LANG_FM_PRESET_SAVE) , save_preset_list },
{ ID2P(LANG_FM_PRESET_CLEAR) , clear_preset_list }, { ID2P(LANG_FM_PRESET_CLEAR) , clear_preset_list },
{ monomode_menu_string , toggle_mono_mode }, { monomode_menu_string , toggle_mono_mode },
#ifndef FM_MODE #ifndef FM_MODE
{ radiomode_menu_string , toggle_radio_mode }, { radiomode_menu_string , toggle_radio_mode },
#endif #endif
{ ID2P(LANG_SOUND_SETTINGS) , sound_menu }, { ID2P(LANG_SOUND_SETTINGS) , sound_menu },
#if !defined(SIMULATOR) && (CONFIG_CODEC != SWCODEC) #ifndef SIMULATOR
{ ID2P(LANG_RECORDING_SETTINGS) , fm_recording_settings}, #if defined(HAVE_FMRADIO_IN) || CONFIG_CODEC != SWCODEC
{ ID2P(LANG_RECORDING_MENU) , fm_recording_screen },
{ ID2P(LANG_RECORDING_SETTINGS) , fm_recording_settings },
#endif #endif
{ ID2P(LANG_FM_SCAN_PRESETS) , scan_presets }, #endif
{ ID2P(LANG_FM_SCAN_PRESETS) , scan_presets },
}; };
create_monomode_menu(); create_monomode_menu();

View file

@ -20,19 +20,19 @@
#define RADIO_H #define RADIO_H
#define FMPRESET_PATH ROCKBOX_DIR "/fmpresets" #define FMPRESET_PATH ROCKBOX_DIR "/fmpresets"
#define FMRADIO_OFF 0 #ifndef FMRADIO_H
#define FMRADIO_PLAYING 1 #include "fmradio.h"
#define FMRADIO_PLAYING_OUT 2 #endif
#define FMRADIO_PAUSED 3
#define FMRADIO_PAUSED_OUT 4
#ifdef CONFIG_TUNER #ifdef CONFIG_TUNER
void radio_load_presets(char *filename); void radio_load_presets(char *filename);
void radio_init(void); void radio_init(void);
bool radio_screen(void); bool radio_screen(void);
void radio_start(void);
void radio_pause(void);
void radio_stop(void); void radio_stop(void);
bool radio_hardware_present(void); bool radio_hardware_present(void);
int get_radio_status(void); bool in_radio_screen(void);
#define MAX_FMPRESET_LEN 27 #define MAX_FMPRESET_LEN 27

View file

@ -24,12 +24,14 @@
#include <stdlib.h> #include <stdlib.h>
#include "system.h" #include "system.h"
#include "power.h"
#include "lcd.h" #include "lcd.h"
#include "led.h" #include "led.h"
#include "mpeg.h" #include "mpeg.h"
#include "audio.h" #include "audio.h"
#if CONFIG_CODEC == SWCODEC #if CONFIG_CODEC == SWCODEC
#include "pcm_record.h" #include "pcm_record.h"
#include "playback.h"
#endif #endif
#ifdef HAVE_UDA1380 #ifdef HAVE_UDA1380
#include "uda1380.h" #include "uda1380.h"
@ -37,7 +39,7 @@
#ifdef HAVE_TLV320 #ifdef HAVE_TLV320
#include "tlv320.h" #include "tlv320.h"
#endif #endif
#include "recording.h"
#include "mp3_playback.h" #include "mp3_playback.h"
#include "mas.h" #include "mas.h"
#include "button.h" #include "button.h"
@ -66,6 +68,7 @@
#include "splash.h" #include "splash.h"
#include "screen_access.h" #include "screen_access.h"
#include "action.h" #include "action.h"
#include "radio.h"
#ifdef HAVE_RECORDING #ifdef HAVE_RECORDING
#define PM_HEIGHT ((LCD_HEIGHT >= 72) ? 2 : 1) #define PM_HEIGHT ((LCD_HEIGHT >= 72) ? 2 : 1)
@ -73,21 +76,6 @@
bool f2_rec_screen(void); bool f2_rec_screen(void);
bool f3_rec_screen(void); bool f3_rec_screen(void);
#define SOURCE_MIC 0
#define SOURCE_LINE 1
#ifdef HAVE_SPDIF_IN
#define SOURCE_SPDIF 2
#define MAX_SOURCE SOURCE_SPDIF
#else
#define MAX_SOURCE SOURCE_LINE
#endif
#if CONFIG_CODEC == SWCODEC
#define REC_FILE_ENDING ".wav"
#else
#define REC_FILE_ENDING ".mp3"
#endif
#define MAX_FILE_SIZE 0x7F800000 /* 2 GB - 4 MB */ #define MAX_FILE_SIZE 0x7F800000 /* 2 GB - 4 MB */
int screen_update = NB_SCREENS; int screen_update = NB_SCREENS;
@ -102,6 +90,19 @@ const char* const freq_str[6] =
"16kHz" "16kHz"
}; };
#if CONFIG_CODEC == SWCODEC
#define REC_ENCODER_ID(q) \
rec_quality_info_afmt[q]
#define REC_QUALITY_LABEL(q) \
(audio_formats[REC_ENCODER_ID(q)].label)
#define REC_FILE_ENDING(q) \
(audio_formats[REC_ENCODER_ID(q)].ext)
#else
/* default record file extension for HWCODEC */
#define REC_QUALITY_LABEL(q) "MP3"
#define REC_FILE_ENDING(q) ".mp3"
#endif
#ifdef HAVE_AGC #ifdef HAVE_AGC
/* Timing counters: /* Timing counters:
* peak_time is incremented every 0.2s, every 2nd run of record screen loop. * peak_time is incremented every 0.2s, every 2nd run of record screen loop.
@ -161,13 +162,14 @@ static short agc_maxgain;
static void set_gain(void) static void set_gain(void)
{ {
if(global_settings.rec_source == SOURCE_MIC) if(global_settings.rec_source == AUDIO_SRC_MIC)
{ {
audio_set_recording_gain(global_settings.rec_mic_gain, audio_set_recording_gain(global_settings.rec_mic_gain,
0, AUDIO_GAIN_MIC); 0, AUDIO_GAIN_MIC);
} }
else else
{ {
/* AUDIO_SRC_LINEIN, AUDIO_SRC_SPDIF, AUDIO_SRC_FMRADIO */
audio_set_recording_gain(global_settings.rec_left_gain, audio_set_recording_gain(global_settings.rec_left_gain,
global_settings.rec_right_gain, global_settings.rec_right_gain,
AUDIO_GAIN_LINEIN); AUDIO_GAIN_LINEIN);
@ -217,12 +219,16 @@ bool agc_gain_is_max(bool left, bool right)
if (agc_preset == 0) if (agc_preset == 0)
return false; return false;
if (global_settings.rec_source == SOURCE_LINE) switch (global_settings.rec_source)
{ {
case AUDIO_SRC_LINEIN:
#ifdef HAVE_FMRADIO_IN
case AUDIO_SRC_FMRADIO:
#endif
gain_current_l = global_settings.rec_left_gain; gain_current_l = global_settings.rec_left_gain;
gain_current_r = global_settings.rec_right_gain; gain_current_r = global_settings.rec_right_gain;
} else break;
{ default:
gain_current_l = global_settings.rec_mic_gain; gain_current_l = global_settings.rec_mic_gain;
gain_current_r = global_settings.rec_mic_gain; gain_current_r = global_settings.rec_mic_gain;
} }
@ -235,13 +241,16 @@ void change_recording_gain(bool increment, bool left, bool right)
{ {
int factor = (increment ? 1 : -1); int factor = (increment ? 1 : -1);
if (global_settings.rec_source == SOURCE_LINE) switch (global_settings.rec_source)
{ {
case AUDIO_SRC_LINEIN:
#ifdef HAVE_FMRADIO_IN
case AUDIO_SRC_FMRADIO:
#endif
if(left) global_settings.rec_left_gain += factor; if(left) global_settings.rec_left_gain += factor;
if (right) global_settings.rec_right_gain += factor; if (right) global_settings.rec_right_gain += factor;
} break;
else default:
{
global_settings.rec_mic_gain += factor; global_settings.rec_mic_gain += factor;
} }
} }
@ -443,12 +452,15 @@ void adjust_cursor(void)
#ifdef HAVE_AGC #ifdef HAVE_AGC
switch(global_settings.rec_source) switch(global_settings.rec_source)
{ {
case SOURCE_MIC: case AUDIO_SRC_MIC:
if(cursor == 2) if(cursor == 2)
cursor = 4; cursor = 4;
else if(cursor == 3) else if(cursor == 3)
cursor = 1; cursor = 1;
case SOURCE_LINE: case AUDIO_SRC_LINEIN:
#ifdef HAVE_FMRADIO_IN
case AUDIO_SRC_FMRADIO:
#endif
max_cursor = 5; max_cursor = 5;
break; break;
default: default:
@ -458,10 +470,13 @@ void adjust_cursor(void)
#else #else
switch(global_settings.rec_source) switch(global_settings.rec_source)
{ {
case SOURCE_MIC: case AUDIO_SRC_MIC:
max_cursor = 1; max_cursor = 1;
break; break;
case SOURCE_LINE: case AUDIO_SRC_LINEIN:
#ifdef HAVE_FMRADIO_IN
case AUDIO_SRC_FMRADIO:
#endif
max_cursor = 3; max_cursor = 3;
break; break;
default: default:
@ -481,10 +496,13 @@ char *rec_create_filename(char *buffer)
else else
strncpy(buffer, rec_base_directory, MAX_PATH); strncpy(buffer, rec_base_directory, MAX_PATH);
#ifdef CONFIG_RTC #ifdef CONFIG_RTC
create_datetime_filename(buffer, buffer, "R", REC_FILE_ENDING); create_datetime_filename(buffer, buffer, "R",
REC_FILE_ENDING(global_settings.rec_quality));
#else #else
create_numbered_filename(buffer, buffer, "rec_", REC_FILE_ENDING, 4); create_numbered_filename(buffer, buffer, "rec_",
REC_FILE_ENDING(global_settings.rec_quality), 4);
#endif #endif
return buffer; return buffer;
} }
@ -515,8 +533,190 @@ int rec_create_directory(void)
return 0; return 0;
} }
#if CONFIG_CODEC == SWCODEC && !defined(SIMULATOR)
/**
* Selects an audio source for recording or playback
* powers/unpowers related devices.
* Here because it calls app code and used only for HAVE_RECORDING atm.
* Would like it in pcm_record.c.
*/
#if defined(HAVE_UDA1380)
#define ac_disable_recording uda1380_disable_recording
#define ac_enable_recording uda1380_enable_recording
#define ac_set_monitor uda1380_set_monitor
#elif defined(HAVE_TLV320)
#define ac_disable_recording tlv320_disable_recording
#define ac_enable_recording tlv320_enable_recording
#define ac_set_monitor tlv320_set_monitor
#endif
void rec_set_source(int source, int flags)
{
/* Prevent pops from unneeded switching */
static int last_source = AUDIO_SRC_PLAYBACK;
#ifdef HAVE_TLV320
static bool last_recording = false;
#endif
bool recording = flags & SRCF_RECORDING;
/* Default to peakmeter record. */
bool pm_playback = false;
bool pm_enabled = true;
/** Do power up/down of associated device(s) **/
#ifdef HAVE_SPDIF_IN
if ((source == AUDIO_SRC_SPDIF) != (source == last_source))
cpu_boost(source == AUDIO_SRC_SPDIF);
#ifdef HAVE_SPDIF_POWER
/* Check if S/PDIF output power should be switched off or on. NOTE: assumes
both optical in and out is controlled by the same power source, which is
the case on H1x0. */
spdif_power_enable((source == AUDIO_SRC_SPDIF) ||
global_settings.spdif_enable);
#endif
#endif
#ifdef CONFIG_TUNER
/* Switch radio off or on per source and flags. */
if (source != AUDIO_SRC_FMRADIO)
radio_stop();
else if (flags & SRCF_FMRADIO_PAUSED)
radio_pause();
else
radio_start();
#endif
switch (source)
{
default: /* playback - no recording */
pm_playback = true;
if (source == last_source)
break;
ac_disable_recording();
ac_set_monitor(false);
pcm_rec_mux(0); /* line in */
break;
case AUDIO_SRC_MIC: /* recording only */
if (source == last_source)
break;
ac_enable_recording(true); /* source mic */
pcm_rec_mux(0); /* line in */
break;
case AUDIO_SRC_LINEIN: /* recording only */
if (source == last_source)
break;
pcm_rec_mux(0); /* line in */
ac_enable_recording(false); /* source line */
break;
#ifdef HAVE_SPDIF_IN
case AUDIO_SRC_SPDIF: /* recording only */
if (recording)
{
/* This was originally done in audio_set_recording_options only */
#ifdef HAVE_SPDIF_POWER
EBU1CONFIG = global_settings.spdif_enable ? (1 << 2) : 0;
/* Input source is EBUin1, Feed-through monitoring if desired */
#else
EBU1CONFIG = (1 << 2);
/* Input source is EBUin1, Feed-through monitoring */
#endif
}
if (source != last_source)
uda1380_disable_recording();
break;
#endif /* HAVE_SPDIF_IN */
#ifdef HAVE_FMRADIO_IN
case AUDIO_SRC_FMRADIO:
if (!recording)
{
audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN),
sound_default(SOUND_RIGHT_GAIN), AUDIO_GAIN_LINEIN);
pm_playback = true;
pm_enabled = false;
}
pcm_rec_mux(1); /* fm radio */
#ifdef HAVE_UDA1380
if (source == last_source)
break;
/* I2S recording and playback */
uda1380_enable_recording(false); /* source line */
uda1380_set_monitor(true);
#endif
#ifdef HAVE_TLV320
/* I2S recording and analog playback */
if (source == last_source && recording == last_recording)
break;
last_recording = recording;
if (recording)
tlv320_enable_recording(false); /* source line */
else
{
tlv320_disable_recording();
tlv320_set_monitor(true); /* analog bypass */
}
#endif
break;
/* #elif defined(CONFIG_TUNER) */
/* Have radio but cannot record it */
/* case AUDIO_SRC_FMRADIO: */
/* break; */
#endif /* HAVE_FMRADIO_IN */
} /* end switch */
peak_meter_playback(pm_playback);
peak_meter_enabled = pm_enabled;
last_source = source;
} /* rec_set_source */
#endif /* CONFIG_CODEC == SWCODEC && !defined(SIMULATOR) */
/* steal the mp3 buffer then actually set options */
void rec_set_recording_options(int frequency, int quality,
int source, int source_flags,
int channel_mode, bool editable,
int prerecord_time)
{
#if CONFIG_CODEC != SWCODEC
if (global_settings.rec_prerecord_time)
#endif
talk_buffer_steal(); /* will use the mp3 buffer */
#if CONFIG_CODEC == SWCODEC
rec_set_source(source, source_flags | SRCF_RECORDING);
#else
(void)source_flags;
#endif
audio_set_recording_options(frequency, quality, source,
channel_mode, editable, prerecord_time);
}
static char path_buffer[MAX_PATH]; static char path_buffer[MAX_PATH];
/* steals mp3 buffer, creates unique filename and starts recording */
void rec_record(void)
{
talk_buffer_steal(); /* we use the mp3 buffer */
audio_record(rec_create_filename(path_buffer));
}
/* creates unique filename and starts recording */
void rec_new_file(void)
{
audio_new_file(rec_create_filename(path_buffer));
}
/* used in trigger_listerner and recording_screen */ /* used in trigger_listerner and recording_screen */
static unsigned int last_seconds = 0; static unsigned int last_seconds = 0;
@ -533,16 +733,16 @@ static void trigger_listener(int trigger_status)
if((audio_status() & AUDIO_STATUS_RECORD) != AUDIO_STATUS_RECORD) if((audio_status() & AUDIO_STATUS_RECORD) != AUDIO_STATUS_RECORD)
{ {
talk_buffer_steal(); /* we use the mp3 buffer */ talk_buffer_steal(); /* we use the mp3 buffer */
audio_record(rec_create_filename(path_buffer)); rec_record();
/* give control to mpeg thread so that it can start
/* give control to mpeg thread so that it can start recording*/ recording */
yield(); yield(); yield(); yield(); yield(); yield();
} }
/* if we're already recording this is a retrigger */ /* if we're already recording this is a retrigger */
else else
{ {
audio_new_file(rec_create_filename(path_buffer)); rec_new_file();
/* tell recording_screen to reset the time */ /* tell recording_screen to reset the time */
last_seconds = 0; last_seconds = 0;
} }
@ -563,10 +763,9 @@ static void trigger_listener(int trigger_status)
} }
} }
bool recording_screen(void) bool recording_screen(bool no_source)
{ {
long button; long button;
long lastbutton = BUTTON_NONE;
bool done = false; bool done = false;
char buf[32]; char buf[32];
char buf2[32]; char buf2[32];
@ -575,11 +774,19 @@ bool recording_screen(void)
bool have_recorded = false; bool have_recorded = false;
unsigned int seconds; unsigned int seconds;
int hours, minutes; int hours, minutes;
char path_buffer[MAX_PATH];
char filename[13]; char filename[13];
bool been_in_usb_mode = false; bool been_in_usb_mode = false;
int last_audio_stat = -1; int last_audio_stat = -1;
int audio_stat; int audio_stat;
#ifdef HAVE_FMRADIO_IN
/* Radio is left on if:
* 1) Is was on at the start and the initial source is FM Radio
* 2) 1) and the source was never changed to something else
*/
int radio_status = (global_settings.rec_source != AUDIO_SRC_FMRADIO) ?
FMRADIO_OFF : get_radio_status();
#endif
int talk_menu = global_settings.talk_menu;
#if CONFIG_LED == LED_REAL #if CONFIG_LED == LED_REAL
bool led_state = false; bool led_state = false;
int led_countdown = 2; int led_countdown = 2;
@ -608,6 +815,18 @@ bool recording_screen(void)
ata_set_led_enabled(false); ata_set_led_enabled(false);
#endif #endif
#if CONFIG_CODEC == SWCODEC
audio_stop();
voice_stop();
/* recording_menu gets messed up: so reset talk_menu */
talk_menu = global_settings.talk_menu;
global_settings.talk_menu = 0;
#else
/* Yes, we use the D/A for monitoring */
peak_meter_enabled = true;
peak_meter_playback(true);
#endif
#ifndef SIMULATOR #ifndef SIMULATOR
audio_init_recording(talk_get_bufsize()); audio_init_recording(talk_get_bufsize());
#else #else
@ -616,44 +835,19 @@ bool recording_screen(void)
sound_set_volume(global_settings.volume); sound_set_volume(global_settings.volume);
#if CONFIG_CODEC == SWCODEC
audio_stop();
/* Set peak meter to recording mode */
peak_meter_playback(false);
#if defined(HAVE_SPDIF_IN) && !defined(SIMULATOR)
if (global_settings.rec_source == SOURCE_SPDIF)
cpu_boost(true);
#endif
#else
/* Yes, we use the D/A for monitoring */
peak_meter_playback(true);
#endif
peak_meter_enabled = true;
#ifdef HAVE_AGC #ifdef HAVE_AGC
peak_meter_get_peakhold(&peak_l, &peak_r); peak_meter_get_peakhold(&peak_l, &peak_r);
#endif #endif
#if CONFIG_CODEC != SWCODEC rec_set_recording_options(global_settings.rec_frequency,
if (global_settings.rec_prerecord_time) global_settings.rec_quality,
#endif global_settings.rec_source,
talk_buffer_steal(); /* will use the mp3 buffer */ 0,
global_settings.rec_channels,
#if defined(HAVE_SPDIF_POWER) && !defined(SIMULATOR) global_settings.rec_editable,
/* Tell recording whether we want S/PDIF power enabled at all times */ global_settings.rec_prerecord_time);
audio_set_spdif_power_setting(global_settings.spdif_enable);
#endif
audio_set_recording_options(global_settings.rec_frequency,
global_settings.rec_quality,
global_settings.rec_source,
global_settings.rec_channels,
global_settings.rec_editable,
global_settings.rec_prerecord_time);
set_gain(); set_gain();
settings_apply_trigger(); settings_apply_trigger();
#ifdef HAVE_AGC #ifdef HAVE_AGC
@ -663,7 +857,7 @@ bool recording_screen(void)
agc_preset_str[3] = str(LANG_AGC_DJSET); agc_preset_str[3] = str(LANG_AGC_DJSET);
agc_preset_str[4] = str(LANG_AGC_MEDIUM); agc_preset_str[4] = str(LANG_AGC_MEDIUM);
agc_preset_str[5] = str(LANG_AGC_VOICE); agc_preset_str[5] = str(LANG_AGC_VOICE);
if (global_settings.rec_source == SOURCE_MIC) { if (global_settings.rec_source == AUDIO_SRC_MIC) {
agc_preset = global_settings.rec_agc_preset_mic; agc_preset = global_settings.rec_agc_preset_mic;
agc_maxgain = global_settings.rec_agc_maxgain_mic; agc_maxgain = global_settings.rec_agc_maxgain_mic;
} }
@ -697,11 +891,7 @@ bool recording_screen(void)
while(!done) while(!done)
{ {
#if CONFIG_CODEC == SWCODEC
audio_stat = pcm_rec_status();
#else
audio_stat = audio_status(); audio_stat = audio_status();
#endif
#if CONFIG_LED == LED_REAL #if CONFIG_LED == LED_REAL
@ -794,8 +984,8 @@ bool recording_screen(void)
} }
else else
{ {
peak_meter_playback(true);
#if CONFIG_CODEC != SWCODEC #if CONFIG_CODEC != SWCODEC
peak_meter_playback(true);
peak_meter_enabled = false; peak_meter_enabled = false;
#endif #endif
done = true; done = true;
@ -815,14 +1005,13 @@ bool recording_screen(void)
/* manual recording */ /* manual recording */
have_recorded = true; have_recorded = true;
talk_buffer_steal(); /* we use the mp3 buffer */ talk_buffer_steal(); /* we use the mp3 buffer */
audio_record(rec_create_filename(path_buffer)); rec_record();
last_seconds = 0; last_seconds = 0;
if (global_settings.talk_menu) if (talk_menu)
{ /* no voice possible here, but a beep */ { /* no voice possible here, but a beep */
audio_beep(HZ/2); /* longer beep on start */ audio_beep(HZ/2); /* longer beep on start */
} }
} }
/* this is triggered recording */ /* this is triggered recording */
else else
{ {
@ -838,7 +1027,7 @@ bool recording_screen(void)
/*if new file button pressed, start new file */ /*if new file button pressed, start new file */
if (button == ACTION_REC_NEWFILE) if (button == ACTION_REC_NEWFILE)
{ {
audio_new_file(rec_create_filename(path_buffer)); rec_new_file();
last_seconds = 0; last_seconds = 0;
} }
else else
@ -847,7 +1036,7 @@ bool recording_screen(void)
if(audio_stat & AUDIO_STATUS_PAUSE) if(audio_stat & AUDIO_STATUS_PAUSE)
{ {
audio_resume_recording(); audio_resume_recording();
if (global_settings.talk_menu) if (talk_menu)
{ /* no voice possible here, but a beep */ { /* no voice possible here, but a beep */
audio_beep(HZ/4); /* short beep on resume */ audio_beep(HZ/4); /* short beep on resume */
} }
@ -883,7 +1072,7 @@ bool recording_screen(void)
sound_set_volume(global_settings.volume); sound_set_volume(global_settings.volume);
break; break;
case 1: case 1:
if(global_settings.rec_source == SOURCE_MIC) if(global_settings.rec_source == AUDIO_SRC_MIC)
{ {
if(global_settings.rec_mic_gain < if(global_settings.rec_mic_gain <
sound_max(SOUND_MIC_GAIN)) sound_max(SOUND_MIC_GAIN))
@ -913,7 +1102,7 @@ bool recording_screen(void)
case 4: case 4:
agc_preset = MIN(agc_preset + 1, AGC_MODE_SIZE); agc_preset = MIN(agc_preset + 1, AGC_MODE_SIZE);
agc_enable = (agc_preset != 0); agc_enable = (agc_preset != 0);
if (global_settings.rec_source == SOURCE_MIC) { if (global_settings.rec_source == AUDIO_SRC_MIC) {
global_settings.rec_agc_preset_mic = agc_preset; global_settings.rec_agc_preset_mic = agc_preset;
agc_maxgain = global_settings.rec_agc_maxgain_mic; agc_maxgain = global_settings.rec_agc_maxgain_mic;
} else { } else {
@ -922,7 +1111,7 @@ bool recording_screen(void)
} }
break; break;
case 5: case 5:
if (global_settings.rec_source == SOURCE_MIC) if (global_settings.rec_source == AUDIO_SRC_MIC)
{ {
agc_maxgain = MIN(agc_maxgain + 1, agc_maxgain = MIN(agc_maxgain + 1,
sound_max(SOUND_MIC_GAIN)); sound_max(SOUND_MIC_GAIN));
@ -951,7 +1140,7 @@ bool recording_screen(void)
sound_set_volume(global_settings.volume); sound_set_volume(global_settings.volume);
break; break;
case 1: case 1:
if(global_settings.rec_source == SOURCE_MIC) if(global_settings.rec_source == AUDIO_SRC_MIC)
{ {
if(global_settings.rec_mic_gain > if(global_settings.rec_mic_gain >
sound_min(SOUND_MIC_GAIN)) sound_min(SOUND_MIC_GAIN))
@ -981,7 +1170,7 @@ bool recording_screen(void)
case 4: case 4:
agc_preset = MAX(agc_preset - 1, 0); agc_preset = MAX(agc_preset - 1, 0);
agc_enable = (agc_preset != 0); agc_enable = (agc_preset != 0);
if (global_settings.rec_source == SOURCE_MIC) { if (global_settings.rec_source == AUDIO_SRC_MIC) {
global_settings.rec_agc_preset_mic = agc_preset; global_settings.rec_agc_preset_mic = agc_preset;
agc_maxgain = global_settings.rec_agc_maxgain_mic; agc_maxgain = global_settings.rec_agc_maxgain_mic;
} else { } else {
@ -990,7 +1179,7 @@ bool recording_screen(void)
} }
break; break;
case 5: case 5:
if (global_settings.rec_source == SOURCE_MIC) if (global_settings.rec_source == AUDIO_SRC_MIC)
{ {
agc_maxgain = MAX(agc_maxgain - 1, agc_maxgain = MAX(agc_maxgain - 1,
sound_min(SOUND_MIC_GAIN)); sound_min(SOUND_MIC_GAIN));
@ -1012,49 +1201,73 @@ bool recording_screen(void)
case ACTION_STD_MENU: case ACTION_STD_MENU:
if(audio_stat != AUDIO_STATUS_RECORD) if(audio_stat != AUDIO_STATUS_RECORD)
{ {
#ifdef HAVE_FMRADIO_IN
const int prev_rec_source = global_settings.rec_source;
#endif
#if CONFIG_LED == LED_REAL #if CONFIG_LED == LED_REAL
/* led is restored at begin of loop / end of function */ /* led is restored at begin of loop / end of function */
led(false); led(false);
#endif #endif
if (recording_menu(false)) if (recording_menu(no_source))
{ {
return SYS_USB_CONNECTED; done = true;
} been_in_usb_mode = true;
settings_save(); #ifdef HAVE_FMRADIO_IN
radio_status = FMRADIO_OFF;
#if CONFIG_CODEC != SWCODEC
if (global_settings.rec_prerecord_time)
#endif #endif
talk_buffer_steal(); /* will use the mp3 buffer */ }
else
{
settings_save();
#ifdef HAVE_FMRADIO_IN
/* If input changes away from FM Radio, radio will
remain off when recording screen closes. */
if (global_settings.rec_source != prev_rec_source
&& prev_rec_source == AUDIO_SRC_FMRADIO)
radio_status = FMRADIO_OFF;
#endif
#if CONFIG_CODEC == SWCODEC
/* reinit after submenu exit */
audio_close_recording();
audio_init_recording(talk_get_bufsize());
#endif
rec_set_recording_options(
global_settings.rec_frequency,
global_settings.rec_quality,
global_settings.rec_source,
0,
global_settings.rec_channels,
global_settings.rec_editable,
global_settings.rec_prerecord_time);
audio_set_recording_options(global_settings.rec_frequency,
global_settings.rec_quality,
global_settings.rec_source,
global_settings.rec_channels,
global_settings.rec_editable,
global_settings.rec_prerecord_time);
#ifdef HAVE_AGC #ifdef HAVE_AGC
if (global_settings.rec_source == SOURCE_MIC) { if (global_settings.rec_source == AUDIO_SRC_MIC) {
agc_preset = global_settings.rec_agc_preset_mic; agc_preset = global_settings.rec_agc_preset_mic;
agc_maxgain = global_settings.rec_agc_maxgain_mic; agc_maxgain = global_settings.rec_agc_maxgain_mic;
} }
else { else {
agc_preset = global_settings.rec_agc_preset_line; agc_preset = global_settings.rec_agc_preset_line;
agc_maxgain = global_settings.rec_agc_maxgain_line; agc_maxgain = global_settings.rec_agc_maxgain_line;
} }
#endif #endif
adjust_cursor(); adjust_cursor();
set_gain(); set_gain();
update_countdown = 1; /* Update immediately */ update_countdown = 1; /* Update immediately */
FOR_NB_SCREENS(i) FOR_NB_SCREENS(i)
{ {
screens[i].setfont(FONT_SYSFIXED); screens[i].setfont(FONT_SYSFIXED);
screens[i].setmargins(global_settings.invert_cursor ? 0 : w, 8); screens[i].setmargins(
global_settings.invert_cursor ? 0 : w, 8);
}
} }
} }
break; break;
#if CONFIG_KEYPAD == RECORDER_PAD #if CONFIG_KEYPAD == RECORDER_PAD
case ACTION_REC_F2: case ACTION_REC_F2:
if(audio_stat != AUDIO_STATUS_RECORD) if(audio_stat != AUDIO_STATUS_RECORD)
@ -1076,7 +1289,7 @@ bool recording_screen(void)
case ACTION_REC_F3: case ACTION_REC_F3:
if(audio_stat & AUDIO_STATUS_RECORD) if(audio_stat & AUDIO_STATUS_RECORD)
{ {
audio_new_file(rec_create_filename(path_buffer)); rec_new_file();
last_seconds = 0; last_seconds = 0;
} }
else else
@ -1097,7 +1310,7 @@ bool recording_screen(void)
} }
} }
break; break;
#endif #endif /* CONFIG_KEYPAD == RECORDER_PAD */
case SYS_USB_CONNECTED: case SYS_USB_CONNECTED:
/* Only accept USB connection when not recording */ /* Only accept USB connection when not recording */
@ -1106,6 +1319,9 @@ bool recording_screen(void)
default_event_handler(SYS_USB_CONNECTED); default_event_handler(SYS_USB_CONNECTED);
done = true; done = true;
been_in_usb_mode = true; been_in_usb_mode = true;
#ifdef HAVE_FMRADIO_IN
radio_status = FMRADIO_OFF;
#endif
} }
break; break;
@ -1113,8 +1329,6 @@ bool recording_screen(void)
default_event_handler(button); default_event_handler(button);
break; break;
} }
if (button != BUTTON_NONE)
lastbutton = button;
#ifdef HAVE_AGC #ifdef HAVE_AGC
peak_read = !peak_read; peak_read = !peak_read;
@ -1230,7 +1444,7 @@ bool recording_screen(void)
if (!(global_settings.rec_split_type) if (!(global_settings.rec_split_type)
|| (num_recorded_bytes >= MAX_FILE_SIZE)) || (num_recorded_bytes >= MAX_FILE_SIZE))
{ {
audio_new_file(rec_create_filename(path_buffer)); rec_new_file();
last_seconds = 0; last_seconds = 0;
} }
else else
@ -1259,8 +1473,9 @@ bool recording_screen(void)
screens[i].puts(0, filename_offset[i] + PM_HEIGHT + 2, buf); screens[i].puts(0, filename_offset[i] + PM_HEIGHT + 2, buf);
} }
if(global_settings.rec_source == SOURCE_MIC) if(global_settings.rec_source == AUDIO_SRC_MIC)
{ {
/* Draw MIC recording gain */
snprintf(buf, 32, "%s:%s", str(LANG_SYSFONT_RECORDING_GAIN), snprintf(buf, 32, "%s:%s", str(LANG_SYSFONT_RECORDING_GAIN),
fmt_gain(SOUND_MIC_GAIN, fmt_gain(SOUND_MIC_GAIN,
global_settings.rec_mic_gain, global_settings.rec_mic_gain,
@ -1278,8 +1493,13 @@ bool recording_screen(void)
PM_HEIGHT + 3, buf); PM_HEIGHT + 3, buf);
} }
} }
else if(global_settings.rec_source == SOURCE_LINE) else if(global_settings.rec_source == AUDIO_SRC_LINEIN
#ifdef HAVE_FMRADIO_IN
|| global_settings.rec_source == AUDIO_SRC_FMRADIO
#endif
)
{ {
/* Draw LINE or FMRADIO recording gain */
snprintf(buf, 32, "%s:%s", snprintf(buf, 32, "%s:%s",
str(LANG_SYSFONT_RECORDING_LEFT), str(LANG_SYSFONT_RECORDING_LEFT),
fmt_gain(SOUND_LEFT_GAIN, fmt_gain(SOUND_LEFT_GAIN,
@ -1319,14 +1539,23 @@ bool recording_screen(void)
FOR_NB_SCREENS(i) FOR_NB_SCREENS(i)
{ {
if (global_settings.rec_source == SOURCE_LINE) switch (global_settings.rec_source)
line[i] = 5; {
else if (global_settings.rec_source == SOURCE_MIC) case AUDIO_SRC_LINEIN:
line[i] = 4; #ifdef HAVE_FMRADIO_IN
#ifdef HAVE_SPDIF_IN case AUDIO_SRC_FMRADIO:
else if (global_settings.rec_source == SOURCE_SPDIF)
line[i] = 3;
#endif #endif
line[i] = 5;
break;
case AUDIO_SRC_MIC:
line[i] = 4;
break;
#ifdef HAVE_SPDIF_IN
case AUDIO_SRC_SPDIF:
line[i] = 3;
break;
#endif
} /* end switch */
#ifdef HAVE_AGC #ifdef HAVE_AGC
if (screens[i].height < h * (2 + filename_offset[i] + PM_HEIGHT + line[i])) if (screens[i].height < h * (2 + filename_offset[i] + PM_HEIGHT + line[i]))
{ {
@ -1358,7 +1587,7 @@ bool recording_screen(void)
snprintf(buf, 32, "%s: %s", snprintf(buf, 32, "%s: %s",
str(LANG_RECORDING_AGC_PRESET), str(LANG_RECORDING_AGC_PRESET),
agc_preset_str[agc_preset]); agc_preset_str[agc_preset]);
else if (global_settings.rec_source == SOURCE_MIC) else if (global_settings.rec_source == AUDIO_SRC_MIC)
snprintf(buf, 32, "%s: %s%s", snprintf(buf, 32, "%s: %s%s",
str(LANG_RECORDING_AGC_PRESET), str(LANG_RECORDING_AGC_PRESET),
agc_preset_str[agc_preset], agc_preset_str[agc_preset],
@ -1382,8 +1611,12 @@ bool recording_screen(void)
screens[i].puts_style_offset(0, filename_offset[i] + screens[i].puts_style_offset(0, filename_offset[i] +
PM_HEIGHT + line[i], buf, STYLE_INVERT,0); PM_HEIGHT + line[i], buf, STYLE_INVERT,0);
} }
else if ((global_settings.rec_source == SOURCE_MIC) else if (global_settings.rec_source == AUDIO_SRC_MIC
|| (global_settings.rec_source == SOURCE_LINE)) || global_settings.rec_source == AUDIO_SRC_LINEIN
#ifdef HAVE_FMRADIO_IN
|| global_settings.rec_source == AUDIO_SRC_FMRADIO
#endif
)
{ {
for(i = 0; i < screen_update; i++) { for(i = 0; i < screen_update; i++) {
if (display_agc[i]) { if (display_agc[i]) {
@ -1393,7 +1626,7 @@ bool recording_screen(void)
} }
} }
if (global_settings.rec_source == SOURCE_MIC) if (global_settings.rec_source == AUDIO_SRC_MIC)
{ {
if(agc_maxgain < (global_settings.rec_mic_gain)) if(agc_maxgain < (global_settings.rec_mic_gain))
change_recording_gain(false, true, true); change_recording_gain(false, true, true);
@ -1418,7 +1651,7 @@ bool recording_screen(void)
filename_offset[i] + filename_offset[i] +
PM_HEIGHT + 3, true); PM_HEIGHT + 3, true);
if(global_settings.rec_source != SOURCE_MIC) if(global_settings.rec_source != AUDIO_SRC_MIC)
{ {
for(i = 0; i < screen_update; i++) for(i = 0; i < screen_update; i++)
screen_put_cursorxy(&screens[i], 0, screen_put_cursorxy(&screens[i], 0,
@ -1456,14 +1689,14 @@ bool recording_screen(void)
} }
/* Can't measure S/PDIF sample rate on Archos yet */ /* Can't measure S/PDIF sample rate on Archos yet */
#if (CONFIG_CODEC != MAS3587F) && defined(HAVE_SPDIF_IN) && !defined(SIMULATOR) #if (CONFIG_CODEC != MAS3587F) && defined(HAVE_SPDIF_IN) && !defined(SIMULATOR)
if (global_settings.rec_source == SOURCE_SPDIF) if (global_settings.rec_source == AUDIO_SRC_SPDIF)
snprintf(spdif_sfreq, 8, "%dHz", audio_get_spdif_sample_rate()); snprintf(spdif_sfreq, 8, "%dHz", audio_get_spdif_sample_rate());
#else #else
(void)spdif_sfreq; (void)spdif_sfreq;
#endif #endif
snprintf(buf, 32, "%s %s", snprintf(buf, 32, "%s %s",
#if (CONFIG_CODEC != MAS3587F) && defined(HAVE_SPDIF_IN) && !defined(SIMULATOR) #if (CONFIG_CODEC != MAS3587F) && defined(HAVE_SPDIF_IN) && !defined(SIMULATOR)
global_settings.rec_source == SOURCE_SPDIF ? global_settings.rec_source == AUDIO_SRC_SPDIF ?
spdif_sfreq : spdif_sfreq :
#endif #endif
freq_str[global_settings.rec_frequency], freq_str[global_settings.rec_frequency],
@ -1473,8 +1706,8 @@ bool recording_screen(void)
for(i = 0; i < screen_update; i++) { for(i = 0; i < screen_update; i++) {
#ifdef HAVE_AGC #ifdef HAVE_AGC
if ((global_settings.rec_source == SOURCE_MIC) if ((global_settings.rec_source == AUDIO_SRC_MIC)
|| (global_settings.rec_source == SOURCE_LINE)) || (global_settings.rec_source == AUDIO_SRC_LINEIN))
screens[i].puts(0, filename_offset[i] + PM_HEIGHT + line[i] + 1, buf); screens[i].puts(0, filename_offset[i] + PM_HEIGHT + line[i] + 1, buf);
else else
#endif #endif
@ -1484,6 +1717,14 @@ bool recording_screen(void)
#ifdef HAVE_AGC #ifdef HAVE_AGC
hist_time++; hist_time++;
#endif #endif
#if CONFIG_CODEC == SWCODEC
snprintf(buf, 32, "%s",
REC_QUALITY_LABEL(global_settings.rec_quality));
for(i = 0; i < screen_update; i++)
screens[i].puts(0, filename_offset[i] + PM_HEIGHT + 6, buf);
#endif
for(i = 0; i < screen_update; i++) for(i = 0; i < screen_update; i++)
{ {
gui_statusbar_draw(&(statusbars.statusbars[i]), true); gui_statusbar_draw(&(statusbars.statusbars[i]), true);
@ -1506,7 +1747,7 @@ bool recording_screen(void)
{ {
done = true; done = true;
} }
} } /* end while(!done) */
#if CONFIG_CODEC == SWCODEC #if CONFIG_CODEC == SWCODEC
@ -1535,14 +1776,22 @@ bool recording_screen(void)
audio_stop_recording(); audio_stop_recording();
audio_close_recording(); audio_close_recording();
#if defined(HAVE_SPDIF_IN) && !defined(SIMULATOR) #ifdef HAVE_FMRADIO_IN
if (global_settings.rec_source == SOURCE_SPDIF) if (radio_status != FMRADIO_OFF)
cpu_boost(false); /* Restore radio playback - radio_status should be unchanged if started
through fm radio screen (barring usb connect) */
rec_set_source(AUDIO_SRC_FMRADIO, (radio_status & FMRADIO_PAUSED) ?
SRCF_FMRADIO_PAUSED : SRCF_FMRADIO_PLAYING);
else
#endif #endif
/* Go back to playback mode */
rec_set_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
#else /* restore talk_menu setting */
global_settings.talk_menu = talk_menu;
#else /* !SWCODEC */
audio_init_playback(); audio_init_playback();
#endif #endif /* CONFIG_CODEC == SWCODEC */
/* make sure the trigger is really turned off */ /* make sure the trigger is really turned off */
peak_meter_trigger(false); peak_meter_trigger(false);
@ -1560,7 +1809,7 @@ bool recording_screen(void)
ata_set_led_enabled(true); ata_set_led_enabled(true);
#endif #endif
return been_in_usb_mode; return been_in_usb_mode;
} } /* recording_screen */
#if CONFIG_KEYPAD == RECORDER_PAD #if CONFIG_KEYPAD == RECORDER_PAD
bool f2_rec_screen(void) bool f2_rec_screen(void)
@ -1680,15 +1929,13 @@ bool f2_rec_screen(void)
} }
} }
if (global_settings.rec_prerecord_time) rec_set_recording_options(global_settings.rec_frequency,
talk_buffer_steal(); /* will use the mp3 buffer */ global_settings.rec_quality,
global_settings.rec_source,
audio_set_recording_options(global_settings.rec_frequency, 0,
global_settings.rec_quality, global_settings.rec_channels,
global_settings.rec_source, global_settings.rec_editable,
global_settings.rec_channels, global_settings.rec_prerecord_time);
global_settings.rec_editable,
global_settings.rec_prerecord_time);
set_gain(); set_gain();
@ -1760,7 +2007,7 @@ bool f3_rec_screen(void)
case BUTTON_LEFT: case BUTTON_LEFT:
case BUTTON_F3 | BUTTON_LEFT: case BUTTON_F3 | BUTTON_LEFT:
global_settings.rec_source++; global_settings.rec_source++;
if(global_settings.rec_source > MAX_SOURCE) if(global_settings.rec_source > AUDIO_SRC_MAX)
global_settings.rec_source = 0; global_settings.rec_source = 0;
used = true; used = true;
break; break;
@ -1782,16 +2029,13 @@ bool f3_rec_screen(void)
} }
} }
if (global_settings.rec_prerecord_time) rec_set_recording_options(global_settings.rec_frequency,
talk_buffer_steal(); /* will use the mp3 buffer */ global_settings.rec_quality,
global_settings.rec_source,
audio_set_recording_options(global_settings.rec_frequency, 0,
global_settings.rec_quality, global_settings.rec_channels,
global_settings.rec_source, global_settings.rec_editable,
global_settings.rec_channels, global_settings.rec_prerecord_time);
global_settings.rec_editable,
global_settings.rec_prerecord_time);
set_gain(); set_gain();
@ -1801,7 +2045,7 @@ bool f3_rec_screen(void)
return false; return false;
} }
#endif /* #ifdef RECORDER_PAD */ #endif /* CONFIG_KEYPAD == RECORDER_PAD */
#if CONFIG_CODEC == SWCODEC #if CONFIG_CODEC == SWCODEC
void audio_beep(int duration) void audio_beep(int duration)
@ -1831,6 +2075,14 @@ unsigned long audio_num_recorded_bytes(void)
return 5 * 1024 * 1024; return 5 * 1024 * 1024;
} }
#if CONFIG_CODEC == SWCODEC
void rec_set_source(int source, int flags)
{
source = source;
flags = flags;
}
#endif
void audio_set_recording_options(int frequency, int quality, void audio_set_recording_options(int frequency, int quality,
int source, int channel_mode, int source, int channel_mode,
bool editable, int prerecord_time) bool editable, int prerecord_time)

View file

@ -19,8 +19,33 @@
#ifndef RECORDING_H #ifndef RECORDING_H
#define RECORDING_H #define RECORDING_H
bool recording_screen(void); bool recording_screen(bool no_source);
char *rec_create_filename(char *buf); char *rec_create_filename(char *buf);
int rec_create_directory(void); int rec_create_directory(void);
#if CONFIG_CODEC == SWCODEC
/* selects an audio source for recording or playback */
#define SRCF_PLAYBACK 0x0000 /* default */
#define SRCF_RECORDING 0x1000
#ifdef CONFIG_TUNER
/* for AUDIO_SRC_FMRADIO */
#define SRCF_FMRADIO_PLAYING 0x0000 /* default */
#define SRCF_FMRADIO_PAUSED 0x2000
#endif
void rec_set_source(int source, int flags);
#endif /* CONFIG_CODEC == SW_CODEC */
/* steals mp3 buffer, sets source and then options */
/* SRCF_RECORDING is implied */
void rec_set_recording_options(int frequency, int quality,
int source, int source_flags,
int channel_mode, bool editable,
int prerecord_time);
/* steals mp3 buffer, creates unique filename and starts recording */
void rec_record(void);
/* creates unique filename and starts recording */
void rec_new_file(void);
#endif #endif

View file

@ -92,7 +92,7 @@ const char rec_base_directory[] = REC_BASE_DIR;
#include "dsp.h" #include "dsp.h"
#endif #endif
#define CONFIG_BLOCK_VERSION 50 #define CONFIG_BLOCK_VERSION 51
#define CONFIG_BLOCK_SIZE 512 #define CONFIG_BLOCK_SIZE 512
#define RTC_BLOCK_SIZE 44 #define RTC_BLOCK_SIZE 44
@ -473,11 +473,21 @@ static const struct bit_entry hd_bits[] =
{1, S_O(rec_split_type), 0, "rec split type", "Split, Stop" }, {1, S_O(rec_split_type), 0, "rec split type", "Split, Stop" },
{1, S_O(rec_split_method), 0, "rec split method", "Time,Filesize" }, {1, S_O(rec_split_method), 0, "rec split method", "Time,Filesize" },
#ifdef HAVE_SPDIF_IN {
{2, S_O(rec_source), 0 /* 0=mic */, "rec source", "mic,line,spdif" }, #if defined(HAVE_SPDIF_IN) || defined(HAVE_FMRADIO_IN)
2,
#else #else
{1, S_O(rec_source), 0 /* 0=mic */, "rec source", "mic,line" }, 1,
#endif #endif
S_O(rec_source), 0 /* 0=mic */, "rec source",
"mic,line"
#ifdef HAVE_SPDIF_IN
",spdif"
#endif
#ifdef HAVE_FMRADIO_IN
",fmradio"
#endif
},
{5, S_O(rec_prerecord_time), 0, "prerecording time", NULL }, /* 0...30 */ {5, S_O(rec_prerecord_time), 0, "prerecording time", NULL }, /* 0...30 */
{1, S_O(rec_directory), 0, /* rec_base_directory */ {1, S_O(rec_directory), 0, /* rec_base_directory */
"rec directory", REC_BASE_DIR ",current" }, "rec directory", REC_BASE_DIR ",current" },
@ -490,14 +500,21 @@ static const struct bit_entry hd_bits[] =
{4, S_O(rec_right_gain), 2 /* 0dB */, "rec right gain", NULL }, /* 0...15 */ {4, S_O(rec_right_gain), 2 /* 0dB */, "rec right gain", NULL }, /* 0...15 */
{3, S_O(rec_frequency), 0, /* 0=44.1kHz */ {3, S_O(rec_frequency), 0, /* 0=44.1kHz */
"rec frequency", "44,48,32,22,24,16" }, "rec frequency", "44,48,32,22,24,16" },
{3, S_O(rec_quality), 5 /* 192 kBit/s max */, "rec quality", NULL },
{1, S_O(rec_editable), false, "editable recordings", off_on }, {1, S_O(rec_editable), false, "editable recordings", off_on },
{3, S_O(rec_quality), 5, "rec quality", NULL }, #elif defined(HAVE_UDA1380) || defined(HAVE_TLV320)
#elif defined(HAVE_UDA1380) #ifdef HAVE_UDA1380
{8|SIGNED, S_O(rec_mic_gain), 16 /* 8 dB */, "rec mic gain", NULL }, /* -128...+108 */ {8|SIGNED, S_O(rec_mic_gain), 16 /* 8 dB */, "rec mic gain", NULL }, /* -128...+108 */
#endif
#ifdef HAVE_TLV320
/* TLV320 only has no mic boost or 20db mic boost */
{1, S_O(rec_mic_gain), 0 /* 0 dB */, "rec mic gain", NULL }, /* 0db or 20db */
#endif
{8|SIGNED, S_O(rec_left_gain), 0, "rec left gain", NULL }, /* -128...+96 */ {8|SIGNED, S_O(rec_left_gain), 0, "rec left gain", NULL }, /* -128...+96 */
{8|SIGNED, S_O(rec_right_gain), 0, "rec right gain", NULL }, /* -128...+96 */ {8|SIGNED, S_O(rec_right_gain), 0, "rec right gain", NULL }, /* -128...+96 */
{3, S_O(rec_frequency), 0, /* 0=44.1kHz */ {3, S_O(rec_frequency), 0, /* 0=44.1kHz */
"rec frequency", "44,48,32,22,24,16" }, "rec frequency", "44,48,32,22,24,16" },
{4, S_O(rec_quality), 4 /* MP3 L3 192 kBit/s */, "rec quality", NULL },
#endif #endif
/* values for the trigger */ /* values for the trigger */

View file

@ -42,6 +42,7 @@
#define BACKDROP_DIR ROCKBOX_DIR"/backdrops" #define BACKDROP_DIR ROCKBOX_DIR"/backdrops"
#define REC_BASE_DIR "/recordings" #define REC_BASE_DIR "/recordings"
#define EQS_DIR ROCKBOX_DIR "/eqs" #define EQS_DIR ROCKBOX_DIR "/eqs"
#define CODECS_DIR "/codecs"
#define MAX_FILENAME 20 #define MAX_FILENAME 20

View file

@ -39,6 +39,12 @@
#include "talk.h" #include "talk.h"
#include "misc.h" #include "misc.h"
#include "sound.h" #include "sound.h"
#ifdef HAVE_RECORDING
#include "audio.h"
#ifdef CONFIG_TUNER
#include "radio.h"
#endif
#endif
#if CONFIG_CODEC == MAS3587F #if CONFIG_CODEC == MAS3587F
#include "peakmeter.h" #include "peakmeter.h"
#include "mas.h" #include "mas.h"
@ -290,19 +296,68 @@ static bool avc(void)
#ifdef HAVE_RECORDING #ifdef HAVE_RECORDING
static bool recsource(void) static bool recsource(void)
{ {
static const struct opt_items names[] = { int n_opts = AUDIO_NUM_SOURCES;
struct opt_items names[AUDIO_NUM_SOURCES] = {
{ STR(LANG_RECORDING_SRC_MIC) }, { STR(LANG_RECORDING_SRC_MIC) },
{ STR(LANG_RECORDING_SRC_LINE) }, { STR(LANG_RECORDING_SRC_LINE) },
#ifdef HAVE_SPDIF_IN #ifdef HAVE_SPDIF_IN
{ STR(LANG_RECORDING_SRC_DIGITAL) }, { STR(LANG_RECORDING_SRC_DIGITAL) },
#endif #endif
}; };
/* caveat: assumes it's the last item! */
#ifdef HAVE_FMRADIO_IN
if (radio_hardware_present())
{
names[AUDIO_SRC_FMRADIO].string = ID2P(LANG_FM_RADIO);
names[AUDIO_SRC_FMRADIO].voice_id = LANG_FM_RADIO;
}
else
n_opts--;
#endif
return set_option(str(LANG_RECORDING_SOURCE), return set_option(str(LANG_RECORDING_SOURCE),
&global_settings.rec_source, INT, names, &global_settings.rec_source, INT, names,
sizeof(names)/sizeof(struct opt_items), NULL ); n_opts, NULL );
} }
/* To be removed when we add support for sample rates and channel settings */ /* To be removed when we add support for sample rates and channel settings */
#if CONFIG_CODEC == SWCODEC
static bool recquality(void)
{
static const struct opt_items names[] = {
{ "MP3 64 kBit/s", TALK_ID( 64, UNIT_KBIT) },
{ "MP3 96 kBit/s", TALK_ID( 96, UNIT_KBIT) },
{ "MP3 128 kBit/s", TALK_ID( 128, UNIT_KBIT) },
{ "MP3 160 kBit/s", TALK_ID( 160, UNIT_KBIT) },
{ "MP3 192 kBit/s", TALK_ID( 192, UNIT_KBIT) },
{ "MP3 224 kBit/s", TALK_ID( 224, UNIT_KBIT) },
{ "MP3 320 kBit/s", TALK_ID( 320, UNIT_KBIT) },
{ "WV 900 kBit/s", TALK_ID( 900, UNIT_KBIT) },
{ "WAV 1411 kBit/s", TALK_ID(1411, UNIT_KBIT) }
};
return set_option(str(LANG_RECORDING_QUALITY),
&global_settings.rec_quality, INT,
names, sizeof (names)/sizeof(struct opt_items),
NULL );
}
#elif CONFIG_CODEC == MAS3587F
static bool recquality(void)
{
return set_int(str(LANG_RECORDING_QUALITY), "", UNIT_INT,
&global_settings.rec_quality,
NULL, 1, 0, 7, NULL );
}
static bool receditable(void)
{
return set_bool(str(LANG_RECORDING_EDITABLE),
&global_settings.rec_editable);
}
#endif
#ifndef HAVE_UDA1380 #ifndef HAVE_UDA1380
static bool recfrequency(void) static bool recfrequency(void)
{ {
@ -331,21 +386,6 @@ static bool recchannels(void)
} }
#endif #endif
#if CONFIG_CODEC == MAS3587F
static bool recquality(void)
{
return set_int(str(LANG_RECORDING_QUALITY), "", UNIT_INT,
&global_settings.rec_quality,
NULL, 1, 0, 7, NULL );
}
static bool receditable(void)
{
return set_bool(str(LANG_RECORDING_EDITABLE),
&global_settings.rec_editable);
}
#endif
static bool rectimesplit(void) static bool rectimesplit(void)
{ {
static const struct opt_items names[] = { static const struct opt_items names[] = {
@ -1011,13 +1051,13 @@ bool recording_menu(bool no_source)
struct menu_item items[13]; struct menu_item items[13];
bool result; bool result;
#if CONFIG_CODEC == MAS3587F #if CONFIG_CODEC == MAS3587F || CONFIG_CODEC == SWCODEC
items[i].desc = ID2P(LANG_RECORDING_QUALITY); items[i].desc = ID2P(LANG_RECORDING_QUALITY);
items[i++].function = recquality; items[i++].function = recquality;
#endif #endif
#ifndef HAVE_UDA1380
/* We don't support frequency selection for UDA1380 yet. Let it just stay at /* We don't support frequency selection for UDA1380 yet. Let it just stay at
the default 44100 Hz. */ the default 44100 Hz. */
#ifndef HAVE_UDA1380
items[i].desc = ID2P(LANG_RECORDING_FREQUENCY); items[i].desc = ID2P(LANG_RECORDING_FREQUENCY);
items[i++].function = recfrequency; items[i++].function = recfrequency;
#endif #endif

View file

@ -103,10 +103,10 @@ int current_playmode(void)
#ifdef CONFIG_TUNER #ifdef CONFIG_TUNER
audio_stat = get_radio_status(); audio_stat = get_radio_status();
if(audio_stat == FMRADIO_PLAYING) if(audio_stat & FMRADIO_PLAYING)
return STATUS_RADIO; return STATUS_RADIO;
if(audio_stat == FMRADIO_PAUSED) if(audio_stat & FMRADIO_PAUSED)
return STATUS_RADIO_PAUSE; return STATUS_RADIO_PAUSE;
#endif #endif

View file

@ -554,6 +554,7 @@ int talk_buffer_steal(void)
} }
#endif #endif
reset_state(); reset_state();
return 0; return 0;
} }
@ -728,6 +729,7 @@ int talk_value(long n, int unit, bool enqueue)
VOICE_PIXEL, VOICE_PIXEL,
VOICE_PER_SEC, VOICE_PER_SEC,
VOICE_HERTZ, VOICE_HERTZ,
VOICE_KBIT_PER_SEC,
}; };
#if CONFIG_CODEC != SWCODEC #if CONFIG_CODEC != SWCODEC

View file

@ -41,6 +41,7 @@ enum {
UNIT_PER_SEC, /* per second */ UNIT_PER_SEC, /* per second */
UNIT_HERTZ, /* hertz */ UNIT_HERTZ, /* hertz */
UNIT_MB, /* Megabytes */ UNIT_MB, /* Megabytes */
UNIT_KBIT, /* kilobits per sec */
UNIT_LAST /* END MARKER */ UNIT_LAST /* END MARKER */
}; };

View file

@ -577,7 +577,7 @@ static bool dirbrowse(void)
if (global_settings.rec_startup) { if (global_settings.rec_startup) {
/* We fake being in the menu structure by calling /* We fake being in the menu structure by calling
the appropriate parent when we drop out of each screen */ the appropriate parent when we drop out of each screen */
recording_screen(); recording_screen(false);
rec_menu(); rec_menu();
main_menu(); main_menu();
} }

View file

@ -38,7 +38,7 @@ bool charger_enabled;
static bool powered = false; static bool powered = false;
bool radio_powered() bool radio_powered(void)
{ {
return powered; return powered;
} }

View file

@ -31,6 +31,9 @@
#define AUDIO_STATUS_PRERECORD 8 #define AUDIO_STATUS_PRERECORD 8
#define AUDIO_STATUS_ERROR 16 #define AUDIO_STATUS_ERROR 16
#define AUDIO_STATUS_STAYON_FLAGS \
(AUDIO_STATUS_PLAY | AUDIO_STATUS_PAUSE | AUDIO_STATUS_RECORD | AUDIO_)
#define AUDIOERR_DISK_FULL 1 #define AUDIOERR_DISK_FULL 1
#define AUDIO_GAIN_LINEIN 0 #define AUDIO_GAIN_LINEIN 0
@ -69,6 +72,7 @@ void audio_resume(void);
void audio_next(void); void audio_next(void);
void audio_prev(void); void audio_prev(void);
int audio_status(void); int audio_status(void);
bool audio_query_poweroff(void);
int audio_track_count(void); /* SWCODEC only */ int audio_track_count(void); /* SWCODEC only */
void audio_pre_ff_rewind(void); /* SWCODEC only */ void audio_pre_ff_rewind(void); /* SWCODEC only */
void audio_ff_rewind(long newtime); void audio_ff_rewind(long newtime);
@ -93,14 +97,56 @@ void audio_stop_recording(void);
void audio_pause_recording(void); void audio_pause_recording(void);
void audio_resume_recording(void); void audio_resume_recording(void);
void audio_new_file(const char *filename); void audio_new_file(const char *filename);
/* audio sources */
enum
{
AUDIO_SRC_PLAYBACK = -1, /* for audio playback (default) */
AUDIO_SRC_MIC, /* monitor mic */
AUDIO_SRC_LINEIN, /* monitor line in */
#ifdef HAVE_SPDIF_IN
AUDIO_SRC_SPDIF, /* monitor spdif */
#endif
#if defined(HAVE_FMRADIO_IN) || defined(CONFIG_TUNER)
AUDIO_SRC_FMRADIO, /* monitor fm radio */
#endif
/* define new audio sources above this line */
AUDIO_SOURCE_LIST_END,
/* AUDIO_SRC_FMRADIO must be declared #ifdef CONFIG_TUNER but is not in
the list of recordable sources. HAVE_FMRADIO_IN implies CONFIG_TUNER. */
#if defined(HAVE_FMRADIO_IN) || !defined(CONFIG_TUNER)
AUDIO_NUM_SOURCES = AUDIO_SOURCE_LIST_END,
#else
AUDIO_NUM_SOURCES = AUDIO_SOURCE_LIST_END-1,
#endif
AUDIO_SRC_MAX = AUDIO_NUM_SOURCES-1
};
/* channel modes */
enum
{
CHN_MODE_MONO = 1,
CHN_MODE_STEREO,
};
void audio_set_recording_options(int frequency, int quality, void audio_set_recording_options(int frequency, int quality,
int source, int channel_mode, int source, int channel_mode,
bool editable, int prerecord_time); bool editable, int prerecord_time);
void audio_set_recording_gain(int left, int right, int type); void audio_set_recording_gain(int left, int right, int type);
unsigned long audio_recorded_time(void); unsigned long audio_recorded_time(void);
unsigned long audio_num_recorded_bytes(void); unsigned long audio_num_recorded_bytes(void);
#if 0
#ifdef HAVE_SPDIF_POWER
void audio_set_spdif_power_setting(bool on); void audio_set_spdif_power_setting(bool on);
#endif
#endif
unsigned long audio_get_spdif_sample_rate(void); unsigned long audio_get_spdif_sample_rate(void);
#if CONFIG_CODEC == SWCODEC
/* audio encoder functions (defined in playback.c) */
int audio_get_encoder_id(void);
void audio_load_encoder(int enc_id);
void audio_remove_encoder(void);
#endif /* CONFIG_CODEC == SWCODEC */

View file

@ -135,6 +135,9 @@
/* Someone with H100 and BDM, please verify if this works. */ /* Someone with H100 and BDM, please verify if this works. */
/* #define HAVE_EEPROM */ /* #define HAVE_EEPROM */
/* Define this for FM radio input available (not for SIMULATOR) */
#define HAVE_FMRADIO_IN
#endif /* !SIMULATOR */ #endif /* !SIMULATOR */
/* Define this for S/PDIF input available */ /* Define this for S/PDIF input available */

View file

@ -132,6 +132,9 @@
/* Define this if the EEPROM chip is used */ /* Define this if the EEPROM chip is used */
#define HAVE_EEPROM_SETTINGS #define HAVE_EEPROM_SETTINGS
/* Define this for FM radio input available (not for SIMULATOR) */
#define HAVE_FMRADIO_IN
#endif /* !SIMULATOR */ #endif /* !SIMULATOR */
/* Define this for S/PDIF input available */ /* Define this for S/PDIF input available */

View file

@ -140,4 +140,7 @@
/* Define this if there is an EEPROM chip */ /* Define this if there is an EEPROM chip */
#define HAVE_EEPROM #define HAVE_EEPROM
/* Define this for FM radio input available (not for SIMULATOR) */
#define HAVE_FMRADIO_IN
#endif /* SIMULATOR */ #endif /* SIMULATOR */

View file

@ -17,6 +17,7 @@
/* define this if you have access to the quickscreen */ /* define this if you have access to the quickscreen */
#define HAVE_QUICKSCREEN #define HAVE_QUICKSCREEN
/* define this if you have access to the pitchscreen */ /* define this if you have access to the pitchscreen */
#define HAVE_PITCHSCREEN #define HAVE_PITCHSCREEN
@ -81,6 +82,9 @@
should be defined as well. */ should be defined as well. */
#define HAVE_LCD_SLEEP #define HAVE_LCD_SLEEP
/* Define this for FM radio input available (not for SIMULATOR) */
#define HAVE_FMRADIO_IN
/* Define this if you have a Motorola SCF5250 */ /* Define this if you have a Motorola SCF5250 */
#define CONFIG_CPU MCF5250 #define CONFIG_CPU MCF5250

View file

@ -20,6 +20,22 @@
#ifndef FMRADIO_H #ifndef FMRADIO_H
#define FMRADIO_H #define FMRADIO_H
/** declare some stuff here so powermgmt.c can properly tell if the radio is
actually playing and not just paused. This break in heirarchy is allowed
for audio_status(). **/
/* set when radio is playing or paused within fm radio screen */
#define FMRADIO_OFF 0x0
#define FMRADIO_PLAYING 0x1
#define FMRADIO_PAUSED 0x2
/* returns the IN flag */
#define FMRADIO_IN_SCREEN(s) ((s) & FMRADIO_IN_FLAG)
#define FMRADIO_STATUS_PLAYING(s) ((s) & FMRADIO_PLAYING_OUT)
#define FMRADIO_STATUS_PAUSED(s) ((s) & FMRADIO_PAUSED_OUT)
extern int get_radio_status(void);
extern int fmradio_read(int addr); extern int fmradio_read(int addr);
extern void fmradio_set(int addr, int data); extern void fmradio_set(int addr, int data);

View file

@ -24,7 +24,6 @@
#include "file.h" #include "file.h"
/* Audio file types. */ /* Audio file types. */
/* NOTE: When adding new audio types, also add to codec_labels[] in id3.c */
enum { enum {
AFMT_UNKNOWN = 0, /* Unknown file format */ AFMT_UNKNOWN = 0, /* Unknown file format */
@ -46,9 +45,48 @@ enum {
/* New formats must be added to the end of this list */ /* New formats must be added to the end of this list */
AFMT_NUM_CODECS AFMT_NUM_CODECS,
#if CONFIG_CODEC == SWCODEC
/* masks to decompose parts */
CODEC_AFMT_MASK = 0x0fff,
CODEC_TYPE_MASK = 0x7000,
/* switch for specifying codec type when requesting a filename */
CODEC_TYPE_DECODER = (0 << 12), /* default */
CODEC_TYPE_ENCODER = (1 << 12)
#endif
}; };
#if CONFIG_CODEC == SWCODEC
#define AFMT_ENTRY(label, codec_fname, codec_enc_fname, enc_ext) \
{ label, codec_fname, codec_enc_fname, enc_ext }
#else
#define AFMT_ENTRY(label, codec_fname, codec_enc_fname, enc_ext) \
{ label }
#endif
/* record describing the audio format */
struct afmt_entry
{
#if CONFIG_CODEC == SWCODEC
char label[8]; /* format label */
char *codec_fn; /* filename of decoder codec */
char *codec_enc_fn; /* filename of encoder codec */
char *ext; /* default extension for file (enc only for now) */
#else
char label[4];
#endif
};
/* database of labels and codecs. add formats per above enum */
extern const struct afmt_entry audio_formats[AFMT_NUM_CODECS];
#if CONFIG_CODEC == SWCODEC
/* recording quality to AFMT_* */
extern const int rec_quality_info_afmt[9];
#endif
struct mp3entry { struct mp3entry {
char path[MAX_PATH]; char path[MAX_PATH];
char* title; char* title;

View file

@ -20,10 +20,22 @@
#ifndef PCM_RECORD_H #ifndef PCM_RECORD_H
#define PCM_RECORD_H #define PCM_RECORD_H
void enc_set_parameters(int chunk_size, int num_chunks,
int samp_per_chunk, char *head_ptr, int head_size,
int enc_id);
void enc_get_inputs(int *buffer_size, int *channels, int *quality);
unsigned int* enc_alloc_chunk(void);
void enc_free_chunk(void);
int enc_wavbuf_near_empty(void);
char* enc_get_wav_data(int size);
extern void (*enc_set_header_callback)(void *head_buffer, int head_size,
int num_pcm_samples, bool is_file_header);
unsigned long pcm_rec_status(void); unsigned long pcm_rec_status(void);
void pcm_rec_init(void); void pcm_rec_init(void);
void pcm_rec_mux(int source); void pcm_rec_mux(int source);
int pcm_rec_current_bitrate(void);
int pcm_get_num_unprocessed(void);
void pcm_rec_get_peaks(int *left, int *right); void pcm_rec_get_peaks(int *left, int *right);
/* audio.h contains audio recording functions */ /* audio.h contains audio recording functions */

View file

@ -85,28 +85,59 @@ static const char* const genres[] = {
"Synthpop" "Synthpop"
}; };
static const char* const codec_labels[] = { /* database of audio formats */
"???", /* Unknown file format */ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
{
"MP1", /* MPEG Audio layer 1 */ /* Unknown file format */
"MP2", /* MPEG Audio layer 2 */ AFMT_ENTRY("???", NULL, NULL, NULL ),
"MP3", /* MPEG Audio layer 3 */ /* MPEG Audio layer 1 */
AFMT_ENTRY("MP1", "mpa.codec", NULL, NULL ),
/* MPEG Audio layer 2 */
AFMT_ENTRY("MP2", "mpa.codec", NULL, NULL ),
/* MPEG Audio layer 3 */
AFMT_ENTRY("MP3", "mpa.codec", "mp3_enc.codec", ".mp3"),
#if CONFIG_CODEC == SWCODEC #if CONFIG_CODEC == SWCODEC
"WAV", /* Uncompressed PCM in a WAV file */ /* Uncompressed PCM in a WAV file */
"Ogg", /* Ogg Vorbis */ AFMT_ENTRY("WAV", "wav.codec", "wav_enc.codec", ".wav"),
"FLAC", /* FLAC */ /* Ogg Vorbis */
"MPC", /* Musepack */ AFMT_ENTRY("Ogg", "vorbis.codec", NULL, NULL ),
"AC3", /* A/52 (aka AC3) audio */ /* FLAC */
"WV", /* WavPack */ AFMT_ENTRY("FLAC", "flac.codec", NULL, NULL ),
"ALAC", /* Apple Lossless Audio Codec */ /* Musepack */
"AAC", /* Advanced Audio Coding in M4A container */ AFMT_ENTRY("MPC", "mpc.codec", NULL, NULL ),
"SHN", /* Shorten */ /* A/52 (aka AC3) audio */
"AIFF", /* Audio Interchange File Format */ AFMT_ENTRY("AC3", "a52.codec", NULL, NULL ),
"SID", /* SID File Format */ /* WavPack */
AFMT_ENTRY("WV", "wavpack.codec", "wavpack_enc.codec", ".wv" ),
/* Apple Lossless Audio Codec */
AFMT_ENTRY("ALAC", "alac.codec", NULL, NULL ),
/* Advanced Audio Coding in M4A container */
AFMT_ENTRY("AAC", "aac.codec", NULL, NULL ),
/* Shorten */
AFMT_ENTRY("SHN", "shorten.codec", NULL, NULL ),
/* Audio Interchange File Format */
AFMT_ENTRY("AIFF", "aiff.codec", NULL, NULL ),
/* SID File Format */
AFMT_ENTRY("SID", "sid.codec", NULL, NULL ),
#endif #endif
}; };
#if CONFIG_CODEC == SWCODEC
/* recording quality to AFMT_* */
const int rec_quality_info_afmt[9] =
{
AFMT_MPA_L3, /* MPEG L3 64 kBit/s */
AFMT_MPA_L3, /* MPEG L3 96 kBit/s */
AFMT_MPA_L3, /* MPEG L3 128 kBit/s */
AFMT_MPA_L3, /* MPEG L3 160 kBit/s */
AFMT_MPA_L3, /* MPEG L3 192 kBit/s */
AFMT_MPA_L3, /* MPEG L3 224 kBit/s */
AFMT_MPA_L3, /* MPEG L3 320 kBit/s */
AFMT_WAVPACK, /* WavPack 909 kBit/s */
AFMT_PCM_WAV, /* PCM Wav 1411 kBit/s */
};
#endif /* SWCODEC */
char* id3_get_genre(const struct mp3entry* id3) char* id3_get_genre(const struct mp3entry* id3)
{ {
if( id3->genre_string ) if( id3->genre_string )
@ -119,8 +150,8 @@ char* id3_get_genre(const struct mp3entry* id3)
char* id3_get_codec(const struct mp3entry* id3) char* id3_get_codec(const struct mp3entry* id3)
{ {
if (id3->codectype < sizeof(codec_labels)/sizeof(char*)) { if (id3->codectype < AFMT_NUM_CODECS) {
return (char*)codec_labels[id3->codectype]; return (char*)audio_formats[id3->codectype].label;
} else { } else {
return NULL; return NULL;
} }

View file

@ -2484,7 +2484,7 @@ void audio_set_recording_options(int frequency, int quality,
DEBUGF("mas_writemem(MAS_BANK_D0, IO_CONTROL_MAIN, %x)\n", shadow_io_control_main); DEBUGF("mas_writemem(MAS_BANK_D0, IO_CONTROL_MAIN, %x)\n", shadow_io_control_main);
if(source == 0) /* Mic */ if(source == AUDIO_SRC_MIC)
{ {
/* Copy left channel to right (mono mode) */ /* Copy left channel to right (mono mode) */
mas_codec_writereg(8, 0x8000); mas_codec_writereg(8, 0x8000);

File diff suppressed because it is too large Load diff

View file

@ -424,6 +424,7 @@ static void battery_status_update(void)
* 1) The USB is connected * 1) The USB is connected
* 2) The charger is connected * 2) The charger is connected
* 3) We are recording, or recording with pause * 3) We are recording, or recording with pause
* 4) The radio is playing
*/ */
static void handle_auto_poweroff(void) static void handle_auto_poweroff(void)
{ {
@ -442,7 +443,7 @@ static void handle_auto_poweroff(void)
if(timeout && if(timeout &&
#ifdef CONFIG_TUNER #ifdef CONFIG_TUNER
(!radio_powered()) && (!(get_radio_status() & FMRADIO_PLAYING)) &&
#endif #endif
!usb_inserted() && !usb_inserted() &&
((audio_stat == 0) || ((audio_stat == 0) ||