1 /* cdrdao - write audio CD-Rs in disc-at-once mode
2 *
3 * Copyright (C) 1998-2001 Andreas Mueller <mueller@daneb.ping.de>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #include "CdTextDialog.h"
21
22 #include <gtkmm.h>
23 #include <gnome.h>
24 #include <libgnomeuimm.h>
25
26 #include <stddef.h>
27 #include <string.h>
28
29 #include "TocEdit.h"
30 #include "Toc.h"
31 #include "util.h"
32
33 #include "guiUpdate.h"
34
CdTextDialog()35 CdTextDialog::CdTextDialog()
36 {
37 int i;
38 Gtk::VBox *contents = manage(new Gtk::VBox);
39 char buf[20];
40
41 active_ = false;
42 tocEdit_ = NULL;
43 trackEntries_ = 0;
44
45 languages_ = manage(new Gtk::Notebook);
46
47 for (i = 0; i < 8; i++) {
48 page_[i].table = new Gtk::Table(3, 3, false);
49 page_[i].table->set_row_spacings(5);
50 page_[i].table->set_col_spacings(5);
51 page_[i].performer = manage(new Gtk::Entry);
52 page_[i].title = manage(new Gtk::Entry);
53 page_[i].tabLabel = new Gtk::Label("");
54 page_[i].performerButton =
55 new Gtk::CheckButton(_("Enable Perfomer Entries"));
56 page_[i].performerButton->set_active(false);
57 page_[i].performerButton->signal_toggled().
58 connect(bind(mem_fun(*this, &CdTextDialog::activatePerformerAction), i));
59 page_[i].tracks = NULL;
60 page_[i].table->attach(*(new Gtk::Label(_("Performer"))), 1, 2, 0, 1);
61 page_[i].table->attach(*(new Gtk::Label(_("Title"))), 2, 3, 0, 1);
62
63 {
64 Gtk::HBox *hbox = manage(new Gtk::HBox);
65 hbox->pack_end(*(new Gtk::Label(_("Album"))));
66
67 page_[i].table->attach(*hbox, 0, 1, 1, 2, Gtk::FILL);
68 page_[i].table->attach(*(page_[i].title), 2, 3, 1, 2);
69 page_[i].table->attach(*(page_[i].performer), 1, 2, 1, 2);
70 }
71
72 {
73 Gtk::HBox *hbox = manage(new Gtk::HBox);
74
75 hbox->pack_start(*(page_[i].performerButton));
76 page_[i].table->attach(*hbox, 1, 2, 2, 3);
77 }
78
79 {
80 Gtk::HBox *hbox1 = manage(new Gtk::HBox);
81 Gtk::VBox *vbox1 = manage(new Gtk::VBox);
82
83 hbox1->pack_start(*(page_[i].table), true, true, 5);
84 vbox1->pack_start(*hbox1, false, false, 5);
85
86 Gtk::ScrolledWindow *swin = manage(new Gtk::ScrolledWindow);
87 swin->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
88 swin->show_all();
89 swin->add(*vbox1);
90
91 sprintf(buf, " %d ", i);
92 languages_->pages().
93 push_back(Gtk::Notebook_Helpers::TabElem(*swin,
94 *(page_[i].tabLabel)));
95 }
96 }
97
98 contents->pack_start(*languages_);
99
100 {
101 Gtk::HBox *hbox = manage(new Gtk::HBox);
102
103 hbox->pack_start(*contents, true, true, 10);
104 get_vbox()->pack_start(*hbox, true, true, 10);
105 }
106
107 Gtk::HButtonBox *bbox = new Gtk::HButtonBox(Gtk::BUTTONBOX_SPREAD);
108
109 applyButton_ = new Gtk::Button(Gtk::StockID(Gtk::Stock::APPLY));
110 bbox->pack_start(*applyButton_);
111 applyButton_->signal_clicked().connect(mem_fun(*this, &CdTextDialog::applyAction));
112
113 Gtk::Button *fillButton = new Gtk::Button(_(" Fill Performer "));
114 bbox->pack_start(*fillButton);
115 fillButton->signal_clicked().connect(mem_fun(*this, &CdTextDialog::fillPerformerAction));
116
117 Gtk::Button *cancelButton = new Gtk::Button(Gtk::StockID(Gtk::Stock::CLOSE));
118 bbox->pack_start(*cancelButton);
119 cancelButton->signal_clicked().connect(mem_fun(*this, &CdTextDialog::stop));
120
121 get_action_area()->pack_start(*bbox);
122
123 show_all_children();
124 set_title(_("CD-TEXT Entry"));
125 }
126
~CdTextDialog()127 CdTextDialog::~CdTextDialog()
128 {
129 }
130
on_delete_event(GdkEventAny *)131 bool CdTextDialog::on_delete_event(GdkEventAny*)
132 {
133 stop();
134 return 1;
135 }
136
updateTabLabels()137 void CdTextDialog::updateTabLabels()
138 {
139 const Toc *toc = tocEdit_->toc();
140 int l;
141
142 for (l = 0; l < 8; l++) {
143 const char *s = CdTextContainer::languageName(toc->cdTextLanguage(l));
144
145 if (page_[l].tabLabel->get_label() != s)
146 page_[l].tabLabel->set_label(s);
147 }
148 }
149
adjustTableEntries(int n)150 void CdTextDialog::adjustTableEntries(int n)
151 {
152 int i, l;
153 char buf[20];
154
155 if (trackEntries_ == n)
156 return;
157
158 for (l = 0; l < 8; l++) {
159 if (n < trackEntries_) {
160 page_[l].table->resize(3 + n, 3);
161
162 for (i = n; i < trackEntries_; i++) {
163 delete page_[l].tracks[i].performer;
164 delete page_[l].tracks[i].title;
165 delete page_[l].tracks[i].hbox;
166 delete page_[l].tracks[i].label;
167 }
168 }
169 else {
170 int performerActive = page_[l].performerButton->get_active();
171
172 TableEntry *newTracks = new TableEntry[n];
173
174 for (i = 0; i < trackEntries_; i++)
175 newTracks[i] = page_[l].tracks[i];
176
177 delete[] page_[l].tracks;
178 page_[l].tracks = newTracks;
179
180 page_[l].table->resize(3 + n, 3);
181
182 for (i = trackEntries_; i < n; i++) {
183 sprintf(buf, _("Track %02d"), i + 1);
184
185 page_[l].tracks[i].performer = manage(new Gtk::Entry);
186 page_[l].tracks[i].performer->set_sensitive(performerActive);
187 page_[l].tracks[i].title = manage(new Gtk::Entry);
188 page_[l].tracks[i].label = new Gtk::Label(buf);
189 page_[l].tracks[i].hbox = manage(new Gtk::HBox);
190
191 page_[l].tracks[i].hbox->pack_end(*(page_[l].tracks[i].label),
192 Gtk::PACK_SHRINK);
193
194 page_[l].table->attach(*(page_[l].tracks[i].hbox),
195 0, 1, i + 3, i + 4, Gtk::FILL);
196 page_[l].table->attach(*(page_[l].tracks[i].title),
197 2, 3, i + 3, i + 4);
198 page_[l].table->attach(*(page_[l].tracks[i].performer),
199 1, 2, i + 3, i + 4);
200 }
201
202 page_[l].table->show_all();
203 }
204 }
205
206 trackEntries_ = n;
207 }
208
update(unsigned long level,TocEdit * view)209 void CdTextDialog::update(unsigned long level, TocEdit *view)
210 {
211 if (view != tocEdit_) {
212 tocEdit_ = view;
213 level = UPD_ALL;
214 }
215
216 std::string s(view->filename());
217 s += " - ";
218 s += APP_NAME;
219 if (view->tocDirty())
220 s += "(*)";
221 set_title(s);
222
223 if (level & UPD_TOC_DATA) {
224 updateTabLabels();
225 }
226
227 if ((level & UPD_TOC_DATA) ||
228 (level & UPD_TRACK_DATA)) {
229 importData();
230 }
231
232 if (level & UPD_EDITABLE_STATE) {
233 applyButton_->set_sensitive(tocEdit_->editable() ? true : false);
234 }
235 }
236
start(TocEdit * view)237 void CdTextDialog::start(TocEdit *view)
238 {
239 update(UPD_ALL, view);
240 present();
241 active_ = true;
242 }
243
stop()244 void CdTextDialog::stop()
245 {
246 hide();
247 active_ = false;
248 }
249
applyAction()250 void CdTextDialog::applyAction()
251 {
252 if (tocEdit_ == NULL || !tocEdit_->editable())
253 return;
254
255 exportData();
256
257 guiUpdate();
258 }
259
fillPerformerAction()260 void CdTextDialog::fillPerformerAction()
261 {
262 int l = languages_->get_current_page();
263
264 if (l >= 0 && l <= 7) {
265 int i;
266 const char *s = checkString(page_[l].performer->get_text());
267
268 if (s == NULL)
269 return;
270
271 char *performer = strdupCC(s);
272
273 for (i = 0; i < trackEntries_; i++) {
274 if (checkString(page_[l].tracks[i].performer->get_text()) == NULL)
275 page_[l].tracks[i].performer->set_text(performer);
276 }
277
278 delete[] performer;
279 }
280 }
281
activatePerformerAction(int l)282 void CdTextDialog::activatePerformerAction(int l)
283 {
284 int i;
285 int val = page_[l].performerButton->get_active();
286
287 for (i = 0; i < trackEntries_; i++) {
288 page_[l].tracks[i].performer->set_sensitive(val);
289 }
290 }
291
importData()292 void CdTextDialog::importData()
293 {
294 const CdTextItem *item;
295 const Toc *toc = tocEdit_->toc();
296 int i, l;
297 int n = toc->nofTracks();
298
299 adjustTableEntries(n);
300
301 for (l = 0; l < 8; l++) {
302 if ((item = toc->getCdTextItem(0, l, CdTextItem::CDTEXT_TITLE)) != NULL)
303 page_[l].title->set_text((const char*)item->data());
304 else
305 page_[l].title->set_text("");
306
307 if ((item = toc->getCdTextItem(0, l, CdTextItem::CDTEXT_PERFORMER))
308 != NULL)
309 page_[l].performer->set_text((const char*)item->data());
310 else
311 page_[l].performer->set_text("");
312
313 for (i = 0; i < n; i++) {
314 if ((item = toc->getCdTextItem(i + 1, l, CdTextItem::CDTEXT_TITLE))
315 != NULL)
316 page_[l].tracks[i].title->set_text((const char*)item->data());
317 else
318 page_[l].tracks[i].title->set_text("");
319
320 if ((item = toc->getCdTextItem(i + 1, l, CdTextItem::CDTEXT_PERFORMER))
321 != NULL)
322 page_[l].tracks[i].performer->set_text((const char*)item->data());
323 else
324 page_[l].tracks[i].performer->set_text("");
325 }
326 }
327 }
328
exportData()329 void CdTextDialog::exportData()
330 {
331 int i, l;
332
333 for (l = 0; l < 8; l++) {
334 setCdTextItem(CdTextItem::CDTEXT_TITLE, 0, l,
335 checkString(page_[l].title->get_text()));
336 setCdTextItem(CdTextItem::CDTEXT_PERFORMER, 0, l,
337 checkString(page_[l].performer->get_text()));
338
339 for (i = 0; i < trackEntries_; i++) {
340 setCdTextItem(CdTextItem::CDTEXT_TITLE, i + 1, l,
341 checkString(page_[l].tracks[i].title->get_text()));
342 setCdTextItem(CdTextItem::CDTEXT_PERFORMER, i + 1, l,
343 checkString(page_[l].tracks[i].performer->get_text()));
344 }
345 }
346 }
347
setCdTextItem(CdTextItem::PackType type,int trackNr,int l,const char * s)348 void CdTextDialog::setCdTextItem(CdTextItem::PackType type, int trackNr,
349 int l, const char *s)
350 {
351 const CdTextItem *item;
352 TocEdit *tocEdit = tocEdit_;
353 const Toc *toc = tocEdit->toc();
354 CdTextItem *newItem;
355
356 if (s != NULL)
357 newItem = new CdTextItem(type, l, s);
358 else
359 newItem = NULL;
360
361 if ((item = toc->getCdTextItem(trackNr, l, type)) != NULL) {
362 if (newItem == NULL)
363 tocEdit->setCdTextItem(trackNr, type, l, NULL);
364 else if (*newItem != *item)
365 tocEdit->setCdTextItem(trackNr, type, l, s);
366 }
367 else if (newItem != NULL) {
368 tocEdit->setCdTextItem(trackNr, type, l, s);
369 }
370
371 delete newItem;
372 }
373
checkString(const std::string & str)374 const char *CdTextDialog::checkString(const std::string &str)
375 {
376 static char *buf = NULL;
377 static long bufLen = 0;
378 char *p, *s;
379 long len = strlen(str.c_str());
380
381 if (len == 0)
382 return NULL;
383
384 if (buf == NULL || len + 1 > bufLen) {
385 delete[] buf;
386 bufLen = len + 1;
387 buf = new char[bufLen];
388 }
389
390 strcpy(buf, str.c_str());
391
392 s = buf;
393 p = buf + len - 1;
394
395 while (*s != 0 && isspace(*s))
396 s++;
397
398 if (*s == 0)
399 return NULL;
400
401 while (p > s && isspace(*p)) {
402 *p = 0;
403 p--;
404 }
405
406 return s;
407 }
408
409