cdaudio.cpp
来自「FreeAMP(MP3播放)程序源代码-用来研究MP3解码」· C++ 代码 · 共 745 行 · 第 1/2 页
CPP
745 行
{
struct disc_timeval time;
time.minutes = startpos / 60;
time.seconds = startpos % 60;
time.frames = 0;
return cd_playctl(cd_desc, PLAY_END_TRACK | PLAY_START_POSITION, starttrack, endtrack, &time);
}
/* Play starttrack to endtrack */
int
cd_play_track(int cd_desc, int starttrack, int endtrack)
{
return cd_playctl(cd_desc, PLAY_END_TRACK, starttrack, endtrack);
}
/* Play starttrack at position pos to end of CD */
int
cd_play_pos(int cd_desc, int track, int startpos)
{
struct disc_timeval time;
time.minutes = startpos / 60;
time.seconds = startpos * 60;
time.frames = 0;
return cd_playctl(cd_desc, PLAY_START_POSITION, track, &time);
}
/* Play starttrack to end of CD */
int
cd_play(int cd_desc, int track)
{
return cd_playctl(cd_desc, PLAY_START_TRACK, track);
}
/* Stop the CD, if it is playing */
int
cd_stop(int cd_desc)
{
if(ioctl(cd_desc, CDAUDIO_STOP) < 0)
return -1;
return 0;
}
/* Pause the CD */
int
cd_pause(int cd_desc)
{
if(ioctl(cd_desc, CDAUDIO_PAUSE) < 0)
return -1;
return 0;
}
/* Resume playing */
int
cd_resume(int cd_desc)
{
if(ioctl(cd_desc, CDAUDIO_RESUME) < 0)
return -1;
return 0;
}
/* Eject the tray */
int
cd_eject(int cd_desc)
{
if(ioctl(cd_desc, CDAUDIO_EJECT) < 0)
return -1;
return 0;
}
/* Close the tray */
int
cd_close(int cd_desc)
{
#ifdef CDAUDIO_CLOSE
if(ioctl(cd_desc, CDAUDIO_CLOSE) < 0)
return -1;
return 0;
#else
errno = ENOTTY;
return -1;
#endif
}
/* Return the current volume setting */
int
cd_get_volume(int cd_desc, struct disc_volume *vol)
{
#ifdef CDAUDIO_GET_VOLUME
struct CDAUDIO_VOLSTAT cdvol;
#ifdef CDAUDIO_VOLSTAT_DATA
struct CDAUDIO_VOLSTAT_DATA cdvol_data;
cdvol.CDVOLSTAT_DATA = &cdvol_data;
cdvol.CDVOLSTAT_DATA_LEN = sizeof(cdvol_data);
#endif
if(ioctl(cd_desc, CDAUDIO_GET_VOLUME, &cdvol) < 0)
return -1;
vol->vol_front.left = cdvol.CDVOLSTAT_FRONT_LEFT;
vol->vol_front.right = cdvol.CDVOLSTAT_FRONT_RIGHT;
vol->vol_back.left = cdvol.CDVOLSTAT_BACK_LEFT;
vol->vol_back.right = cdvol.CDVOLSTAT_BACK_RIGHT;
#ifdef CDAUDIO_VOLSTAT_DATA
vol->vol_front.left = cdvol_data.CDVOLSTAT_FRONT_LEFT;
vol->vol_front.right = cdvol_data.CDVOLSTAT_FRONT_RIGHT;
vol->vol_back.left = cdvol_data.CDVOLSTAT_BACK_LEFT;
vol->vol_back.right = cdvol_data.CDVOLSTAT_BACK_RIGHT;
#endif
return 0;
#else
errno = ENOTTY;
return -1;
#endif
}
/* Set the volume */
int
cd_set_volume(int cd_desc, struct disc_volume vol)
{
struct CDAUDIO_VOLCTRL cdvol;
#ifdef CDAUDIO_VOLCTRL_DATA
struct cd_playback cdvol_data;
cdvol.CDVOLCTRL_DATA = &cdvol_data;
cdvol.CDVOLCTRL_DATA_LEN = sizeof(cdvol_data);
#endif
if(vol.vol_front.left > 255 || vol.vol_front.left < 0 || vol.vol_front.right > 255 || vol.vol_front.right < 0 || vol.vol_back.left > 255 || vol.vol_back.left < 0 || vol.vol_back.right > 255 || vol.vol_back.right < 0)
return -1;
cdvol.CDVOLCTRL_FRONT_LEFT = vol.vol_front.left;
cdvol.CDVOLCTRL_FRONT_RIGHT = vol.vol_front.right;
cdvol.CDVOLCTRL_BACK_LEFT = vol.vol_back.left;
cdvol.CDVOLCTRL_BACK_RIGHT = vol.vol_back.right;
#ifdef CDAUDIO_VOLCTRL_SELECT
cdvol_data.CDVOLCTRL_FRONT_LEFT_SELECT = CDAUDIO_MAX_VOLUME;
cdvol_data.CDVOLCTRL_FRONT_RIGHT_SELECT = CDAUDIO_MAX_VOLUME;
cdvol_data.CDVOLCTRL_BACK_LEFT_SELECT = CDAUDIO_MAX_VOLUME;
cdvol_data.CDVOLCTRL_BACK_RIGHT_SELECT = CDAUDIO_MAX_VOLUME;
#endif
if(ioctl(cd_desc, CDAUDIO_SET_VOLUME, &cdvol) < 0)
return -1;
return 0;
}
#endif /* IRIX_CDAUDIO */
/*
Because all these functions are solely mathematical and/or only make callbacks
to previously existing functions they can be used for any platform.
*/
/* Convert frames to a logical block address */
int
cd_frames_to_lba(int frames)
{
if(frames >= 150)
return frames - 150;
return 0;
}
/* Convert a logical block address to frames */
int
cd_lba_to_frames(int lba)
{
return lba + 150;
}
/* Convert disc_timeval to frames */
int
cd_msf_to_frames(struct disc_timeval time)
{
return time.minutes * 4500 + time.seconds * 75 + time.frames;
}
/* Convert disc_timeval to a logical block address */
int
cd_msf_to_lba(struct disc_timeval time)
{
if(cd_msf_to_frames(time) > 150)
return cd_msf_to_frames(time) - 150;
return 0;
}
/* Convert frames to disc_timeval */
void
cd_frames_to_msf(struct disc_timeval *time, int frames)
{
time->minutes = frames / 4500;
time->seconds = (frames % 4500) / 75;
time->frames = frames % 75;
}
/* Convert a logical block address to disc_timeval */
void
cd_lba_to_msf(struct disc_timeval *time, int lba)
{
cd_frames_to_msf(time, lba + 150);
}
/* Internal advance function */
int
__internal_cd_track_advance(int cd_desc, struct disc_info disc, int endtrack, struct disc_timeval time)
{
disc.disc_track_time.minutes += time.minutes;
disc.disc_track_time.seconds += time.seconds;
disc.disc_track_time.frames += time.frames;
if(disc.disc_track_time.frames > 74) {
disc.disc_track_time.frames -= 74;
disc.disc_track_time.seconds++;
}
if(disc.disc_track_time.frames < 0) {
disc.disc_track_time.frames += 75;
disc.disc_track_time.seconds--;
}
if(disc.disc_track_time.seconds > 59) {
disc.disc_track_time.seconds -= 59;
disc.disc_track_time.minutes++;
}
if(disc.disc_track_time.seconds < 0) {
disc.disc_track_time.seconds += 60;
disc.disc_track_time.minutes--;
}
if(disc.disc_track_time.minutes < 0) {
disc.disc_current_track--;
if(disc.disc_current_track == 0)
disc.disc_current_track = 1;
return cd_play_track(cd_desc, disc.disc_current_track, endtrack);
}
if((disc.disc_track_time.minutes == disc.disc_track[disc.disc_current_track].track_pos.minutes && disc.disc_track_time.seconds > disc.disc_track[disc.disc_current_track].track_pos.seconds) || disc.disc_track_time.minutes > disc.disc_track[disc.disc_current_track].track_pos.minutes) {
disc.disc_current_track++;
if(disc.disc_current_track > endtrack)
disc.disc_current_track = endtrack;
return cd_play_track(cd_desc, disc.disc_current_track, endtrack);
}
return cd_play_track_pos(cd_desc, disc.disc_current_track, endtrack, disc.disc_track_time.minutes * 60 + disc.disc_track_time.seconds);
}
/* Advance the position within a track */
int
cd_track_advance(int cd_desc, int endtrack, struct disc_timeval time)
{
struct disc_info disc;
if(cd_stat(cd_desc, &disc) < 0)
return -1;
if(!disc.disc_present)
return -1;
if(__internal_cd_track_advance(cd_desc, disc, endtrack, time) < 0)
return -1;
return 0;
}
/* Advance the position within the track without preserving an endtrack */
int
cd_advance(int cd_desc, struct disc_timeval time)
{
struct disc_info disc;
if(cd_stat(cd_desc, &disc) < 0)
return -1;
if(__internal_cd_track_advance(cd_desc, disc, disc.disc_total_tracks, time) < 0)
return -1;
return 0;
}
/* Update information in a disc_info structure using a disc_status structure */
int
cd_update(struct disc_info *disc, struct disc_status status)
{
if(!(disc->disc_present = status.status_present))
return -1;
disc->disc_mode = status.status_mode;
memcpy(&disc->disc_time, &status.status_disc_time, sizeof(struct disc_timeval));
memcpy(&disc->disc_track_time, &status.status_track_time, sizeof(struct disc_timeval));
disc->disc_current_track = 0;
while(disc->disc_current_track < disc->disc_total_tracks &&
cd_msf_to_frames(disc->disc_time) >= cd_msf_to_frames(disc->disc_track[disc->disc_current_track].track_pos) )
disc->disc_current_track++;
return 0;
}
/* Universal play control function */
int
cd_playctl(int cd_desc, int options, int start_track, ...)
{
int end_track;
struct disc_info disc;
struct disc_timeval *startpos, *endpos, start_position, end_position;
va_list arglist;
va_start(arglist, start_track);
if(cd_stat(cd_desc, &disc) < 0)
return -1;
if(options & PLAY_END_TRACK)
end_track = va_arg(arglist, int);
else
end_track = disc.disc_total_tracks;
if(options & PLAY_START_POSITION)
startpos = va_arg(arglist, struct disc_timeval *);
else
startpos = 0;
if(options & PLAY_END_POSITION)
endpos = va_arg(arglist, struct disc_timeval *);
else
endpos = 0;
va_end(arglist);
if(options & PLAY_START_POSITION) {
start_position.minutes = disc.disc_track[start_track - 1].track_pos.minutes + startpos->minutes;
start_position.seconds = disc.disc_track[start_track - 1].track_pos.seconds + startpos->seconds;
start_position.frames = disc.disc_track[start_track - 1].track_pos.frames + startpos->frames;
} else {
start_position.minutes = disc.disc_track[start_track - 1].track_pos.minutes;
start_position.seconds = disc.disc_track[start_track - 1].track_pos.seconds;
start_position.frames = disc.disc_track[start_track - 1].track_pos.frames;
}
if(options & PLAY_END_TRACK) {
if(options & PLAY_END_POSITION) {
end_position.minutes = disc.disc_track[end_track].track_pos.minutes + endpos->minutes;
end_position.seconds = disc.disc_track[end_track].track_pos.seconds + endpos->seconds;
end_position.frames = disc.disc_track[end_track].track_pos.frames + endpos->frames;
} else {
end_position.minutes = disc.disc_track[end_track].track_pos.minutes;
end_position.seconds = disc.disc_track[end_track].track_pos.seconds;
end_position.frames = disc.disc_track[end_track].track_pos.frames;
}
} else {
end_position.minutes = disc.disc_track[disc.disc_total_tracks].track_pos.minutes;
end_position.seconds = disc.disc_track[disc.disc_total_tracks].track_pos.seconds;
end_position.frames = disc.disc_track[disc.disc_total_tracks].track_pos.frames;
}
return cd_play_frames(cd_desc, cd_msf_to_frames(start_position), cd_msf_to_frames(end_position));
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?