Makefile: Only `dvd-sector-copy' needs `-lm'.
[dvdrip] / lib.c
1 #include "lib.h"
2
3 const char *prog = "<unset>";
4
5 void set_prog(const char *p)
6 { const char *q = strrchr(p, '/'); prog = q ? q + 1 : p; }
7
8 void vmoan(const char *fmt, va_list ap)
9 { fprintf(stderr, "%s: ", prog); vfprintf(stderr, fmt, ap); }
10
11 __attribute__((format(printf, 1, 2)))
12 void moan(const char *fmt, ...)
13 {
14 va_list ap;
15
16 va_start(ap, fmt); vmoan(fmt, ap); va_end(ap);
17 fputc('\n', stderr);
18 }
19
20 __attribute__((noreturn, format(printf, 1, 2)))
21 void bail(const char *fmt, ...)
22 {
23 va_list ap;
24
25 va_start(ap, fmt); vmoan(fmt, ap); va_end(ap);
26 fputc('\n', stderr);
27 exit(2);
28 }
29
30 __attribute__((noreturn, format(printf, 2, 3)))
31 void bail_syserr(int err, const char *fmt, ...)
32 {
33 va_list ap;
34
35 va_start(ap, fmt); vmoan(fmt, ap); va_end(ap);
36 if (err) fprintf(stderr, ": %s", strerror(errno));
37 fputc('\n', stderr);
38 exit(2);
39 }
40
41 void sit(double t)
42 {
43 struct timeval tv;
44 double whole = floor(t);
45
46 if (t) {
47 tv.tv_sec = whole; tv.tv_usec = floor((t - whole)*1.0e6) + 1;
48 if (select(0, 0, 0, 0, &tv) < 0) bail_syserr(errno, "failed to sleep");
49 }
50 }
51
52 void store_filename(char *buf, ident id)
53 {
54 switch (id_kind(id)) {
55 case RAW:
56 sprintf(buf, "#<raw device>");
57 break;
58 case IFO:
59 if (!id_title(id)) sprintf(buf, "/VIDEO_TS/VIDEO_TS.IFO");
60 else sprintf(buf, "/VIDEO_TS/VTS_%02u_0.IFO", id_title(id));
61 break;
62 case BUP:
63 if (!id_title(id)) sprintf(buf, "/VIDEO_TS/VIDEO_TS.BUP");
64 else sprintf(buf, "/VIDEO_TS/VTS_%02u_0.BUP", id_title(id));
65 break;
66 case VOB:
67 if (!id_title(id)) sprintf(buf, "/VIDEO_TS/VIDEO_TS.VOB");
68 else
69 sprintf(buf, "/VIDEO_TS/VTS_%02u_%u.VOB", id_title(id), id_part(id));
70 break;
71 default:
72 abort();
73 }
74 }
75
76 struct progress_state progress = PROGRESS_STATE_INIT;
77 static struct banner_progress_item banner_progress;
78
79 static void render_banner_progress(struct progress_item *item,
80 struct progress_render_state *render)
81 {
82 struct banner_progress_item *bi = (struct banner_progress_item *)item;
83
84 progress_putleft(render, " %s", bi->msg);
85 progress_shownotice(render, 4, 7);
86 }
87
88 void show_banner(const char *msg)
89 {
90 banner_progress._base.render = render_banner_progress;
91 progress_additem(&progress, &banner_progress._base);
92 banner_progress.msg = msg;
93 progress_update(&progress);
94 }
95
96 void hide_banner(void)
97 {
98 if (!progress_removeitem(&progress, &banner_progress._base))
99 progress_update(&progress);
100 }
101
102 #ifdef notdef
103 static void logfn(void *p, dvd_logger_level_t lev,
104 const char *fmt, va_list ap)
105 {
106 switch (lev) {
107 case DVD_LOGGER_LEVEL_ERROR:
108 fprintf("%s (libdvdread error): ", prog);
109 break;
110 case DVD_LOGGER_LEVEL_WARN:
111 fprintf("%s (libdvdread warning): ", prog);
112 break;
113 default:
114 return;
115 }
116 vfprintf(stderr, fmt, ap);
117 fputc('\n', stderr);
118 }
119 static const dvd_logger_cb logger = { logfn };
120 #endif
121
122 void open_dvd(const char *device, int *fd_out, dvd_reader_t **dvd_out)
123 {
124 int fd;
125 dvd_reader_t *dvd;
126 int bannerp = 0;
127
128 for (;;) {
129 fd = open(device, O_RDONLY);
130 if (fd >= 0 || errno != ENOMEDIUM) break;
131 if (!bannerp) {
132 show_banner("Waiting for disc to be inserted...");
133 bannerp = 1;
134 }
135 sit(0.2);
136 }
137 if (bannerp) hide_banner();
138 if (fd < 0) bail_syserr(errno, "failed to open device `%s'", device);
139 if (dvd_out) {
140 #ifdef notdef
141 dvd = DVDOpen2(0, &logger, device);
142 #else
143 dvd = DVDOpen(device);
144 #endif
145 if (!dvd) bail("failed to open DVD on `%s'", device);
146 *dvd_out = dvd;
147 }
148 if (fd_out) *fd_out = fd;
149 else close(fd);
150 }