3 const char *prog = "<unset>";
5 void set_prog(const char *p)
6 { const char *q = strrchr(p, '/'); prog = q ? q + 1 : p; }
8 void vmoan(const char *fmt, va_list ap)
9 { fprintf(stderr, "%s: ", prog); vfprintf(stderr, fmt, ap); }
11 void moan(const char *fmt, ...)
15 va_start(ap, fmt); vmoan(fmt, ap); va_end(ap);
19 void bail(const char *fmt, ...)
23 va_start(ap, fmt); vmoan(fmt, ap); va_end(ap);
28 void bail_syserr(int err, const char *fmt, ...)
32 va_start(ap, fmt); vmoan(fmt, ap); va_end(ap);
33 if (err) fprintf(stderr, ": %s", strerror(errno));
41 double whole = floor(t);
44 tv.tv_sec = whole; tv.tv_usec = floor((t - whole)*1.0e6) + 1;
45 if (select(0, 0, 0, 0, &tv) < 0) bail_syserr(errno, "failed to sleep");
49 void carefully_write(int fd, const void *buf, size_t sz)
51 const unsigned char *p = buf;
58 if (errno == EINTR) continue;
59 bail_syserr(errno, "failed to write to output file");
61 if (!n) bail("unexpected short write to output file");
66 void open_file_on_demand(const char *file, FILE **fp_inout, const char *what)
71 fp = fopen(file, "w");
72 if (!fp) bail_syserr(errno, "failed to open %s file `%s'", what, file);
73 fprintf(fp, "## %s\n\n", what);
78 void check_write(FILE *fp, const char *what)
81 if (ferror(fp)) bail_syserr(errno, "error writing %s file", what);
84 void carefully_fclose(FILE *fp, const char *what)
86 if (fp && (ferror(fp) || fclose(fp)))
87 bail_syserr(errno, "error writing %s file", what);
90 void store_filename(char *buf, ident id)
92 switch (id_kind(id)) {
94 sprintf(buf, "#<raw device>");
97 if (!id_title(id)) sprintf(buf, "/VIDEO_TS/VIDEO_TS.IFO");
98 else sprintf(buf, "/VIDEO_TS/VTS_%02u_0.IFO", id_title(id));
101 if (!id_title(id)) sprintf(buf, "/VIDEO_TS/VIDEO_TS.BUP");
102 else sprintf(buf, "/VIDEO_TS/VTS_%02u_0.BUP", id_title(id));
105 if (!id_title(id)) sprintf(buf, "/VIDEO_TS/VIDEO_TS.VOB");
107 sprintf(buf, "/VIDEO_TS/VTS_%02u_%u.VOB", id_title(id), id_part(id));
114 struct progress_state progress = PROGRESS_STATE_INIT;
115 static struct banner_progress_item banner_progress;
117 static void render_banner_progress(struct progress_item *item,
118 struct progress_render_state *render)
120 struct banner_progress_item *bi = (struct banner_progress_item *)item;
122 progress_putleft(render, " %s", bi->msg);
123 progress_shownotice(render, 4, 7);
126 void show_banner(const char *msg)
128 banner_progress._base.render = render_banner_progress;
129 progress_additem(&progress, &banner_progress._base);
130 banner_progress.msg = msg;
131 progress_update(&progress);
134 void hide_banner(void)
136 if (!progress_removeitem(&progress, &banner_progress._base))
137 progress_update(&progress);
141 static void logfn(void *p, dvd_logger_level_t lev,
142 const char *fmt, va_list ap)
145 case DVD_LOGGER_LEVEL_ERROR:
146 fprintf("%s (libdvdread error): ", prog);
148 case DVD_LOGGER_LEVEL_WARN:
149 fprintf("%s (libdvdread warning): ", prog);
154 vfprintf(stderr, fmt, ap);
157 static const dvd_logger_cb logger = { logfn };
160 void open_dvd(const char *device, int *fd_out, dvd_reader_t **dvd_out)
167 fd = open(device, O_RDONLY);
168 if (fd >= 0 || errno != ENOMEDIUM) break;
170 show_banner("Waiting for disc to be inserted...");
175 if (bannerp) hide_banner();
176 if (fd < 0) bail_syserr(errno, "failed to open device `%s'", device);
179 dvd = DVDOpen2(0, &logger, device);
181 dvd = DVDOpen(device);
183 if (!dvd) bail("failed to open DVD on `%s'", device);
186 if (fd_out) *fd_out = fd;