1 
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <sys/ioctl.h>
5 #include <unistd.h>
6 #include <ctype.h>
7 #include <string.h>
8 
9 #define CDPARANOIA_OUTPUT_BUF_LENGTH             1024
10 #define CDPARANOIA_OUTPUT_LINE_LENGTH            74
11 #define CDPARANOIA_STAT_LENGTH      42
12 #define CDPARANOIA_GRAPH_LENGTH     30
13 
14 #define PRINTOUT_INTERVAL           0.5
15 
16 extern int errno;
17 int cdparanoia_read_stat (unsigned *current, char **graph_string);
18 int find_cdparanoia_output_read_offset (char *buf, int begin, int end);
19 void print_msg (int begin, int length, int current, char *graph);
20 
21 int
cdparanoia_read_stat(unsigned * current,char ** graph_string)22 cdparanoia_read_stat (unsigned *current, char **graph_string)
23 {
24 	extern int errno;
25 	static char buf[CDPARANOIA_OUTPUT_BUF_LENGTH];
26 	static char status[CDPARANOIA_STAT_LENGTH + 1];
27 	static char graph[CDPARANOIA_GRAPH_LENGTH + 1];
28 	ssize_t bytes_read;
29 	int bytes_avail;
30 	static int prev_bytes_avail = -1;
31 	int read_offset, temp_offset, count;
32 
33 	ioctl (0, FIONREAD, &bytes_avail);
34 	if (bytes_avail < 4 * CDPARANOIA_OUTPUT_LINE_LENGTH) {
35 		if (bytes_avail == prev_bytes_avail)
36 			/* nothing available, let's wait */
37 			return -1;
38 		else {
39 			/* Record available bytes, and let's just wait */
40 			prev_bytes_avail = bytes_avail;
41 			return -1;
42 		}
43 	}
44 	prev_bytes_avail = -1;
45 
46 	count = 0;
47 	do {
48 		bytes_read = read (0, (void *) buf, sizeof (buf));
49 		temp_offset = bytes_read - 4 * CDPARANOIA_OUTPUT_LINE_LENGTH - 1;
50 		read_offset = find_cdparanoia_output_read_offset (buf,
51 		              temp_offset,
52 		              sizeof (buf) - 1);
53 		if (read_offset < 0
54 			        || read_offset > sizeof (buf) - CDPARANOIA_OUTPUT_LINE_LENGTH) {
55 			if (count == 0)
56 				return -1;
57 			else
58 				break;
59 		}
60 
61 		strncpy (status, buf + read_offset, sizeof (status));
62 		status[sizeof (status) - 1] = '\0';
63 		count++;
64 	} while (bytes_read == sizeof (buf));
65 
66 	strncpy (graph, status, sizeof (graph));
67 	graph[sizeof (graph) - 1] = '\0';
68 	*graph_string = graph;
69 
70 	temp_offset = CDPARANOIA_GRAPH_LENGTH + 1;
71 
72 	sscanf (status + temp_offset + 1, "%u", current);
73 
74 	return 0;
75 }
76 
77 int
find_cdparanoia_output_read_offset(char * buf,int begin,int end)78 find_cdparanoia_output_read_offset (char *buf, int begin, int end)
79 {
80 	int i;
81 
82 	i = begin;
83 
84 	do {
85 		while (buf[i] != '=' && i <= end - 16)
86 			i++;
87 
88 		if (buf[i + 3] == 'P'
89 			        && isdigit (buf[i + 16 + CDPARANOIA_GRAPH_LENGTH + 3]))
90 			return i + 16;
91 		else
92 			i++;
93 	} while (i <= end - 16);
94 	return -1;
95 }
96 
97 // print out [P 0.xxxx "---->          "]\n
98 void
print_msg(int begin,int length,int current,char * graph)99 print_msg (int begin, int length, int current, char *graph)
100 {
101 	printf ("[P ");
102 	printf ("%f ", (double) (current - begin) / (double) length);
103 	printf ("\"%s\"]\n", graph);
104 }
105 
106 int
main(int argc,char ** argv)107 main (int argc, char **argv)
108 {
109 	int begin, length;
110 	int current;
111 	char *graph_string;
112 
113 	if (argc != 3) {
114 		fprintf (stderr, "This is ripperX plugin for cdparanoia. Syntax is\n"
115 		         "ripperX_plugin-cdparanoia beginning_sector length_in_sector\n");
116 		exit (1);
117 	}
118 
119 	sscanf (argv[1], "%d", &begin);
120 	sscanf (argv[2], "%d", &length);
121 
122 	while (1) {
123 		if (cdparanoia_read_stat (&current, &graph_string) == 0)
124 			print_msg (begin, length, current, graph_string);
125 		usleep (PRINTOUT_INTERVAL * 1000000);
126 	}
127 }
128