1/* ++++++++++ 2 play.cpp 3 Copyright (C) 1995 Be Incorporated. All Rights Reserved. 4 5 modified on November 03, 2003 by Jerome Duval 6+++++ */ 7/* 8 * was released as sample code; source: 9 * ftp://planetmirror.com/raid/13/beos/samples/media_kit/obsolete/play.cpp 10 */ 11 12#include <errno.h> 13#include <stdio.h> 14#include <stdlib.h> 15#include <string.h> 16#include <scsi.h> 17#include <unistd.h> 18#include <Directory.h> 19#include <Entry.h> 20#include <Path.h> 21 22 23/* ---------- 24 play requested track 25----- */ 26 27void 28play(int id, scsi_play_track *track) 29{ 30 track->start_index = 1; 31 track->end_track = 99; 32 track->end_index = 1; 33 if (!ioctl(id, B_SCSI_PLAY_TRACK, track)) 34 printf("Playing audio...\n"); 35 else 36 printf("Play audio failed\n"); 37} 38 39 40/* ---------- 41 show valid cd-rom id's 42 (from /boot/optional/sample-code/interface_kit/CDButton/CDEngine.cpp) 43----- */ 44 45static void 46try_dir(const char *directory, long *count, bool show) 47{ 48 bool add = false; 49 BDirectory dir; 50 dir.SetTo(directory); 51 if(dir.InitCheck() != B_NO_ERROR) { 52 return; 53 } 54 dir.Rewind(); 55 BEntry entry; 56 while(dir.GetNextEntry(&entry) >= 0) { 57 BPath path; 58 const char *name; 59 entry_ref e; 60 61 if(entry.GetPath(&path) != B_NO_ERROR) 62 continue; 63 name = path.Path(); 64 65 if(entry.GetRef(&e) != B_NO_ERROR) 66 continue; 67 68 if(entry.IsDirectory()) { 69 if(strcmp(e.name, "floppy") == 0) 70 continue; // ignore floppy (it is not silent) 71 try_dir(name, count, show); 72 } 73 else { 74 int devfd; 75 device_geometry g; 76 77 if(strcmp(e.name, "raw") != 0) 78 continue; // ignore partitions 79 80 devfd = open(name, O_RDONLY); 81 if(devfd < 0) 82 continue; 83 84 if(ioctl(devfd, B_GET_GEOMETRY, &g, sizeof(g)) >= 0) { 85 if(g.device_type == B_CD) 86 { 87 add = true; 88 } 89 } 90 close(devfd); 91 } 92 if (add) { 93 *count += 1; 94 if (show) 95 printf(" %s\n", name); 96 } 97 } 98} 99 100/* ---------- 101 show valid cd-rom id's 102----- */ 103 104int count_ids(bool show) 105{ 106 long count = 0; 107 108 try_dir("/dev/disk", &count, show); 109 return (count); 110} 111 112 113/* ---------- 114 main 115----- */ 116 117int 118main (int argc, char **argv) 119{ 120 int id; 121 int i; 122 int length; 123 int start; 124 long command; 125 long req_track = 0; 126 long vol; 127 long index; 128 ulong frames; 129 short tmp; 130 uchar *buf; 131 scsi_toc toc; 132 scsi_play_track track; 133 scsi_volume volume; 134 scsi_position position; 135 scsi_read_cd read_cd; 136 scsi_scan scan; 137 FILE *f; 138 139 length = count_ids(FALSE); 140 if (!length) { 141 printf("No CD-ROM drive present.\n"); 142 return 0; 143 } 144 errno = 0; 145 146 if (argc > 2) 147 command = strtol (argv[2], 0, 0); 148 else 149 command = 0; 150 151 if ((argc < 2) || (errno) || 152 (command < 0) || (command > 8)) { 153 printf("Usage: play device [command [param]]\n\n"); 154 printf(" Valid devices:\n"); 155 count_ids(TRUE); 156 printf("\n"); 157 printf(" Valid commands:\n"); 158 printf(" 0 [n] - play from track n [1]\n"); 159 printf(" 1 - pause\n"); 160 printf(" 2 - resume\n"); 161 printf(" 3 - stop\n"); 162 printf(" 4 - eject\n"); 163 printf(" 5 n - set volume to n (0 <= n <= 255)\n"); 164 printf(" 6 - current position\n"); 165 printf(" 7 n s - save track n to file s\n"); 166 printf(" 8 [c] - scan in direction c (f = forward, b = backward)\n\n"); 167 return 0; 168 } 169 170 if ((id = open(argv[1], 0)) >= 0) { 171 switch (command) { 172 case 0: 173 if (!ioctl(id, B_SCSI_GET_TOC, &toc)) { 174 track.start_track = 0; 175 for (i = toc.toc_data[2]; i <= toc.toc_data[3]; i++) { 176 length = (toc.toc_data[(((i + 1) - toc.toc_data[2]) * 8) + 4 + 5] * 60) + 177 (toc.toc_data[(((i + 1) - toc.toc_data[2]) * 8) + 4 + 6]); 178 length -= ((toc.toc_data[((i - toc.toc_data[2]) * 8) + 4 + 5] * 60) + 179 (toc.toc_data[((i - toc.toc_data[2]) * 8) + 4 + 6])); 180 printf(" Track %.2d: %.2d:%.2d - ", i, length / 60, length % 60); 181 if (toc.toc_data[((i - toc.toc_data[2]) * 8) + 4 + 1] & 4) 182 printf("DATA\n"); 183 else { 184 printf("AUDIO\n"); 185 if (!track.start_track) 186 track.start_track = i; 187 } 188 } 189 if (track.start_track) { 190 if (argc > 3) { 191 req_track = strtol (argv[3], 0, 0); 192 if ((req_track < toc.toc_data[2]) || (req_track > toc.toc_data[3])) 193 printf("Requested track is out of range\n"); 194 else 195 if (toc.toc_data[((req_track - toc.toc_data[2]) * 8) + 4 + 1] & 4) 196 printf("Requested track is not an audio track\n"); 197 else { 198 track.start_track = req_track; 199 play(id, &track); 200 } 201 } 202 else 203 play(id, &track); 204 } 205 else 206 printf("No audio tracks on CD\n"); 207 } 208 else 209 printf("Could not read table of contents on CD\n"); 210 break; 211 212 case 1: 213 printf("Pausing audio\n"); 214 ioctl(id, B_SCSI_PAUSE_AUDIO); 215 break; 216 217 case 2: 218 printf("Resuming audio\n"); 219 ioctl(id, B_SCSI_RESUME_AUDIO); 220 break; 221 222 case 3: 223 printf("Stopping audio\n"); 224 ioctl(id, B_SCSI_STOP_AUDIO); 225 break; 226 227 case 4: 228 printf("Ejecting CD\n"); 229 ioctl(id, B_SCSI_EJECT); 230 break; 231 232 case 5: 233 if (argc < 4) 234 printf("Specify the volume\n"); 235 else { 236 vol = strtol (argv[3], 0, 0); 237 if ((vol < 0) || (vol > 255)) 238 printf("Volume is out of range (0 - 255)\n"); 239 else { 240 printf("Setting volume to %ld\n", vol); 241 volume.port0_volume = vol; 242 volume.port1_volume = vol; 243 volume.flags = B_SCSI_PORT0_VOLUME | B_SCSI_PORT1_VOLUME; 244 ioctl(id, B_SCSI_SET_VOLUME, &volume); 245 } 246 } 247 break; 248 249 case 6: 250 if (ioctl(id, B_SCSI_GET_POSITION, &position) == B_ERROR) 251 printf("Could not get current position\n"); 252 else { 253 switch(position.position[1]) { 254 case 0x00: 255 printf("Position not supported by device\n"); 256 break; 257 258 case 0x11: 259 printf("Playing track %d (%.2d:%.2d:%.2d)\n", 260 position.position[6], 261 position.position[9], 262 position.position[10], 263 position.position[11]); 264 break; 265 266 case 0x12: 267 printf("Paused at track %d (%.2d:%.2d:%.2d)\n", 268 position.position[6], 269 position.position[9], 270 position.position[10], 271 position.position[11]); 272 break; 273 274 case 0x13: 275 printf("Play has been completed\n"); 276 break; 277 278 case 0x14: 279 printf("Play stopped due to error\n"); 280 break; 281 282 case 0x15: 283 printf("No status to return\n"); 284 break; 285 286 default: 287 printf("Unexpected result: %.2x\n", 288 position.position[1]); 289 } 290 } 291 break; 292 293 case 7: 294 if (argc < 4) { 295 printf("Specify the track to save\n"); 296 break; 297 } 298 299 if (argc < 5) { 300 printf("Specify a file to save to\n"); 301 break; 302 } 303 304 f = fopen(argv[4], "w"); 305 if (f == NULL) { 306 printf("Un-able to create %s\n", argv[4]); 307 break; 308 } 309 310 req_track = strtol (argv[3], 0, 0); 311 if (!ioctl(id, B_SCSI_GET_TOC, &toc)) { 312 if (req_track > toc.toc_data[3]) { 313 printf("Track %ld is out of range [%d-%d]\n", req_track, 314 toc.toc_data[2], toc.toc_data[3]); 315 break; 316 } 317 index = 0; 318 while (toc.toc_data[4 + (index * 8) + 2] != req_track) { 319 index++; 320 } 321 start = (toc.toc_data[4 + (index * 8) + 5] * 60 * 75) + 322 (toc.toc_data[4 + (index * 8) + 6] * 75) + 323 toc.toc_data[4 + (index * 8) + 7]; 324 index++; 325 length = ((toc.toc_data[4 + (index * 8) + 5] * 60 * 75) + 326 (toc.toc_data[4 + (index * 8) + 6] * 75) + 327 toc.toc_data[4 + (index * 8) + 7]) - start; 328 329 frames = min_c(1 * 75, (int) length); 330 read_cd.buffer = (char *)malloc(frames * 2352); 331 332 printf("Saving track %ld to %s...\n", req_track, argv[4]); 333 while (length) { 334 index = start; 335 read_cd.start_m = index / (60 * 75); 336 index %= (60 * 75); 337 read_cd.start_s = index / 75; 338 index %= 75; 339 read_cd.start_f = index; 340 341 index = min_c((int)frames, length); 342 read_cd.buffer_length = index * 2352; 343 length -= index; 344 start += index; 345 346 read_cd.length_m = index / (60 * 75); 347 index %= (60 * 75); 348 read_cd.length_s = index / 75; 349 index %= 75; 350 read_cd.length_f = index; 351 352 for (i = 0; i < 5; i++) 353 if (ioctl(id, B_SCSI_READ_CD, &read_cd) == B_NO_ERROR) 354 break; 355 if (i == 5) { 356 printf("Error reading CD-DA\n"); 357 break; 358 } 359 buf = (uchar *)read_cd.buffer; 360 for (i = 0; i < read_cd.buffer_length; i += 2) { 361 tmp = (short)((buf[1] << 8) | buf[0]); 362 *(short *)(&buf[0]) = tmp; 363 buf += 2; 364 } 365 fwrite(read_cd.buffer, read_cd.buffer_length, 1, f); 366 } 367 free(read_cd.buffer); 368 fclose(f); 369 } 370 else 371 printf("Failed to read table of contents\n"); 372 break; 373 374 case 8: 375 if (argc == 4) { 376 if (!strcmp(argv[3], "f") || !strcmp(argv[3], "F")) 377 scan.direction = 1; 378 else if (!strcmp(argv[3], "b") || !strcmp(argv[3], "B")) 379 scan.direction = -1; 380 else { 381 printf("Use 'f' to scan forward, 'b' to scan backwards\n"); 382 break; 383 } 384 } 385 else 386 scan.direction = 0; 387 scan.speed = 0; 388 if (ioctl(id, B_SCSI_SCAN, &scan) == B_ERROR) 389 printf("Error trying to scan\n"); 390 else 391 printf("Scanning...\n"); 392 break; 393 } 394 close(id); 395 } 396 else 397 printf("CD player is empty or invalid scsi-id\n"); 398 return 0; 399} 400