diff --git a/include/cdio/audio.h b/include/cdio/audio.h index 4bf7d636..0d9249ca 100644 --- a/include/cdio/audio.h +++ b/include/cdio/audio.h @@ -1,5 +1,5 @@ /* -*- c -*- - $Id: audio.h,v 1.2 2005/03/01 10:53:15 rocky Exp $ + $Id: audio.h,v 1.3 2005/03/02 04:23:59 rocky Exp $ Copyright (C) 2005 Rocky Bernstein @@ -49,10 +49,7 @@ extern "C" { /*! This struct is used by cdio_audio_get_volume and cdio_audio_set_volume */ typedef struct cdio_audio_volume_s { - uint8_t channel0; - uint8_t channel1; - uint8_t channel2; - uint8_t channel3; + uint8_t level[4]; } cdio_audio_volume_t; diff --git a/include/cdio/mmc.h b/include/cdio/mmc.h index 668d45fc..e774da71 100644 --- a/include/cdio/mmc.h +++ b/include/cdio/mmc.h @@ -1,5 +1,5 @@ /* - $Id: mmc.h,v 1.15 2005/03/01 10:53:15 rocky Exp $ + $Id: mmc.h,v 1.16 2005/03/02 04:24:00 rocky Exp $ Copyright (C) 2003, 2004, 2005 Rocky Bernstein @@ -180,14 +180,34 @@ typedef enum { /*! Page codes for MODE SENSE and MODE SET. */ #define CDIO_MMC_R_W_ERROR_PAGE 0x01 #define CDIO_MMC_WRITE_PARMS_PAGE 0x05 -#define CDIO_MMC_AUDIO_CTL_PAGE 0x0e #define CDIO_MMC_CDR_PARMS_PAGE 0x0d +#define CDIO_MMC_AUDIO_CTL_PAGE 0x0e #define CDIO_MMC_POWER_PAGE 0x1a #define CDIO_MMC_FAULT_FAIL_PAGE 0x1c #define CDIO_MMC_TO_PROTECT_PAGE 0x1d #define CDIO_MMC_CAPABILITIES_PAGE 0x2a #define CDIO_MMC_ALL_PAGES 0x3f +PRAGMA_BEGIN_PACKED + struct mmc_audio_volume_entry_s + { + uint8_t selection; /* Only the lower 4 bits are used. */ + uint8_t volume; + } GNUC_PACKED; + + typedef struct mmc_audio_volume_entry_s mmc_audio_volume_entry_t; + + /*! This struct is used by cdio_audio_get_volume and cdio_audio_set_volume */ + struct mmc_audio_volume_s + { + mmc_audio_volume_entry_t port[4]; + } GNUC_PACKED; + + typedef struct mmc_audio_volume_s mmc_audio_volume_t; + +PRAGMA_END_PACKED + + /*! Return type codes for GET_CONFIGURATION. */ #define CDIO_MMC_GET_CONF_ALL_FEATURES 0 /**< all features without regard to currency. */ @@ -501,6 +521,13 @@ int mmc_get_media_changed(const CdIo_t *p_cdio); */ char * mmc_get_mcn ( const CdIo_t *p_cdio ); +/** Get the output port volumes and port selections used on AUDIO PLAY + commands via a MMC MODE SENSE command using the CD Audio Control + Page. + */ +driver_return_code_t mmc_audio_get_volume (CdIo_t *p_cdio, /*out*/ + mmc_audio_volume_t *p_volume); + /*! Report if CD-ROM has a praticular kind of interface (ATAPI, SCSCI, ...) Is it possible for an interface to have serveral? If not this diff --git a/lib/driver/_cdio_linux.c b/lib/driver/_cdio_linux.c index b5223024..be7900d1 100644 --- a/lib/driver/_cdio_linux.c +++ b/lib/driver/_cdio_linux.c @@ -1,5 +1,5 @@ /* - $Id: _cdio_linux.c,v 1.34 2005/03/01 11:00:49 rocky Exp $ + $Id: _cdio_linux.c,v 1.35 2005/03/02 04:24:00 rocky Exp $ Copyright (C) 2001 Herbert Valerio Riedel Copyright (C) 2002, 2003, 2004, 2005 Rocky Bernstein @@ -27,7 +27,7 @@ # include "config.h" #endif -static const char _rcsid[] = "$Id: _cdio_linux.c,v 1.34 2005/03/01 11:00:49 rocky Exp $"; +static const char _rcsid[] = "$Id: _cdio_linux.c,v 1.35 2005/03/02 04:24:00 rocky Exp $"; #include @@ -194,6 +194,20 @@ check_mounts_linux(const char *mtab) return NULL; } +/*! + Get the volume of an audio CD. + + @param p_cdio the CD object to be acted upon. +*/ +static driver_return_code_t +audio_get_volume_linux (void *p_user_data, + /*out*/ cdio_audio_volume_t *p_volume) +{ + + const _img_private_t *p_env = p_user_data; + return ioctl(p_env->gen.fd, CDROMVOLREAD, p_volume); +} + /*! Pause playing CD through analog output @@ -265,7 +279,7 @@ audio_resume_linux (void *p_user_data) } /*! - Resume playing an audio CD. + Set the volume of an audio CD. @param p_cdio the CD object to be acted upon. @@ -1268,7 +1282,7 @@ cdio_open_am_linux (const char *psz_orig_source, const char *access_mode) char *psz_source; cdio_funcs_t _funcs = { - // .audio_get_volume = audio_get_volume_linux, + .audio_get_volume = audio_get_volume_linux, .audio_pause = audio_pause_linux, .audio_play_msf = audio_play_msf_linux, .audio_play_track_index= audio_play_track_index_linux, diff --git a/lib/driver/mmc.c b/lib/driver/mmc.c index f98c7b3d..1ecef173 100644 --- a/lib/driver/mmc.c +++ b/lib/driver/mmc.c @@ -1,6 +1,6 @@ /* Common Multimedia Command (MMC) routines. - $Id: mmc.c,v 1.18 2005/03/01 10:53:15 rocky Exp $ + $Id: mmc.c,v 1.19 2005/03/02 04:24:00 rocky Exp $ Copyright (C) 2004, 2005 Rocky Bernstein @@ -154,6 +154,30 @@ set_speed_mmc (void *p_user_data, int i_speed) return mmc_set_speed( p_env->cdio, i_speed ); } +/** Get the output port volumes and port selections used on AUDIO PLAY + commands via a MMC MODE SENSE command using the CD Audio Control + Page. + */ +driver_return_code_t +mmc_audio_get_volume( CdIo_t *p_cdio, /*out*/ mmc_audio_volume_t *p_volume ) +{ + uint8_t buf[16]; + int i_rc = mmc_mode_sense(p_cdio, buf, sizeof(buf), CDIO_MMC_AUDIO_CTL_PAGE); + + if ( DRIVER_OP_SUCCESS == i_rc ) { + p_volume->port[0].selection = 0xF & buf[8]; + p_volume->port[0].volume = buf[9]; + p_volume->port[1].selection = 0xF & buf[10]; + p_volume->port[1].volume = buf[11]; + p_volume->port[2].selection = 0xF & buf[12]; + p_volume->port[2].volume = buf[13]; + p_volume->port[3].selection = 0xF & buf[14]; + p_volume->port[3].volume = buf[15]; + return DRIVER_OP_SUCCESS; + } + return i_rc; +} + /*! On input a MODE_SENSE command was issued and we have the results in p. We interpret this and return a bit mask set according to the diff --git a/src/cd-info.c b/src/cd-info.c index 74042778..81da3ba0 100644 --- a/src/cd-info.c +++ b/src/cd-info.c @@ -1,5 +1,5 @@ /* - $Id: cd-info.c,v 1.125 2005/03/01 11:29:52 rocky Exp $ + $Id: cd-info.c,v 1.126 2005/03/02 04:24:00 rocky Exp $ Copyright (C) 2003, 2004, 2005 Rocky Bernstein Copyright (C) 1996, 1997, 1998 Gerd Knorr @@ -949,7 +949,7 @@ main(int argc, const char *argv[]) CdIo_t *p_cdio = cdio_open(source_name, driver_id); cdio_hwinfo_t hwinfo; printf("Drive %s\n", *d); - if (scsi_mmc_get_hwinfo(p_cdio, &hwinfo)) { + if (mmc_get_hwinfo(p_cdio, &hwinfo)) { printf("%-8s: %s\n%-8s: %s\n%-8s: %s\n", "Vendor" , hwinfo.psz_vendor, "Model" , hwinfo.psz_model, @@ -1162,32 +1162,54 @@ main(int argc, const char *argv[]) report( stdout, "audio status: "); fflush(stdout); if (DRIVER_OP_SUCCESS == rc) { + bool b_volume = false; + bool b_position = false; switch (subchannel.audio_status) { case CDIO_MMC_READ_SUB_ST_INVALID: report( stdout, "invalid\n" ); break; case CDIO_MMC_READ_SUB_ST_PLAY: b_playing_audio = true; + b_position = true; + b_volume = true; report( stdout, "playing" ); break; case CDIO_MMC_READ_SUB_ST_PAUSED: + b_position = true; + b_volume = true; report( stdout, "paused" ); break; case CDIO_MMC_READ_SUB_ST_COMPLETED: report( stdout, "completed\n"); break; case CDIO_MMC_READ_SUB_ST_ERROR: report( stdout, "error\n" ); break; case CDIO_MMC_READ_SUB_ST_NO_STATUS: + b_volume = true; report( stdout, "no status\n" ); break; default: report( stdout, "Oops: unknown\n" ); } - if (subchannel.audio_status == CDIO_MMC_READ_SUB_ST_PLAY || - subchannel.audio_status == CDIO_MMC_READ_SUB_ST_PAUSED) { + + if (b_position) report( stdout, " at: %02d:%02d abs / %02d:%02d track %d\n", subchannel.abs_addr.msf.m, subchannel.abs_addr.msf.s, subchannel.rel_addr.msf.m, subchannel.rel_addr.msf.s, subchannel.track ); + + if (b_volume) { + cdio_audio_volume_t volume; + + if (DRIVER_OP_SUCCESS == cdio_audio_get_volume (p_cdio, &volume)) { + uint8_t i=0; + for (i=0; i<4; i++) { + uint8_t i_level = volume.level[i]; + report( stdout, + "volume level port %d: %3d (0..255) %3d (0..100)\n", + i, i_level, (i_level*100+128) / 256 ); + } + + } else + report( stdout, " can't get volume levels\n" ); } } else if (DRIVER_OP_UNSUPPORTED == rc) { report( stdout, "not implemented\n" );