I guess I forgot to add these to the repository last time. Oops. :D
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13374 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
b7a96f02fd
commit
8cc39dac67
451
src/apps/cdplayer/CDAudioDevice.cpp
Normal file
451
src/apps/cdplayer/CDAudioDevice.cpp
Normal file
@ -0,0 +1,451 @@
|
||||
#include "CDAudioDevice.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <String.h>
|
||||
#include <string.h>
|
||||
#include <Debug.h>
|
||||
#include <Directory.h>
|
||||
#include <Entry.h>
|
||||
#include <Path.h>
|
||||
#include <errno.h>
|
||||
#include "scsi.h"
|
||||
|
||||
|
||||
CDAudioDevice::CDAudioDevice(void)
|
||||
{
|
||||
FindDrives("/dev/disk");
|
||||
SetDrive(0);
|
||||
}
|
||||
|
||||
CDAudioDevice::~CDAudioDevice(void)
|
||||
{
|
||||
for(int32 i=0; i<fDriveList.CountItems(); i++)
|
||||
delete (BString*) fDriveList.ItemAt(i);
|
||||
}
|
||||
|
||||
|
||||
// This plays only one track - the track specified
|
||||
bool
|
||||
CDAudioDevice::Play(const int16 &track)
|
||||
{
|
||||
if(GetState() == kNoCD)
|
||||
{
|
||||
// no CD available, bail out
|
||||
ioctl(fFileHandle, B_LOAD_MEDIA, 0, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
scsi_play_track playtrack;
|
||||
|
||||
playtrack.start_track = track;
|
||||
playtrack.start_index = 1;
|
||||
playtrack.end_track = track;
|
||||
playtrack.end_index = 1;
|
||||
|
||||
status_t result = ioctl(fFileHandle, B_SCSI_PLAY_TRACK, &playtrack);
|
||||
if (result != B_OK)
|
||||
{
|
||||
printf("Couldn't play track: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CDAudioDevice::Pause(void)
|
||||
{
|
||||
status_t result = ioctl(fFileHandle, B_SCSI_PAUSE_AUDIO);
|
||||
if (result != B_OK)
|
||||
{
|
||||
printf("Couldn't pause track: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CDAudioDevice::Resume(void)
|
||||
{
|
||||
CDState state = GetState();
|
||||
if(state == kNoCD)
|
||||
{
|
||||
// no CD available, bail out
|
||||
ioctl(fFileHandle, B_LOAD_MEDIA, 0, 0);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
if(state == kStopped)
|
||||
return Play(0);
|
||||
|
||||
status_t result = ioctl(fFileHandle, B_SCSI_RESUME_AUDIO);
|
||||
if (result != B_OK)
|
||||
{
|
||||
printf("Couldn't resume track: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CDAudioDevice::Stop(void)
|
||||
{
|
||||
status_t result = ioctl(fFileHandle, B_SCSI_STOP_AUDIO);
|
||||
if (result != B_OK)
|
||||
{
|
||||
printf("Couldn't stop CD: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// open or close the CD tray
|
||||
bool
|
||||
CDAudioDevice::Eject(void)
|
||||
{
|
||||
status_t media_status = B_DEV_NO_MEDIA;
|
||||
|
||||
// get the status first
|
||||
ioctl(fFileHandle, B_GET_MEDIA_STATUS, &media_status, sizeof(media_status));
|
||||
|
||||
// if door open, load the media, else eject the CD
|
||||
status_t result = ioctl(fFileHandle,
|
||||
media_status == B_DEV_DOOR_OPEN ?
|
||||
B_LOAD_MEDIA : B_EJECT_DEVICE);
|
||||
|
||||
if (result != B_OK)
|
||||
{
|
||||
printf("Couldn't eject CD: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CDAudioDevice::StartFastFwd(void)
|
||||
{
|
||||
scsi_scan scan;
|
||||
scan.direction = 1;
|
||||
scan.speed = 1;
|
||||
status_t result = ioctl(fFileHandle, B_SCSI_SCAN, &scan);
|
||||
if (result != B_OK)
|
||||
{
|
||||
printf("Couldn't fast forward: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CDAudioDevice::StopFastFwd(void)
|
||||
{
|
||||
scsi_scan scan;
|
||||
scan.direction = 0;
|
||||
scan.speed = 1;
|
||||
status_t result = ioctl(fFileHandle, B_SCSI_SCAN, &scan);
|
||||
if (result != B_OK)
|
||||
{
|
||||
printf("Couldn't stop fast forwarding: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CDAudioDevice::StartRewind(void)
|
||||
{
|
||||
scsi_scan scan;
|
||||
scan.direction = -1;
|
||||
scan.speed = 1;
|
||||
status_t result = ioctl(fFileHandle, B_SCSI_SCAN, &scan);
|
||||
if (result != B_OK)
|
||||
{
|
||||
printf("Couldn't rewind: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CDAudioDevice::StopRewind(void)
|
||||
{
|
||||
scsi_scan scan;
|
||||
scan.direction = 0;
|
||||
scan.speed = 1;
|
||||
status_t result = ioctl(fFileHandle, B_SCSI_SCAN, &scan);
|
||||
if (result != B_OK)
|
||||
{
|
||||
printf("Couldn't stop rewinding: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CDAudioDevice::SetVolume(uint8 value)
|
||||
{
|
||||
scsi_volume vol;
|
||||
|
||||
// change only port0's volume
|
||||
vol.flags=2;
|
||||
vol.port0_volume=value;
|
||||
|
||||
status_t result = ioctl(fFileHandle,B_SCSI_SET_VOLUME,&vol);
|
||||
if (result != B_OK)
|
||||
{
|
||||
printf("Couldn't set volume: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8
|
||||
CDAudioDevice::GetVolume(void)
|
||||
{
|
||||
scsi_volume vol;
|
||||
ioctl(fFileHandle, B_SCSI_GET_VOLUME, &vol);
|
||||
return vol.port0_volume;
|
||||
}
|
||||
|
||||
// check the current CD play state
|
||||
CDState
|
||||
CDAudioDevice::GetState(void)
|
||||
{
|
||||
scsi_position pos;
|
||||
status_t media_status = B_DEV_NO_MEDIA;
|
||||
|
||||
ioctl(fFileHandle, B_GET_MEDIA_STATUS, &media_status, sizeof(media_status));
|
||||
if (media_status != B_OK)
|
||||
return kNoCD;
|
||||
|
||||
status_t result = ioctl(fFileHandle, B_SCSI_GET_POSITION, &pos);
|
||||
if (result != B_OK)
|
||||
return kNoCD;
|
||||
else
|
||||
if ((!pos.position[1]) || (pos.position[1] >= 0x13) ||
|
||||
((pos.position[1] == 0x12) && (!pos.position[6])))
|
||||
return kStopped;
|
||||
else
|
||||
if (pos.position[1] == 0x11)
|
||||
return kPlaying;
|
||||
else
|
||||
return kPaused;
|
||||
}
|
||||
|
||||
int16
|
||||
CDAudioDevice::CountTracks(void)
|
||||
{
|
||||
scsi_toc toc;
|
||||
status_t result = ioctl(fFileHandle, B_SCSI_GET_TOC, &toc);
|
||||
|
||||
if (result != B_OK)
|
||||
return -1;
|
||||
|
||||
return toc.toc_data[3];
|
||||
}
|
||||
|
||||
// Get the 0-based index of the current track
|
||||
int16
|
||||
CDAudioDevice::GetTrack(void)
|
||||
{
|
||||
scsi_position pos;
|
||||
|
||||
status_t media_status = B_DEV_NO_MEDIA;
|
||||
|
||||
ioctl(fFileHandle, B_GET_MEDIA_STATUS, &media_status, sizeof(media_status));
|
||||
if (media_status != B_OK)
|
||||
return -1;
|
||||
|
||||
status_t result = ioctl(fFileHandle, B_SCSI_GET_POSITION, &pos);
|
||||
if (result != B_OK)
|
||||
return -1;
|
||||
|
||||
if (!pos.position[1] || pos.position[1] >= 0x13
|
||||
|| (pos.position[1] == 0x12 && !pos.position[6]))
|
||||
return 0;
|
||||
else
|
||||
return pos.position[6];
|
||||
}
|
||||
|
||||
uint8
|
||||
CDAudioDevice::CountDrives(void)
|
||||
{
|
||||
return fDriveList.CountItems();
|
||||
}
|
||||
|
||||
bool
|
||||
CDAudioDevice::SetDrive(const int32 &drive)
|
||||
{
|
||||
BString *path = (BString*) fDriveList.ItemAt(drive);
|
||||
|
||||
if(!path)
|
||||
return false;
|
||||
|
||||
int device = open(path->String(), O_RDONLY);
|
||||
if(device >= 0)
|
||||
{
|
||||
fFileHandle = device;
|
||||
fDrivePath = path;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *
|
||||
CDAudioDevice::GetDrivePath(void) const
|
||||
{
|
||||
if(!fDrivePath)
|
||||
return NULL;
|
||||
|
||||
return fDrivePath->String();
|
||||
}
|
||||
|
||||
int32 CDAudioDevice::FindDrives(const char *path)
|
||||
{
|
||||
BDirectory dir(path);
|
||||
|
||||
if(dir.InitCheck() != B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
dir.Rewind();
|
||||
|
||||
BEntry entry;
|
||||
while(dir.GetNextEntry(&entry) >= 0)
|
||||
{
|
||||
BPath path;
|
||||
const char *name;
|
||||
entry_ref e;
|
||||
|
||||
if(entry.GetPath(&path) != B_OK)
|
||||
continue;
|
||||
|
||||
name = path.Path();
|
||||
if(entry.GetRef(&e) != B_OK)
|
||||
continue;
|
||||
|
||||
if(entry.IsDirectory())
|
||||
{
|
||||
// ignore floppy -- it is not silent
|
||||
if(strcmp(e.name, "floppy") == 0)
|
||||
continue;
|
||||
|
||||
int32 count = FindDrives(name);
|
||||
|
||||
if(count > 0)
|
||||
return count;
|
||||
}
|
||||
else
|
||||
{
|
||||
int devfd;
|
||||
device_geometry g;
|
||||
|
||||
// ignore partitions
|
||||
if(strcmp(e.name, "raw") != 0)
|
||||
continue;
|
||||
|
||||
devfd = open(name, O_RDONLY);
|
||||
if(devfd < 0)
|
||||
continue;
|
||||
|
||||
if(ioctl(devfd, B_GET_GEOMETRY, &g, sizeof(g)) >= 0)
|
||||
{
|
||||
if(g.device_type == B_CD)
|
||||
fDriveList.AddItem(new BString(name));
|
||||
}
|
||||
close(devfd);
|
||||
}
|
||||
}
|
||||
return fDriveList.CountItems();
|
||||
}
|
||||
|
||||
bool
|
||||
CDAudioDevice::GetTime(cdaudio_time &track, cdaudio_time &disc)
|
||||
{
|
||||
scsi_position pos;
|
||||
|
||||
// Sanity check
|
||||
status_t media_status = B_DEV_NO_MEDIA;
|
||||
ioctl(fFileHandle, B_GET_MEDIA_STATUS, &media_status, sizeof(media_status));
|
||||
if (media_status != B_OK)
|
||||
return false;
|
||||
|
||||
status_t result = ioctl(fFileHandle, B_SCSI_GET_POSITION, &pos);
|
||||
|
||||
if (result != B_OK)
|
||||
return false;
|
||||
|
||||
if ((!pos.position[1]) || (pos.position[1] >= 0x13) ||
|
||||
((pos.position[1] == 0x12) && (!pos.position[6])))
|
||||
{
|
||||
// This indicates that we have a CD, but we are stopped.
|
||||
return false;
|
||||
}
|
||||
|
||||
disc.minutes = pos.position[9];
|
||||
disc.seconds = pos.position[10];
|
||||
track.minutes = pos.position[13];
|
||||
track.seconds = pos.position[14];
|
||||
return true;
|
||||
}
|
||||
|
||||
struct ConvertedToc
|
||||
{
|
||||
int32 min;
|
||||
int32 sec;
|
||||
int32 frame;
|
||||
};
|
||||
|
||||
static int32
|
||||
cddb_sum(int n)
|
||||
{
|
||||
char buf[12];
|
||||
int32 ret = 0;
|
||||
|
||||
sprintf(buf, "%u", n);
|
||||
for (const char *p = buf; *p != '\0'; p++)
|
||||
ret += (*p - '0');
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32
|
||||
CDAudioDevice::GetDiscID(void)
|
||||
{
|
||||
// Read the disc
|
||||
scsi_toc toc;
|
||||
status_t result = ioctl(fFileHandle, B_SCSI_GET_TOC, &toc);
|
||||
|
||||
if (result != B_OK)
|
||||
return -1;
|
||||
|
||||
|
||||
int32 id, numTracks;
|
||||
BString frameOffsetsString;
|
||||
|
||||
ConvertedToc tocData[100];
|
||||
|
||||
// figure out the disc ID
|
||||
for (int index = 0; index < 100; index++)
|
||||
{
|
||||
tocData[index].min = toc.toc_data[9 + 8*index];
|
||||
tocData[index].sec = toc.toc_data[10 + 8*index];
|
||||
tocData[index].frame = toc.toc_data[11 + 8*index];
|
||||
}
|
||||
numTracks = toc.toc_data[3] - toc.toc_data[2] + 1;
|
||||
|
||||
int32 sum1 = 0;
|
||||
int32 sum2 = 0;
|
||||
for (int index = 0; index < numTracks; index++)
|
||||
{
|
||||
sum1 += cddb_sum((tocData[index].min * 60) + tocData[index].sec);
|
||||
|
||||
// the following is probably running over too far
|
||||
sum2 += (tocData[index + 1].min * 60 + tocData[index + 1].sec) -
|
||||
(tocData[index].min * 60 + tocData[index].sec);
|
||||
}
|
||||
id = ((sum1 % 0xff) << 24) + (sum2 << 8) + numTracks;
|
||||
|
||||
return id;
|
||||
}
|
72
src/apps/cdplayer/CDAudioDevice.h
Normal file
72
src/apps/cdplayer/CDAudioDevice.h
Normal file
@ -0,0 +1,72 @@
|
||||
#ifndef CDAUDIODEVICE_H
|
||||
#define CDAUDIODEVICE_H
|
||||
|
||||
#include <SupportDefs.h>
|
||||
#include <String.h>
|
||||
#include <List.h>
|
||||
|
||||
enum CDState {
|
||||
kNoCD=0,
|
||||
kStopped,
|
||||
kPaused,
|
||||
kPlaying,
|
||||
kSkipping
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int32 minutes;
|
||||
int32 seconds;
|
||||
} cdaudio_time;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int32 disc_id;
|
||||
int32 track_count;
|
||||
int32 length;
|
||||
|
||||
BString frame_offsets;
|
||||
} cdaudio_data;
|
||||
|
||||
class CDAudioDevice
|
||||
{
|
||||
public:
|
||||
CDAudioDevice(void);
|
||||
~CDAudioDevice(void);
|
||||
|
||||
bool Play(const int16 &track);
|
||||
bool Pause(void);
|
||||
bool Resume(void);
|
||||
bool Stop(void);
|
||||
bool Eject(void);
|
||||
|
||||
bool StartFastFwd(void);
|
||||
bool StopFastFwd(void);
|
||||
|
||||
bool StartRewind(void);
|
||||
bool StopRewind(void);
|
||||
|
||||
bool SetVolume(uint8 value);
|
||||
uint8 GetVolume(void);
|
||||
|
||||
CDState GetState(void);
|
||||
|
||||
int16 CountTracks(void);
|
||||
int16 GetTrack(void);
|
||||
|
||||
uint8 CountDrives(void);
|
||||
bool SetDrive(const int32 &drive);
|
||||
const char * GetDrivePath(void) const;
|
||||
|
||||
bool GetTime(cdaudio_time &track, cdaudio_time &disc);
|
||||
int32 GetDiscID(void);
|
||||
|
||||
private:
|
||||
int32 FindDrives(const char *path);
|
||||
|
||||
int fFileHandle;
|
||||
BString * fDrivePath;
|
||||
BList fDriveList;
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user