Use bitmasks to define which inputs are available. Makes it easier to remove old assumptions of which are available. Inspired by e200 being unique in having FM Radio and Mic but no Line. Doesn't remove the assumption that Mic is available or that one of Mic and/or Line is available just to avoid excessive #ifdef'ing until needed.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13448 a1c6a512-1295-4272-9138-f99709370657
diff --git a/apps/gui/statusbar.c b/apps/gui/statusbar.c
index e082063..9eb766f 100644
--- a/apps/gui/statusbar.c
+++ b/apps/gui/statusbar.c
@@ -680,7 +680,7 @@
 #ifdef SIMULATOR
     samprk = 44100;
 #else
-#ifdef HAVE_SPDIF_IN
+#ifdef HAVE_SPDIF_REC
     if (global_settings.rec_source == AUDIO_SRC_SPDIF)
         /* Use rate in use, not current measured rate if it changed */
         samprk = pcm_rec_sample_rate();
@@ -731,7 +731,7 @@
     gui_statusbar_write_samplerate_info(display);
 #else /* !SWCODEC */
     /* hwcodec targets have sysfont characters */ 
-#ifdef HAVE_SPDIF_IN
+#ifdef HAVE_SPDIF_REC
     if (global_settings.rec_source == AUDIO_SRC_SPDIF)
     {
         /* Can't measure S/PDIF sample rate on Archos/Sim yet */
diff --git a/apps/menus/recording_menu.c b/apps/menus/recording_menu.c
index 1bc84e9..62af2f9 100644
--- a/apps/menus/recording_menu.c
+++ b/apps/menus/recording_menu.c
@@ -67,21 +67,21 @@
 
 static int recsource_func(void)
 {
-    int n_opts = AUDIO_NUM_SOURCES;
+    int n_opts = REC_NUM_SOURCES;
 
     static const struct opt_items names[AUDIO_NUM_SOURCES] = {
-        [AUDIO_SRC_MIC]     = { STR(LANG_RECORDING_SRC_MIC) },
-        [AUDIO_SRC_LINEIN]  = { STR(LANG_RECORDING_SRC_LINE) },
-#ifdef HAVE_SPDIF_IN
-        [AUDIO_SRC_SPDIF]   = { STR(LANG_RECORDING_SRC_DIGITAL) },
-#endif
-#ifdef HAVE_FMRADIO_IN
-        [AUDIO_SRC_FMRADIO] = { STR(LANG_FM_RADIO) }
-#endif
+        HAVE_MIC_REC_([AUDIO_SRC_MIC]
+            = { STR(LANG_RECORDING_SRC_MIC) },)
+        HAVE_LINE_REC_([AUDIO_SRC_LINEIN]
+            = { STR(LANG_RECORDING_SRC_LINE) },)
+        HAVE_SPDIF_REC_([AUDIO_SRC_SPDIF]
+            = { STR(LANG_RECORDING_SRC_DIGITAL) },)
+        HAVE_FMRADIO_REC_([AUDIO_SRC_FMRADIO]
+            = { STR(LANG_FM_RADIO) },)
     };
 
     /* caveat: assumes it's the last item! */
-#ifdef HAVE_FMRADIO_IN
+#ifdef HAVE_FMRADIO_REC
     if (!radio_hardware_present())
         n_opts--;
 #endif
@@ -145,15 +145,15 @@
     int              rec_frequency;
     bool             ret;
 
-#ifdef HAVE_SPDIF_IN
-    if (global_settings.rec_source == AUDIO_SRC_SPDIF)
+#ifdef HAVE_SPDIF_REC
+    if (global_settings.rec_source == REC_SRC_SPDIF)
     {
         /* Inform user that frequency follows the source's frequency */
         opts[0].string    = ID2P(LANG_SOURCE_FREQUENCY);
         opts[0].voice_id  = LANG_SOURCE_FREQUENCY;
         n_opts            = 1;
         rec_frequency     = 0;
-}
+    }
     else
 #endif
     {
@@ -189,9 +189,7 @@
                      &rec_frequency, INT, opts, n_opts, NULL );
 
     if (!ret
-#ifdef HAVE_SPDIF_IN
-        && global_settings.rec_source != AUDIO_SRC_SPDIF
-#endif
+        HAVE_SPDIF_REC_( && global_settings.rec_source != REC_SRC_SPDIF)
     )
     {
         /* Translate back to full index */
diff --git a/apps/recorder/radio.c b/apps/recorder/radio.c
index ae534ac..79febc9 100644
--- a/apps/recorder/radio.c
+++ b/apps/recorder/radio.c
@@ -1429,7 +1429,7 @@
 
 #ifdef HAVE_RECORDING
 
-#if defined(HAVE_FMRADIO_IN) && CONFIG_CODEC == SWCODEC
+#if defined(HAVE_FMRADIO_REC) && CONFIG_CODEC == SWCODEC
 #define FM_RECORDING_SCREEN
 static int fm_recording_screen(void)
 {
@@ -1450,9 +1450,9 @@
     return ret;
 }
 
-#endif /* defined(HAVE_FMRADIO_IN) && CONFIG_CODEC == SWCODEC */
+#endif /* defined(HAVE_FMRADIO_REC) && CONFIG_CODEC == SWCODEC */
 
-#if defined(HAVE_FMRADIO_IN) || CONFIG_CODEC != SWCODEC
+#if defined(HAVE_FMRADIO_REC) || CONFIG_CODEC != SWCODEC
 #define FM_RECORDING_SETTINGS
 static int fm_recording_settings(void)
 {
@@ -1471,7 +1471,7 @@
     return ret;
 }
 
-#endif /* defined(HAVE_FMRADIO_IN) || CONFIG_CODEC != SWCODEC */
+#endif /* defined(HAVE_FMRADIO_REC) || CONFIG_CODEC != SWCODEC */
 #endif /* HAVE_RECORDING */
 
 #ifdef FM_RECORDING_SCREEN
diff --git a/apps/recorder/recording.c b/apps/recorder/recording.c
index 0981cb8..0323ae1 100644
--- a/apps/recorder/recording.c
+++ b/apps/recorder/recording.c
@@ -183,7 +183,7 @@
     }
     else
     {
-        /* AUDIO_SRC_LINEIN, AUDIO_SRC_SPDIF, AUDIO_SRC_FMRADIO */
+        /* AUDIO_SRC_LINEIN, AUDIO_SRC_FMRADIO, AUDIO_SRC_SPDIF */
         audio_set_recording_gain(global_settings.rec_left_gain,
                                  global_settings.rec_right_gain,
                                  AUDIO_GAIN_LINEIN);
@@ -235,13 +235,12 @@
 
     switch (global_settings.rec_source)
     {
-    case AUDIO_SRC_LINEIN:
-#ifdef HAVE_FMRADIO_IN
-    case AUDIO_SRC_FMRADIO:
-#endif
+    HAVE_LINE_REC_(case AUDIO_SRC_LINEIN:)
+    HAVE_FMRADIO_REC_(case AUDIO_SRC_FMRADIO:)
         gain_current_l = global_settings.rec_left_gain;
         gain_current_r = global_settings.rec_right_gain;
         break;
+    case AUDIO_SRC_MIC:
     default:
         gain_current_l = global_settings.rec_mic_gain;
         gain_current_r = global_settings.rec_mic_gain;
@@ -257,14 +256,12 @@
 
     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;
+    HAVE_LINE_REC_(case AUDIO_SRC_LINEIN:)
+    HAVE_FMRADIO_REC_(case AUDIO_SRC_FMRADIO:)
+        if (left) global_settings.rec_left_gain += factor;
         if (right) global_settings.rec_right_gain += factor;
         break;
-    default:
+    case AUDIO_SRC_MIC:
          global_settings.rec_mic_gain += factor;
     }
 }
@@ -469,31 +466,27 @@
 #ifdef HAVE_AGC
     switch(global_settings.rec_source)
     {
-    case AUDIO_SRC_MIC:
+    case REC_SRC_MIC:
         if(cursor == 2)
             cursor = 4;
         else if(cursor == 3)
             cursor = 1;
-    case AUDIO_SRC_LINEIN:
-#ifdef HAVE_FMRADIO_IN
-    case AUDIO_SRC_FMRADIO:
-#endif
+    HAVE_LINE_REC_(case AUDIO_SRC_LINEIN:)
+    HAVE_FMRADIO_REC_(case AUDIO_SRC_FMRADIO:)
         max_cursor = 5;
         break;
     default:
         max_cursor = 0;
         break;
     }
-#else
+#else /* !HAVE_AGC */
     switch(global_settings.rec_source)
     {
     case AUDIO_SRC_MIC:
         max_cursor = 1;
         break;
-    case AUDIO_SRC_LINEIN:
-#ifdef HAVE_FMRADIO_IN
-    case AUDIO_SRC_FMRADIO:
-#endif
+    HAVE_LINE_REC_(case AUDIO_SRC_LINEIN:)
+    HAVE_FMRADIO_REC_(case AUDIO_SRC_FMRADIO:)
         max_cursor = 3;
         break;
     default:
@@ -556,7 +549,7 @@
 
 #if CONFIG_CODEC == SWCODEC && !defined(SIMULATOR)
 
-# ifdef HAVE_SPDIF_IN
+# ifdef HAVE_SPDIF_REC
 #  ifdef HAVE_ADJUSTABLE_CPU_FREQ
 static void rec_boost(bool state)
 {
@@ -588,7 +581,7 @@
     /** Do power up/down of associated device(s) **/
 
     /** SPDIF **/
-#ifdef HAVE_SPDIF_IN
+#ifdef HAVE_SPDIF_REC
     /* Always boost for SPDIF */
     rec_boost(source == AUDIO_SRC_SPDIF);
 #endif /* HAVE_SPDIF_IN */
@@ -766,7 +759,7 @@
     int warning_counter = 0;
     #define WARNING_PERIOD 7
 #endif
-#ifdef HAVE_FMRADIO_IN
+#ifdef HAVE_FMRADIO_REC
     /* 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
@@ -849,7 +842,7 @@
         agc_preset = global_settings.rec_agc_preset_line;
         agc_maxgain = global_settings.rec_agc_maxgain_line;
     }
-#endif
+#endif /* HAVE_AGC */
 
     FOR_NB_SCREENS(i)
     {
@@ -1117,7 +1110,7 @@
                             global_settings.rec_agc_maxgain_line = agc_maxgain;
                         }
                         break;
-#endif
+#endif /* HAVE_AGC */
                 }
                 set_gain();
                 update_countdown = 1; /* Update immediately */
@@ -1185,7 +1178,7 @@
                             global_settings.rec_agc_maxgain_line = agc_maxgain;
                         }
                         break;
-#endif
+#endif /* HAVE_AGC */
                 }
                 set_gain();
                 update_countdown = 1; /* Update immediately */
@@ -1194,7 +1187,7 @@
             case ACTION_STD_MENU:
                 if(audio_stat != AUDIO_STATUS_RECORD)
                 {
-#ifdef HAVE_FMRADIO_IN
+#ifdef HAVE_FMRADIO_REC
                     const int prev_rec_source = global_settings.rec_source;
 #endif
 
@@ -1206,13 +1199,13 @@
                     {
                         done = true;
                         been_in_usb_mode = true;
-#ifdef HAVE_FMRADIO_IN
+#ifdef HAVE_FMRADIO_REC
                         radio_status = FMRADIO_OFF;
 #endif
                     }
                     else
                     {
-#ifdef HAVE_FMRADIO_IN
+#ifdef HAVE_FMRADIO_REC
                         /* If input changes away from FM Radio, radio will
                            remain off when recording screen closes. */
                         if (global_settings.rec_source != prev_rec_source
@@ -1306,7 +1299,7 @@
                     default_event_handler(SYS_USB_CONNECTED);
                     done = true;
                     been_in_usb_mode = true;
-#ifdef HAVE_FMRADIO_IN
+#ifdef HAVE_FMRADIO_REC
                     radio_status = FMRADIO_OFF;
 #endif
                 }
@@ -1493,11 +1486,10 @@
                                             PM_HEIGHT + 3, buf);
                 }
             }
-            else if(global_settings.rec_source == AUDIO_SRC_LINEIN
-#ifdef HAVE_FMRADIO_IN
-                    || global_settings.rec_source == AUDIO_SRC_FMRADIO
-#endif
-                    )
+            else if(0
+                HAVE_LINE_REC_( || global_settings.rec_source == AUDIO_SRC_LINEIN)
+                HAVE_FMRADIO_REC_( || global_settings.rec_source == AUDIO_SRC_FMRADIO)
+            )
             {
                 /* Draw LINE or FMRADIO recording gain */
                 snprintf(buf, sizeof(buf), "%s:%s",
@@ -1541,16 +1533,14 @@
             {
                 switch (global_settings.rec_source)
                 {
-                case AUDIO_SRC_LINEIN:
-#ifdef HAVE_FMRADIO_IN
-                case AUDIO_SRC_FMRADIO:
-#endif
+                HAVE_LINE_REC_(case AUDIO_SRC_LINEIN:)
+                HAVE_FMRADIO_REC_(case AUDIO_SRC_FMRADIO:)
                     line[i] = 5;
                     break;
                 case AUDIO_SRC_MIC:
                     line[i] = 4;
                     break;
-#ifdef HAVE_SPDIF_IN
+#ifdef HAVE_SPDIF_REC
                 case AUDIO_SRC_SPDIF:
                     line[i] = 3;
                     break;
@@ -1615,12 +1605,11 @@
                     screens[i].puts_style_offset(0, filename_offset[i] + 
                                         PM_HEIGHT + line[i], buf, STYLE_INVERT,0);
             }
-            else if (global_settings.rec_source == AUDIO_SRC_MIC
-                    || global_settings.rec_source == AUDIO_SRC_LINEIN
-#ifdef HAVE_FMRADIO_IN
-                    || global_settings.rec_source == AUDIO_SRC_FMRADIO
-#endif
-                    )    
+            else if (
+                global_settings.rec_source == AUDIO_SRC_MIC
+                HAVE_LINE_REC_(|| global_settings.rec_source == AUDIO_SRC_LINEIN)
+                HAVE_FMRADIO_REC_(|| global_settings.rec_source == AUDIO_SRC_FMRADIO)
+                )    
             {
                 for(i = 0; i < screen_update; i++) {
                     if (display_agc[i]) {
@@ -1629,7 +1618,7 @@
                     }
                 }
             }
-            
+
             if (global_settings.rec_source == AUDIO_SRC_MIC)
             {
                 if(agc_maxgain < (global_settings.rec_mic_gain))
@@ -1642,7 +1631,7 @@
                 if(agc_maxgain < (global_settings.rec_right_gain))
                     change_recording_gain(false, false, true);
             }
-#else
+#else  /* !HAVE_AGC */
             }
 #endif /* HAVE_AGC */
 
@@ -1758,7 +1747,7 @@
     audio_stop_recording(); 
     audio_close_recording();
 
-#ifdef HAVE_FMRADIO_IN
+#ifdef HAVE_FMRADIO_REC
     if (radio_status != FMRADIO_OFF)
         /* Restore radio playback - radio_status should be unchanged if started
            through fm radio screen (barring usb connect) */
diff --git a/apps/settings_list.c b/apps/settings_list.c
index d397796..c6adfe8 100644
--- a/apps/settings_list.c
+++ b/apps/settings_list.c
@@ -747,14 +747,12 @@
         "rec split method", "Time,Filesize", NULL, 2,
         ID2P(LANG_REC_TIME), ID2P(LANG_REC_SIZE)),
     {F_T_INT,&global_settings.rec_source,LANG_RECORDING_SOURCE,INT(0),
-        "rec source","mic,line"
-#ifdef HAVE_SPDIF_IN
-        ",spdif"
-#endif
-#ifdef HAVE_FMRADIO_IN
-        ",fmradio"
-#endif
-    ,UNUSED},
+        "rec source",
+        &HAVE_MIC_REC_(",mic")
+         HAVE_LINE_REC_(",line")
+         HAVE_SPDIF_REC_(",spdif")
+         HAVE_FMRADIO_REC_(",fmradio")[1]
+        ,UNUSED},
     INT_SETTING(0, rec_prerecord_time, LANG_RECORD_PRERECORD_TIME,
                 0, "prerecording time",
                 UNIT_SEC, 0, 30, 1, rectime_formatter, rectime_getlang, NULL),
diff --git a/firmware/export/audio.h b/firmware/export/audio.h
index ebcb316..a0da846 100644
--- a/firmware/export/audio.h
+++ b/firmware/export/audio.h
@@ -127,32 +127,37 @@
 #define CHN_CAP_ALL     (CHN_CAP_STEREO | CHN_CAP_MONO)
 #endif /* CONFIG_CODEC == SWCODEC */
 
-/* audio sources */
 enum audio_sources
 {
-    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) || 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 #if CONFIG_TUNER but is not in
-       the list of recordable sources. HAVE_FMRADIO_IN implies CONFIG_TUNER. */
-#if defined(HAVE_FMRADIO_IN) || (CONFIG_TUNER == 0)
-    AUDIO_NUM_SOURCES = AUDIO_SOURCE_LIST_END,
-#else
-    AUDIO_NUM_SOURCES = AUDIO_SOURCE_LIST_END-1,
-#endif
-    AUDIO_SRC_MAX = AUDIO_NUM_SOURCES-1
+    AUDIO_SRC_PLAYBACK = -1, /* Virtual source */
+    HAVE_MIC_IN_(AUDIO_SRC_MIC,)
+    HAVE_LINE_IN_(AUDIO_SRC_LINEIN,)
+    HAVE_SPDIF_IN_(AUDIO_SRC_SPDIF,)
+    HAVE_FMRADIO_IN_(AUDIO_SRC_FMRADIO,)
+    AUDIO_NUM_SOURCES,
+    AUDIO_SRC_MAX = AUDIO_NUM_SOURCES-1,
+    AUDIO_SRC_DEFAULT = AUDIO_SRC_PLAYBACK
 };
 
+#ifdef HAVE_RECORDING
+/* Recordable source implies it has the input as well */
+
+/* For now there's no restrictions on any targets with which inputs
+   are recordable so define them as equivalent - if they do differ,
+   special handling is needed right now. */
+enum rec_sources
+{
+    __REC_SRC_FIRST = -1,
+    HAVE_MIC_REC_(REC_SRC_MIC,)
+    HAVE_LINE_REC_(REC_SRC_LINEIN,)
+    HAVE_SPDIF_REC_(REC_SRC_SPDIF,)
+    HAVE_FMRADIO_REC_(REC_SRC_FMRADIO,)
+    REC_NUM_SOURCES
+};
+#endif /* HAVE_RECORDING */
+
 #if CONFIG_CODEC == SWCODEC
-/* selects an audio source for recording or playback */
+/* selects a source to monitor for recording or playback */
 #define SRCF_PLAYBACK         0x0000    /* default */
 #define SRCF_RECORDING        0x1000
 #if CONFIG_TUNER
diff --git a/firmware/export/config-e200.h b/firmware/export/config-e200.h
index d477289..edb73e8 100644
--- a/firmware/export/config-e200.h
+++ b/firmware/export/config-e200.h
@@ -9,6 +9,9 @@
 
 /* define this if you have recording possibility */
 /*#define HAVE_RECORDING*/ /* TODO: add support for this */
+/* Define bitmask of input sources - recordable bitmask can be defined
+   explicitly if different */
+/* #define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_FMRADIO) */
 
 /* define this if you have a bitmap LCD display */
 #define HAVE_LCD_BITMAP
diff --git a/firmware/export/config-fmrecorder.h b/firmware/export/config-fmrecorder.h
index 211dccb..479815e 100644
--- a/firmware/export/config-fmrecorder.h
+++ b/firmware/export/config-fmrecorder.h
@@ -1,6 +1,10 @@
 /* define this if you have recording possibility */
 #define HAVE_RECORDING
 
+/* Define bitmask of input sources - recordable bitmask can be defined
+   explicitly if different */
+#define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_LINEIN | SRC_CAP_SPDIF)
+
 /* define this if you have a bitmap LCD display */
 #define HAVE_LCD_BITMAP
 
@@ -48,9 +52,6 @@
 /* Define this if you have a MAS3587F */
 #define CONFIG_CODEC MAS3587F
 
-/* Define this for S/PDIF input available */
-#define HAVE_SPDIF_IN
-
 /* Define this for LCD backlight available */
 #define HAVE_BACKLIGHT
 
diff --git a/firmware/export/config-h10.h b/firmware/export/config-h10.h
index 4d37214..a5d32eb 100644
--- a/firmware/export/config-h10.h
+++ b/firmware/export/config-h10.h
@@ -10,6 +10,9 @@
 
 /* define this if you have recording possibility */
 #define HAVE_RECORDING
+/* Define bitmask of input sources - recordable bitmask can be defined
+   explicitly if different */
+#define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_LINEIN)
 
 /* define the bitmask of hardware sample rates */
 #define HW_SAMPR_CAPS   (SAMPR_CAP_44)
diff --git a/firmware/export/config-h100.h b/firmware/export/config-h100.h
index cc2bfd7..af51e81 100644
--- a/firmware/export/config-h100.h
+++ b/firmware/export/config-h100.h
@@ -156,8 +156,10 @@
 
 #endif /* !SIMULATOR */
 
-/* Define this for S/PDIF input available */
-#define HAVE_SPDIF_IN
+/* Define bitmask of input sources - recordable bitmask can be defined
+   explicitly if different */
+#define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_LINEIN | \
+                        SRC_CAP_FMRADIO | SRC_CAP_SPDIF)
 
 /* Define this for S/PDIF output available */
 #define HAVE_SPDIF_OUT
diff --git a/firmware/export/config-h10_5gb.h b/firmware/export/config-h10_5gb.h
index 3b3cebb..48d7317 100644
--- a/firmware/export/config-h10_5gb.h
+++ b/firmware/export/config-h10_5gb.h
@@ -10,6 +10,9 @@
 
 /* define this if you have recording possibility */
 #define HAVE_RECORDING
+/* Define bitmask of input sources - recordable bitmask can be defined
+   explicitly if different */
+#define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_LINEIN)
 
 /* define the bitmask of hardware sample rates */
 #define HW_SAMPR_CAPS   (SAMPR_CAP_44)
diff --git a/firmware/export/config-h120.h b/firmware/export/config-h120.h
index a0ad638..7e5a66a 100644
--- a/firmware/export/config-h120.h
+++ b/firmware/export/config-h120.h
@@ -75,6 +75,11 @@
 /* define this if you have recording possibility */
 #define HAVE_RECORDING
 
+/* Define bitmask of input sources - recordable bitmask can be defined
+   explicitly if different */
+#define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_LINEIN | \
+                        SRC_CAP_FMRADIO | SRC_CAP_SPDIF)
+
 /* define hardware samples rate caps mask */
 #define HW_SAMPR_CAPS   (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11)
 
@@ -150,18 +155,12 @@
 
 #endif /* !SIMULATOR */
 
-/* Define this for S/PDIF input available */
-#define HAVE_SPDIF_IN
-
 /* Define this for S/PDIF output available */
 #define HAVE_SPDIF_OUT
 
 /* Define this if you can control the S/PDIF power */
 #define HAVE_SPDIF_POWER
 
-/* Define this for FM radio input available */
-#define HAVE_FMRADIO_IN
-
 /* Define this if you have a serial port */
 /*#define HAVE_SERIAL*/
 
diff --git a/firmware/export/config-h300.h b/firmware/export/config-h300.h
index 0b2406b..43239e4 100644
--- a/firmware/export/config-h300.h
+++ b/firmware/export/config-h300.h
@@ -72,6 +72,10 @@
 /* define this if you have recording possibility */
 #define HAVE_RECORDING
 
+/* Define bitmask of input sources - recordable bitmask can be defined
+   explicitly if different */
+#define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_LINEIN | SRC_CAP_FMRADIO)
+
 /* define hardware samples rate caps mask */
 #define HW_SAMPR_CAPS   (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11)
 
diff --git a/firmware/export/config-iaudiom5.h b/firmware/export/config-iaudiom5.h
index bcc843f..d4e09dd 100644
--- a/firmware/export/config-iaudiom5.h
+++ b/firmware/export/config-iaudiom5.h
@@ -9,6 +9,10 @@
 /* define this if you have recording possibility */
 #define HAVE_RECORDING
 
+/* Define bitmask of input sources - recordable bitmask can be defined
+   explicitly if different */
+#define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_LINEIN)
+
 /* define the bitmask of hardware sample rates */
 #define HW_SAMPR_CAPS   (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11)
 
diff --git a/firmware/export/config-iaudiox5.h b/firmware/export/config-iaudiox5.h
index 43c02a0..fbcb69a 100644
--- a/firmware/export/config-iaudiox5.h
+++ b/firmware/export/config-iaudiox5.h
@@ -9,6 +9,10 @@
 /* define this if you have recording possibility */
 #define HAVE_RECORDING
 
+/* Define bitmask of input sources - recordable bitmask can be defined
+   explicitly if different */
+#define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_LINEIN | SRC_CAP_FMRADIO)
+
 /* define the bitmask of hardware sample rates */
 #define HW_SAMPR_CAPS   (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11)
 
diff --git a/firmware/export/config-ipod4g.h b/firmware/export/config-ipod4g.h
index 4a8d4f1..14a4e82 100644
--- a/firmware/export/config-ipod4g.h
+++ b/firmware/export/config-ipod4g.h
@@ -11,6 +11,10 @@
 /* define this if you have recording possibility */
 #define HAVE_RECORDING
 
+/* Define bitmask of input sources - recordable bitmask can be defined
+   explicitly if different */
+#define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_LINEIN)
+
 /* define the bitmask of hardware sample rates */
 #define HW_SAMPR_CAPS   (SAMPR_CAP_44)
 
diff --git a/firmware/export/config-ipodcolor.h b/firmware/export/config-ipodcolor.h
index 4127704..5e4e3b3 100644
--- a/firmware/export/config-ipodcolor.h
+++ b/firmware/export/config-ipodcolor.h
@@ -11,6 +11,10 @@
 /* define this if you have recording possibility */
 #define HAVE_RECORDING
 
+/* Define bitmask of input sources - recordable bitmask can be defined
+   explicitly if different */
+#define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_LINEIN)
+
 /* define the bitmask of hardware sample rates */
 #define HW_SAMPR_CAPS   (SAMPR_CAP_44)
 
diff --git a/firmware/export/config-ipodnano.h b/firmware/export/config-ipodnano.h
index 74bfe34..1d024d8 100644
--- a/firmware/export/config-ipodnano.h
+++ b/firmware/export/config-ipodnano.h
@@ -11,6 +11,10 @@
 /* define this if you have recording possibility */
 #define HAVE_RECORDING
 
+/* Define bitmask of input sources - recordable bitmask can be defined
+   explicitly if different */
+#define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_LINEIN)
+
 /* define the bitmask of hardware sample rates */
 #define HW_SAMPR_CAPS   (SAMPR_CAP_44)
 
diff --git a/firmware/export/config-ipodvideo.h b/firmware/export/config-ipodvideo.h
index b5318d7..b2b4ae9 100644
--- a/firmware/export/config-ipodvideo.h
+++ b/firmware/export/config-ipodvideo.h
@@ -11,6 +11,10 @@
 /* define this if you have recording possibility */
 #define HAVE_RECORDING
 
+/* Define bitmask of input sources - recordable bitmask can be defined
+   explicitly if different */
+#define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_LINEIN)
+
 /* define the bitmask of hardware sample rates */
 #define HW_SAMPR_CAPS   (SAMPR_CAP_44)
 
diff --git a/firmware/export/config-ondiofm.h b/firmware/export/config-ondiofm.h
index c168ecf..ea806a4 100644
--- a/firmware/export/config-ondiofm.h
+++ b/firmware/export/config-ondiofm.h
@@ -1,6 +1,10 @@
 /* define this if you have recording possibility */
 #define HAVE_RECORDING
 
+/* Define bitmask of input sources - recordable bitmask can be defined
+   explicitly if different */
+#define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_LINEIN)
+
 /* define this if you have a bitmap LCD display */
 #define HAVE_LCD_BITMAP
 
diff --git a/firmware/export/config-recorder.h b/firmware/export/config-recorder.h
index 3fe7365..29f187f 100644
--- a/firmware/export/config-recorder.h
+++ b/firmware/export/config-recorder.h
@@ -1,6 +1,10 @@
 /* define this if you have recording possibility */
 #define HAVE_RECORDING
 
+/* Define bitmask of input sources - recordable bitmask can be defined
+   explicitly if different */
+#define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_LINEIN | SRC_CAP_SPDIF)
+
 /* define this if you have a bitmap LCD display */
 #define HAVE_LCD_BITMAP
 
@@ -42,9 +46,6 @@
 /* Define this if you have a MAS3587F */
 #define CONFIG_CODEC MAS3587F
 
-/* Define this for S/PDIF input available */
-#define HAVE_SPDIF_IN
-
 /* Define this for LCD backlight available */
 #define HAVE_BACKLIGHT
 
diff --git a/firmware/export/config-recorderv2.h b/firmware/export/config-recorderv2.h
index 8211994..b534be5 100644
--- a/firmware/export/config-recorderv2.h
+++ b/firmware/export/config-recorderv2.h
@@ -1,6 +1,10 @@
 /* define this if you have recording possibility */
 #define HAVE_RECORDING
 
+/* Define bitmask of input sources - recordable bitmask can be defined
+   explicitly if different */
+#define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_LINEIN | SRC_CAP_SPDIF)
+
 /* define this if you have a bitmap LCD display */
 #define HAVE_LCD_BITMAP
 
@@ -45,9 +49,6 @@
 /* Define this if you have a MAS3587F */
 #define CONFIG_CODEC MAS3587F
 
-/* Define this for S/PDIF input available */
-#define HAVE_SPDIF_IN
-
 /* Define this for LCD backlight available */
 #define HAVE_BACKLIGHT
 
diff --git a/firmware/export/config.h b/firmware/export/config.h
index ceb63cd..0ad4fab 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -204,6 +204,9 @@
 /* no known platform */
 #endif
 
+/* setup basic macros from capability masks */
+#include "config_caps.h"
+
 /* now set any CONFIG_ defines correctly if they are not used,
    No need to do this on CONFIG_'s which are compulsary (e.g CONFIG_CODEC ) */
 #ifndef CONFIG_TUNER
diff --git a/firmware/export/config_caps.h b/firmware/export/config_caps.h
new file mode 100644
index 0000000..8e3832d
--- /dev/null
+++ b/firmware/export/config_caps.h
@@ -0,0 +1,107 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (C) 2007 by Michael Sevakis
+ *
+ * Convert caps masks into HAVE_* defines
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+/** INPUTS **/
+
+/* NOTE: Playback is implied in all this. Make sense? :) */
+#define SRC_MIC      0
+#define SRC_LINEIN   1
+#define SRC_SPDIF    2
+#define SRC_FMRADIO  3
+
+#define SRC_CAP_MIC     (1 << SRC_MIC)
+#define SRC_CAP_LINEIN  (1 << SRC_LINEIN)
+#define SRC_CAP_SPDIF   (1 << SRC_SPDIF)
+#define SRC_CAP_FMRADIO (1 << SRC_FMRADIO)
+
+/* audio monitor mux sources */
+#ifndef INPUT_SRC_CAPS
+#define INPUT_SRC_CAPS 0 /* Nothing but playback */
+#endif
+
+/* Microphone */
+#if (INPUT_SRC_CAPS & SRC_CAP_MIC)
+    #define HAVE_MIC_IN
+    #define HAVE_MIC_IN_(...) __VA_ARGS__
+#else
+    #define HAVE_MIC_IN_(...)
+#endif
+/* Line In */
+#if (INPUT_SRC_CAPS & SRC_CAP_LINEIN)
+    #define HAVE_LINE_IN
+    #define HAVE_LINE_IN_(...) __VA_ARGS__
+#else
+    #define HAVE_LINE_IN_(...)
+#endif
+/* S/PDIF */
+#if (INPUT_SRC_CAPS & SRC_CAP_SPDIF)
+    #define HAVE_SPDIF_IN
+    #define HAVE_SPDIF_IN_(...) __VA_ARGS__
+#else
+    #define HAVE_SPDIF_IN_(...)
+#endif
+/* FM Radio */
+#if (INPUT_SRC_CAPS & SRC_CAP_FMRADIO)
+    #define HAVE_FMRADIO_IN
+    #define HAVE_FMRADIO_IN_(...) __VA_ARGS__
+#else
+    #define HAVE_FMRADIO_IN_(...)
+#endif
+
+#ifdef HAVE_RECORDING
+/* Recordable source implies it has the input as well */
+
+/* For now there's no restrictions on any targets with which inputs
+   are recordable so define them as equivalent - if they do differ,
+   special handling is needed right now. */
+#ifndef REC_SRC_CAPS
+#define REC_SRC_CAPS INPUT_SRC_CAPS
+#endif
+
+/* Microphone */
+#if (REC_SRC_CAPS & SRC_CAP_MIC)
+    #define HAVE_MIC_REC
+    #define HAVE_MIC_REC_(...) __VA_ARGS__
+#else
+    #define HAVE_MIC_REC_(...)
+#endif
+/* Line In */
+#if (REC_SRC_CAPS & SRC_CAP_LINEIN)
+    #define HAVE_LINE_REC
+    #define HAVE_LINE_REC_(...) __VA_ARGS__
+#else
+    #define HAVE_LINE_REC_(...)
+#endif
+/* S/PDIF */
+#if (REC_SRC_CAPS & SRC_CAP_SPDIF)
+    #define HAVE_SPDIF_REC
+    #define HAVE_SPDIF_REC_(...) __VA_ARGS__
+#else
+    #define HAVE_SPDIF_REC_(...)
+#endif
+/* FM Radio */
+#if (REC_SRC_CAPS & SRC_CAP_FMRADIO)
+    #define HAVE_FMRADIO_REC
+    #define HAVE_FMRADIO_REC_(...) __VA_ARGS__
+#else
+    #define HAVE_FMRADIO_REC_(...)
+#endif
+#endif /* HAVE_RECORDING */
diff --git a/firmware/export/pcm_record.h b/firmware/export/pcm_record.h
index 8075b00..dcc473c 100644
--- a/firmware/export/pcm_record.h
+++ b/firmware/export/pcm_record.h
@@ -21,7 +21,7 @@
 #define PCM_RECORD_H
 
 #define DMA_REC_ERROR_DMA       (-1)
-#ifdef HAVE_SPDIF_IN
+#ifdef HAVE_SPDIF_REC
 #define DMA_REC_ERROR_SPDIF     (-2)
 #endif
 
diff --git a/firmware/target/arm/audio-pp.c b/firmware/target/arm/audio-pp.c
index 603bbad..82c5545 100644
--- a/firmware/target/arm/audio-pp.c
+++ b/firmware/target/arm/audio-pp.c
@@ -40,7 +40,6 @@
     {
         default:                        /* playback - no recording */
             source = AUDIO_SRC_PLAYBACK;
-#ifdef HAVE_RECORDING
         case AUDIO_SRC_PLAYBACK:
             if (source != last_source)
             {
@@ -48,6 +47,7 @@
                 audiohw_set_monitor(false);
             }
         break;
+#ifdef HAVE_MIC_REC
         case AUDIO_SRC_MIC:             /* recording only */
             if (source != last_source)
             {
@@ -55,7 +55,8 @@
                 audiohw_set_monitor(false);
             }
         break;
-
+#endif
+#ifdef HAVE_LINEIN_REC
         case AUDIO_SRC_LINEIN:          /* recording only */
             if (source != last_source)
             {
@@ -64,7 +65,7 @@
             }
         break;
 #endif
-#if CONFIG_TUNER
+#ifdef HAVE_FMRADIO_REC
         case AUDIO_SRC_FMRADIO:         /* recording and playback */
             if (!recording)
                 audiohw_set_recvol(0, 0, AUDIO_GAIN_LINEIN);
diff --git a/firmware/target/arm/system-pp502x.c b/firmware/target/arm/system-pp502x.c
index 1f2d27a..0148f3d 100644
--- a/firmware/target/arm/system-pp502x.c
+++ b/firmware/target/arm/system-pp502x.c
@@ -62,6 +62,11 @@
 void irq(void)
 {
     if(CURRENT_CORE == CPU) {
+        if (CPU_HI_INT_STAT)
+        {
+            gui_syncsplash(0, "%08X %08X", inl(0x6000414c), CPU_HI_INT_STAT);
+        }
+
         if (CPU_INT_STAT & TIMER1_MASK) {
 #ifdef SANSA_E200
             if (GPIOF_INT_STAT & 0xff)
@@ -239,6 +244,11 @@
         CPU_INT_CLR         = -1;
         INT_FORCED_CLR      = -1;
 
+        outl(0, 0x6000414c);
+        outl(0, 0x60004144);
+
+//        outl(0x80000, 0x6000414c);
+
         GPIOA_INT_EN        = 0;
         GPIOB_INT_EN        = 0;
         GPIOC_INT_EN        = 0;
diff --git a/firmware/target/coldfire/pcm-coldfire.c b/firmware/target/coldfire/pcm-coldfire.c
index b52e5e0..dc40dac 100644
--- a/firmware/target/coldfire/pcm-coldfire.c
+++ b/firmware/target/coldfire/pcm-coldfire.c
@@ -22,7 +22,7 @@
 #include "logf.h"
 #include "audio.h"
 #include "sound.h"
-#if defined(HAVE_SPDIF_IN) || defined(HAVE_SPDIF_OUT)
+#if defined(HAVE_SPDIF_REC) || defined(HAVE_SPDIF_OUT)
 #include "spdif.h"
 #endif
 
@@ -276,7 +276,7 @@
     audiohw_set_frequency(freq_ent[FPARM_FSEL]);
     coldfire_set_pllcr_audio_bits(PLLCR_SET_AUDIO_BITS_DEFPARM);
 
-#if defined(HAVE_SPDIF_IN) || defined(HAVE_SPDIF_OUT)
+#if defined(HAVE_SPDIF_REC) || defined(HAVE_SPDIF_OUT)
     spdif_init();
 #endif
     /* Enable interrupt at level 6, priority 0 */
@@ -365,7 +365,7 @@
     _pcm_apply_settings(!is_playback_monitoring());
 
     /* Start the DMA transfer.. */
-#ifdef HAVE_SPDIF_IN
+#ifdef HAVE_SPDIF_REC
     /* clear: ebu1cnew, valnogood, symbolerr, parityerr */
     INTERRUPTCLEAR = (1 << 25) | (1 << 24) | (1 << 23) | (1 << 22);
 #endif
@@ -462,7 +462,7 @@
         logf("  DCR1: %08x", DCR1);
 #endif
     }
-#ifdef HAVE_SPDIF_IN
+#ifdef HAVE_SPDIF_REC
     else if (DATAINCONTROL == 0xc038 &&
         (INTERRUPTSTAT & ((1 << 24) | (1 << 23) | (1 << 22))))
     {