pac - freie Software

Hallo zusammen!

Ich habe hier einen CD-Player für Linux-Systeme programmiert. Es war/ist ein Lernprogramm und hat
deswegen nur die nötigsten Funktionen.
Es wird gezeigt wie man unter Linux mit den CD-Rom Treiber interagieren kann.
Es gibt einfache Abspielfunktionen (Play, Pause, Resume, Stop) und noch ein paar kleine Extras.
Da es kein SDL oder Ähnliches benutzt, sollte es auf allen Linux-Systemen funktionieren, die einen C-Compiler installiert haben.
Es ist recht einfach eine Repeat-Funktion einzubauen oder auch Playlisten anzulegen, aber ich habe bewusst nur das Nötigste implementiert. Wer wirklich weiterentwickeln will, kann mir eine PM/E-Mail schicken!

Das UI ist trivial, aber naja.

Code:
#include <stdio.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <stdlib.h>
#include <linux/cdrom.h>
#include <errno.h>
#define clr() printf("\x1B[2J")

int fd;							/* global filedescriptor */
int print_help(void); 				/* prints the help screen on the display */
static int open_driver(char *); 	  /* opens the cdrom driver for interaction */
static int open_tray(int); 		      /* opens the cdrom tray */
static int close_tray(int);		       /* closes the cdrom tray */
static int stop_cdrom(int);		     /* stops the cdrom, should be done before closing fd */
static int capabilities(int); 			/* shows the capabilities of the selected (argv[1]) drive */
static int pause_cdrom(int); 		   /* pauses the cd */
static int resume_cdrom(int);		  /* resume playing after the cd was paused */
static int print_content(int); 		     /* prints some details about the cd content like frame positions, lenght etc. on the screen */
static play_cdrom(int, int); 		     /* plays either the whole cd or just a single track, you decide */
static int print_status(int); 		      /* prints the actual drive status on the screen */
int main(int, char**); 				/* main function, basicly to interact with the user */

int print_help(void)
{
	clr();
	printf("This is just a simple program, that shows how you can\n");
	printf("interact with the cdrom driver on a Linux box\n\n");
	printf("Usage: pac <device>\n");
	printf("Example: pac /dev/cdrom\n\n");
	getchar();getchar();
}

static int open_driver(char *device)
{
	fd = open(device, O_RDONLY | O_NONBLOCK);
	if(fd == -1)
	{
		if(errno == ENOMEDIUM) /* This does not work, but I don't know why */
			printf("No cd in the drive\n");
		else
			perror("open_driver()");
		exit(EXIT_FAILURE);
	}
}

static int open_tray(int device)
{
	if(ioctl(device, CDROMEJECT) == -1)
	{
		perror("open_tray()");
		return EXIT_FAILURE;
	}
}

static int close_tray(int device)
{
	if(ioctl(device, CDROMCLOSETRAY) == -1)
	{
		perror("close_tray()");
		return EXIT_FAILURE;
	}
}

static int stop_cdrom(int device)
{
	if(ioctl(device, CDROMSTOP) ==-1)
	{
		perror("stop_cdrom()");
		return EXIT_FAILURE;
	}
}

static int pause_cdrom(int device)
{
	if(ioctl(device, CDROMPAUSE) == -1)
	{
		perror("pause_cdrom()");
		return EXIT_FAILURE;
	}
}

static int resume_cdrom(int device)
{
	if(ioctl(device, CDROMRESUME) == -1)
	{
		perror("resume_cdrom()");
		return EXIT_FAILURE;
	}
}

static int capabilities(int device)
{
	const char *answer[] = {"no", "yes"};
	int caps = ioctl(device, CDROM_GET_CAPABILITY);
	if(caps == -1)
	{
		perror("capabilities()");
		return EXIT_FAILURE;
	}
	clr();
	printf("drive capabilities:\n");
	printf("\tcan close tray:\t\t\t\t%s\n", answer[!!(caps & CDC_CLOSE_TRAY)]);
	printf("\tcan open tray:\t\t\t\t\%s\n", answer[!!(caps & CDC_OPEN_TRAY)]);
	printf("\tcan lock tray:\t\t\t\t%s\n", answer[!!(caps & CDC_LOCK)]);
	printf("\tprogrammable speed:\t\t\t%s\n", answer[!!(caps & CDC_SELECT_SPEED)]);
	printf("\tdisc selection (jukebox):\t\t%s\n", answer[!!(caps & CDC_SELECT_DISC)]);
	printf("\tcan read multi sessions:\t\t%s\n", answer[!!(caps & CDC_MULTI_SESSION)]);
	printf("\tmedium catalog number (MCN):\t\t%s\n", answer[!!(caps & CDC_MCN)]);
	printf("\tmedium changed:\t\t\t\t%s\n", answer[!!(caps & CDC_MEDIA_CHANGED)]);
	printf("\taudio functions:\t\t\t%s\n", answer[!!(caps & CDC_PLAY_AUDIO)]);
	printf("\thard reset device:\t\t\t%s\n", answer[!!(caps & CDC_RESET)]);
	printf("\tdriver has non-standard ioctls:\t\t%s\n", answer[!!(caps & CDC_IOCTLS)]);
	printf("\tdriver implements drive status:\t\t%s\n", answer[!!(caps & CDC_DRIVE_STATUS)]);
	printf("\tdriver implements generic packtes:\t%s\n", answer[!!(caps & CDC_GENERIC_PACKET)]);
	printf("\tdrive is a CD-R:\t\t\t%s\n", answer[!!(caps & CDC_CD_R)]);
	printf("\tdrive is a CD-RW:\t\t\t%s\n", answer[!!(caps & CDC_CD_RW)]);
	printf("\tdrive is a DVD:\t\t\t\t%s\n", answer[!!(caps & CDC_DVD)]);
	printf("\tdrive is a DVD-R:\t\t\t%s\n", answer[!!(caps & CDC_DVD_R)]);
	printf("\tdrive is a DVD-RAM:\t\t\t%s\n", answer[!!(caps & CDC_DVD_RAM)]);
	printf("\tdrive is an MO device:\t\t\t%s\n", answer[!!(caps & CDC_MO_DRIVE)]);
	printf("\tdrive can read MRW:\t\t\t%s\n", answer[!!(caps & CDC_MRW)]);
	printf("\tdrive can write MRW:\t\t\t%s\n", answer[!!(caps & CDC_MRW_W)]);
	printf("\tOK to open for WRITE:\t\t\t%s\n", answer[!!(caps & CDC_RAM)]);
	getchar();getchar();
}

static int print_content(int device)
{
	struct cdrom_tochdr tochdr;
	struct cdrom_tocentry tocentry;
	int track;

	if(ioctl(device, CDROMREADTOCHDR, &tochdr) == -1)
	{
		perror("print_content()");
		exit (EXIT_FAILURE);
	}

	clr();
	printf("cd contains %i track(s):\n", tochdr.cdth_trk1);

	for(track = tochdr.cdth_trk0; track <= tochdr.cdth_trk1; track++)
	{
		tocentry.cdte_track = track;
		tocentry.cdte_format = CDROM_MSF;
		if(ioctl(device, CDROMREADTOCENTRY, &tocentry) == -1)
		{
			perror("print_content()");
			exit (EXIT_FAILURE);
		}

		printf("%3d: %02d:%02d:%02d (%06d) %s%s\n",
				tocentry.cdte_track,																		 tocentry.cdte_addr.msf.minute,
				tocentry.cdte_addr.msf.second,
				tocentry.cdte_addr.msf.frame,
				tocentry.cdte_addr.msf.frame +
				tocentry.cdte_addr.msf.second * 75 +
				tocentry.cdte_addr.msf.minute * 75 * 60 - 150,
				(tocentry.cdte_ctrl & CDROM_DATA_TRACK) ? "data" : "audio",
				(track == CDROM_LEADOUT) ? " (leadout)" : ""); /*Does not work ??? */
	}
	getchar();getchar();
}

static int play_cdrom(int device, int song)
{
	struct cdrom_tocentry tocentry;
	struct cdrom_msf msf;

	int track = song;
	int lead = song;

	if(song == 0)
	{
		track = 1;
		lead = CDROM_LEADOUT;
	}
	else
	{
		track = song;
		lead = song+1;
	}

	tocentry.cdte_track = track;
	tocentry.cdte_format = CDROM_MSF;
	if(ioctl(device, CDROMREADTOCENTRY, &tocentry) == -1)
	{
		perror("startrack(s) - play_cdrom()");
		return EXIT_FAILURE;
	}

	msf.cdmsf_min0 = tocentry.cdte_addr.msf.minute;
	msf.cdmsf_sec0 = tocentry.cdte_addr.msf.second;
	msf.cdmsf_frame0 = tocentry.cdte_addr.msf.frame;

	tocentry.cdte_track = lead;
	tocentry.cdte_format = CDROM_MSF;
	if(ioctl(device, CDROMREADTOCENTRY, &tocentry) == -1)
	{
		perror("lead track(s) - play_cdrom()");
		return EXIT_FAILURE;
	}

	msf.cdmsf_min1 = tocentry.cdte_addr.msf.minute;
	msf.cdmsf_sec1 = tocentry.cdte_addr.msf.second;
	msf.cdmsf_frame1 = tocentry.cdte_addr.msf.frame;

	if(ioctl(device, CDROMPLAYMSF, &msf) == -1)
	{
		perror("playing - play_cdrom()");
		return EXIT_FAILURE;
	}
}

static int print_status(int device)
{
	struct cdrom_subchnl sub;

	fflush(stdout);
	sub.cdsc_format = CDROM_MSF;

	if(ioctl(device, CDROMSUBCHNL, &sub) == -1)
	{
		perror("print_status()");
		return EXIT_FAILURE;
	}

	clr();
	printf("actual drive status: ");
	switch (sub.cdsc_audiostatus)
	{
		case	CDROM_AUDIO_INVALID:	printf("invalid\n"); break;
		case	CDROM_AUDIO_PLAY:		printf("playing"); break;
		case	CDROM_AUDIO_PAUSED:		printf("paused"); break;
		case	CDROM_AUDIO_COMPLETED:	printf("completed\n"); break;
		case 	CDROM_AUDIO_ERROR:		printf("error\n"); break;
		case	CDROM_AUDIO_NO_STATUS:	printf("no status\n"); break;
		default:						printf("internal error: status unknown\n");
	}

	if(sub.cdsc_audiostatus == CDROM_AUDIO_PLAY || sub.cdsc_audiostatus == CDROM_AUDIO_PAUSED)
	{
			printf(" at: %02d:%02d (absolute) / %02d:%02d (relative) - track %d\n",
					 sub.cdsc_absaddr.msf.minute,
					 sub.cdsc_absaddr.msf.second,
					 sub.cdsc_reladdr.msf.minute,
					 sub.cdsc_reladdr.msf.second,
					 sub.cdsc_trk);
	}
	getchar();getchar();
}

int main(int argc, char **argv)
{
	int track, input;

	if(argc < 2)
	{
		print_help();
		return EXIT_FAILURE;
	}

	open_driver(argv[1]);

	do{
		clr();
		printf(" -1- open cd tray\n");
		printf(" -2- close cd tray\n");
		printf(" -3- show drive capabilities\n");
		printf(" -4- play the whole cd\n");
		printf(" -5- play a single track\n");
		printf(" -6- pause the cd\n");
		printf(" -7- resume playing\n");
		printf(" -8- stop the cd\n");
		printf(" -9- show cd status\n");
		printf("-10- show cd content\n");
		printf("-11- show help dialog\n");
		printf("-12- quit the program\n");
		printf("your selection: ");
		scanf("%d", &input);

		switch(input)
		{
			case 	1:		open_tray(fd); break;
			case 	2:		close_tray(fd); break;
			case	3:		capabilities(fd); break;
			case	4:		play_cdrom(fd, 0); break;
			case	5:		printf("enter track to play: ");
							scanf("%i", &track);
							play_cdrom(fd, track); break;
			case	6:		pause_cdrom(fd); break;
			case	7:		resume_cdrom(fd); break;
			case	8:		stop_cdrom(fd); break;
			case	9:		print_status(fd); break;
			case 	10:		print_content(fd); break;
			case 	11:		print_help(); break;
			case	12:		printf("thanks for using;)\n"); break;
			default:		printf("not a valid option\n");
		}
	}while(input != 12);

	close(fd);
	return EXIT_SUCCESS;
}

PS.: Die Code-Formatierung ist mir hier nicht so gelungen!;)

Falls ihr mal mit Hardware-Programmierung anfangt, hilft euch das vielleicht etwas weiter.
 
Zurück
Oben