xfreecd.c (162771B)
1 /* --------------------------------------------------------------------- 2 3 XfreeCD v0.7.8 4 5 Copyright (C) 1998 Brian C. Lane 6 nexus@tatoosh.com 7 http://www.tatoosh.com/nexus 8 9 This program is free software; you can redistribute it and/or 10 modify it under the terms of the GNU General Public License 11 as published by the Free Software Foundation; either version 2 12 of the License, or (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 22 23 ============================[ HISTORY ]============================== 24 12/02/98 Tracking down the crash on CDDB retrieveal bug that people 25 have been reporting. I've finally duplicated it myself 26 and narrowed it down to the code after printing the string 27 "Got the new data ok" and the call to local_cddb(); 28 My theory is that display.plabel or display.progress don't 29 get set to a NULL when deleted, so my checks fail and 30 it tries to write to already freed memory. 31 Removed the progress update right before destroying the 32 progress box, no point if its going to get deleted! 33 I cannot be 100% positive, but I think this has fixed the 34 recall problem. Needs testing. 35 36 Another bug. If the progress box is killed, it never opens 37 again until the program is restarted. Fix this in next 38 version. 39 40 41 07/05/98 Fixed intermittant bug with recalling CD info. There was 42 a spare strcat(tmpstr) in the request loop of offsets! 43 Depending on the state of memory this could really hose 44 the requests. 45 46 06/26/98 Fixing Revision # for original submissions. Store them 47 locally as #0 so that the first send to the server will 48 increment it to #1 and the server will get #1. 49 Also added the VERSION number to the makefile to make 50 changing the version easier. 51 52 06/22/98 I just noticed a problem. The Length of track #1 is wrong! 53 Seems to be stuck at 20:36. cd_control.c was waiting until 54 the track was at #2 before calculating the length. FIXED. 55 56 06/20/98 TODO 57 1. Fix EXT problems. 58 FIXED. 59 2. Reread spec on blank tracks. It refused 'Track 6' 60 I shouldn't save any default strings to disk or send 61 them to the database. Only show them when updating 62 the clist. DONE. Sends a blank ttitle if none is 63 entered. 64 65 3. Made change, but edit doesn't work and it complains 66 about lots of g_strings != NULL (means ==) that need 67 to be fixed (probably in the edit an edit copy). Make 68 sure the (blank) placeholders are not copied over unless 69 they are edited. 70 Writing of blank tracks doesn't work when the user has 71 deleted everything since it holds a string of zero 72 length. 73 FIXED. Check the length for 0. 74 75 4. If the CD is paused when XfreeCD is run it doesn't 76 show the current track in the display. FIXED. 77 78 5. If the CD is paused when XfreeCD is run and you show 79 the track names, it is blank. The database has not 80 been read yet. FIXED. 81 82 6. Main Tracklist display is updated every second... 83 This is because some of the CDDB entries have a revision 84 of -1. I convert these into revision 1 now. 85 86 06/19/98 Finishing up the extended data support. Adding free_cdinfo 87 to the appropriate places. Need to make sure its only called 88 when its needed and not in the update loop. 89 Changed Cancel button in edit window to Close 90 91 Shit. Nov I've broken it and I don't know how. Well, then 92 I'll just break it more. Changing all string usage to 93 dynamically allocated GString * from gtk. 94 95 Whew! Okay, I've converted all the static string storage 96 over to GString usage. It appears to be working okay for 97 the moment. Now to stress test it with all the CDDB 98 requirements. 99 100 Testing and making submissions to CDDB test server. 101 1. Inexact doesn't save to disk with my ID, it saves it 102 with the downloaded id (because I canged the way it 103 is saved after being received!). Change in cddbd.c 104 so it save to local, reads it, changes discid and 105 saves it again <ICK>. FIXED. 106 107 2. There is a problem when reading extended info. It 108 is writing a blank EXTD and EXT0 then another EXT0 109 and then up to the end-1 tracks. Fix it tomorrow. 110 FIXED. 1 - off error. 111 112 06/16/98 Things that need fixing: 113 1. 99 track CD isn't downloaded, causes an error and 114 it retries the server endlessly. 115 The track array in cdinfo was 1 short! I should use 116 0-98 instead of 1-99 for all access. 117 FIXED. 118 119 2. Server error caused by not sending all the track offsets 120 (buffer overflow). Fixed by sending it the offsets one 121 at a time. FIXED. 122 123 3. Edit window coredumps when trying to edit 99 track 124 NIN-broken. FIXED. display structure had a [99] in it. 125 126 4. Main tracklist window flickers every second... 127 128 5. Need to process extended data, save to local database, 129 resend it to server when tracks change. Don't need 130 to edit it or display it (most CDs don't use it at all). 131 Reading works now. 132 a. Need to write it back to disk. DONE. 133 b. Need to free the used memory when a CD is ejected 134 DONE. 135 136 6. Need to read the Revision # correctly 137 DONE. 138 139 06/06/98 Fixed problem with changing categories. Once the new 140 category has successfully been written it erases the 141 old category. 142 While it is waiting to get new data from the server 143 it is displaying the old track data. Needs to be erased 144 from the cdinfo structure as well as the display. 145 FIXED. 146 I would like to make long title in the track window 147 wrap automatically, but the GTK label doesn't have 148 wrapping, so too bad. 149 Adding a Send to Server option. This just uses the 150 local mail binary (must be in the path). This should 151 work for everyone. 152 Works, Tested successfully. 153 Added support for multiple TITLEx lines. Tested, and it 154 works fine. Sent 5 test of long title and long track 155 names to the cddb-test server. 156 I just noticed a bug with the clist edit window. It 157 is resetting the vertical scroll bar when you select 158 a track that has to be scrolled down to. Probably 159 because I reload the clist when the trackname is 160 edited. FIXED. 161 162 06/05/98 Trying to tidy up all the loose ends. 163 GTK cannot figure out the geometry of the window before 164 it is actually showing, so the negative geometry with 165 titlebar doean't work right. Hardcoded the window size 166 to 137x60 167 168 06/02/98 Adding display of full string returned by server error. 169 Fixed close error, I was returning the wrong thing from 170 delete_event. 171 172 06/01/98 Adding seperate Window Class names to the different 173 windows so that the user can individually control the 174 title bar, move/resize, etc. As suggested by Michael 175 J. Hammel 176 177 05/31/98 Adding support for -geometry, apparently this has not 178 been added to GTK+ itself yet, so I have to do it 179 myself, using XParseGeometry. Works Great! 180 When geometry is passed a '- it needs to be relative 181 to the other corner of the window, not the upper 182 left. Fixed. 183 184 05/28/98 Bug with eject on exit. It needs to send the current 185 state to the cd_control process when it reads the 186 config file. FIXED. 187 Need to add dropdown list for categories in edit. DONE. 188 189 05/27/98 More finishing touches <G>. 190 Added selection of next track in the track window when 191 it goes to the next track. Looks nicer. 192 Fixed a bug with multiple DTITLE lines. 193 194 NEED TO DO: 195 x 1. Build local cddb directories sometime (either under 196 the setup menu, or the first time it writes, 197 or at compile time). The best would be when it 198 tries to write to a non-existant directory, create 199 the structure needed. 200 Works. It creates only the category directory 201 needed and the root cddb directory if it doesn't 202 exist yet. This way the categories aren't limited 203 to a static list. 204 x 2. Editing track names and saving to local database. 205 x 3. Sending edited track info to the database, or just 206 a new discid for the CD. Requires email. Use the 207 mail binary, but allow users to spec. it? 208 x 4. Allow user to select local .cddb support or internet 209 so they can build their own database in the cddb 210 format even if they have no inet connection. 211 5. Clean up code. Add comments. 212 There is a bunch of duplicated code that can be 213 put into a subroutine with maybe 1 parameter 214 passed to it. The clist updating routines are 215 one. 216 x 6. Convert my usage of printf to g_print 217 218 05/26/98 Finishing touches. Got the text window to work, thanks 219 to Owen. I had to add it to the notebook before 220 it is realized, otherwise it doesn't know who its 221 parent is (this is because text windows are changes as 222 you add to them). 223 Changed to main window to be a POPUP so that it has no 224 title bars. Keeps people from resizing it too! 225 226 05/25/98 Problem with using device from main process -- we only 227 send 2 bytes to the cd_control process!! How am I going 228 to pass the new device? A 2 stage send? With the second 229 part being the new device? 230 231 Added CD_SET_DEVICE to cd_control. 232 Adding sending of it to read_config. 233 Switching cd device is now working! 234 235 Adding clear of display.tclist to no disc display points 236 237 238 05/24/98 Adding support for inexact matches. CDDBD_INEX_LINE. 239 Inexact matching works!!! It saves it as the locally 240 calculated discid (recalculated just before the save). 241 242 x 1. Need to update the track list if its already open 243 when the new data is downloaded from the server or 244 read from disk. 245 x 2. Clear the track list and title when nodisc info is 246 available (on change, use Track #, etc). 247 x 3. Click on a track in the track list to jump to 248 that track directly. 249 no 5. CD changer support... 250 x 6. Volume update is slow, needs to be called on click. 251 252 I've decided not to include changer support. Too hard to 253 integrate into the current GUI. And there probably isn't 254 a great need. 255 256 05/23/98 The Help/Setup dialog is partially working. It still 257 complains when making the help text box, why? 258 The startup sequence isn't working right. Not playing 259 after closing the tray, or even when already closed. 260 261 I also don't like the startup pause for checking for the 262 current status. That should be handled by a startup 263 state machine in the status callback. May help solve the 264 startup play problem. Fixed. Status returned was NO_STATUS 265 which I was checking for some reason. 266 267 Software selectable eject on exit with no play is now 268 working correctly. 269 270 Server refresh is working as far as updating the internal 271 list but the list in the setup dialog isn't working. Also 272 changes to cddb and device are cross-polinated! It is 273 happening at the realloc in the device_edit and cddb_edit 274 routines. Pointer copied over somehow? realloc wrong? 275 typical bug. Assignment to wrong place. 276 277 Some of th things left to do: 278 x 1. refresh server listing after update from internet 279 while dialog box is still open. 280 x 2. Status box showing the info while connected to the 281 server. 282 x 3. Implement Inexact match 283 x a. receive list of discids and titles from the server 284 Add a new command to cddbd return value 285 x b. Show a dialog box with the list of titles and have 286 the user pick one or Cancel. 287 x c. re-submit the query using the user selected discid 288 x 4. Saving to disk saves the wrong revision #, -1 289 o 5. Popup window when display is left clicked that shows 290 and allows editing of title and tracks. 291 showing title and track is working. 292 6. Need to switch to using config.device and telling the 293 cd_control process about it when we change it. 294 7. Submitting a new disc to the database (via email?) 295 296 297 05/22/98 Need to finish the help/setup menu window. 298 x Device (defaults to /dev/cdrom) 299 x Server List 300 x cddb support 301 no changer support 302 x Eject at end? 303 x Startup behavior 304 305 306 Since I have the WM set to no titles and bars it makes it 307 hard to manipulate the setup screen! How about if I were 308 to extend the cdplayers window up or down (how to tell?) 309 and include the setup/server/tracklist data that way? 310 How do you delete things once you've packed them? Or can 311 you? 312 313 314 05/21/98 Right click on display window and dragging now works 315 fine for moving the window around. 316 317 318 05/20/98 Blink isn't working. Fixed. Multiple places calling 319 update_display. FIXED. 320 Also need to add window dragging if right clicked in 321 the display area. 322 Need to add parallel tracklist window popup if right 323 click on either of the track digits (or area). 324 325 At startup we need to know the current state of the 326 CD before we go off and send a play command to it. FIXED. 327 When it has to close the door to play it doesn't start 328 playing automatically. 329 When it tries to play with no CD in the drive it doesn't 330 recover when you insert a disc and hit play. 331 Because fd_cd is < 0. Check for this. 332 333 There is a problem with setting the play button graphic 334 and state at the point where it is sent to control. 335 it it fails then the state/button is wrong! But if I 336 wait until it succeeds/fails then response time is 337 greatly delayed... Added code to make sure the button 338 state matched the display state and to change it if it 339 differs. Seems to work nicely. Shows playup until it 340 fails and then switches to stopup. WORKS WELL. 341 342 Eject doesn't work with status doing an init. Do an 343 initial init when cd_control is started. FIXED. 344 345 Dragging now sortof works. It loses track of the cursor 346 if its moved too fast, and won't ungrab (ick!) 347 348 05/19/98 Read/Write config now works, needs to still be tested 349 with multiple servers though. 350 351 05/18/98 Adding configuration writing and reading 352 353 05/17/98 Found a chunck of startup code that was double-copied, 354 The player actually plays, ejects, etc. OK. 355 The volume display needs to update immediatly as does 356 the time display update when the key is pressed. Eject 357 should eject even when no cd has been opened. 358 At startup we should? 359 Play automatically 360 Show no disc and do nothing until play pressed 361 Show total # of tracks and time remaining 362 All of these should be user selectable. 363 When a CD is opened for the first time (no discid stored 364 in cdinfo) we should query the database. 365 Clicking (right probably) on the display should pop up a 366 list of the tracks (editable). 367 There are some == NULL problems that need to be taken care 368 at starup, probably due to not realizing widgets first? 369 Blink isn't working right (doesn't blink) 370 Remaining on track counts up, not down! 371 Help/Setup dialog needs to be nicer looking, black to match 372 the look of the main box (how do I change the colors of 373 the dialogs?) 374 375 05/16/98 Finishing up the cd control, adding get motd and get 376 server list from cddb.cddb.com 377 I really should add protocol support, but really, it 378 works fine like this... 379 OK, it 'looks like' the low level and server support is 380 now working okay. The code is a bit hard to read and 381 could probably use some macroing or other cleanups, 382 but I'll save that for later. 383 384 Now to start adding the GTK+ GUI stuff again and integrate 385 it with the data returning from the server and the CD 386 control process. 387 388 Well, the UI is sort of running. It complains a little, 389 and puts two 'NO DISC' pixmaps in the window, but it 390 starts at least! 391 392 05/09/98 Added local cddb database support. It successfully reads 393 the disc info from the database. 394 395 05/03/98 Restarted this whole project from the ground up. I am 396 writing the CD control and cddb support code first, 397 and then adding the GUI interface. 398 399 cd_control and cddb will be seperate processes forked 400 from the main process at startup. 401 402 -------------------------------------------------------------------- */ 403 #include <stdio.h> 404 #include <unistd.h> 405 #include <string.h> 406 #include <stdlib.h> 407 #include <signal.h> 408 #include <sys/types.h> 409 #include <sys/wait.h> 410 #include <gtk/gtk.h> 411 #include <gdk/gdk.h> 412 #include <gdk/gdkx.h> 413 #include "cd_control.h" 414 #include "cddbd.h" 415 #include "cddb.h" 416 #include "xfreecd.h" 417 #include "xpm_button.h" 418 419 420 /* Include all the bitmaps used (in xpm format) */ 421 #include "bitmaps/ffup.xpm" 422 #include "bitmaps/ffdn.xpm" 423 #include "bitmaps/rewup.xpm" 424 #include "bitmaps/rewdn.xpm" 425 #include "bitmaps/sfwddn.xpm" 426 #include "bitmaps/srevdn.xpm" 427 #include "bitmaps/stopup.xpm" 428 #include "bitmaps/playup.xpm" 429 #include "bitmaps/playdn.xpm" 430 #include "bitmaps/pauseup.xpm" 431 #include "bitmaps/ejup.xpm" 432 #include "bitmaps/ejdn.xpm" 433 #include "bitmaps/exitup.xpm" 434 #include "bitmaps/exitdn.xpm" 435 #include "bitmaps/helpup.xpm" 436 #include "bitmaps/helpdn.xpm" 437 #include "bitmaps/rptup.xpm" 438 #include "bitmaps/rptdn.xpm" 439 #include "bitmaps/rptupact.xpm" 440 #include "bitmaps/volup.xpm" 441 #include "bitmaps/voldn.xpm" 442 #include "bitmaps/null.xpm" 443 #include "bitmaps/nodisc.xpm" 444 #include "bitmaps/plstrkup.xpm" 445 #include "bitmaps/plstrkdn.xpm" 446 #include "bitmaps/mnstrkup.xpm" 447 #include "bitmaps/mnstrkdn.xpm" 448 #include "bitmaps/plscdup.xpm" 449 #include "bitmaps/plscddn.xpm" 450 #include "bitmaps/mnscdup.xpm" 451 #include "bitmaps/mnscddn.xpm" 452 #include "bitmaps/minus.xpm" 453 #include "bitmaps/bar.xpm" 454 #include "bitmaps/redbar.xpm" 455 #include "bitmaps/nobar.xpm" 456 #include "bitmaps/a0.xpm" 457 #include "bitmaps/a1.xpm" 458 #include "bitmaps/a2.xpm" 459 #include "bitmaps/a3.xpm" 460 #include "bitmaps/a4.xpm" 461 #include "bitmaps/a5.xpm" 462 #include "bitmaps/a6.xpm" 463 #include "bitmaps/a7.xpm" 464 #include "bitmaps/a8.xpm" 465 #include "bitmaps/a9.xpm" 466 #include "bitmaps/an.xpm" 467 #include "bitmaps/b0.xpm" 468 #include "bitmaps/b1.xpm" 469 #include "bitmaps/b2.xpm" 470 #include "bitmaps/b3.xpm" 471 #include "bitmaps/b4.xpm" 472 #include "bitmaps/b5.xpm" 473 #include "bitmaps/b6.xpm" 474 #include "bitmaps/b7.xpm" 475 #include "bitmaps/b8.xpm" 476 #include "bitmaps/b9.xpm" 477 #include "bitmaps/bn.xpm" 478 479 480 #undef DEBUG1 481 #undef DEBUG2 482 #undef DEBUG3 483 #undef DEBUG4 484 #undef DEBUG5 485 #undef DEBUG6 486 #undef DEBUG7 487 #undef DEBUG8 488 #undef DEBUG9 489 #undef MAIL_DEBUG 490 491 #define CDROM_NODISC 0 492 #define CDROM_PLAYING 1 493 #define CDROM_PAUSED 2 494 495 #define TRACK_ELAPSED 0 496 #define TRACK_REMAIN 1 497 #define CD_ELAPSED 2 498 #define CD_REMAIN 3 499 500 501 #define HELP_TEXT( x ) gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, x, -1) 502 #define COLOR_TEXT( x, y ) gtk_text_insert (GTK_TEXT (text), NULL, y, NULL, x, -1) 503 504 int read_config( struct CONFIG * ); 505 int run_gtk(); 506 void free_config( struct CONFIG * ); 507 gint delete_event(GtkWidget *, gpointer); 508 void destroy (GtkWidget *, gpointer); 509 void cd_fd_read( gpointer, gint, GdkInputCondition); 510 void cddbd_fd_read( gpointer, gint, GdkInputCondition); 511 void ff_press(GtkWidget *, GdkEventButton *); 512 void ff_release(GtkWidget *, GdkEventButton *); 513 void rew_press(GtkWidget *, GdkEventButton *); 514 void rew_release(GtkWidget *, GdkEventButton *); 515 void play_press(GtkWidget *, GdkEventButton *); 516 void play_release(GtkWidget *, GdkEventButton *); 517 void eject_press(GtkWidget *, GdkEventButton *); 518 void eject_release(GtkWidget *, GdkEventButton *); 519 void ex_press(GtkWidget *, GdkEventButton *); 520 void ex_release(GtkWidget *, GdkEventButton *); 521 void help_press(GtkWidget *, GdkEventButton *); 522 void help_release(GtkWidget *, GdkEventButton *); 523 void tdisp_press(GtkWidget *, GdkEventButton *); 524 void tdisp_release(GtkWidget *, GdkEventButton *); 525 void rpt_press(GtkWidget *, GdkEventButton *); 526 void rpt_release(GtkWidget *, GdkEventButton *); 527 void vol_press(GtkWidget *, GdkEventButton *); 528 void vol_release(GtkWidget *, GdkEventButton *); 529 void set_vol( int amount ); 530 static int expose_display( GtkWidget *, GdkEventExpose *); 531 gint update_cdrom( gpointer ); 532 void play_next(); 533 void play_previous(); 534 void pause_cdrom(); 535 void resume_cdrom(); 536 void play_track(int); 537 void update_display(); 538 void stop_cdrom(); 539 void eject_cdrom(); 540 int cdrom_status(); 541 int write_config( struct CONFIG * ); 542 static void display_released (GtkWidget *); 543 static void display_motion (GtkWidget *, GdkEventMotion *); 544 static void display_pressed (GtkWidget *, GdkEventButton *); 545 void wait_status(); 546 gint show_tracks(); 547 void set_eject( int ); 548 549 550 typedef struct _cursoroffset {gint x,y;} CursorOffset; 551 552 /* Global Variables and structures */ 553 struct CDINFO cdinfo; 554 struct CONFIG config; 555 556 char cmnd[2]; 557 int cd_pid, cd_fd, /* Communications with the CD control */ 558 cddbd_pid, cddbd_fd; /* Communications with cd database */ 559 gint gdk_cd_fd, 560 gdk_cddbd_fd; 561 562 563 static GdkWindow *root_win = NULL; 564 565 566 struct _pbutton ff, /* Fast Forward button */ 567 rew, /* Rewind */ 568 play, /* Play */ 569 vol, /* Volume control */ 570 eject, /* Elect */ 571 tdisp, /* Time Display */ 572 rpt, /* Repeat */ 573 ex, /* Exit button */ 574 help; /* Help */ 575 576 /* Display pixmaps and current disc status */ 577 struct _display 578 { 579 GtkWidget *main_window; /* The main window */ 580 GtkWidget *vbox; /* Vbox holding everything */ 581 GtkWidget *wid; /* Widget for placing pixmaps */ 582 GtkWidget *progress; /* CDDBD progress dialog window */ 583 GtkWidget *plabel; /* Progress dialog label */ 584 GtkWidget *twindow; /* Track Window pointer */ 585 GtkWidget *tclist; /* List of tracks */ 586 GtkWidget *ttitle; /* Track list title widget */ 587 GtkWidget *tewindow; /* Track Edit Window */ 588 GtkWidget *teentry; /* Track Entry Window */ 589 GtkWidget *teclist; /* Clist for Track Edit */ 590 GtkWidget *cb; /* ComboBox list of Servers */ 591 GdkPixmap *image; /* image to paint onto */ 592 GdkPixmap *null_pixmap; /* Blank with : */ 593 GdkBitmap *null_mask; 594 GdkPixmap *nodisc_pixmap; /* NO DISC */ 595 GdkBitmap *nodisc_mask; 596 GdkPixmap *minus_pixmap; /* Minus sign */ 597 GdkBitmap *minus_mask; 598 GdkPixmap *playup_pixmap; /* Play in white */ 599 GdkBitmap *playup_mask; 600 GdkPixmap *playdn_pixmap; 601 GdkBitmap *playdn_mask; 602 GdkPixmap *pauseup_pixmap; /* Pause bars in white */ 603 GdkBitmap *pauseup_mask; 604 GdkPixmap *stopup_pixmap; /* play and pause in gray */ 605 GdkBitmap *stopup_mask; 606 GdkPixmap *sfwddn_pixmap; /* Seek forward down button */ 607 GdkBitmap *sfwddn_mask; 608 GdkPixmap *srevdn_pixmap; /* Seek reverse down button */ 609 GdkBitmap *srevdn_mask; 610 GdkPixmap *rptupact_pixmap; /* repeat active (white) */ 611 GdkBitmap *rptupact_mask; 612 GdkPixmap *plstrkup_pixmap; /* Elapsed track time */ 613 GdkBitmap *plstrkup_mask; 614 GdkPixmap *plstrkdn_pixmap; 615 GdkBitmap *plstrkdn_mask; 616 GdkPixmap *mnstrkup_pixmap; /* Remaining track time */ 617 GdkBitmap *mnstrkup_mask; 618 GdkPixmap *mnstrkdn_pixmap; 619 GdkBitmap *mnstrkdn_mask; 620 GdkPixmap *plscdup_pixmap; /* Elapsed CD time */ 621 GdkBitmap *plscdup_mask; 622 GdkPixmap *plscddn_pixmap; 623 GdkBitmap *plscddn_mask; 624 GdkPixmap *mnscdup_pixmap; /* Remaining CD time */ 625 GdkBitmap *mnscdup_mask; 626 GdkPixmap *mnscddn_pixmap; 627 GdkBitmap *mnscddn_mask; 628 GdkPixmap *bar_pixmap; /* Volume Bargraph */ 629 GdkBitmap *bar_mask; 630 GdkPixmap *redbar_pixmap; /* Volume Bargraph */ 631 GdkBitmap *redbar_mask; 632 GdkPixmap *nobar_pixmap; /* Volume Bargraph */ 633 GdkBitmap *nobar_mask; 634 635 GdkPixmap *a_pixmap[11]; /* Large digits */ 636 GdkBitmap *a_mask[11]; 637 GdkPixmap *b_pixmap[11]; /* Small Digits */ 638 GdkBitmap *b_mask[11]; 639 640 GString *tmp_category; /* New Category entry */ 641 GString *tmp_title; /* Title storage for edit_tracks*/ 642 GString *tmp_track[99]; /* Song names for editing */ 643 int tmp_row; /* Current row in tmp_track */ 644 645 short startup; /* Startup State machine */ 646 short cddb_lock; /* Lock cddb access while busy */ 647 int status; /* Current player status 648 0 = no disc in drive 649 1 = stopped 650 2 = playing 651 3 = paused 652 */ 653 int playbtn; /* State of play button, same as 654 above (use CDROM_ equates) 655 */ 656 int time; /* Time mode */ 657 int track, /* track # - 1 to end of CD */ 658 minute, 659 second; /* Info for the display */ 660 int repeat; /* Repeat status */ 661 } display; 662 663 664 665 /* Signal handling code */ 666 static int caught_fatal_sig = 0; 667 668 static void on_signal (int sig_num) 669 { 670 if (caught_fatal_sig) 671 /* raise (sig_num);*/ 672 kill (getpid (), sig_num); 673 caught_fatal_sig = 1; 674 675 switch (sig_num) 676 { 677 case SIGHUP: 678 g_print("sighup caught\n"); 679 gdk_exit(1); 680 break; 681 case SIGINT: 682 g_print("sigint caught\n"); 683 gdk_exit(1); 684 break; 685 case SIGQUIT: 686 g_print("sigquit caught\n"); 687 gdk_exit(1); 688 break; 689 case SIGABRT: 690 g_print("sigabrt caught\n"); 691 gdk_exit(1); 692 break; 693 case SIGBUS: 694 g_print("sigbus caught\n"); 695 destroy(NULL,NULL); 696 break; 697 case SIGSEGV: 698 g_print("sigsegv caught\n"); 699 destroy(NULL,NULL); 700 break; 701 case SIGPIPE: 702 g_print("sigpipe caught\n"); 703 gdk_exit(1); 704 break; 705 case SIGTERM: 706 g_print("sigterm caught\n"); 707 gdk_exit(1); 708 break; 709 case SIGFPE: 710 g_print("sigfpe caught\n"); 711 destroy(NULL,NULL); 712 break; 713 default: 714 g_print("unknown signal\n"); 715 destroy(NULL,NULL); 716 break; 717 } 718 } 719 720 static void on_sig_child (int sig_num) 721 { 722 int pid; 723 int status; 724 725 while (1) 726 { 727 pid = waitpid (WAIT_ANY, &status, WNOHANG); 728 if (pid <= 0) 729 break; 730 } 731 } 732 733 734 /* ------------------------------------------------------------------------ 735 Where it all begins... 736 ------------------------------------------------------------------------ */ 737 int main( int argc, char *argv[] ) 738 { 739 int x, 740 x_ret, 741 y_ret, 742 w_ret, 743 h_ret, 744 stat=0; 745 746 bzero( &cdinfo, sizeof( struct CDINFO ) ); 747 748 /* Start up the CD control process */ 749 if( ( cd_fd = start_cd_control( &cd_pid ) ) < 0 ) 750 { 751 perror("start_cd_control error"); 752 exit(-1); 753 } 754 755 /* Start up the CDDBD control process */ 756 if( ( cddbd_fd = start_cddbd( &cddbd_pid ) ) < 0 ) 757 { 758 perror("start_cd_dbd error"); 759 exit(-1); 760 } 761 762 /* Startup GTK */ 763 gtk_init (&argc, &argv); 764 765 /* Tell gdk to watch the cd control and cddb pipes for reading */ 766 gdk_cd_fd = gdk_input_add( cd_fd, GDK_INPUT_READ, cd_fd_read, 0 ); 767 gdk_cddbd_fd = gdk_input_add( cddbd_fd, GDK_INPUT_READ, cddbd_fd_read, 0 ); 768 769 /* Get the -geometry parameters */ 770 for( x = 0; x < argc; x++ ) 771 { 772 if( (strcasecmp( argv[x], "-geometry" ) == 0) || (strcasecmp( argv[x], "-geom" ) == 0) ) 773 { 774 if( argv[x+1] != NULL ) 775 { 776 #ifdef DEBUG7 777 g_print("Passing %s to XParseGeometry\n", argv[x+1]); 778 #endif 779 780 stat = XParseGeometry( argv[x+1], &x_ret, &y_ret, &w_ret, &h_ret ); 781 782 #ifdef DEBUG7 783 g_print("%d = XParseGeometry( s, %d, %d, %d, %d )\n", 784 stat, x_ret, y_ret, w_ret, h_ret ); 785 #endif 786 } 787 } 788 } 789 790 /* Handle some signals */ 791 signal (SIGHUP, on_signal); 792 signal (SIGINT, on_signal); 793 signal (SIGQUIT, on_signal); 794 signal (SIGABRT, on_signal); 795 signal (SIGBUS, on_signal); 796 signal (SIGSEGV, on_signal); 797 signal (SIGPIPE, on_signal); 798 signal (SIGTERM, on_signal); 799 signal (SIGFPE, on_signal); 800 801 /* Handle child exits */ 802 signal (SIGCHLD, on_sig_child); 803 804 run_gtk( stat, x_ret, y_ret ); 805 806 gdk_input_remove( gdk_cd_fd ); 807 gdk_input_remove( gdk_cddbd_fd ); 808 809 /* Tell cd_control to quit */ 810 cmnd[0] = CD_QUIT; 811 cmnd[1] = 0; 812 if( write( cd_fd, &cmnd, 2 ) < 0 ) 813 { 814 perror("write to cd_control error"); 815 close( cd_fd ); 816 exit(-1); 817 } 818 819 /* Tell cddbd to quit */ 820 cdinfo.cddbd_cmnd = DB_QUIT; 821 if( write( cddbd_fd, &cdinfo, sizeof( struct CDINFO ) ) < 0 ) 822 { 823 perror("write to cddbd error"); 824 close( cd_fd ); 825 close( cddbd_fd ); 826 exit(-1); 827 } 828 829 close( cd_fd ); 830 close( cddbd_fd ); 831 return(0); 832 } 833 834 835 836 /* ----- subroutines follow ------ */ 837 838 839 void send_device() 840 { 841 char buffer[80]; 842 843 /* Send the CD device to the cd_control process */ 844 buffer[0] = CD_SET_DEVICE; 845 buffer[1] = 0; 846 if( write( cd_fd, buffer, 2 ) < 0 ) 847 { 848 perror("write to cd_control error - 1a"); 849 } 850 851 sprintf( buffer, "%s\n", config.device ); 852 if( write( cd_fd, buffer, strlen(buffer) ) < 0 ) 853 { 854 perror("write to cd_control error - 1b"); 855 } 856 } 857 858 859 /* ------------------------------------------------------------------------ 860 Read the configuration file from $HOME/.xfreecdrc 861 862 Return -2 if a malloc fails 863 ------------------------------------------------------------------------ */ 864 int read_config( struct CONFIG *config ) 865 { 866 FILE *fp; 867 char fname[1024], 868 line[80], 869 *p; 870 struct SITE *sp, *sp2; 871 872 if( ( p = getenv( "HOME" ) ) == NULL ) 873 { 874 g_print("Cannot find HOME enviornmental variable\n"); 875 return(-1); 876 } 877 878 strncpy( fname, p, 1023 ); 879 if( fname[strlen(fname)-1] != '/' ) 880 strcat( fname, "/" ); 881 strcat( fname, ".xfreecdrc" ); 882 883 if( ( fp = fopen( fname, "rb" ) ) == NULL ) 884 { 885 /* Setup reasonable defaults */ 886 887 /* Setup for the default device (/dev/cdrom) */ 888 if( ( config->device = (char *) malloc( strlen(DEFAULT_DEVICE)+1 ) ) == NULL ) 889 { 890 return(-2); 891 } 892 strcpy( config->device, DEFAULT_DEVICE ); 893 894 /* Get some memory for the path to the local database. 895 By default I put this in the user's home directory ~/.cddb 896 */ 897 if( ( config->local_cddb = (char *) malloc( strlen(DEFAULT_CDDB_PATH)+1 ) ) == NULL ) 898 { 899 return(-2); 900 } 901 strcpy( config->local_cddb, DEFAULT_CDDB_PATH ); 902 strcpy( cdinfo.local_cddb, config->local_cddb ); 903 904 /* Get some memory for the cddbd email address */ 905 if( ( config->to_cddbd = (char *) malloc( strlen(DEFAULT_TO_CDDBD)+1 ) ) == NULL ) 906 { 907 return(-2); 908 } 909 strcpy( config->to_cddbd, DEFAULT_TO_CDDBD ); 910 911 /* Get some memory for the SITE */ 912 if( ( config->server = (struct SITE *) malloc( sizeof(struct SITE) ) ) == NULL ) 913 { 914 return(-2); 915 } 916 917 bzero( config->server, sizeof(struct SITE) ); 918 919 /* Fill in the site with cddb.cddb.com */ 920 if( ( config->server->name = (char *) malloc( strlen(DEFAULT_SERVER)+1 ) ) == NULL ) 921 { 922 return(-2); 923 } 924 strcpy( config->server->name, DEFAULT_SERVER ); 925 config->server->port = 888; 926 config->server->next = NULL; 927 928 /* Set current server to the default */ 929 if( ( config->current = (char *) malloc( strlen(DEFAULT_SERVER)+1 ) ) == NULL ) 930 { 931 return(-2); 932 } 933 strcpy( config->current, DEFAULT_SERVER ); 934 935 config->done_eject = 0; /* Eject when done playing */ 936 config->exit_eject = 0; /* Eject on exit when not playing */ 937 config->startup = 1; /* Play at startup */ 938 config->cddb = 0; 939 config->changer = 0; 940 config->saved = 0; /* Needs to be saved */ 941 942 /* Write this as the default */ 943 return( write_config( config ) ); 944 } 945 946 /* Process the lines in the file */ 947 while( fgets( line, 80, fp ) != NULL ) 948 { 949 if( (line[0] == '#') || (line[0] == '\n') ) 950 continue; 951 952 p = strtok( line, "= \n" ); 953 if( strcmp( p, "DEVICE" ) == 0 ) 954 { 955 p = strtok( NULL, "= \n" ); 956 /* Get some memory for the device */ 957 if( ( config->device = (char *) malloc( strlen(p)+1 ) ) == NULL ) 958 { 959 fclose( fp ); 960 return(-2); 961 } 962 strcpy( config->device, p ); 963 964 continue; 965 } 966 967 if( strcmp( p, "LOCAL_CDDB" ) == 0 ) 968 { 969 p = strtok( NULL, "= \n" ); 970 /* Get some memory for the path to the local database. 971 */ 972 if( ( config->local_cddb = (char *) malloc( strlen(p)+1 ) ) == NULL ) 973 { 974 fclose( fp ); 975 return(-2); 976 } 977 strcpy( config->local_cddb, p ); 978 strcpy( cdinfo.local_cddb, p ); 979 continue; 980 } 981 982 if( strcmp( p, "TO_CDDBD" ) == 0 ) 983 { 984 p = strtok( NULL, "= \n" ); 985 /* Get some memory for the path to the local database. 986 */ 987 if( ( config->to_cddbd = (char *) malloc( strlen(p)+1 ) ) == NULL ) 988 { 989 fclose( fp ); 990 return(-2); 991 } 992 strcpy( config->to_cddbd, p ); 993 continue; 994 } 995 996 if( strcmp( p, "SERVER" ) == 0 ) 997 { 998 p = strtok( NULL, "=: \n" ); 999 1000 /* Reserve some space for this server, add it to the end of the list */ 1001 if( ( sp = (struct SITE *) malloc( sizeof(struct SITE) ) ) == NULL ) 1002 { 1003 return(-2); 1004 } 1005 bzero( sp, sizeof(struct SITE) ); 1006 1007 /* Reserve space for the name */ 1008 if( ( sp->name = (char *) malloc( strlen(p)+1 ) ) == NULL ) 1009 { 1010 return(-2); 1011 } 1012 strcpy( sp->name, p ); 1013 1014 p = strtok( NULL, "=: \n" ); 1015 sp->port = atoi(p); 1016 sp->next = NULL; 1017 1018 /* Is it the first in the list? */ 1019 if( config->server == NULL ) 1020 { 1021 /* Yep, First in the list */ 1022 config->server = sp; 1023 } else { 1024 /* Walk to the end of the list (no cuts!!) */ 1025 sp2 = config->server; 1026 while( sp2->next != NULL ) 1027 { 1028 sp2 = sp2->next; 1029 } 1030 1031 /* Add the new site to the end of the list */ 1032 sp2->next = sp; 1033 } 1034 1035 continue; 1036 } 1037 1038 if( strcmp( p, "CURRENT" ) == 0 ) 1039 { 1040 p = strtok( NULL, "= \n" ); 1041 1042 /* Get some memory for the current server name */ 1043 if( ( config->current = (char *) malloc( strlen(p)+1 ) ) == NULL ) 1044 { 1045 fclose( fp ); 1046 return(-2); 1047 } 1048 strcpy( config->current, p ); 1049 continue; 1050 } 1051 1052 if( strcmp( p, "DONE_EJECT" ) == 0 ) 1053 { 1054 p = strtok( NULL, "= \n" ); 1055 config->done_eject = atoi( p ); 1056 continue; 1057 } 1058 1059 if( strcmp( p, "EXIT_EJECT" ) == 0 ) 1060 { 1061 p = strtok( NULL, "= \n" ); 1062 config->exit_eject = atoi( p ); 1063 set_eject( config->exit_eject ); /* Tell the CD_CONTROL device about state */ 1064 continue; 1065 } 1066 1067 if( strcmp( p, "STARTUP" ) == 0 ) 1068 { 1069 p = strtok( NULL, "= \n" ); 1070 config->startup = atoi( p ); 1071 continue; 1072 } 1073 1074 if( strcmp( p, "CDDB" ) == 0 ) 1075 { 1076 p = strtok( NULL, "= \n" ); 1077 config->cddb = atoi( p ); 1078 continue; 1079 } 1080 1081 if( strcmp( p, "CHANGER" ) == 0 ) 1082 { 1083 p = strtok( NULL, "= \n" ); 1084 config->changer = atoi( p ); 1085 continue; 1086 } 1087 1088 1089 } 1090 fclose( fp ); 1091 1092 1093 /* 1094 I've added config->to_cddbd since last release, so if it wasn't read from the 1095 rcfile give it a default value so people don't need to erase their old rcfile 1096 */ 1097 if( config->to_cddbd == NULL ) 1098 { 1099 if( ( config->to_cddbd = (char *) malloc( strlen( DEFAULT_TO_CDDBD ) + 1 ) ) == NULL ) 1100 { 1101 fclose( fp ); 1102 return(-2); 1103 } 1104 strcpy( config->to_cddbd, DEFAULT_TO_CDDBD ); 1105 } 1106 1107 config->saved = 1; /* Just read it, same as saved file */ 1108 1109 return 0; 1110 } 1111 1112 1113 /* ------------------------------------------------------------------------ 1114 Write the configuration file to $HOME/.xfreecdrc 1115 ------------------------------------------------------------------------ */ 1116 int write_config( struct CONFIG *config ) 1117 { 1118 FILE *fp; 1119 char fname[1024], 1120 *p; 1121 struct SITE *sp; 1122 1123 /* Already saved, no need to save it again */ 1124 if( config->saved == 1 ) 1125 return(0); 1126 1127 if( ( p = getenv( "HOME" ) ) == NULL ) 1128 { 1129 g_print("Cannot find HOME enviornmental variable\n"); 1130 return(-1); 1131 } 1132 1133 strncpy( fname, p, 1023 ); 1134 if( fname[strlen(fname)-1] != '/' ) 1135 strcat( fname, "/" ); 1136 strcat( fname, ".xfreecdrc" ); 1137 1138 if( ( fp = fopen( fname, "wb" ) ) == NULL ) 1139 { 1140 return(-2); 1141 } 1142 1143 fprintf( fp, "# XfreeCD v%s configuration file\n", VERSION ); 1144 fprintf( fp, "#\n"); 1145 fprintf( fp, "DEVICE=%s\n", config->device ); 1146 fprintf( fp, "LOCAL_CDDB=%s\n", config->local_cddb ); 1147 fprintf( fp, "TO_CDDBD=%s\n", config->to_cddbd ); 1148 1149 /* Walk down the list of servers */ 1150 sp = config->server; 1151 while( sp != NULL ) 1152 { 1153 fprintf( fp, "SERVER=%s:%d\n", sp->name, sp->port); 1154 sp = sp->next; 1155 } 1156 1157 fprintf( fp, "CURRENT=%s\n", config->current ); 1158 fprintf( fp, "DONE_EJECT=%d\n", config->done_eject ); 1159 fprintf( fp, "EXIT_EJECT=%d\n", config->exit_eject ); 1160 fprintf( fp, "STARTUP=%d\n", config->startup ); 1161 fprintf( fp, "CDDB=%d\n", config->cddb ); 1162 fprintf( fp, "CHANGER=%d\n", config->changer ); 1163 1164 fclose( fp ); 1165 1166 config->saved = 1; /* config is now same as saved on disk */ 1167 1168 return 0; 1169 } 1170 1171 1172 1173 /* ----------------------------------------------------------------------- 1174 Free up the info used in the cdinfo structure 1175 ----------------------------------------------------------------------- */ 1176 void free_cdinfo() 1177 { 1178 int x; 1179 1180 #ifdef DEBUG8 1181 g_print("Freeing any used extended data\n" ); 1182 #endif 1183 1184 if( cdinfo.title != NULL ) 1185 { 1186 g_string_free( cdinfo.title, 1 ); 1187 cdinfo.title = NULL; 1188 } 1189 1190 if( cdinfo.category != NULL ) 1191 { 1192 g_string_free( cdinfo.category, 1 ); 1193 cdinfo.category = NULL; 1194 } 1195 1196 for( x = 0; x < 99; x++ ) 1197 { 1198 if( cdinfo.name[x] != NULL ) 1199 { 1200 g_string_free( cdinfo.name[x], 1 ); 1201 cdinfo.name[x] = NULL; 1202 } 1203 } 1204 1205 1206 if( cdinfo.extd != NULL ) 1207 { 1208 g_string_free( cdinfo.extd, 1 ); 1209 cdinfo.extd = NULL; 1210 } 1211 1212 for( x = 0; x < 99; x++ ) 1213 { 1214 if( cdinfo.extt[x] != NULL ) 1215 { 1216 g_string_free( cdinfo.extt[x], 1 ); 1217 cdinfo.extt[x] = NULL; 1218 } 1219 } 1220 1221 /* Clean up the display's temporary storage */ 1222 if( display.tmp_category != NULL ) 1223 { 1224 g_string_free( display.tmp_category, 1 ); 1225 display.tmp_category = NULL; 1226 } 1227 1228 if( display.tmp_title != NULL ) 1229 { 1230 g_string_free( display.tmp_title, 1 ); 1231 display.tmp_title = NULL; 1232 } 1233 1234 for( x = 0; x < 99; x++ ) 1235 { 1236 if( display.tmp_track[x] != NULL ) 1237 { 1238 g_string_free( display.tmp_track[x], 1 ); 1239 display.tmp_track[x] = NULL; 1240 } 1241 } 1242 } 1243 1244 1245 /* ----------------------------------------------------------------------- 1246 Free up any memory used by the config structure to store the paths 1247 and site names. 1248 ----------------------------------------------------------------------- */ 1249 void free_config( struct CONFIG *config ) 1250 { 1251 struct SITE *sp; 1252 1253 /* Need to free up memory usage */ 1254 free( config->local_cddb ); 1255 free( config->device ); 1256 free( config->to_cddbd ); 1257 1258 /* Walk the server list, freeing up memory */ 1259 while( config->server != NULL ) 1260 { 1261 sp = config->server; 1262 config->server = config->server->next; 1263 free( sp->name ); 1264 free( sp ); 1265 } 1266 1267 /* Free up the dynamically allocated strings in cdinfo */ 1268 free_cdinfo(); 1269 } 1270 1271 1272 1273 /* ----------------------------------------------------------------------- 1274 Load the CD info from the local database or set defaults 1275 ----------------------------------------------------------------------- */ 1276 void local_cddb() 1277 { 1278 1279 #ifdef DEBUG1 1280 g_print("Loading local Database\n"); 1281 #endif 1282 1283 /* No internet support, just try and read the local DB */ 1284 if( read_cddb( &cdinfo ) < 0 ) 1285 { 1286 1287 #ifdef DEBUG1 1288 g_print("Not found on disk, defaulting\n"); 1289 #endif 1290 1291 /* Unknown title */ 1292 if( cdinfo.title == NULL ) 1293 cdinfo.title = g_string_new( "Unknown CD" ); 1294 else 1295 cdinfo.title = g_string_assign( cdinfo.title, "Unknown CD" ); 1296 1297 if( cdinfo.category == NULL ) 1298 cdinfo.category = g_string_new( "misc" ); 1299 else 1300 cdinfo.category = g_string_assign( cdinfo.category, "misc" ); 1301 1302 /* Set a default revision, so they can edit the list */ 1303 cdinfo.revision = 0; 1304 } 1305 1306 #ifdef DEBUG9 1307 g_print("local_cddb() revision = %d\n", cdinfo.revision ); 1308 #endif 1309 1310 } 1311 1312 1313 /* ----------------------------------------------------------------------- 1314 The Main GTK setup routine 1315 ----------------------------------------------------------------------- */ 1316 int run_gtk( int stat, int x_ret, int y_ret ) 1317 { 1318 GtkWidget *window, 1319 *button, 1320 *hbox1, 1321 *hbox2, 1322 *table; 1323 GtkTooltips *tips; 1324 GtkStyle *style; 1325 GdkColor tip_color; 1326 GdkColormap *colormap; 1327 gint timer; 1328 CursorOffset *icon_pos; 1329 int x_pos, 1330 y_pos; 1331 1332 bzero( &config, sizeof( struct CONFIG ) ); 1333 bzero( &display, sizeof( struct _display ) ); 1334 bzero( &cdinfo, sizeof( struct CDINFO ) ); 1335 1336 cdinfo.revision = -1; /* Initalize the revision number */ 1337 1338 /* Copyright info, version info */ 1339 g_print("XfreeCD v%s\n", VERSION ); 1340 g_print("Copyright 1998 by Brian C. Lane\n<http://www.tatoosh.com/nexus>\n\n"); 1341 1342 root_win = gdk_window_foreign_new (GDK_ROOT_WINDOW ()); 1343 1344 window = gtk_window_new (GTK_WINDOW_TOPLEVEL); 1345 display.main_window = window; 1346 gtk_container_border_width( GTK_CONTAINER( window ), 0 ); 1347 1348 /* Give it a name */ 1349 gtk_window_set_title (GTK_WINDOW (window), "XfreeCD"); 1350 gtk_window_set_wmclass(GTK_WINDOW(window), "XfreeCD", NULL ); 1351 1352 /* when the window is given the "delete_event" signal (this is given 1353 * by the window manager (usually the 'close' option, or on the 1354 * titlebar), we ask it to call the delete_event () function 1355 * as defined above. The data passed to the callback 1356 * function is NULL and is ignored in the callback. */ 1357 gtk_signal_connect (GTK_OBJECT (window), "delete_event", 1358 GTK_SIGNAL_FUNC (delete_event), NULL); 1359 1360 /* here we connect the "destroy" event to a signal handler. 1361 * This event occurs when we call gtk_widget_destroy() on the window, 1362 * or if we return 'FALSE' in the "delete_event" callback. */ 1363 gtk_signal_connect (GTK_OBJECT (window), "destroy", 1364 GTK_SIGNAL_FUNC (destroy), NULL); 1365 1366 gtk_widget_realize(window); 1367 1368 /* Start up a new list of tool tips */ 1369 tips = gtk_tooltips_new(); 1370 1371 /* Show the tooltips after the cursor has paused for 2 seconds */ 1372 gtk_tooltips_set_delay( tips, 2000 ); 1373 1374 /* 1375 * This section fills in all the data structures used by the xpm_button 1376 * subroutine call to create buttons. 1377 * Eventually this will be more automatic/cleaner/maybe a widget? 1378 */ 1379 1380 ff.up_xpm = (gchar *) ffup_xpm; 1381 ff.dn_xpm = (gchar *) ffdn_xpm; 1382 ff.press = &ff_press; 1383 ff.release = &ff_release; 1384 1385 rew.up_xpm = (gchar *) rewup_xpm; 1386 rew.dn_xpm = (gchar *) rewdn_xpm; 1387 rew.press = &rew_press; 1388 rew.release = &rew_release; 1389 1390 play.up_xpm = (gchar *) stopup_xpm; 1391 play.dn_xpm = (gchar *) playdn_xpm; 1392 play.press = &play_press; 1393 play.release = &play_release; 1394 1395 eject.up_xpm = (gchar *) ejup_xpm; 1396 eject.dn_xpm = (gchar *) ejdn_xpm; 1397 eject.press = &eject_press; 1398 eject.release = &eject_release; 1399 1400 ex.up_xpm = (gchar *) exitup_xpm; 1401 ex.dn_xpm = (gchar *) exitdn_xpm; 1402 ex.press = &ex_press; 1403 ex.release = &ex_release; 1404 1405 help.up_xpm = (gchar *) helpup_xpm; 1406 help.dn_xpm = (gchar *) helpdn_xpm; 1407 help.press = &help_press; 1408 help.release = &help_release; 1409 1410 tdisp.up_xpm = (gchar *) plstrkup_xpm; 1411 tdisp.dn_xpm = (gchar *) plstrkdn_xpm; 1412 tdisp.press = &tdisp_press; 1413 tdisp.release = &tdisp_release; 1414 1415 rpt.up_xpm = (gchar *) rptup_xpm; 1416 rpt.dn_xpm = (gchar *) rptdn_xpm; 1417 rpt.press = &rpt_press; 1418 rpt.release = &rpt_release; 1419 1420 vol.up_xpm = (gchar *) volup_xpm; 1421 vol.dn_xpm = (gchar *) voldn_xpm; 1422 vol.press = &vol_press; 1423 vol.release = &vol_release; 1424 1425 1426 /* 1427 * The XfreeCD window consists of: 1428 * one vertical box that contains: 1429 * Two vertical boxes 1430 * The top one with hbox of the display and right justified, a 3x2 table 1431 * The bottom one with a hbox of 3 buttons 1432 */ 1433 1434 /* Make a vbox to hold our hboxes */ 1435 display.vbox = gtk_vbox_new( FALSE, 0 ); 1436 gtk_container_add( GTK_CONTAINER( window ), display.vbox ); 1437 gtk_widget_show( display.vbox ); 1438 1439 /* Make a hbox to hold the bottom row of buttons REW/PLAY/FF */ 1440 hbox1 = gtk_hbox_new( FALSE, 0 ); 1441 gtk_box_pack_end( GTK_BOX( display.vbox ), hbox1, FALSE, FALSE, 0 ); 1442 gtk_widget_show( hbox1 ); 1443 1444 /* Make a hbox to put the table into */ 1445 hbox2 = gtk_hbox_new( FALSE, 0 ); 1446 gtk_box_pack_start( GTK_BOX( display.vbox ), hbox2, FALSE, FALSE, 0 ); 1447 gtk_widget_show( hbox2 ); 1448 1449 /* Make the xpm_buttons and add the tooltips for each one */ 1450 button = xpm_button( window, &rew ); 1451 gtk_box_pack_start( GTK_BOX( hbox1 ), button, FALSE, FALSE, 0 ); 1452 gtk_widget_show( button ); 1453 gtk_tooltips_set_tip( tips, button, "Previous Track", "ContextHelp/buttons/Prev" ); 1454 1455 button = xpm_button( window, &play ); 1456 gtk_box_pack_start( GTK_BOX( hbox1 ), button, FALSE, FALSE, 0 ); 1457 gtk_widget_show( button ); 1458 gtk_tooltips_set_tip( tips, button, "Play/Pause", "ContextHelp/buttons/Play" ); 1459 1460 button = xpm_button( window, &ff ); 1461 gtk_box_pack_start( GTK_BOX( hbox1 ), button, FALSE, FALSE, 0 ); 1462 gtk_widget_show( button ); 1463 gtk_tooltips_set_tip( tips, button, "Next Track", "ContextHelp/buttons/Next" ); 1464 1465 /* Make a table for the 6 control buttons */ 1466 table = gtk_table_new( 2, 3, TRUE ); 1467 1468 /* Add the table to the end of the hbox (the display goes first) */ 1469 gtk_box_pack_end( GTK_BOX( hbox2 ), table, FALSE, FALSE, 0 ); 1470 1471 /* Make sure it is showing */ 1472 gtk_widget_show( table ); 1473 1474 button = xpm_button( window, &vol ); 1475 gtk_table_attach( GTK_TABLE( table ), button, 0, 1, 0, 1, 0, 0, 0, 0 ); 1476 gtk_widget_show( button ); 1477 gtk_tooltips_set_tip( tips, button, "Volume", "ContextHelp/buttons/Volume" ); 1478 1479 button = xpm_button( window, &tdisp ); 1480 gtk_table_attach( GTK_TABLE( table ), button, 1, 2, 0, 1, 0, 0, 0, 0 ); 1481 gtk_widget_show( button ); 1482 gtk_tooltips_set_tip( tips, button, "Time Display", "ContextHelp/buttons/Time" ); 1483 1484 button = xpm_button( window, &ex ); 1485 gtk_table_attach( GTK_TABLE( table ), button, 2, 3, 0, 1, 0, 0, 0, 0 ); 1486 gtk_widget_show( button ); 1487 gtk_tooltips_set_tip( tips, button, "Exit", "ContextHelp/buttons/Exit" ); 1488 1489 button = xpm_button( window, &rpt ); 1490 gtk_table_attach( GTK_TABLE( table ), button, 0, 1, 1, 2, 0, 0, 0, 0 ); 1491 gtk_widget_show( button ); 1492 gtk_tooltips_set_tip( tips, button, "Repeat", "ContextHelp/buttons/Repeat" ); 1493 1494 button = xpm_button( window, &eject ); 1495 gtk_table_attach( GTK_TABLE( table ), button, 1, 2, 1, 2, 0, 0, 0, 0 ); 1496 gtk_widget_show( button ); 1497 gtk_tooltips_set_tip( tips, button, "Eject", "ContextHelp/buttons/Eject" ); 1498 1499 button = xpm_button( window, &help ); 1500 gtk_table_attach( GTK_TABLE( table ), button, 2, 3, 1, 2, 0, 0, 0, 0 ); 1501 gtk_widget_show( button ); 1502 gtk_tooltips_set_tip( tips, button, "Help", "ContextHelp/buttons/Help" ); 1503 1504 1505 /* Get the window's style info */ 1506 style = gtk_widget_get_style( window ); 1507 1508 /* Load all the other pixmaps (some are duplicates) */ 1509 display.null_pixmap = gdk_pixmap_create_from_xpm_d( window->window, 1510 &display.null_mask, 1511 &style->bg[GTK_STATE_NORMAL], 1512 (gchar **) null_xpm ); 1513 1514 display.nodisc_pixmap = gdk_pixmap_create_from_xpm_d( window->window, 1515 &display.nodisc_mask, 1516 &style->bg[GTK_STATE_NORMAL], 1517 (gchar **) nodisc_xpm ); 1518 1519 display.minus_pixmap = gdk_pixmap_create_from_xpm_d( window->window, 1520 &display.minus_mask, 1521 &style->bg[GTK_STATE_NORMAL], 1522 (gchar **) minus_xpm ); 1523 1524 display.playup_pixmap = gdk_pixmap_create_from_xpm_d( window->window, 1525 &display.playup_mask, 1526 &style->bg[GTK_STATE_NORMAL], 1527 (gchar **) playup_xpm ); 1528 1529 display.playdn_pixmap = gdk_pixmap_create_from_xpm_d( window->window, 1530 &display.playdn_mask, 1531 &style->bg[GTK_STATE_NORMAL], 1532 (gchar **) playdn_xpm ); 1533 1534 display.pauseup_pixmap = gdk_pixmap_create_from_xpm_d( window->window, 1535 &display.pauseup_mask, 1536 &style->bg[GTK_STATE_NORMAL], 1537 (gchar **) pauseup_xpm ); 1538 1539 display.stopup_pixmap = gdk_pixmap_create_from_xpm_d( window->window, 1540 &display.stopup_mask, 1541 &style->bg[GTK_STATE_NORMAL], 1542 (gchar **) stopup_xpm ); 1543 1544 display.sfwddn_pixmap = gdk_pixmap_create_from_xpm_d( window->window, 1545 &display.sfwddn_mask, 1546 &style->bg[GTK_STATE_NORMAL], 1547 (gchar **) sfwddn_xpm ); 1548 1549 display.srevdn_pixmap = gdk_pixmap_create_from_xpm_d( window->window, 1550 &display.srevdn_mask, 1551 &style->bg[GTK_STATE_NORMAL], 1552 (gchar **) srevdn_xpm ); 1553 1554 display.rptupact_pixmap = gdk_pixmap_create_from_xpm_d( window->window, 1555 &display.rptupact_mask, 1556 &style->bg[GTK_STATE_NORMAL], 1557 (gchar **) rptupact_xpm ); 1558 1559 display.plstrkup_pixmap = gdk_pixmap_create_from_xpm_d( window->window, 1560 &display.plstrkup_mask, 1561 &style->bg[GTK_STATE_NORMAL], 1562 (gchar **) plstrkup_xpm ); 1563 1564 display.plstrkdn_pixmap = gdk_pixmap_create_from_xpm_d( window->window, 1565 &display.plstrkdn_mask, 1566 &style->bg[GTK_STATE_NORMAL], 1567 (gchar **) plstrkdn_xpm ); 1568 1569 display.mnstrkup_pixmap = gdk_pixmap_create_from_xpm_d( window->window, 1570 &display.mnstrkup_mask, 1571 &style->bg[GTK_STATE_NORMAL], 1572 (gchar **) mnstrkup_xpm ); 1573 1574 display.mnstrkdn_pixmap = gdk_pixmap_create_from_xpm_d( window->window, 1575 &display.mnstrkdn_mask, 1576 &style->bg[GTK_STATE_NORMAL], 1577 (gchar **) mnstrkdn_xpm ); 1578 1579 display.plscdup_pixmap = gdk_pixmap_create_from_xpm_d( window->window, 1580 &display.plscdup_mask, 1581 &style->bg[GTK_STATE_NORMAL], 1582 (gchar **) plscdup_xpm ); 1583 1584 display.plscddn_pixmap = gdk_pixmap_create_from_xpm_d( window->window, 1585 &display.plscddn_mask, 1586 &style->bg[GTK_STATE_NORMAL], 1587 (gchar **) plscddn_xpm ); 1588 1589 display.mnscdup_pixmap = gdk_pixmap_create_from_xpm_d( window->window, 1590 &display.mnscdup_mask, 1591 &style->bg[GTK_STATE_NORMAL], 1592 (gchar **) mnscdup_xpm ); 1593 1594 display.mnscddn_pixmap = gdk_pixmap_create_from_xpm_d( window->window, 1595 &display.mnscddn_mask, 1596 &style->bg[GTK_STATE_NORMAL], 1597 (gchar **) mnscddn_xpm ); 1598 1599 display.bar_pixmap = gdk_pixmap_create_from_xpm_d( window->window, 1600 &display.bar_mask, 1601 &style->bg[GTK_STATE_NORMAL], 1602 (gchar **) bar_xpm ); 1603 1604 display.nobar_pixmap = gdk_pixmap_create_from_xpm_d( window->window, 1605 &display.nobar_mask, 1606 &style->bg[GTK_STATE_NORMAL], 1607 (gchar **) nobar_xpm ); 1608 1609 display.redbar_pixmap = gdk_pixmap_create_from_xpm_d( window->window, 1610 &display.redbar_mask, 1611 &style->bg[GTK_STATE_NORMAL], 1612 (gchar **) redbar_xpm ); 1613 1614 display.a_pixmap[0] = gdk_pixmap_create_from_xpm_d( window->window, 1615 &display.a_mask[0], 1616 &style->bg[GTK_STATE_NORMAL], 1617 (gchar **) a0_xpm ); 1618 1619 display.a_pixmap[1] = gdk_pixmap_create_from_xpm_d( window->window, 1620 &display.a_mask[1], 1621 &style->bg[GTK_STATE_NORMAL], 1622 (gchar **) a1_xpm ); 1623 1624 display.a_pixmap[2] = gdk_pixmap_create_from_xpm_d( window->window, 1625 &display.a_mask[2], 1626 &style->bg[GTK_STATE_NORMAL], 1627 (gchar **) a2_xpm ); 1628 1629 display.a_pixmap[3] = gdk_pixmap_create_from_xpm_d( window->window, 1630 &display.a_mask[3], 1631 &style->bg[GTK_STATE_NORMAL], 1632 (gchar **) a3_xpm ); 1633 1634 display.a_pixmap[4] = gdk_pixmap_create_from_xpm_d( window->window, 1635 &display.a_mask[4], 1636 &style->bg[GTK_STATE_NORMAL], 1637 (gchar **) a4_xpm ); 1638 1639 display.a_pixmap[5] = gdk_pixmap_create_from_xpm_d( window->window, 1640 &display.a_mask[5], 1641 &style->bg[GTK_STATE_NORMAL], 1642 (gchar **) a5_xpm ); 1643 1644 display.a_pixmap[6] = gdk_pixmap_create_from_xpm_d( window->window, 1645 &display.a_mask[6], 1646 &style->bg[GTK_STATE_NORMAL], 1647 (gchar **) a6_xpm ); 1648 1649 display.a_pixmap[7] = gdk_pixmap_create_from_xpm_d( window->window, 1650 &display.a_mask[7], 1651 &style->bg[GTK_STATE_NORMAL], 1652 (gchar **) a7_xpm ); 1653 1654 display.a_pixmap[8] = gdk_pixmap_create_from_xpm_d( window->window, 1655 &display.a_mask[8], 1656 &style->bg[GTK_STATE_NORMAL], 1657 (gchar **) a8_xpm ); 1658 1659 display.a_pixmap[9] = gdk_pixmap_create_from_xpm_d( window->window, 1660 &display.a_mask[9], 1661 &style->bg[GTK_STATE_NORMAL], 1662 (gchar **) a9_xpm ); 1663 1664 display.a_pixmap[10] = gdk_pixmap_create_from_xpm_d( window->window, 1665 &display.a_mask[10], 1666 &style->bg[GTK_STATE_NORMAL], 1667 (gchar **) an_xpm ); 1668 1669 1670 display.b_pixmap[0] = gdk_pixmap_create_from_xpm_d( window->window, 1671 &display.b_mask[0], 1672 &style->bg[GTK_STATE_NORMAL], 1673 (gchar **) b0_xpm ); 1674 1675 display.b_pixmap[1] = gdk_pixmap_create_from_xpm_d( window->window, 1676 &display.b_mask[1], 1677 &style->bg[GTK_STATE_NORMAL], 1678 (gchar **) b1_xpm ); 1679 1680 display.b_pixmap[2] = gdk_pixmap_create_from_xpm_d( window->window, 1681 &display.b_mask[2], 1682 &style->bg[GTK_STATE_NORMAL], 1683 (gchar **) b2_xpm ); 1684 1685 display.b_pixmap[3] = gdk_pixmap_create_from_xpm_d( window->window, 1686 &display.b_mask[3], 1687 &style->bg[GTK_STATE_NORMAL], 1688 (gchar **) b3_xpm ); 1689 1690 display.b_pixmap[4] = gdk_pixmap_create_from_xpm_d( window->window, 1691 &display.b_mask[4], 1692 &style->bg[GTK_STATE_NORMAL], 1693 (gchar **) b4_xpm ); 1694 1695 display.b_pixmap[5] = gdk_pixmap_create_from_xpm_d( window->window, 1696 &display.b_mask[5], 1697 &style->bg[GTK_STATE_NORMAL], 1698 (gchar **) b5_xpm ); 1699 1700 display.b_pixmap[6] = gdk_pixmap_create_from_xpm_d( window->window, 1701 &display.b_mask[6], 1702 &style->bg[GTK_STATE_NORMAL], 1703 (gchar **) b6_xpm ); 1704 1705 display.b_pixmap[7] = gdk_pixmap_create_from_xpm_d( window->window, 1706 &display.b_mask[7], 1707 &style->bg[GTK_STATE_NORMAL], 1708 (gchar **) b7_xpm ); 1709 1710 display.b_pixmap[8] = gdk_pixmap_create_from_xpm_d( window->window, 1711 &display.b_mask[8], 1712 &style->bg[GTK_STATE_NORMAL], 1713 (gchar **) b8_xpm ); 1714 1715 display.b_pixmap[9] = gdk_pixmap_create_from_xpm_d( window->window, 1716 &display.b_mask[9], 1717 &style->bg[GTK_STATE_NORMAL], 1718 (gchar **) b9_xpm ); 1719 1720 display.b_pixmap[10] = gdk_pixmap_create_from_xpm_d( window->window, 1721 &display.b_mask[10], 1722 &style->bg[GTK_STATE_NORMAL], 1723 (gchar **) bn_xpm ); 1724 1725 /* 1726 * Create a drawing area for us to show the track and time 1727 */ 1728 display.wid = gtk_drawing_area_new(); 1729 gtk_box_pack_start( GTK_BOX( hbox2 ), display.wid, FALSE, FALSE, 0 ); 1730 gtk_widget_show( display.wid ); 1731 1732 /* Make sure it is redrawn when covered and uncovered by others */ 1733 gtk_signal_connect( GTK_OBJECT( display.wid ), "expose_event", 1734 (GtkSignalFunc) expose_display, NULL ); 1735 1736 gtk_drawing_area_size( GTK_DRAWING_AREA(display.wid), 92, 30 ); 1737 gtk_widget_set_events( display.wid, GDK_EXPOSURE_MASK | 1738 GDK_BUTTON_MOTION_MASK | 1739 GDK_POINTER_MOTION_HINT_MASK | 1740 GDK_BUTTON_PRESS_MASK); 1741 1742 /* gtk_widget_realize (display.wid);*/ 1743 1744 gtk_signal_connect (GTK_OBJECT (display.wid), "button_press_event", 1745 GTK_SIGNAL_FUNC (display_pressed),NULL); 1746 gtk_signal_connect (GTK_OBJECT (display.wid), "button_release_event", 1747 GTK_SIGNAL_FUNC (display_released),NULL); 1748 gtk_signal_connect (GTK_OBJECT (display.wid), "motion_notify_event", 1749 GTK_SIGNAL_FUNC (display_motion),NULL); 1750 1751 /* Data area to keep track of the cursor position for moving the window */ 1752 icon_pos = g_new (CursorOffset, 1); 1753 gtk_object_set_user_data(GTK_OBJECT(display.wid), icon_pos); 1754 1755 x_pos = 0; 1756 y_pos = 0; 1757 /* Check the retun bits -- we want XValue & YValue */ 1758 if( stat & XValue ) 1759 { 1760 /* Is the value negative (relative to right side?) */ 1761 if( stat & XNegative ) 1762 { 1763 /* Make sure it returned a negative value */ 1764 if( x_ret < 0 ) 1765 x_pos = (gdk_screen_width()-137) + x_ret; 1766 else 1767 x_pos = (gdk_screen_width()-137) - x_ret; 1768 } else { 1769 x_pos = x_ret; 1770 } 1771 } 1772 1773 /* Did we get a Y position? */ 1774 if( stat & YValue ) 1775 { 1776 /* Is the value negative (relative to bottom side?) */ 1777 if( stat & YNegative ) 1778 { 1779 /* Make sure it returned a negative value */ 1780 if( y_ret < 0 ) 1781 y_pos = (gdk_screen_height()-60) + y_ret; 1782 else 1783 y_pos = (gdk_screen_height()-60) - y_ret; 1784 } else { 1785 y_pos = y_ret; 1786 } 1787 } 1788 1789 #ifdef DEBUG7 1790 g_print("Setting x=%d y=%d\n", x_pos, y_pos ); 1791 #endif 1792 1793 /* Put the window where the user wants it (x_pos,y_pos) */ 1794 gtk_widget_set_uposition( window, x_pos, y_pos ); 1795 1796 /* Setup the colors for the tooltip windows, postit yellow */ 1797 colormap = gdk_window_get_colormap (window->window); 1798 tip_color.red = 61669; 1799 tip_color.green = 59113; 1800 tip_color.blue = 35979; 1801 gdk_color_alloc (colormap, &tip_color); 1802 1803 /* Set the foreground/background of the tooltips */ 1804 gtk_tooltips_set_colors( tips, &tip_color, &window->style->fg[GTK_STATE_NORMAL] ); 1805 1806 /* Showing the window last so everything pops up at once. */ 1807 gtk_widget_show (window); 1808 1809 /* Start the 1 second update timer */ 1810 timer = gtk_timeout_add( 1000, update_cdrom, NULL ); 1811 1812 /* 1813 Read some useful info from .xfreecdrc 1814 Path to local database 1815 server list 1816 default server 1817 */ 1818 if( read_config( &config ) < 0 ) 1819 { 1820 g_print("read_config failed\n"); 1821 g_free( icon_pos ); 1822 exit(-1); 1823 } 1824 1825 /* Send the device to the cd_control process */ 1826 send_device(); 1827 1828 /* Tell cd_control about the exit on eject decision */ 1829 set_eject( config.exit_eject ); 1830 1831 gtk_main (); 1832 1833 /* Turn off the 1 second timeout */ 1834 gtk_timeout_remove( timer ); 1835 1836 g_free( icon_pos ); 1837 1838 free_config( &config ); /* Free up config's memory usage */ 1839 1840 return(0); 1841 } 1842 1843 1844 gint delete_event(GtkWidget *widget, gpointer data) 1845 { 1846 /* if you return FALSE in the "delete_event" signal handler, 1847 * GTK will emit the "destroy" signal. Returning TRUE means 1848 * you don't want the window to be destroyed. 1849 * This is useful for popping up 'are you sure you want to quit ?' 1850 * type dialogs. */ 1851 1852 /* Change TRUE to FALSE and the main window will be destroyed with 1853 * a "delete_event". */ 1854 1855 return (FALSE); 1856 } 1857 1858 /* another callback */ 1859 void destroy (GtkWidget *widget, gpointer data) 1860 { 1861 gtk_main_quit (); 1862 } 1863 1864 1865 1866 /* -------------------------------------------------------------- 1867 Copy the edited data over to cdinfo and write to local database 1868 --------------------------------------------------------------- */ 1869 void write_tracks() 1870 { 1871 GString *old_category; 1872 int x; 1873 char *texts[3], 1874 *p, 1875 text1[255], 1876 text2[255], 1877 fname[1024], 1878 tmp_fname[1024]; 1879 1880 1881 /* Sanity checks. We can't save or send if some of the important fields 1882 are blank. 1883 */ 1884 if( display.tmp_title == NULL ) 1885 return; 1886 1887 if( display.tmp_category == NULL ) 1888 return; 1889 1890 if( cdinfo.category == NULL ) 1891 return; 1892 1893 /* Save the old category so we can erase it if its changed */ 1894 old_category = g_string_new( cdinfo.category->str ); 1895 1896 /* Copy the new title into the cdinfo structure */ 1897 cdinfo.title = g_string_assign( cdinfo.title, display.tmp_title->str ); 1898 g_string_free( display.tmp_title, 1 ); 1899 display.tmp_title = NULL; 1900 1901 /* Copy the track names if they exist and delete display storage */ 1902 for( x = 0; x < cdinfo.tochdr.cdth_trk1; x++ ) 1903 { 1904 if( display.tmp_track[x] != NULL ) 1905 { 1906 if( cdinfo.name[x] == NULL ) 1907 cdinfo.name[x] = g_string_new( display.tmp_track[x]->str ); 1908 else 1909 cdinfo.name[x] = g_string_assign( cdinfo.name[x], display.tmp_track[x]->str ); 1910 g_string_free( display.tmp_track[x], 1 ); 1911 display.tmp_track[x] = NULL; 1912 } 1913 } 1914 1915 /* Copy the new categry name over */ 1916 cdinfo.category = g_string_assign( cdinfo.category, display.tmp_category->str ); 1917 1918 /* Update the track window's info if its still open */ 1919 if( display.twindow != NULL ) 1920 { 1921 gtk_clist_freeze (GTK_CLIST (display.tclist)); 1922 1923 /* Clear out the old list first */ 1924 gtk_clist_clear( GTK_CLIST( display.tclist ) ); 1925 1926 /* Set the new title */ 1927 if( cdinfo.title != NULL ) 1928 sprintf( text1, "%s", cdinfo.title->str ); 1929 else 1930 strcpy( text1, "" ); 1931 1932 gtk_label_set( GTK_LABEL( display.ttitle ), text1 ); 1933 1934 /* Add the track names */ 1935 for( x = 0; x < cdinfo.tochdr.cdth_trk1; x++ ) 1936 { 1937 sprintf( text1, "%d", x+1 ); 1938 sprintf( text2, "%d:%02d",cdinfo.track[x].length/60,cdinfo.track[x].length%60 ); 1939 texts[0] = text1; 1940 texts[2] = text2; 1941 if( cdinfo.name[x] != NULL ) 1942 texts[1] = cdinfo.name[x]->str; 1943 else 1944 texts[1] = "(blank)"; 1945 1946 gtk_clist_append (GTK_CLIST (display.tclist), texts); 1947 } 1948 gtk_clist_thaw( GTK_CLIST( display.tclist ) ); 1949 gtk_clist_select_row( GTK_CLIST(display.tclist), display.track-1, -1 ); 1950 } 1951 1952 /* Save to database -- overwrite previous */ 1953 if( write_cddb( &cdinfo, 1 ) < 0 ) 1954 { 1955 perror("write_cddb error"); 1956 } else { 1957 #ifdef DEBUG3 1958 g_print("Wrote %08lx ok\n", cddb_discid( &cdinfo ) ); 1959 #endif 1960 1961 /* The write was successful, we can erase the old category if it is different */ 1962 if( strcmp( cdinfo.category->str, old_category->str ) != 0 ) 1963 { 1964 /* Build the path to the old entry */ 1965 /* Convert a leading ~ into the user's HOME directory */ 1966 if( cdinfo.local_cddb[0] == '~' ) 1967 { 1968 /* Copy the reset of the path/filename to tmp_fname */ 1969 strncpy( tmp_fname, &cdinfo.local_cddb[1], 1023 ); 1970 1971 if( ( p = (char *) getenv("HOME") ) == NULL ) 1972 { 1973 return; 1974 } 1975 strncpy( fname, p, 1023 ); 1976 1977 /* Make sure there is a slash inbetween the two */ 1978 if( (fname[strlen(fname)-1] != '/') && (tmp_fname[0] != '/') ) 1979 { 1980 strcat( fname, "/" ); 1981 } 1982 1983 strncat( fname, tmp_fname, 1023-strlen( p ) ); 1984 } else { 1985 strncpy( fname, cdinfo.local_cddb, 1023 ); 1986 } 1987 1988 if( fname[strlen(fname)-1] != '/') 1989 strcat( fname, "/" ); 1990 1991 /* Add the category name */ 1992 strcat( fname, old_category->str ); 1993 strcat( fname, "/" ); 1994 sprintf( tmp_fname, "%08lx", cdinfo.discid ); 1995 strcat( fname, tmp_fname ); 1996 1997 /* Delete it */ 1998 unlink( fname ); 1999 } 2000 } 2001 2002 g_string_free( old_category, 1 ); 2003 } 2004 2005 2006 2007 /* -------------------------------------------------------------- 2008 Send the cdinfo to the database 2009 2010 Increment the revision and save the new one to disk. 2011 Use a system call to mail and cat 2012 --------------------------------------------------------------- */ 2013 void send_cddbd( GtkWidget *widget, GtkWidget *window) 2014 { 2015 char *p, 2016 tmp_fname[1024], 2017 fname[1024], 2018 buffer[1024]; 2019 2020 /* Close the edit window */ 2021 gtk_widget_destroy( window ); 2022 2023 /* Increment the revision number */ 2024 cdinfo.revision++; 2025 2026 /* Copy all the changes to the cdinfo structure */ 2027 write_tracks(); 2028 2029 /* Make sure it has a title */ 2030 if( cdinfo.title != NULL ) 2031 { 2032 /* Convert a leading ~ into the user's HOME directory */ 2033 if( cdinfo.local_cddb[0] == '~' ) 2034 { 2035 /* Copy the reset of the path/filename to tmp_fname */ 2036 strncpy( tmp_fname, &cdinfo.local_cddb[1], 1023 ); 2037 2038 if( ( p = (char *) getenv("HOME") ) == NULL ) 2039 { 2040 return; 2041 } 2042 strncpy( fname, p, 1023 ); 2043 2044 /* Make sure there is a slash inbetween the two */ 2045 if( (fname[strlen(fname)-1] != '/') && (tmp_fname[0] != '/') ) 2046 { 2047 strcat( fname, "/" ); 2048 } 2049 2050 strncat( fname, tmp_fname, 1023-strlen( p ) ); 2051 } else { 2052 strncpy( fname, cdinfo.local_cddb, 1023 ); 2053 } 2054 2055 if( fname[strlen(fname)-1] != '/') 2056 strcat( fname, "/" ); 2057 2058 /* Add the category name */ 2059 strcat( fname, cdinfo.category->str ); 2060 strcat( fname, "/" ); 2061 sprintf( tmp_fname, "%08lx", cdinfo.discid ); 2062 strcat( fname, tmp_fname ); 2063 2064 sprintf( buffer, "cat %s | %s -s \"cddb %s %08lx\" %s", fname, MAIL_BINARY, cdinfo.category->str, cdinfo.discid, config.to_cddbd ); 2065 2066 #ifdef MAIL_DEBUG 2067 g_print( "%s\n", buffer ); 2068 #else 2069 /* Make a system call */ 2070 system( buffer ); 2071 #endif 2072 } 2073 } 2074 2075 2076 /* -------------------------------------------------------------- 2077 Save the new cd data to the local cd database 2078 --------------------------------------------------------------- */ 2079 void save_tracks( GtkWidget *widget, GtkWidget *window) 2080 { 2081 gtk_widget_destroy( window ); 2082 2083 /* Update cdinfo and write the new data to the local database */ 2084 write_tracks(); 2085 } 2086 2087 2088 /* ---------------------------------------------------------------------- 2089 The track entry data has changed. Copy it to a temporary location... 2090 ---------------------------------------------------------------------- */ 2091 void track_entry(GtkWidget *widget, GtkWidget *entry) 2092 { 2093 gchar *entry_text; 2094 char *texts[3], 2095 text1[255], 2096 text2[255]; 2097 2098 entry_text = gtk_entry_get_text(GTK_ENTRY(entry)); 2099 2100 if( display.tmp_track[display.tmp_row] == NULL ) 2101 display.tmp_track[display.tmp_row] = g_string_new( entry_text ); 2102 else 2103 display.tmp_track[display.tmp_row] = g_string_assign( display.tmp_track[display.tmp_row], entry_text ); 2104 2105 /* Update the clist in the edit window */ 2106 if( display.tewindow != NULL ) 2107 { 2108 gtk_clist_freeze (GTK_CLIST (display.teclist)); 2109 2110 /* Remove the old entry first */ 2111 gtk_clist_remove( GTK_CLIST( display.teclist ), display.tmp_row ); 2112 2113 /* Insert the new data */ 2114 sprintf( text1, "%d", display.tmp_row+1 ); 2115 sprintf( text2, "%d:%02d",cdinfo.track[display.tmp_row].length/60,cdinfo.track[display.tmp_row].length%60 ); 2116 texts[0] = text1; 2117 texts[2] = text2; 2118 if( display.tmp_track[display.tmp_row] != NULL ) 2119 texts[1] = display.tmp_track[display.tmp_row]->str; 2120 else 2121 texts[1] = "(blank)"; 2122 gtk_clist_insert (GTK_CLIST (display.teclist), display.tmp_row, texts); 2123 2124 /* Select the correct row in the clist */ 2125 gtk_clist_select_row( GTK_CLIST(display.teclist), display.tmp_row, -1 ); 2126 2127 gtk_clist_thaw( GTK_CLIST( display.teclist ) ); 2128 2129 } 2130 } 2131 2132 2133 /* ------------------------------------------------------------------- 2134 The Title entry data has changed, copy it to a temporary location 2135 ------------------------------------------------------------------- */ 2136 void title_entry(GtkWidget *widget, GtkWidget *entry) 2137 { 2138 gchar *entry_text; 2139 2140 entry_text = gtk_entry_get_text(GTK_ENTRY(entry)); 2141 2142 if( display.tmp_title == NULL ) 2143 display.tmp_title = g_string_new( entry_text ); 2144 else 2145 display.tmp_title = g_string_assign( display.tmp_title, entry_text ); 2146 } 2147 2148 2149 /* ---------------------------------------------------------------------- 2150 The user selected a track, copy its data into the edit widget 2151 (display.teedit) 2152 ---------------------------------------------------------------------- */ 2153 void select_teclist (GtkWidget *widget, 2154 gint row, 2155 gint column, 2156 GdkEventButton * bevent) 2157 { 2158 2159 #ifdef DEBUG9 2160 g_print ("Selection: Track #%d by button %d\n", row, bevent ? bevent->button : 0 ); 2161 #endif 2162 2163 if( bevent ) 2164 { 2165 if( bevent->button == 1 ) 2166 { 2167 display.tmp_row = row; 2168 /* Copy the track name into the edit widget */ 2169 if( display.tmp_track[display.tmp_row] != NULL ) 2170 gtk_entry_set_text( GTK_ENTRY( display.teentry ), display.tmp_track[display.tmp_row]->str); 2171 else 2172 gtk_entry_set_text( GTK_ENTRY( display.teentry ), "(blank)" ); 2173 } 2174 } 2175 } 2176 2177 2178 2179 2180 /* -------------------------------------------------------------------- 2181 If the user select a track in the tracklist window, play that 2182 track now. 2183 -------------------------------------------------------------------- */ 2184 void select_tclist (GtkWidget *widget, 2185 gint row, 2186 gint column, 2187 GdkEventButton * bevent) 2188 { 2189 2190 #ifdef DEBUG9 2191 g_print ("Selection: Track #%d by button %d\n", row, bevent ? bevent->button : 0 ); 2192 #endif 2193 2194 if( bevent ) 2195 { 2196 if( bevent->button == 1 ) 2197 { 2198 play_track( row+1 ); 2199 } 2200 } 2201 } 2202 2203 2204 2205 2206 /* ----------------------------------------------------------------------- 2207 Handle the button press events 2208 2209 Each button has a xx_press and xx_release event where they change their 2210 pixmaps to show a up or down state. 2211 2212 The FF, REW, Eject button also have to update the state of the play 2213 button since they can effect the state that the player is in. I'm sure 2214 there is a better way to do this... 2215 ----------------------------------------------------------------------- */ 2216 2217 2218 /* ----------------------------------------------------------------------- 2219 Copy the selected item into the category 2220 ----------------------------------------------------------------------- */ 2221 static void menuitem_response (gchar *string) 2222 { 2223 if( display.tmp_category == NULL ) 2224 display.tmp_category = g_string_new( string ); 2225 else 2226 display.tmp_category = g_string_assign( display.tmp_category, string ); 2227 } 2228 2229 2230 /* ----------------------------------------------------------------------- 2231 Start up the window for editing the track list. 2232 Close the normal track list while doing this. 2233 Save it to cddb format when close is clicked. 2234 Don't save when Cancel is clicked. 2235 ----------------------------------------------------------------------- */ 2236 static void edit_tracks(GtkWidget *widget, GtkWidget *data) 2237 { 2238 GtkWidget *vbox1, 2239 *hbox1, 2240 *button, 2241 *edit, 2242 *optionmenu, 2243 *menu, 2244 *menuitem; 2245 int x, 2246 curr_cat; 2247 char *texts[3], 2248 text1[255], 2249 text2[255]; 2250 static char *titles[] = 2251 { 2252 "Track #", 2253 "Title", 2254 "Length" 2255 }; 2256 static char *categories[] = 2257 { 2258 "blues", 2259 "classical", 2260 "country", 2261 "data", 2262 "folk", 2263 "jazz", 2264 "misc", 2265 "newage", 2266 "reggae", 2267 "rock", 2268 "soundtrack" 2269 }; 2270 2271 2272 /* Don't allow edit if there's no disk */ 2273 if( display.status == CDROM_NODISC ) 2274 return; 2275 2276 if (!display.tewindow) 2277 { 2278 display.tewindow = gtk_window_new (GTK_WINDOW_TOPLEVEL); 2279 gtk_widget_set_usize (display.tewindow, 300, 400); 2280 2281 gtk_signal_connect (GTK_OBJECT (display.tewindow), "destroy", 2282 GTK_SIGNAL_FUNC(gtk_widget_destroyed), 2283 &display.tewindow); 2284 2285 gtk_window_set_title (GTK_WINDOW (display.tewindow), "Edit Track Info" ); 2286 gtk_container_border_width (GTK_CONTAINER (display.tewindow), 4); 2287 gtk_window_set_wmclass(GTK_WINDOW(display.tewindow), "XfreeCDet", NULL ); 2288 2289 /* create a vbox to hold the clist and buttons */ 2290 vbox1 = gtk_vbox_new (FALSE, 0); 2291 gtk_container_add (GTK_CONTAINER (display.tewindow), vbox1); 2292 gtk_widget_show (vbox1); 2293 2294 /* Make a hbox to hold discid and category dropdown */ 2295 hbox1 = gtk_hbox_new (FALSE, 0); 2296 gtk_box_pack_start( GTK_BOX( vbox1 ), hbox1, FALSE, FALSE, 2 ); 2297 gtk_widget_show (hbox1); 2298 2299 /* Need to show the disc id and category */ 2300 /* Maybe category should be a drop-down listing of the standard categories? */ 2301 sprintf( text1, "Discid: 0x%08lx Category : ", cdinfo.discid ); 2302 button = gtk_label_new( text1 ); 2303 gtk_box_pack_start( GTK_BOX( hbox1 ), button, FALSE, FALSE, 2 ); 2304 gtk_widget_show( button ); 2305 2306 /* Optionmenu for selecting the category */ 2307 optionmenu = gtk_option_menu_new(); 2308 menu = gtk_menu_new(); 2309 2310 curr_cat = 0; 2311 /* Add the categories */ 2312 for( x = 0; x < 11; x++ ) 2313 { 2314 /* Set the current category */ 2315 if( cdinfo.category != NULL ) 2316 { 2317 if( strcmp( cdinfo.category->str, categories[x] ) == 0 ) 2318 { 2319 curr_cat = x; 2320 if( display.tmp_category == NULL ) 2321 display.tmp_category = g_string_new( cdinfo.category->str ); 2322 else 2323 display.tmp_category = g_string_assign( display.tmp_category, cdinfo.category->str ); 2324 } 2325 } else { 2326 display.tmp_category= g_string_new( categories[0] ); 2327 } 2328 menuitem = gtk_menu_item_new_with_label( categories[x] ); 2329 gtk_menu_append (GTK_MENU (menu), menuitem); 2330 gtk_signal_connect_object( GTK_OBJECT(menuitem), "activate", 2331 GTK_SIGNAL_FUNC(menuitem_response), (gpointer) categories[x] ); 2332 gtk_widget_show (menuitem); 2333 } 2334 gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu), menu); 2335 gtk_option_menu_set_history (GTK_OPTION_MENU (optionmenu), curr_cat ); 2336 gtk_box_pack_start (GTK_BOX (hbox1), optionmenu, FALSE, FALSE, 0); 2337 gtk_widget_show (optionmenu); 2338 2339 2340 2341 /* Entry Widget for the title of the CD */ 2342 edit = gtk_entry_new_with_max_length( 254 ); 2343 gtk_signal_connect(GTK_OBJECT(edit), "changed", 2344 GTK_SIGNAL_FUNC(title_entry), 2345 edit); 2346 2347 if( cdinfo.title != NULL ) 2348 gtk_entry_set_text( GTK_ENTRY( edit ), cdinfo.title->str ); 2349 gtk_editable_select_region( GTK_EDITABLE( edit ), 0, -1 ); 2350 gtk_box_pack_start( GTK_BOX( vbox1 ), edit, FALSE, FALSE, 2 ); 2351 gtk_widget_show( edit ); 2352 2353 /* Initalize the title */ 2354 if( cdinfo.title != NULL ) 2355 display.tmp_title = g_string_new( cdinfo.title->str ); 2356 2357 /* Entry Widget for the track name-changed by selecting a diff. track */ 2358 display.teentry = gtk_entry_new_with_max_length( 254 ); 2359 gtk_box_pack_start( GTK_BOX( vbox1 ), display.teentry, FALSE, FALSE, 2 ); 2360 gtk_widget_show( display.teentry ); 2361 2362 /* Create the clist */ 2363 display.teclist = gtk_clist_new_with_titles (3, titles); 2364 gtk_clist_set_row_height (GTK_CLIST (display.teclist), 20); 2365 gtk_clist_set_column_width (GTK_CLIST (display.teclist), 0, 45); 2366 gtk_clist_set_column_width (GTK_CLIST (display.teclist), 1, 150); 2367 gtk_clist_set_column_width (GTK_CLIST (display.teclist), 2, 45); 2368 gtk_signal_connect (GTK_OBJECT (display.teclist), 2369 "select_row", 2370 (GtkSignalFunc) select_teclist, 2371 NULL); 2372 #ifdef GOOBER 2373 gtk_clist_set_selection_mode (GTK_CLIST (display.teclist), GTK_SELECTION_BROWSE); 2374 #endif 2375 gtk_clist_set_policy (GTK_CLIST (display.teclist), 2376 GTK_POLICY_AUTOMATIC, 2377 GTK_POLICY_AUTOMATIC); 2378 2379 gtk_clist_set_column_justification (GTK_CLIST (display.teclist), 0, GTK_JUSTIFY_CENTER); 2380 gtk_clist_set_column_justification (GTK_CLIST (display.teclist), 1, GTK_JUSTIFY_LEFT); 2381 gtk_clist_set_column_justification (GTK_CLIST (display.teclist), 2, GTK_JUSTIFY_LEFT); 2382 2383 gtk_clist_freeze (GTK_CLIST (display.teclist)); 2384 2385 display.tmp_row = 0; 2386 /* Add the track names */ 2387 for( x = 0; x < cdinfo.tochdr.cdth_trk1; x++ ) 2388 { 2389 sprintf( text1, "%d", x+1 ); 2390 sprintf( text2, "%d:%02d",cdinfo.track[x].length/60,cdinfo.track[x].length%60 ); 2391 texts[0] = text1; 2392 texts[2] = text2; 2393 if( cdinfo.name[x] != NULL ) 2394 texts[1] = cdinfo.name[x]->str; 2395 else 2396 texts[1] = "(blank)"; 2397 gtk_clist_append (GTK_CLIST (display.teclist), texts); 2398 2399 /* Initalize the temporary storage */ 2400 if( cdinfo.name[x] != NULL ) 2401 display.tmp_track[x] = g_string_new( cdinfo.name[x]->str ); 2402 else 2403 display.tmp_track[x] = NULL; 2404 } 2405 gtk_clist_thaw( GTK_CLIST( display.teclist ) ); 2406 2407 gtk_container_border_width (GTK_CONTAINER (display.teclist), 5); 2408 gtk_box_pack_start (GTK_BOX (vbox1), display.teclist, TRUE, TRUE, 0); 2409 gtk_widget_show (display.teclist); 2410 2411 /* Now we can update the track edit control, since the tclist is setup */ 2412 gtk_signal_connect(GTK_OBJECT(display.teentry), "changed", 2413 GTK_SIGNAL_FUNC(track_entry), 2414 display.teentry); 2415 if( display.tmp_track[0] != NULL ) 2416 gtk_entry_set_text( GTK_ENTRY( display.teentry ), display.tmp_track[0]->str ); 2417 gtk_editable_select_region( GTK_EDITABLE( display.teentry ), 0, -1 ); 2418 2419 button = gtk_button_new_with_label ("Send To Server"); 2420 gtk_signal_connect_object (GTK_OBJECT (button), "clicked", 2421 GTK_SIGNAL_FUNC(send_cddbd), 2422 GTK_OBJECT (display.tewindow)); 2423 gtk_box_pack_start (GTK_BOX (vbox1), button, FALSE, FALSE, 2); 2424 gtk_widget_show (button); 2425 2426 button = gtk_button_new_with_label ("Save"); 2427 gtk_signal_connect_object (GTK_OBJECT (button), "clicked", 2428 GTK_SIGNAL_FUNC(save_tracks), 2429 GTK_OBJECT (display.tewindow)); 2430 gtk_box_pack_start (GTK_BOX (vbox1), button, FALSE, FALSE, 2); 2431 gtk_widget_show (button); 2432 2433 button = gtk_button_new_with_label ("Close"); 2434 gtk_signal_connect_object (GTK_OBJECT (button), "clicked", 2435 GTK_SIGNAL_FUNC(gtk_widget_destroy), 2436 GTK_OBJECT (display.tewindow)); 2437 gtk_box_pack_start (GTK_BOX (vbox1), button, FALSE, FALSE, 2); 2438 gtk_widget_show (button); 2439 2440 gtk_widget_show( display.tewindow ); 2441 } 2442 } 2443 2444 2445 2446 /* 2447 Handle button press in the display window. 2448 Determine if its a click for a track list or a drag to move the window 2449 */ 2450 static void display_pressed (GtkWidget *widget, GdkEventButton *event) 2451 { 2452 CursorOffset *p; 2453 GtkWidget *vbox1, 2454 *button; 2455 int x; 2456 char *texts[3], 2457 text1[255], 2458 text2[255]; 2459 static char *titles[] = 2460 { 2461 "Track #", 2462 "Title", 2463 "Length" 2464 }; 2465 2466 2467 /* ignore double and triple click */ 2468 if (event->type != GDK_BUTTON_PRESS) 2469 return; 2470 2471 /* Right button is move window */ 2472 if( event->button == 3 ) 2473 { 2474 if( ( p = gtk_object_get_user_data (GTK_OBJECT(widget)) ) != NULL ) 2475 { 2476 p->x = (int) event->x; 2477 p->y = (int) event->y; 2478 2479 gtk_grab_add (widget); 2480 gdk_pointer_grab (widget->window, TRUE, 2481 GDK_BUTTON_RELEASE_MASK | 2482 GDK_BUTTON_MOTION_MASK | 2483 GDK_POINTER_MOTION_HINT_MASK, 2484 NULL, NULL, 0); 2485 } 2486 } else if( event->button == 1 ) { 2487 /* Show the title and the tracks, using a clist */ 2488 if (!display.twindow) 2489 { 2490 display.twindow = gtk_window_new (GTK_WINDOW_TOPLEVEL); 2491 gtk_widget_set_usize (display.twindow, 300, 350); 2492 2493 gtk_signal_connect (GTK_OBJECT (display.twindow), "destroy", 2494 GTK_SIGNAL_FUNC(gtk_widget_destroyed), 2495 &display.twindow); 2496 2497 /* gtk_window_set_title (GTK_WINDOW (display.twindow), cdinfo.title); */ 2498 gtk_container_border_width (GTK_CONTAINER (display.twindow), 4); 2499 gtk_window_set_wmclass(GTK_WINDOW(display.twindow), "XfreeCDt", NULL ); 2500 2501 /* create a vbox to hold the clist and buttons */ 2502 vbox1 = gtk_vbox_new (FALSE, 0); 2503 gtk_container_add (GTK_CONTAINER (display.twindow), vbox1); 2504 gtk_widget_show (vbox1); 2505 2506 if( cdinfo.title != NULL ) 2507 sprintf( text1, "%s", cdinfo.title->str ); 2508 else 2509 strcpy( text1, "" ); 2510 display.ttitle = gtk_label_new( text1 ); 2511 gtk_box_pack_start( GTK_BOX( vbox1 ), display.ttitle, FALSE, FALSE, 0 ); 2512 gtk_widget_show( display.ttitle ); 2513 2514 /* Create the clist */ 2515 display.tclist = gtk_clist_new_with_titles (3, titles); 2516 gtk_clist_set_row_height (GTK_CLIST (display.tclist), 20); 2517 gtk_clist_set_column_width (GTK_CLIST (display.tclist), 0, 45); 2518 gtk_clist_set_column_width (GTK_CLIST (display.tclist), 1, 150); 2519 gtk_clist_set_column_width (GTK_CLIST (display.tclist), 2, 45); 2520 gtk_signal_connect (GTK_OBJECT (display.tclist), 2521 "select_row", 2522 (GtkSignalFunc) select_tclist, 2523 NULL); 2524 2525 #ifdef GOOBER 2526 gtk_clist_set_selection_mode (GTK_CLIST (display.tclist), GTK_SELECTION_BROWSE); 2527 #endif 2528 gtk_clist_set_policy (GTK_CLIST (display.tclist), 2529 GTK_POLICY_AUTOMATIC, 2530 GTK_POLICY_AUTOMATIC); 2531 2532 gtk_clist_set_column_justification (GTK_CLIST (display.tclist), 0, GTK_JUSTIFY_CENTER); 2533 gtk_clist_set_column_justification (GTK_CLIST (display.tclist), 1, GTK_JUSTIFY_LEFT); 2534 gtk_clist_set_column_justification (GTK_CLIST (display.tclist), 2, GTK_JUSTIFY_LEFT); 2535 2536 if( display.status != CDROM_NODISC ) 2537 { 2538 gtk_clist_freeze (GTK_CLIST (display.tclist)); 2539 /* Add the track names */ 2540 for( x = 0; x < cdinfo.tochdr.cdth_trk1; x++ ) 2541 { 2542 sprintf( text1, "%d", x+1 ); 2543 sprintf( text2, "%d:%02d",cdinfo.track[x].length/60,cdinfo.track[x].length%60 ); 2544 texts[0] = text1; 2545 texts[2] = text2; 2546 if( cdinfo.name[x] != NULL ) 2547 texts[1] = cdinfo.name[x]->str; 2548 else 2549 texts[1] = "(blank)"; 2550 gtk_clist_append (GTK_CLIST (display.tclist), texts); 2551 } 2552 gtk_clist_thaw( GTK_CLIST( display.tclist ) ); 2553 } 2554 2555 gtk_container_border_width (GTK_CONTAINER (display.tclist), 5); 2556 gtk_box_pack_start (GTK_BOX (vbox1), display.tclist, TRUE, TRUE, 0); 2557 gtk_widget_show (display.tclist); 2558 2559 button = gtk_button_new_with_label ("Edit Info"); 2560 gtk_signal_connect_object (GTK_OBJECT (button), "clicked", 2561 GTK_SIGNAL_FUNC(edit_tracks), 2562 GTK_OBJECT (display.twindow)); 2563 gtk_box_pack_start (GTK_BOX (vbox1), button, FALSE, FALSE, 2); 2564 gtk_widget_show (button); 2565 2566 button = gtk_button_new_with_label ("Close"); 2567 gtk_signal_connect_object (GTK_OBJECT (button), "clicked", 2568 GTK_SIGNAL_FUNC(gtk_widget_destroy), 2569 GTK_OBJECT (display.twindow)); 2570 2571 gtk_box_pack_start (GTK_BOX (vbox1), button, FALSE, FALSE, 2); 2572 /* GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); */ 2573 /* gtk_widget_grab_default (button); */ 2574 gtk_widget_show (button); 2575 gtk_widget_show( display.twindow ); 2576 } 2577 } 2578 } 2579 2580 2581 static void display_released (GtkWidget *widget) 2582 { 2583 gtk_grab_remove (widget); 2584 gdk_pointer_ungrab (0); 2585 } 2586 2587 2588 static void display_motion (GtkWidget *widget, GdkEventMotion *event) 2589 { 2590 gint xp, yp; 2591 CursorOffset * p; 2592 GdkModifierType mask; 2593 2594 if( ( p = gtk_object_get_user_data (GTK_OBJECT (widget)) ) != NULL ) 2595 { 2596 /* 2597 * Can't use event->x / event->y here 2598 * because I need absolute coordinates. 2599 */ 2600 gdk_window_get_pointer (root_win, &xp, &yp, &mask); 2601 gtk_widget_set_uposition (display.main_window, xp - p->x, yp - p->y); 2602 } 2603 } 2604 2605 2606 2607 2608 void ff_press (GtkWidget *widget, GdkEventButton *event) 2609 { 2610 /* Left button pressed */ 2611 if( event->button == 1 ) 2612 { 2613 /* Set the FF down image */ 2614 gtk_pixmap_set( GTK_PIXMAP( ff.wid ), 2615 ff.image.dn_pixmap, 2616 ff.image.dn_mask ); 2617 2618 /* Tell the CD control to play the next track */ 2619 play_next(); 2620 2621 2622 /* Update the state of the play button -- Should be a subroutine */ 2623 if( (display.playbtn != CDROM_PLAYING) && (display.status != CDROM_NODISC)) 2624 { 2625 gtk_pixmap_set( GTK_PIXMAP( play.wid ), 2626 display.playup_pixmap, 2627 display.playup_mask ); 2628 display.playbtn = CDROM_PLAYING; 2629 } 2630 } 2631 } 2632 2633 2634 void ff_release (GtkWidget *widget, GdkEventButton *event) 2635 { 2636 if( (event->button == 1) ) 2637 { 2638 /* Draw the button up image */ 2639 gtk_pixmap_set( GTK_PIXMAP( ff.wid ), 2640 ff.image.up_pixmap, 2641 ff.image.up_mask ); 2642 } 2643 } 2644 2645 2646 void rew_press (GtkWidget *widget, GdkEventButton *event) 2647 { 2648 /* Left button pressed */ 2649 if( event->button == 1 ) 2650 { 2651 /* Draw the down image for REW */ 2652 gtk_pixmap_set( GTK_PIXMAP( rew.wid ), 2653 rew.image.dn_pixmap, 2654 rew.image.dn_mask ); 2655 2656 /* Tell the CD to play the previous track */ 2657 play_previous(); 2658 2659 2660 /* Update the state of the Play button -- should be a subroutine */ 2661 if( (display.playbtn != CDROM_PLAYING) && (display.status != CDROM_NODISC)) 2662 { 2663 gtk_pixmap_set( GTK_PIXMAP( play.wid ), 2664 display.playup_pixmap, 2665 display.playup_mask ); 2666 display.playbtn = CDROM_PLAYING; 2667 } 2668 2669 } 2670 } 2671 2672 2673 void rew_release (GtkWidget *widget, GdkEventButton *event) 2674 { 2675 if( (event->button == 1) ) 2676 { 2677 /* Draw the up image for the button */ 2678 gtk_pixmap_set( GTK_PIXMAP( rew.wid ), 2679 rew.image.up_pixmap, 2680 rew.image.up_mask ); 2681 } 2682 } 2683 2684 2685 void play_press (GtkWidget *widget, GdkEventButton *event) 2686 { 2687 int x; 2688 2689 /* Left button press */ 2690 if( event->button == 1 ) 2691 { 2692 /* Depending on the current state of the button, display the correct image */ 2693 switch( display.playbtn ) 2694 { 2695 case CDROM_PLAYING: gtk_pixmap_set( GTK_PIXMAP( play.wid ), 2696 display.playdn_pixmap, 2697 display.playdn_mask ); 2698 pause_cdrom(); 2699 display.playbtn = CDROM_PAUSED; 2700 break; 2701 2702 case CDROM_PAUSED: gtk_pixmap_set( GTK_PIXMAP( play.wid ), 2703 display.playdn_pixmap, 2704 display.playdn_mask ); 2705 resume_cdrom(); 2706 display.playbtn = CDROM_PLAYING; 2707 break; 2708 2709 case CDROM_NODISC: gtk_pixmap_set( GTK_PIXMAP( play.wid ), 2710 display.playdn_pixmap, 2711 display.playdn_mask ); 2712 2713 play_track( 1 ); 2714 update_display(); 2715 display.playbtn = CDROM_PLAYING; 2716 break; 2717 } 2718 } else if( event->button ==3 ) { 2719 /* Stop playing without ejecting the CD */ 2720 switch( display.playbtn ) 2721 { 2722 2723 case CDROM_PLAYING : 2724 case CDROM_PAUSED : 2725 stop_cdrom(); 2726 gtk_pixmap_set( GTK_PIXMAP( play.wid ), 2727 display.playdn_pixmap, 2728 display.playdn_mask ); 2729 update_display(); 2730 display.playbtn = CDROM_NODISC; 2731 2732 /* Clear out the track list */ 2733 if( display.twindow != NULL ) 2734 { 2735 gtk_clist_clear( GTK_CLIST( display.tclist ) ); 2736 2737 /* Clear the title */ 2738 gtk_label_set( GTK_LABEL( display.ttitle ), "" ); 2739 } 2740 2741 /* Erase the title and track names */ 2742 if( cdinfo.title != NULL ) 2743 { 2744 g_string_free( cdinfo.title, 1 ); 2745 cdinfo.title = NULL; 2746 } 2747 2748 for( x = 0; x < cdinfo.tochdr.cdth_trk1; x++ ) 2749 { 2750 if( cdinfo.name[x] != NULL ) 2751 { 2752 g_string_free( cdinfo.name[x], 1 ); 2753 cdinfo.name[x] = NULL; 2754 } 2755 } 2756 2757 /* Free up dynamically allocated cdinfo strings */ 2758 free_cdinfo(); 2759 break; 2760 2761 case CDROM_NODISC : 2762 break; 2763 } 2764 } 2765 } 2766 2767 2768 void play_release (GtkWidget *widget, GdkEventButton *event) 2769 { 2770 if( (event->button == 1) || (event->button ==3) ) 2771 { 2772 switch( display.playbtn ) 2773 { 2774 case CDROM_PAUSED: gtk_pixmap_set( GTK_PIXMAP( play.wid ), 2775 display.pauseup_pixmap, 2776 display.pauseup_mask ); 2777 break; 2778 2779 case CDROM_PLAYING: gtk_pixmap_set( GTK_PIXMAP( play.wid ), 2780 display.playup_pixmap, 2781 display.playup_mask ); 2782 break; 2783 2784 case CDROM_NODISC: gtk_pixmap_set( GTK_PIXMAP( play.wid ), 2785 display.stopup_pixmap, 2786 display.stopup_mask ); 2787 break; 2788 2789 } 2790 } 2791 } 2792 2793 2794 void eject_press (GtkWidget *widget, GdkEventButton *event) 2795 { 2796 int x; 2797 2798 if( event->button == 1 ) 2799 { 2800 gtk_pixmap_set( GTK_PIXMAP( eject.wid ), 2801 eject.image.dn_pixmap, 2802 eject.image.dn_mask ); 2803 2804 2805 /* 2806 * If we are playing or paused then we will be stopped, so change 2807 * the play button to the stop button 2808 */ 2809 switch( display.status ) 2810 { 2811 case CDROM_PAUSED : 2812 case CDROM_PLAYING : 2813 gtk_pixmap_set( GTK_PIXMAP( play.wid ), 2814 display.stopup_pixmap, 2815 display.stopup_mask ); 2816 display.playbtn = CDROM_NODISC; 2817 break; 2818 } 2819 eject_cdrom(); 2820 display.playbtn = CDROM_NODISC; 2821 gdk_draw_pixmap( display.wid->window, 2822 display.wid->style->black_gc, 2823 display.nodisc_pixmap, 2824 0, 0, 2825 0, 0, 92, 30 ); 2826 2827 /* Clear out the track list */ 2828 if( display.twindow != NULL ) 2829 { 2830 gtk_clist_clear( GTK_CLIST( display.tclist ) ); 2831 2832 /* Clear the title */ 2833 gtk_label_set( GTK_LABEL( display.ttitle ), "" ); 2834 } 2835 2836 2837 /* Erase the title and track names */ 2838 if( cdinfo.title != NULL ) 2839 { 2840 g_string_free( cdinfo.title, 1 ); 2841 cdinfo.title = NULL; 2842 } 2843 2844 for( x = 0; x < cdinfo.tochdr.cdth_trk1; x++ ) 2845 { 2846 if( cdinfo.name[x] != NULL ) 2847 { 2848 g_string_free( cdinfo.name[x], 1 ); 2849 cdinfo.name[x] = NULL; 2850 } 2851 } 2852 2853 /* Free up the dynamically allocated cdinfo strings */ 2854 free_cdinfo(); 2855 } 2856 } 2857 2858 2859 void eject_release (GtkWidget *widget, GdkEventButton *event) 2860 { 2861 if( event->button == 1 ) 2862 { 2863 gtk_pixmap_set( GTK_PIXMAP( eject.wid ), 2864 eject.image.up_pixmap, 2865 eject.image.up_mask ); 2866 } 2867 } 2868 2869 2870 gint ex_timer( gpointer data ) 2871 { 2872 gtk_timeout_remove( ex.timer ); 2873 2874 gtk_main_quit(); 2875 2876 return FALSE; 2877 } 2878 2879 2880 void ex_press (GtkWidget *widget, GdkEventButton *event) 2881 { 2882 if( event->button == 1 ) 2883 { 2884 gtk_pixmap_set( GTK_PIXMAP( ex.wid ), 2885 ex.image.dn_pixmap, 2886 ex.image.dn_mask ); 2887 2888 /* In 100mS execute the play_next function */ 2889 ex.timer = gtk_timeout_add( 500, ex_timer, NULL ); 2890 2891 } 2892 } 2893 2894 2895 void ex_release (GtkWidget *widget, GdkEventButton *event) 2896 { 2897 if( event->button == 1 ) 2898 { 2899 gtk_pixmap_set( GTK_PIXMAP( ex.wid ), 2900 ex.image.up_pixmap, 2901 ex.image.up_mask ); 2902 } 2903 } 2904 2905 2906 void 2907 destroy_window (GtkWidget *widget, 2908 GtkWidget **window) 2909 { 2910 *window = NULL; 2911 } 2912 2913 2914 void close_setup( GtkWidget *widget, GtkWidget *window) 2915 { 2916 gtk_widget_destroy( window ); 2917 2918 /* Write configuration */ 2919 write_config( &config ); 2920 2921 /* Send the new device to the cd_control process */ 2922 send_device(); 2923 } 2924 2925 2926 /* Toggle the state of the cddb button */ 2927 static void toggle_cddb (GtkWidget *checkbutton, 2928 GtkWidget *text) 2929 { 2930 config.cddb = GTK_TOGGLE_BUTTON(checkbutton)->active; 2931 2932 #ifdef DEBUG3 2933 g_print("Toggling cddb = %d\n", config.cddb ); 2934 #endif 2935 2936 config.saved = 0; /* Needs to be written to disk */ 2937 } 2938 2939 2940 #ifdef CHANGER_SUPPORT 2941 /* Toggle the CD changer support button */ 2942 static void toggle_changer (GtkWidget *checkbutton, 2943 GtkWidget *text) 2944 { 2945 config.changer = GTK_TOGGLE_BUTTON(checkbutton)->active; 2946 2947 #ifdef DEBUG3 2948 g_print("Toggling changer = %d\n", config.changer ); 2949 #endif 2950 2951 config.saved = 0; /* Needs to be written to disk */ 2952 } 2953 #endif 2954 2955 2956 /* Toggle the Eject when done playing */ 2957 static void toggle_eject_done(GtkWidget *checkbutton, 2958 GtkWidget *text) 2959 { 2960 config.done_eject = GTK_TOGGLE_BUTTON(checkbutton)->active; 2961 2962 #ifdef DEBUG3 2963 g_print("Toggling done_eject = %d\n", config.done_eject ); 2964 #endif 2965 2966 config.saved = 0; /* Needs to be written to disk */ 2967 } 2968 2969 2970 /* Toggle the Eject at Close */ 2971 static void toggle_eject_exit(GtkWidget *checkbutton, 2972 GtkWidget *text) 2973 { 2974 config.exit_eject = GTK_TOGGLE_BUTTON(checkbutton)->active; 2975 2976 #ifdef DEBUG3 2977 g_print("Toggling exit_eject = %d\n", config.exit_eject ); 2978 #endif 2979 2980 set_eject( config.exit_eject ); 2981 config.saved = 0; /* Needs to be written to disk */ 2982 } 2983 2984 static void toggle_startup(GtkWidget *checkbutton, 2985 GtkWidget *text) 2986 { 2987 config.startup = GTK_TOGGLE_BUTTON(checkbutton)->active; 2988 config.saved = 0; /* Needs to be written to disk */ 2989 } 2990 2991 2992 void cddb_servers() 2993 { 2994 2995 /* Placeholder for server listing/editing */ 2996 } 2997 2998 2999 static void 3000 page_switch (GtkWidget *widget, GtkNotebookPage *page, gint page_num) 3001 { 3002 GtkNotebookPage *oldpage; 3003 3004 oldpage = GTK_NOTEBOOK (widget)->cur_page; 3005 3006 if (page == oldpage) 3007 return; 3008 3009 } 3010 3011 3012 void device_entry(GtkWidget *widget, GtkWidget *entry) 3013 { 3014 gchar *entry_text; 3015 3016 entry_text = gtk_entry_get_text(GTK_ENTRY(entry)); 3017 3018 config.device = realloc( config.device, strlen(entry_text)+1); 3019 strcpy( config.device, entry_text ); 3020 config.saved = 0; /* Needs to be written to disk */ 3021 } 3022 3023 void cddb_entry(GtkWidget *widget, GtkWidget *entry) 3024 { 3025 gchar *entry_text; 3026 3027 entry_text = gtk_entry_get_text(GTK_ENTRY(entry)); 3028 3029 config.local_cddb = realloc( config.local_cddb, strlen(entry_text)+1); 3030 strcpy( config.local_cddb, entry_text ); 3031 strcpy( cdinfo.local_cddb, entry_text ); 3032 3033 config.saved = 0; /* Needs to be written to disk */ 3034 } 3035 3036 void cddb_to_email(GtkWidget *widget, GtkWidget *entry) 3037 { 3038 gchar *entry_text; 3039 3040 entry_text = gtk_entry_get_text(GTK_ENTRY(entry)); 3041 3042 config.to_cddbd = realloc( config.to_cddbd, strlen(entry_text)+1); 3043 strcpy( config.to_cddbd, entry_text ); 3044 3045 config.saved = 0; /* Needs to be written to disk */ 3046 } 3047 3048 3049 void server_entry(GtkWidget *widget, GtkWidget *entry) 3050 { 3051 gchar *entry_text; 3052 3053 entry_text = gtk_entry_get_text(GTK_ENTRY(entry)); 3054 3055 config.current = realloc( config.current, strlen(entry_text)+1); 3056 strcpy( config.current, entry_text ); 3057 config.saved = 0; /* Needs to be written to disk */ 3058 } 3059 3060 3061 void refresh_servers() 3062 { 3063 char buffer[80]; 3064 3065 /* Need to lock this routine until we complete the last request */ 3066 if( display.cddb_lock == 0 ) 3067 { 3068 /* Get the server list from cddb.cddb.com - DB_SITES */ 3069 /* Tell it to print the diagnostic string */ 3070 cdinfo.cddbd_cmnd = DB_SITES; 3071 3072 /* Set the server to connect to */ 3073 strncpy( cdinfo.server, "cddb.cddb.com", 80 ); 3074 cdinfo.port = 888; 3075 if( write( cddbd_fd, &cdinfo, sizeof( struct CDINFO ) ) < 0 ) 3076 { 3077 perror("write to cddbd error"); 3078 } 3079 3080 display.cddb_lock = 1; 3081 3082 /* Start up a progress dialog */ 3083 display.progress = gtk_dialog_new (); 3084 3085 sprintf( buffer, "Connecting to %s:%d", cdinfo.server, cdinfo.port ); 3086 3087 gtk_signal_connect( GTK_OBJECT( display.progress ), "destroy", 3088 GTK_SIGNAL_FUNC(gtk_widget_destroy), 3089 &display.progress); 3090 3091 gtk_window_set_title (GTK_WINDOW (display.progress), "CDDBD Status"); 3092 gtk_container_border_width (GTK_CONTAINER (display.progress), 0); 3093 gtk_window_set_wmclass(GTK_WINDOW(display.progress), "XfreeCDp", NULL ); 3094 3095 display.plabel = gtk_label_new (buffer); 3096 gtk_misc_set_padding (GTK_MISC (display.plabel), 10, 10); 3097 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (display.progress)->vbox), 3098 display.plabel, FALSE, FALSE, 0); 3099 gtk_widget_show( display.plabel ); 3100 gtk_widget_show( display.progress ); 3101 } 3102 } 3103 3104 3105 /* ----------------------------------------------------------------------- 3106 Display the help/setup dialog box 3107 3108 All changed info is saved when this dialog is exited. 3109 ----------------------------------------------------------------------- */ 3110 gint help_timer( gpointer data ) 3111 { 3112 struct SITE *sp; 3113 static GtkWidget *window = NULL; 3114 GtkWidget *notebook, 3115 *text, 3116 *vbox1, 3117 *vbox2, 3118 *label, 3119 *button, 3120 *table, 3121 *hscrollbar, 3122 *vscrollbar, 3123 *edit; 3124 GList *cbitems = NULL; 3125 3126 3127 gtk_timeout_remove( help.timer ); 3128 help.timer = 0; 3129 3130 /* Create the main window for the notebook */ 3131 if( !window ) 3132 { 3133 window = gtk_window_new (GTK_WINDOW_TOPLEVEL); 3134 gtk_signal_connect (GTK_OBJECT (window), "destroy", 3135 GTK_SIGNAL_FUNC(gtk_widget_destroyed), 3136 &window); 3137 3138 gtk_window_set_title (GTK_WINDOW (window), "notebook"); 3139 gtk_container_border_width (GTK_CONTAINER (window), 0); 3140 gtk_window_set_title (GTK_WINDOW( window ), "XfreeCD Setup"); 3141 gtk_widget_set_usize (window, 250, 300); 3142 gtk_window_set_wmclass(GTK_WINDOW(window), "XfreeCDs", NULL ); 3143 3144 /* Create a vbox to hold the notebook */ 3145 vbox1 = gtk_vbox_new (FALSE, 0); 3146 gtk_container_add (GTK_CONTAINER (window), vbox1); 3147 3148 /* Create the notebook */ 3149 notebook = gtk_notebook_new (); 3150 gtk_signal_connect (GTK_OBJECT (notebook), "switch_page", 3151 GTK_SIGNAL_FUNC (page_switch), NULL); 3152 gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP); 3153 gtk_box_pack_start (GTK_BOX (vbox1), notebook, TRUE, TRUE, 0); 3154 gtk_container_border_width (GTK_CONTAINER (notebook), 10); 3155 gtk_widget_realize (notebook); 3156 3157 /* Create the about page for the notebook -- Put a text window in it */ 3158 vbox2 = gtk_vbox_new( FALSE, 0 ); 3159 gtk_widget_show( vbox2 ); 3160 3161 table = gtk_table_new (2, 2, FALSE); 3162 gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2); 3163 gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2); 3164 gtk_box_pack_start (GTK_BOX (vbox2), table, TRUE, TRUE, 0); 3165 gtk_widget_show (table); 3166 3167 text = gtk_text_new (NULL, NULL); 3168 gtk_text_set_editable (GTK_TEXT (text), FALSE); 3169 gtk_table_attach (GTK_TABLE (table), text, 0, 1, 0, 1, 3170 GTK_EXPAND | GTK_SHRINK | GTK_FILL, 3171 GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0); 3172 gtk_widget_show (text); 3173 3174 hscrollbar = gtk_hscrollbar_new (GTK_TEXT (text)->hadj); 3175 gtk_table_attach (GTK_TABLE (table), hscrollbar, 0, 1, 1, 2, 3176 GTK_EXPAND | GTK_FILL | GTK_SHRINK, GTK_FILL, 0, 0); 3177 gtk_widget_show (hscrollbar); 3178 3179 vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj); 3180 gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1, 3181 GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0); 3182 gtk_widget_show (vscrollbar); 3183 3184 /* Create the label box for the About page */ 3185 label = gtk_label_new ("About"); 3186 3187 /* Add it to the notebook */ 3188 gtk_notebook_append_page_menu (GTK_NOTEBOOK(notebook), vbox2, label, label ); 3189 3190 gtk_text_freeze (GTK_TEXT (text)); 3191 3192 gtk_widget_realize (text); 3193 3194 /* Add the actual text */ 3195 HELP_TEXT( "XfreeCD v0.7.8\n" ); 3196 HELP_TEXT( "Copyright 1998 Brian C. Lane\n" ); 3197 HELP_TEXT( "<nexus@tatoosh.com>\n" ); 3198 HELP_TEXT( "http://www.tatoosh.com/nexus\n\n" ); 3199 3200 HELP_TEXT( "Click on the 'SETUP' tab to set the\n" ); 3201 HELP_TEXT( "CD device and some options:\n\n" ); 3202 HELP_TEXT( "AutoPlay will start playing the CD\n" ); 3203 HELP_TEXT( "when XfreeCD is started\n\n" ); 3204 HELP_TEXT( "Eject when done will eject the CD\n" ); 3205 HELP_TEXT( "when it is finished playing if repeat\n" ); 3206 HELP_TEXT( "is not turned on (the button on the\n" ); 3207 HELP_TEXT( "main panel).\n\n" ); 3208 HELP_TEXT( "Eject on Exit will eject the CD if it\n"); 3209 HELP_TEXT( "is not playing when you exit.\n\n" ); 3210 HELP_TEXT( "Click on the 'CDDB' tab to set up\n" ); 3211 HELP_TEXT( "the support for online cd database\n" ); 3212 HELP_TEXT( "support. The Local CDDB Path\n" ); 3213 HELP_TEXT( "should point to a directory where\n" ); 3214 HELP_TEXT( "you have read and write\n"); 3215 HELP_TEXT( "permission. This is where the\n" ); 3216 HELP_TEXT( "track lists for the CDs will be\n"); 3217 HELP_TEXT( "saved.\n\n"); 3218 HELP_TEXT( "The CDDB Submit email field is for\n" ); 3219 HELP_TEXT( "the email address of the CDDB\n"); 3220 HELP_TEXT( "server to submit CD information\n" ); 3221 HELP_TEXT( "to. The send button is located\n" ); 3222 HELP_TEXT( "in the Track Edit window. Please\n" ); 3223 HELP_TEXT( "only submit CDs that do not exist\n"); 3224 HELP_TEXT( "in the database and that have\n" ); 3225 HELP_TEXT( "complete title and track text\n" ); 3226 HELP_TEXT( "entered.\n\n" ); 3227 HELP_TEXT( "The CDDB server is the internet\n" ); 3228 HELP_TEXT( "site where requests for unknown\n" ); 3229 HELP_TEXT( "CDs will be sent to. Initially only\n" ); 3230 HELP_TEXT( "cddb.cddb.com is listed. Click\n"); 3231 HELP_TEXT( "Refresh Server List to download a\n"); 3232 HELP_TEXT( "list of the available servers.\n" ); 3233 HELP_TEXT( "Use the combobox to pick a server\n" ); 3234 HELP_TEXT( "close to you. If you unselect cddb\n" ); 3235 HELP_TEXT( "support the internet server will\n" ); 3236 HELP_TEXT( "not be queried, but the local\n" ); 3237 HELP_TEXT( "database will be used.\n\n" ); 3238 HELP_TEXT( "Right click & drag on the main\n"); 3239 HELP_TEXT( "display window will allow you to\n" ); 3240 HELP_TEXT( "move XfreeCD even when you\n"); 3241 HELP_TEXT( "have title bars and handles. Left\n"); 3242 HELP_TEXT( "Clicking on the display will open\n"); 3243 HELP_TEXT( "up the Track List window.\n\n" ); 3244 HELP_TEXT( "In the Track List window you can\n"); 3245 HELP_TEXT( "click on the title of a track and\n"); 3246 HELP_TEXT( "XfreeCD will jump directly to\n" ); 3247 HELP_TEXT( "that track and play it.\n\n" ); 3248 HELP_TEXT( "Right clicking on the play/pause\n"); 3249 HELP_TEXT( "button will stop playing and\n"); 3250 HELP_TEXT( "turn off the CD player.\n\n"); 3251 HELP_TEXT( "Volume is controlled by left/right\n"); 3252 HELP_TEXT( "clicking on the volume button.\n\n"); 3253 HELP_TEXT( "Thanks to Ti Kan and Steve Scherf\n" ); 3254 HELP_TEXT( "for creating CDDB.\n\n" ); 3255 3256 gtk_text_thaw (GTK_TEXT (text)); 3257 3258 /* Add the general setup page */ 3259 vbox2 = gtk_vbox_new( FALSE, 0 ); 3260 gtk_widget_show( vbox2 ); 3261 3262 /* Add an editable field for the device */ 3263 label = gtk_label_new ("CDROM device:"); 3264 gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, FALSE, 0); 3265 gtk_widget_show (label); 3266 3267 edit = gtk_entry_new_with_max_length(20); 3268 gtk_signal_connect(GTK_OBJECT(edit), "changed", 3269 GTK_SIGNAL_FUNC(device_entry), 3270 edit); 3271 gtk_widget_show( edit ); 3272 3273 #ifdef DEBUG3 3274 g_print("config.device = %s\n", config.device ); 3275 #endif 3276 3277 if( config.device != NULL ) 3278 gtk_entry_set_text( GTK_ENTRY( edit ), config.device ); 3279 gtk_editable_select_region( GTK_EDITABLE( edit ), 0, -1 ); 3280 gtk_box_pack_start( GTK_BOX( vbox2 ), edit, FALSE, FALSE, 0 ); 3281 gtk_widget_show( edit ); 3282 3283 #ifdef DEBUG3 3284 g_print("config.startup = %d\n", config.startup ); 3285 #endif 3286 3287 /* Create a check button for Playing at Startup */ 3288 button = gtk_check_button_new_with_label("AutoPlay"); 3289 gtk_box_pack_start( GTK_BOX( vbox2 ), button, FALSE, FALSE, 0 ); 3290 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), (config.startup == 1)); 3291 gtk_signal_connect( GTK_OBJECT( button ), "toggled", 3292 GTK_SIGNAL_FUNC( toggle_startup ), NULL ); 3293 gtk_widget_show( button ); 3294 3295 #ifdef DEBUG3 3296 g_print("config.changer = %d\n", config.changer ); 3297 #endif 3298 3299 #ifdef CHANGER_SUPPORT 3300 /* Create a check button for CD Changer */ 3301 button = gtk_check_button_new_with_label("CD Changer"); 3302 gtk_box_pack_start( GTK_BOX( vbox2 ), button, FALSE, FALSE, 0 ); 3303 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), (config.changer == 1)); 3304 gtk_signal_connect( GTK_OBJECT( button ), "toggled", 3305 GTK_SIGNAL_FUNC( toggle_changer ), NULL ); 3306 gtk_widget_show( button ); 3307 #endif 3308 3309 #ifdef DEBUG3 3310 g_print("config.done_eject = %d\n", config.done_eject ); 3311 #endif 3312 3313 /* Create a check button for Eject on Close */ 3314 button = gtk_check_button_new_with_label("Eject when done"); 3315 gtk_box_pack_start( GTK_BOX( vbox2 ), button, FALSE, FALSE, 0 ); 3316 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), (config.done_eject==1)); 3317 gtk_signal_connect( GTK_OBJECT( button ), "toggled", 3318 GTK_SIGNAL_FUNC( toggle_eject_done ), NULL ); 3319 gtk_widget_show( button ); 3320 3321 /* Create a check button for Eject on Exit (and not playing) */ 3322 button = gtk_check_button_new_with_label("Eject on Exit"); 3323 gtk_box_pack_start( GTK_BOX( vbox2 ), button, FALSE, FALSE, 0 ); 3324 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), (config.exit_eject==1)); 3325 gtk_signal_connect( GTK_OBJECT( button ), "toggled", 3326 GTK_SIGNAL_FUNC( toggle_eject_exit ), NULL ); 3327 gtk_widget_show( button ); 3328 3329 3330 /* Create the label box for the Setup page */ 3331 label = gtk_label_new ("Setup"); 3332 3333 /* Add it to the notebook */ 3334 gtk_notebook_append_page_menu( GTK_NOTEBOOK( notebook ), vbox2, label, label ); 3335 3336 3337 /* Create the CDDB page for the notebook */ 3338 vbox2 = gtk_vbox_new( FALSE, 0 ); 3339 gtk_widget_show( vbox2 ); 3340 3341 /* Path to the local cddb database */ 3342 label = gtk_label_new( "Local CDDB Path" ); 3343 gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, FALSE, 0); 3344 gtk_widget_show (label); 3345 3346 /* Add an editable field for the local CDDBD database */ 3347 edit = gtk_entry_new_with_max_length( 1023 ); 3348 gtk_signal_connect(GTK_OBJECT(edit), "changed", 3349 GTK_SIGNAL_FUNC(cddb_entry), 3350 edit); 3351 gtk_widget_show( edit ); 3352 3353 #ifdef DEBUG3 3354 g_print("config.local_cddb = %s\n", config.local_cddb ); 3355 #endif 3356 3357 if( config.local_cddb != NULL ) 3358 gtk_entry_set_text( GTK_ENTRY( edit ), config.local_cddb ); 3359 gtk_editable_select_region( GTK_EDITABLE( edit ), 0, -1 ); 3360 gtk_box_pack_start( GTK_BOX( vbox2 ), edit, FALSE, FALSE, 0 ); 3361 gtk_widget_show( edit ); 3362 3363 /* Email address for submitting to the database */ 3364 label = gtk_label_new( "CDDB Submit Email" ); 3365 gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, FALSE, 0); 3366 gtk_widget_show (label); 3367 3368 /* Add an editable field for the email address */ 3369 edit = gtk_entry_new_with_max_length( 1023 ); 3370 gtk_signal_connect(GTK_OBJECT(edit), "changed", 3371 GTK_SIGNAL_FUNC(cddb_to_email), 3372 edit); 3373 gtk_widget_show( edit ); 3374 3375 #ifdef DEBUG3 3376 g_print("config.local_cddb = %s\n", config.local_cddb ); 3377 #endif 3378 3379 if( config.to_cddbd != NULL ) 3380 gtk_entry_set_text( GTK_ENTRY( edit ), config.to_cddbd ); 3381 gtk_editable_select_region( GTK_EDITABLE( edit ), 0, -1 ); 3382 gtk_box_pack_start( GTK_BOX( vbox2 ), edit, FALSE, FALSE, 0 ); 3383 gtk_widget_show( edit ); 3384 3385 3386 #ifdef DEBUG3 3387 g_print("config.cddb = %d\n", config.cddb ); 3388 #endif 3389 3390 /* Create a check button for CDDB support */ 3391 button = gtk_check_button_new_with_label("CDDB Support"); 3392 gtk_box_pack_start( GTK_BOX( vbox2 ), button, FALSE, FALSE, 0 ); 3393 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), (config.cddb == 1)); 3394 gtk_signal_connect( GTK_OBJECT( button ), "toggled", 3395 GTK_SIGNAL_FUNC( toggle_cddb ), NULL ); 3396 gtk_widget_show( button ); 3397 3398 3399 /* Create the list of servers, use a combobox for this */ 3400 label = gtk_label_new( "CDDB Server" ); 3401 gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, FALSE, 0); 3402 gtk_widget_show (label); 3403 3404 /* Walk the list */ 3405 cbitems = NULL; 3406 sp = config.server; 3407 while( sp != NULL ) 3408 { 3409 cbitems = g_list_append(cbitems, sp->name); 3410 sp = sp->next; 3411 } 3412 3413 display.cb = gtk_combo_new (); 3414 gtk_combo_set_popdown_strings (GTK_COMBO (display.cb), cbitems); 3415 3416 /* Here we should put the selected server into the entry box */ 3417 gtk_entry_set_text (GTK_ENTRY (GTK_COMBO(display.cb)->entry), config.current); 3418 3419 gtk_signal_connect(GTK_OBJECT(GTK_COMBO(display.cb)->entry), "changed", 3420 GTK_SIGNAL_FUNC(server_entry), 3421 GTK_COMBO(display.cb)->entry); 3422 gtk_editable_select_region (GTK_EDITABLE (GTK_COMBO(display.cb)->entry), 3423 0, -1); 3424 gtk_box_pack_start (GTK_BOX (vbox2), display.cb, FALSE, FALSE, 0); 3425 gtk_widget_show (display.cb); 3426 3427 3428 /* Add a button to refresh the list with */ 3429 button = gtk_button_new_with_label("Refresh Server List"); 3430 gtk_signal_connect_object (GTK_OBJECT (button), "clicked", 3431 GTK_SIGNAL_FUNC (refresh_servers), 3432 GTK_OBJECT( window )); 3433 gtk_box_pack_end (GTK_BOX (vbox2), button, FALSE, FALSE, 0); 3434 3435 /* Create the label box for the CDDB page */ 3436 label = gtk_label_new ("CDDB"); 3437 3438 /* Add it to the notebook */ 3439 gtk_notebook_append_page_menu( GTK_NOTEBOOK( notebook ), vbox2, label, label ); 3440 3441 /* Add the close button */ 3442 button = gtk_button_new_with_label ("close"); 3443 gtk_signal_connect_object (GTK_OBJECT (button), "clicked", 3444 GTK_SIGNAL_FUNC (close_setup), 3445 GTK_OBJECT( window )); 3446 gtk_box_pack_start (GTK_BOX (vbox1), button, FALSE, FALSE, 0); 3447 GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); 3448 gtk_widget_grab_default (button); 3449 } 3450 3451 if (!GTK_WIDGET_VISIBLE (window)) 3452 gtk_widget_show_all (window); 3453 else 3454 gtk_widget_destroy( window ); 3455 3456 return FALSE; 3457 } 3458 3459 3460 #ifdef GOOBER1 3461 void old_stuff() 3462 { 3463 3464 /* A useful frame with 3 radio buttons in it */ 3465 3466 /* Create a frame with the Startup options as radio buttons */ 3467 frame = gtk_frame_new("Startup Action"); 3468 gtk_box_pack_start(GTK_BOX(vbox2), frame, FALSE, FALSE, 0); 3469 gtk_widget_show(frame); 3470 3471 /* Add the general setup page */ 3472 vbox3 = gtk_vbox_new( FALSE, 0 ); 3473 gtk_container_add(GTK_CONTAINER(frame), vbox3); 3474 gtk_container_border_width(GTK_CONTAINER(vbox3), 0); 3475 gtk_widget_show( vbox3 ); 3476 3477 /* create radio button for Play at startup */ 3478 button = gtk_radio_button_new_with_label( NULL, "Play CD"); 3479 if( config.startup == STARTUP_PLAY ) 3480 gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE); 3481 else 3482 gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), FALSE); 3483 gtk_signal_connect( GTK_OBJECT( button ), "toggled", 3484 GTK_SIGNAL_FUNC( play_setup ), NULL ); 3485 gtk_box_pack_start(GTK_BOX(vbox3), button, FALSE, FALSE, 0); 3486 gtk_widget_show(button); 3487 3488 button = gtk_radio_button_new_with_label( 3489 gtk_radio_button_group (GTK_RADIO_BUTTON (button)), "Show Tracks"); 3490 if( config.startup == STARTUP_TRACKS ) 3491 gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE); 3492 else 3493 gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), FALSE); 3494 gtk_signal_connect( GTK_OBJECT( button ), "toggled", 3495 GTK_SIGNAL_FUNC( tracks_setup ), NULL ); 3496 gtk_box_pack_start(GTK_BOX(vbox3), button, FALSE, FALSE, 0); 3497 gtk_widget_show(button); 3498 3499 button = gtk_radio_button_new_with_label( 3500 gtk_radio_button_group (GTK_RADIO_BUTTON (button)), "No Disc"); 3501 if( config.startup == STARTUP_NODISC ) 3502 gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE); 3503 else 3504 gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), FALSE); 3505 gtk_signal_connect( GTK_OBJECT( button ), "toggled", 3506 GTK_SIGNAL_FUNC( nothing_setup ), NULL ); 3507 gtk_box_pack_start(GTK_BOX(vbox3), button, FALSE, FALSE, 0); 3508 gtk_widget_show(button); 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 GtkWidget *hbox; 3519 GtkWidget *button; 3520 GtkWidget *check; 3521 GtkWidget *separator; 3522 GtkWidget *table; 3523 GtkWidget *hscrollbar; 3524 GtkWidget *vscrollbar; 3525 GtkWidget *text; 3526 3527 gtk_container_border_width (GTK_CONTAINER (box2), 10); 3528 gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0); 3529 gtk_widget_show (box2); 3530 3531 3532 table = gtk_table_new (2, 2, FALSE); 3533 gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2); 3534 gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2); 3535 gtk_box_pack_start (GTK_BOX (box2), table, TRUE, TRUE, 0); 3536 gtk_widget_show (table); 3537 3538 text = gtk_text_new (NULL, NULL); 3539 gtk_text_set_editable (GTK_TEXT (text), TRUE); 3540 gtk_table_attach (GTK_TABLE (table), text, 0, 1, 0, 1, 3541 GTK_EXPAND | GTK_SHRINK | GTK_FILL, 3542 GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0); 3543 gtk_widget_show (text); 3544 3545 /* hscrollbar = gtk_hscrollbar_new (GTK_TEXT (text)->hadj); 3546 * gtk_table_attach (GTK_TABLE (table), hscrollbar, 0, 1, 1, 2, 3547 * GTK_EXPAND | GTK_FILL | GTK_SHRINK, GTK_FILL, 0, 0); 3548 * gtk_widget_show (hscrollbar); 3549 */ 3550 3551 vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj); 3552 gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1, 3553 GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0); 3554 gtk_widget_show (vscrollbar); 3555 3556 3557 gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, 3558 "This program will play CDs using an attached ", -1); 3559 gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, 3560 "IDE or SoundBlaster CD player. It currently ", -1); 3561 gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, 3562 "does not work with SCSI drives.\n\n", -1); 3563 gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, 3564 "The latest version is available from my webpage.", -1); 3565 gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, 3566 "Please email me with any suggestions, problems,", -1); 3567 gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, 3568 "or comments you may have\n\n", -1); 3569 3570 hbox = gtk_hbutton_box_new (); 3571 gtk_box_pack_start (GTK_BOX (box2), hbox, FALSE, FALSE, 0); 3572 gtk_widget_show (hbox); 3573 3574 /* check = gtk_check_button_new_with_label("Editable"); 3575 * gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, FALSE, 0); 3576 * gtk_signal_connect (GTK_OBJECT(check), "toggled", 3577 * GTK_SIGNAL_FUNC(text_toggle_editable), text); 3578 * gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(check), TRUE); 3579 * gtk_widget_show (check); 3580 */ 3581 3582 /* check = gtk_check_button_new_with_label("Wrap Words"); 3583 * gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0); 3584 * gtk_signal_connect (GTK_OBJECT(check), "toggled", 3585 * GTK_SIGNAL_FUNC(text_toggle_word_wrap), text); 3586 * gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(check), FALSE); 3587 * gtk_widget_show (check); 3588 */ 3589 3590 /* Checkbox for www.cddb.com support */ 3591 check = gtk_check_button_new_with_label("www.cddb.com"); 3592 gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0); 3593 gtk_signal_connect (GTK_OBJECT(check), "toggled", 3594 GTK_SIGNAL_FUNC(about_toggle_cddb), text); 3595 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(check), FALSE); 3596 gtk_widget_show (check); 3597 3598 /* Checkbox for CD Changer support */ 3599 check = gtk_check_button_new_with_label("CD changer"); 3600 gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0); 3601 gtk_signal_connect (GTK_OBJECT(check), "toggled", 3602 GTK_SIGNAL_FUNC(about_toggle_cddb), text); 3603 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(check), FALSE); 3604 gtk_widget_show (check); 3605 3606 gtk_text_set_word_wrap(GTK_TEXT(text), TRUE ); 3607 3608 separator = gtk_hseparator_new (); 3609 gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0); 3610 gtk_widget_show (separator); 3611 3612 3613 box2 = gtk_vbox_new (FALSE, 10); 3614 gtk_container_border_width (GTK_CONTAINER (box2), 10); 3615 gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0); 3616 gtk_widget_show (box2); 3617 3618 } 3619 #endif 3620 3621 3622 void help_press (GtkWidget *widget, GdkEventButton *event) 3623 { 3624 if( event->button == 1 ) 3625 { 3626 gtk_pixmap_set( GTK_PIXMAP( help.wid ), 3627 help.image.dn_pixmap, 3628 help.image.dn_mask ); 3629 3630 /* In XXXmS execute the help dialog window function */ 3631 help.timer = gtk_timeout_add( 500, help_timer, NULL ); 3632 } 3633 } 3634 3635 3636 void help_release (GtkWidget *widget, GdkEventButton *event) 3637 { 3638 if( event->button == 1 ) 3639 { 3640 gtk_pixmap_set( GTK_PIXMAP( help.wid ), 3641 help.image.up_pixmap, 3642 help.image.up_mask ); 3643 } 3644 } 3645 3646 3647 void tdisp_press (GtkWidget *widget, GdkEventButton *event) 3648 { 3649 if( event->button == 1 ) 3650 { 3651 /* Cycle through the time display options */ 3652 switch( display.time ) 3653 { 3654 case TRACK_ELAPSED : display.time = TRACK_REMAIN; 3655 gtk_pixmap_set( GTK_PIXMAP( tdisp.wid ), 3656 display.plstrkdn_pixmap, 3657 display.plstrkdn_mask ); 3658 break; 3659 3660 case TRACK_REMAIN : display.time = CD_ELAPSED; 3661 gtk_pixmap_set( GTK_PIXMAP( tdisp.wid ), 3662 display.mnstrkdn_pixmap, 3663 display.mnstrkdn_mask ); 3664 break; 3665 3666 case CD_ELAPSED : display.time = CD_REMAIN; 3667 gtk_pixmap_set( GTK_PIXMAP( tdisp.wid ), 3668 display.plscddn_pixmap, 3669 display.plscddn_mask ); 3670 break; 3671 3672 case CD_REMAIN : display.time = TRACK_ELAPSED; 3673 gtk_pixmap_set( GTK_PIXMAP( tdisp.wid ), 3674 display.mnscddn_pixmap, 3675 display.mnscddn_mask ); 3676 break; 3677 } 3678 } 3679 } 3680 3681 3682 void tdisp_release (GtkWidget *widget, GdkEventButton *event) 3683 { 3684 if( event->button == 1 ) 3685 { 3686 switch( display.time ) 3687 { 3688 case TRACK_ELAPSED : gtk_pixmap_set( GTK_PIXMAP( tdisp.wid ), 3689 display.plstrkup_pixmap, 3690 display.plstrkup_mask ); 3691 break; 3692 3693 case TRACK_REMAIN : gtk_pixmap_set( GTK_PIXMAP( tdisp.wid ), 3694 display.mnstrkup_pixmap, 3695 display.mnstrkup_mask ); 3696 break; 3697 3698 case CD_ELAPSED : gtk_pixmap_set( GTK_PIXMAP( tdisp.wid ), 3699 display.plscdup_pixmap, 3700 display.plscdup_mask ); 3701 break; 3702 3703 case CD_REMAIN : gtk_pixmap_set( GTK_PIXMAP( tdisp.wid ), 3704 display.mnscdup_pixmap, 3705 display.mnscdup_mask ); 3706 break; 3707 } 3708 } 3709 } 3710 3711 3712 void rpt_press (GtkWidget *widget, GdkEventButton *event) 3713 { 3714 if( event->button == 1 ) 3715 { 3716 gtk_pixmap_set( GTK_PIXMAP( rpt.wid ), 3717 rpt.image.dn_pixmap, 3718 rpt.image.dn_mask ); 3719 3720 if( display.repeat == 0 ) 3721 display.repeat = 1; 3722 else 3723 display.repeat = 0; 3724 } 3725 } 3726 3727 3728 void rpt_release (GtkWidget *widget, GdkEventButton *event) 3729 { 3730 if( event->button == 1 ) 3731 { 3732 if( display.repeat == 0 ) 3733 { 3734 gtk_pixmap_set( GTK_PIXMAP( rpt.wid ), 3735 rpt.image.up_pixmap, 3736 rpt.image.up_mask ); 3737 } else { 3738 gtk_pixmap_set( GTK_PIXMAP( rpt.wid ), 3739 display.rptupact_pixmap, 3740 display.rptupact_mask ); 3741 } 3742 } 3743 } 3744 3745 3746 void vol_press (GtkWidget *widget, GdkEventButton *event) 3747 { 3748 switch( event->button ) 3749 { 3750 case 1 : gtk_pixmap_set( GTK_PIXMAP( vol.wid ), 3751 vol.image.dn_pixmap, 3752 vol.image.dn_mask ); 3753 set_vol( +10 ); 3754 update_display(); 3755 break; 3756 3757 case 3 : gtk_pixmap_set( GTK_PIXMAP( vol.wid ), 3758 vol.image.dn_pixmap, 3759 vol.image.dn_mask ); 3760 set_vol( -10 ); 3761 update_display(); 3762 break; 3763 3764 } 3765 } 3766 3767 void vol_release (GtkWidget *widget, GdkEventButton *event) 3768 { 3769 if( (event->button == 1) || (event->button == 3) ) 3770 { 3771 gtk_pixmap_set( GTK_PIXMAP( vol.wid ), 3772 vol.image.up_pixmap, 3773 vol.image.up_mask ); 3774 } 3775 } 3776 3777 /* ----------------------------------------------------------------------------------------- 3778 Show the track title listbox, allow editing of it. Hilight the current track. Show 3779 total time for each track. Show discid for the CD. Allow sending to CDDB. 3780 ----------------------------------------------------------------------------------------- */ 3781 gint show_tracks( ) 3782 { 3783 3784 return FALSE; 3785 } 3786 3787 3788 /* ----------------------------------------------------------------------- 3789 Redraw the uncovered part of the display 3790 ----------------------------------------------------------------------- */ 3791 static int expose_display( GtkWidget *widget, GdkEventExpose *event ) 3792 { 3793 switch( display.status ) 3794 { 3795 case CDROM_PLAYING : gdk_draw_pixmap (widget->window, 3796 widget->style->black_gc, 3797 display.null_pixmap, 3798 event->area.x, event->area.y, 3799 event->area.x, event->area.y, 3800 event->area.width, event->area.height); 3801 break; 3802 3803 case CDROM_NODISC : gdk_draw_pixmap (widget->window, 3804 widget->style->black_gc, 3805 display.nodisc_pixmap, 3806 event->area.x, event->area.y, 3807 event->area.x, event->area.y, 3808 event->area.width, event->area.height); 3809 break; 3810 } 3811 3812 return FALSE; 3813 } 3814 3815 3816 3817 3818 3819 /* ----------------------------------------------------------------------- 3820 Update the cdrom status and the display 3821 3822 This routine is called once per second to check for the end of the CD 3823 and to update the display. 3824 ----------------------------------------------------------------------- */ 3825 gint update_cdrom( gpointer data ) 3826 { 3827 /* Get the latest info into cdinfo structure */ 3828 cdrom_status(); 3829 3830 return TRUE; 3831 } 3832 3833 3834 /* ----------------------------------------------------------------------- 3835 Draw the current track # onto the null_pixmap and then copy the 3836 pixmap to the display 3837 ----------------------------------------------------------------------- */ 3838 void draw_track() 3839 { 3840 gdk_draw_pixmap( display.null_pixmap, 3841 display.wid->style->black_gc, 3842 display.a_pixmap[display.track/10], 3843 0, 0, 3844 2, 2, 11, 22 ); 3845 3846 gdk_draw_pixmap( display.null_pixmap, 3847 display.wid->style->black_gc, 3848 display.a_pixmap[display.track%10], 3849 0, 0, 3850 15, 2, 11, 22 ); 3851 3852 gdk_draw_pixmap( display.wid->window, 3853 display.wid->style->black_gc, 3854 display.null_pixmap, 3855 0, 0, 3856 0, 0, 92, 30 ); 3857 } 3858 3859 3860 /* ----------------------------------------------------------------------- 3861 Draw the minute digits onto the null_pixmap and then copy the 3862 pixmap to the display. Also draws the minus sign if needed. 3863 ----------------------------------------------------------------------- */ 3864 void draw_minute() 3865 { 3866 /* Show or don't show the minus sign */ 3867 if((display.minute<0) || (display.second<0)) 3868 { 3869 gdk_draw_pixmap( display.null_pixmap, 3870 display.wid->style->black_gc, 3871 display.minus_pixmap, 3872 0, 0, 3873 32, 10, 8, 16 ); 3874 } else { 3875 gdk_draw_pixmap( display.null_pixmap, 3876 display.wid->style->black_gc, 3877 display.b_pixmap[10], 3878 0, 0, 3879 32, 10, 8, 16 ); 3880 } 3881 3882 gdk_draw_pixmap( display.null_pixmap, 3883 display.wid->style->black_gc, 3884 display.b_pixmap[abs(display.minute)/10], 3885 0, 0, 3886 42, 10, 8, 16 ); 3887 3888 gdk_draw_pixmap( display.null_pixmap, 3889 display.wid->style->black_gc, 3890 display.b_pixmap[abs(display.minute)%10], 3891 0, 0, 3892 52, 10, 8, 16 ); 3893 3894 gdk_draw_pixmap( display.wid->window, 3895 display.wid->style->black_gc, 3896 display.null_pixmap, 3897 0, 0, 3898 0, 0, 92, 30 ); 3899 } 3900 3901 3902 /* ----------------------------------------------------------------------- 3903 Draw the second digits onto the null_pixmap and then copy the 3904 pixmap to the display. 3905 ----------------------------------------------------------------------- */ 3906 void draw_second() 3907 { 3908 /* Show or don't show the minus sign */ 3909 if((display.minute<0) || (display.second<0)) 3910 { 3911 gdk_draw_pixmap( display.null_pixmap, 3912 display.wid->style->black_gc, 3913 display.minus_pixmap, 3914 0, 0, 3915 32, 10, 8, 16 ); 3916 } else { 3917 gdk_draw_pixmap( display.null_pixmap, 3918 display.wid->style->black_gc, 3919 display.b_pixmap[10], 3920 0, 0, 3921 32, 10, 8, 16 ); 3922 } 3923 3924 gdk_draw_pixmap( display.null_pixmap, 3925 display.wid->style->black_gc, 3926 display.b_pixmap[abs(display.second/10)], 3927 0, 0, 3928 68, 10, 8, 16 ); 3929 3930 gdk_draw_pixmap( display.null_pixmap, 3931 display.wid->style->black_gc, 3932 display.b_pixmap[abs(display.second%10)], 3933 0, 0, 3934 78, 10, 8, 16 ); 3935 3936 gdk_draw_pixmap( display.wid->window, 3937 display.wid->style->black_gc, 3938 display.null_pixmap, 3939 0, 0, 3940 0, 0, 92, 30 ); 3941 } 3942 3943 3944 /* ----------------------------------------------------------------------- 3945 Erase the minute digits and the minus sign. This is used by the blink 3946 routine. 3947 ----------------------------------------------------------------------- */ 3948 void erase_minute() 3949 { 3950 gdk_draw_pixmap( display.null_pixmap, 3951 display.wid->style->black_gc, 3952 display.b_pixmap[10], 3953 0, 0, 3954 32, 10, 8, 16 ); 3955 3956 gdk_draw_pixmap( display.null_pixmap, 3957 display.wid->style->black_gc, 3958 display.b_pixmap[10], 3959 0, 0, 3960 42, 10, 8, 16 ); 3961 3962 gdk_draw_pixmap( display.null_pixmap, 3963 display.wid->style->black_gc, 3964 display.b_pixmap[10], 3965 0, 0, 3966 52, 10, 8, 16 ); 3967 3968 gdk_draw_pixmap( display.wid->window, 3969 display.wid->style->black_gc, 3970 display.null_pixmap, 3971 0, 0, 3972 0, 0, 92, 30 ); 3973 } 3974 3975 3976 /* ----------------------------------------------------------------------- 3977 Erase the second digits. This is used by the blink routine. 3978 ----------------------------------------------------------------------- */ 3979 void erase_second() 3980 { 3981 gdk_draw_pixmap( display.null_pixmap, 3982 display.wid->style->black_gc, 3983 display.b_pixmap[10], 3984 0, 0, 3985 68, 10, 8, 16 ); 3986 3987 gdk_draw_pixmap( display.null_pixmap, 3988 display.wid->style->black_gc, 3989 display.b_pixmap[10], 3990 0, 0, 3991 78, 10, 8, 16 ); 3992 3993 gdk_draw_pixmap( display.wid->window, 3994 display.wid->style->black_gc, 3995 display.null_pixmap, 3996 0, 0, 3997 0, 0, 92, 30 ); 3998 } 3999 4000 4001 /* ----------------------------------------------------------------------- 4002 Decide what to show on the display 4003 If there is no disc, then show NO DISC bitmap 4004 If playing then update the display digits 4005 If paused then blink the time 4006 4007 It keeps track of the previous states of things so only the areas that 4008 have changed get updated each time. An improvement would be to only 4009 update the digits that change (instead of both minute or both second 4010 digits), but it isn't that important. 4011 ----------------------------------------------------------------------- */ 4012 void update_display() 4013 { 4014 static int curr_track=-1, /* Default to unknown value */ 4015 curr_minute=-1, 4016 curr_second=-1, 4017 curr_status=-1, 4018 curr_volume=-1, 4019 blinking=0, 4020 tclist_track=-1; /* Track selected in tclist */ 4021 4022 int x; 4023 4024 /* 4025 * If the volume needs updating then we draw a bargraph, one bar for 4026 * every 17 volume units. 15 bars maximum with the last 5 being red 4027 */ 4028 if( curr_volume != cdinfo.volume ) 4029 { 4030 for( x = 0; x < (cdinfo.volume / 17); x++ ) 4031 { 4032 if( x < 10 ) 4033 { 4034 gdk_draw_pixmap( display.null_pixmap, 4035 display.wid->style->black_gc, 4036 display.bar_pixmap, 4037 0, 0, 4038 30+(x*4), 1, 4, 7 ); 4039 } else { 4040 gdk_draw_pixmap( display.null_pixmap, 4041 display.wid->style->black_gc, 4042 display.redbar_pixmap, 4043 0, 0, 4044 30+(x*4), 1, 4, 7 ); 4045 } 4046 } 4047 for( ; x < 15; x++ ) 4048 { 4049 gdk_draw_pixmap( display.null_pixmap, 4050 display.wid->style->black_gc, 4051 display.nobar_pixmap, 4052 0, 0, 4053 30+(x*4), 1, 4, 7 ); 4054 } 4055 4056 gdk_draw_pixmap( display.wid->window, 4057 display.wid->style->black_gc, 4058 display.null_pixmap, 4059 0, 0, 4060 0, 0, 92, 30 ); 4061 4062 curr_volume = cdinfo.volume; 4063 } 4064 4065 switch( display.time ) 4066 { 4067 case TRACK_ELAPSED : 4068 display.minute = cdinfo.sc.cdsc_reladdr.msf.minute; 4069 display.second = cdinfo.sc.cdsc_reladdr.msf.second; 4070 break; 4071 4072 case TRACK_REMAIN : 4073 display.minute = 0 - ( (cdinfo.track[display.track-1].length/60) - cdinfo.sc.cdsc_reladdr.msf.minute); 4074 display.second = 0 - ( (cdinfo.track[display.track-1].length%60) - cdinfo.sc.cdsc_reladdr.msf.second); 4075 break; 4076 4077 case CD_ELAPSED : 4078 display.minute = cdinfo.sc.cdsc_absaddr.msf.minute; 4079 display.second = cdinfo.sc.cdsc_absaddr.msf.second; 4080 break; 4081 4082 case CD_REMAIN : 4083 display.minute = 0-cdinfo.cd_remaining/60; 4084 display.second = 0-cdinfo.cd_remaining%60; 4085 break; 4086 } 4087 4088 4089 switch( display.status ) 4090 { 4091 case CDROM_PLAYING : if( display.track != curr_track ) 4092 { 4093 draw_track(); 4094 4095 curr_track = display.track; 4096 } 4097 4098 if( display.minute != curr_minute ) 4099 { 4100 draw_minute(); 4101 4102 curr_minute = display.minute; 4103 } 4104 4105 if( display.second != curr_second ) 4106 { 4107 draw_second(); 4108 4109 curr_second = display.second; 4110 } 4111 curr_status = display.status; 4112 4113 if( display.playbtn != CDROM_PLAYING ) 4114 { 4115 gtk_pixmap_set( GTK_PIXMAP( play.wid ), 4116 display.playup_pixmap, 4117 display.playup_mask ); 4118 4119 display.playbtn = CDROM_PLAYING; 4120 } 4121 4122 /* If the track window is open, update selected track */ 4123 if( display.twindow != NULL ) 4124 { 4125 if( tclist_track+1 != curr_track ) 4126 { 4127 if( curr_track > 0 ) 4128 tclist_track = curr_track -1; 4129 else 4130 tclist_track = 0; 4131 gtk_clist_select_row( GTK_CLIST(display.tclist), tclist_track, -1 ); 4132 } 4133 } 4134 4135 break; 4136 4137 /* Flash the min/sec digits while paused */ 4138 case CDROM_PAUSED : if( display.track != curr_track ) 4139 { 4140 draw_track(); 4141 4142 curr_track = display.track; 4143 } 4144 4145 4146 if( blinking ) 4147 { 4148 draw_second(); 4149 draw_minute(); 4150 blinking=0; 4151 } else { 4152 erase_second(); 4153 erase_minute(); 4154 curr_second = -1; 4155 curr_minute = -1; 4156 blinking=1; 4157 } 4158 4159 if( display.playbtn != CDROM_PAUSED ) 4160 { 4161 gtk_pixmap_set( GTK_PIXMAP( play.wid ), 4162 display.pauseup_pixmap, 4163 display.pauseup_mask ); 4164 display.playbtn = CDROM_PAUSED; 4165 } 4166 break; 4167 4168 /* Display NO DISC */ 4169 case CDROM_NODISC : if( curr_status != display.status ) 4170 { 4171 gdk_draw_pixmap( display.wid->window, 4172 display.wid->style->black_gc, 4173 display.nodisc_pixmap, 4174 0, 0, 4175 0, 0, 92, 30 ); 4176 4177 curr_status = display.status; 4178 } 4179 4180 if( display.playbtn != CDROM_NODISC ) 4181 { 4182 gtk_pixmap_set( GTK_PIXMAP( play.wid ), 4183 display.stopup_pixmap, 4184 display.stopup_mask ); 4185 display.playbtn = CDROM_NODISC; 4186 } 4187 4188 break; 4189 } 4190 4191 #ifdef DEBUG4 4192 g_print( "update called. status = %d remain = %d\n", display.status, cdinfo.cd_remaining ); 4193 g_print( " curr new\n"); 4194 g_print( "track %03d : %03d\n", curr_track, display.track ); 4195 g_print( "minute %03d : %03d\n", curr_minute, display.minute ); 4196 g_print( "second %03d : %03d\n", curr_second, display.second ); 4197 g_print( "volume %03d : %03d\n", curr_volume, cdinfo.volume ); 4198 #endif 4199 4200 } 4201 4202 4203 /* ------------------------------------------------------------------------ 4204 Process data coming back from the cd_control process 4205 4206 This is a stateless process since it only returns a cdinfo structure 4207 ------------------------------------------------------------------------ */ 4208 void wait_status() 4209 { 4210 struct CDINFO tmpinfo; 4211 struct SITE *sp; 4212 char buffer[80]; 4213 int x; 4214 char *texts[3], 4215 text1[255], 4216 text2[255]; 4217 4218 4219 /* Read the new cdinfo structure from the cd_control process */ 4220 if( read( cd_fd, &tmpinfo, sizeof(struct CDINFO) ) < 0 ) 4221 perror("cdrom_status(read)"); 4222 4223 /* Copy the useful bits from tmpinfo to cdinfo */ 4224 memcpy( &cdinfo.tochdr, &tmpinfo.tochdr, sizeof(tmpinfo.tochdr) ); 4225 memcpy( &cdinfo.leadout, &tmpinfo.leadout, sizeof(tmpinfo.leadout) ); 4226 memcpy( &cdinfo.volume, &tmpinfo.volume, sizeof(tmpinfo.volume) ); 4227 4228 /* Copy track length, but not the track name over from the status */ 4229 for( x = 0; x < cdinfo.tochdr.cdth_trk1; x++ ) 4230 { 4231 cdinfo.track[x].te = tmpinfo.track[x].te; 4232 cdinfo.track[x].length = tmpinfo.track[x].length; 4233 cdinfo.track[x].frame_offset = tmpinfo.track[x].frame_offset; 4234 } 4235 4236 memcpy( &cdinfo.sc, &tmpinfo.sc, sizeof(tmpinfo.sc) ); 4237 memcpy( &cdinfo.ti, &tmpinfo.ti, sizeof(tmpinfo.ti) ); 4238 cdinfo.cd_length = tmpinfo.cd_length; 4239 cdinfo.discid = tmpinfo.discid; 4240 4241 switch( cdinfo.sc.cdsc_audiostatus ) 4242 { 4243 case CDROM_AUDIO_PLAY : 4244 case CDROM_AUDIO_PAUSED : 4245 if( cdinfo.sc.cdsc_audiostatus == CDROM_AUDIO_PLAY ) 4246 display.status = CDROM_PLAYING; 4247 else 4248 display.status = CDROM_PAUSED; 4249 4250 /* Update the currently playing track */ 4251 display.track = cdinfo.sc.cdsc_trk; 4252 4253 /* Update the number of seconds remaining on the CD */ 4254 cdinfo.cd_remaining = cdinfo.cd_length - ((cdinfo.sc.cdsc_absaddr.msf.minute*60)+cdinfo.sc.cdsc_absaddr.msf.second); 4255 4256 /* Do we need track data? Can we request it? */ 4257 if( (display.cddb_lock == 0) && (cdinfo.revision == -1)) 4258 { 4259 if( config.cddb == 1 ) 4260 { 4261 #ifdef DEBUG9 4262 g_print("reading cddb info %d\n", cdinfo.revision ); 4263 #endif 4264 /* Try and find a cddb entry in the local CD database */ 4265 if( read_cddb( &cdinfo ) < 0 ) 4266 { 4267 /* Default server to query */ 4268 strcpy( cdinfo.server, "cddb.cddb.com" ); 4269 cdinfo.port = 888; 4270 4271 /* So here we query the default internet server */ 4272 if( config.current != NULL ) 4273 { 4274 /* Use the current + 888 even if not found in the list */ 4275 strcpy( cdinfo.server, config.current ); 4276 4277 /* Find the current server in the list */ 4278 sp = config.server; 4279 while( sp != NULL ) 4280 { 4281 if( strcmp( sp->name, config.current ) == 0 ) 4282 { 4283 strcpy( cdinfo.server, sp->name ); 4284 cdinfo.port = sp->port; 4285 sp = NULL; 4286 }else { 4287 sp = sp->next; 4288 } 4289 } 4290 } 4291 /* Send the command to the server - Starts a state machine */ 4292 cdinfo.cddbd_cmnd = DB_READ; 4293 if( write( cddbd_fd, &cdinfo, sizeof( struct CDINFO) ) < 0 ) 4294 { 4295 perror("write to cddbd_fd error"); 4296 if( cdinfo.revision < 0 ) 4297 cdinfo.revision = -2; /* Failed, Don't try again */ 4298 } 4299 /* Lock the use of the internet database */ 4300 display.cddb_lock = 1; 4301 4302 /* !!!! This could probably be turned into a subroutine 4303 !!!! */ 4304 4305 /* Start up a progress dialog */ 4306 display.progress = gtk_dialog_new (); 4307 4308 sprintf(buffer, "Connecting to %s:%d", cdinfo.server, 4309 cdinfo.port ); 4310 4311 gtk_signal_connect( GTK_OBJECT( display.progress ), "destroy", 4312 GTK_SIGNAL_FUNC(gtk_widget_destroy), 4313 &display.progress); 4314 4315 gtk_window_set_title (GTK_WINDOW (display.progress), "CDDBD Status"); 4316 gtk_container_border_width (GTK_CONTAINER (display.progress), 0); 4317 gtk_window_set_wmclass(GTK_WINDOW(display.progress), "XfreeCDp", NULL ); 4318 4319 display.plabel = gtk_label_new (buffer); 4320 gtk_misc_set_padding (GTK_MISC (display.plabel), 10, 10); 4321 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (display.progress)->vbox), 4322 display.plabel, FALSE, FALSE, 0); 4323 gtk_widget_show( display.plabel ); 4324 gtk_widget_show( display.progress ); 4325 } else { 4326 /* Read of local database successful */ 4327 #ifdef DEBUG5 4328 g_print("Title : %s\n", cdinfo.title->str ); 4329 for( x = 0; x < cdinfo.tochdr.cdth_trk1; x++ ) 4330 { 4331 g_print("Track %d : %s\n", x+1, cdinfo.name[x]->str ); 4332 } 4333 #endif 4334 } 4335 } else { 4336 /* Read the data from the local database, or set defaults */ 4337 local_cddb(); 4338 } 4339 4340 /* If the track list window is open, update the list */ 4341 if( display.twindow != NULL ) 4342 { 4343 #ifdef DEBUG9 4344 g_print("Updating Track Window revision=%d\n", cdinfo.revision); 4345 #endif 4346 4347 gtk_clist_freeze (GTK_CLIST (display.tclist)); 4348 4349 /* Clear out the old list first */ 4350 gtk_clist_clear( GTK_CLIST( display.tclist ) ); 4351 4352 /* Set the new title */ 4353 if( cdinfo.title != NULL ) 4354 sprintf( text1, "%s", cdinfo.title->str ); 4355 else 4356 strcpy( text1, "" ); 4357 gtk_label_set( GTK_LABEL( display.ttitle ), text1 ); 4358 4359 /* Add the track names */ 4360 for( x = 0; x < cdinfo.tochdr.cdth_trk1; x++ ) 4361 { 4362 sprintf( text1, "%d", x+1 ); 4363 sprintf( text2, "%d:%02d",cdinfo.track[x].length/60,cdinfo.track[x].length%60 ); 4364 texts[0] = text1; 4365 texts[2] = text2; 4366 if( cdinfo.name[x] != NULL ) 4367 texts[1] = cdinfo.name[x]->str; 4368 else 4369 texts[1] = "(blank)"; 4370 gtk_clist_append (GTK_CLIST (display.tclist), texts); 4371 } 4372 gtk_clist_thaw( GTK_CLIST( display.tclist ) ); 4373 gtk_clist_select_row( GTK_CLIST(display.tclist), display.track-1, -1 ); 4374 } 4375 } 4376 break; 4377 4378 #ifdef OLD_WAY 4379 case CDROM_AUDIO_PAUSED : 4380 display.status = CDROM_PAUSED; 4381 break; 4382 #endif 4383 4384 case CDROM_AUDIO_NO_STATUS : 4385 /* Only clean things up once */ 4386 if( display.status != CDROM_NODISC ) 4387 { 4388 /* Clear out the track list */ 4389 if( display.twindow != NULL ) 4390 { 4391 gtk_clist_clear( GTK_CLIST( display.tclist ) ); 4392 4393 /* Clear the title */ 4394 gtk_label_set( GTK_LABEL( display.ttitle ), "" ); 4395 } 4396 4397 /* Free dynamically allocated cdinfo strings */ 4398 free_cdinfo(); 4399 4400 display.status = CDROM_NODISC; 4401 /* Reset the revision # so next will recall from database*/ 4402 cdinfo.revision = -1; 4403 } 4404 break; 4405 4406 default: 4407 /* Only cleanup once */ 4408 if( display.status != CDROM_NODISC ) 4409 { 4410 /* Clear out the track list */ 4411 if( display.twindow != NULL ) 4412 { 4413 gtk_clist_clear( GTK_CLIST( display.tclist ) ); 4414 4415 /* Clear the title */ 4416 gtk_label_set( GTK_LABEL( display.ttitle ), "" ); 4417 } 4418 4419 /* Free dynamically allocated cdinfo strings */ 4420 free_cdinfo(); 4421 4422 display.status = CDROM_NODISC; 4423 cdinfo.revision = -1; 4424 } 4425 break; 4426 } 4427 4428 4429 /* 4430 * If the CD is over then either restart it, or eject it, or show NO DISC 4431 */ 4432 if( (cdinfo.cd_remaining == 0) && (display.status == CDROM_PLAYING) ) 4433 { 4434 /* If repeat is on, start playing the cd over from the start */ 4435 if( display.repeat == 1 ) 4436 { 4437 display.track = cdinfo.tochdr.cdth_trk0; 4438 play_track( cdinfo.tochdr.cdth_trk0 ); 4439 } else { 4440 /* Clear out the track list */ 4441 if( display.twindow != NULL ) 4442 { 4443 gtk_clist_clear( GTK_CLIST( display.tclist ) ); 4444 4445 /* Clear the title */ 4446 gtk_label_set( GTK_LABEL( display.ttitle ), "" ); 4447 } 4448 4449 /* Free up any dynamically allocated cdinfo strings */ 4450 free_cdinfo(); 4451 4452 /* Eject when done Playing - only eject if the user has enabled this */ 4453 if( config.done_eject == 1 ) 4454 { 4455 /* All done, eject it for the next disc! */ 4456 eject_cdrom(); 4457 } else { 4458 stop_cdrom(); 4459 } 4460 4461 gtk_pixmap_set( GTK_PIXMAP( play.wid ), 4462 display.stopup_pixmap, 4463 display.stopup_mask ); 4464 display.playbtn = CDROM_NODISC; 4465 } 4466 } 4467 } 4468 4469 4470 /* ------------------------------------------------------------------------- 4471 Process data coming back from the cd_control process 4472 4473 This is a stateless process since it only returns a cdinfo structure 4474 ------------------------------------------------------------------------- */ 4475 void cd_fd_read( gpointer data, gint source, GdkInputCondition condition) 4476 { 4477 wait_status(); 4478 4479 if( display.startup == 0 ) 4480 { 4481 if( config.startup == 1 ) 4482 { 4483 /* If it is already playing, don't restart it */ 4484 if( ( cdinfo.sc.cdsc_audiostatus != CDROM_AUDIO_PLAY ) && 4485 (cdinfo.discid != 0 ) ) 4486 { 4487 #ifdef DEBUG6 4488 g_print("Starting play of cd. audiostatus = %d\n", cdinfo.sc.cdsc_audiostatus ); 4489 #endif 4490 play_track( 1 ); 4491 } 4492 } 4493 4494 /* Stop trying after the discid gets set by cd_control process */ 4495 if( cdinfo.discid != 0 ) 4496 display.startup = 1; 4497 } 4498 4499 update_display(); 4500 } 4501 4502 4503 /* ------------------------------------------------------------------------ 4504 this is the signal handler that gets called if GtkList 4505 emits the "selection_changed" signal 4506 ------------------------------------------------------------------------ */ 4507 void inexact_selected( GtkWidget *gtklist, gpointer func_data) 4508 { 4509 char *p, 4510 buffer[80]; 4511 GList *dlist; 4512 GtkObject *list_item; 4513 gchar *item_data_string; 4514 4515 4516 /* fetch the doubly linked list of selected items 4517 * of the GtkList, remember to treat this as read-only! 4518 */ 4519 dlist=GTK_LIST(gtklist)->selection; 4520 4521 /* if there are no selected items there is nothing more 4522 * to do than just telling the user so 4523 */ 4524 if (dlist) 4525 { 4526 list_item=GTK_OBJECT(dlist->data); 4527 item_data_string=gtk_object_get_data(list_item, 4528 "XfreeCDkey"); 4529 p = strtok( item_data_string, " \n" ); 4530 p = strtok( NULL, " \n" ); 4531 4532 #ifdef DEBUG3 4533 g_print("Retrieving data for %s\n", p); 4534 #endif 4535 4536 /* Change the discid so the new request will work */ 4537 sscanf( p, "%lx", &cdinfo.discid ); 4538 cdinfo.cddbd_cmnd = DB_READ; 4539 if( write( cddbd_fd, &cdinfo, sizeof( struct CDINFO) ) < 0 ) 4540 { 4541 perror("write to cddbd_fd error"); 4542 if( cdinfo.revision < 0 ) 4543 cdinfo.revision = -2; /* Failed, Don't try again */ 4544 } 4545 /* Lock use of the CDDB internet server */ 4546 display.cddb_lock = 1; 4547 4548 /* Delete the old progress box */ 4549 gtk_widget_destroy( display.progress ); 4550 display.plabel = NULL; 4551 4552 /* Start up a new progress dialog */ 4553 display.progress = gtk_dialog_new (); 4554 4555 sprintf(buffer, "Connecting to %s:%d", cdinfo.server, cdinfo.port ); 4556 4557 gtk_signal_connect( GTK_OBJECT( display.progress ), "destroy", 4558 GTK_SIGNAL_FUNC(gtk_widget_destroy), 4559 &display.progress); 4560 4561 gtk_window_set_title (GTK_WINDOW (display.progress), "CDDBD Status"); 4562 gtk_container_border_width (GTK_CONTAINER (display.progress), 0); 4563 gtk_window_set_wmclass(GTK_WINDOW(display.progress), "XfreeCDp", NULL ); 4564 4565 display.plabel = gtk_label_new (buffer); 4566 gtk_misc_set_padding (GTK_MISC (display.plabel), 10, 10); 4567 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (display.progress)->vbox), 4568 display.plabel, FALSE, FALSE, 0); 4569 gtk_widget_show( display.plabel ); 4570 gtk_widget_show( display.progress ); 4571 } else { 4572 gtk_widget_destroy( display.progress ); 4573 display.plabel = NULL; 4574 } 4575 } 4576 4577 4578 4579 4580 /* ------------------------------------------------------------------------- 4581 Process data coming back from the cddbd process 4582 4583 This routine processes data from the pipe to the cddbd process. This gets 4584 the track names and site list from the server. 4585 ------------------------------------------------------------------------- */ 4586 void cddbd_fd_read( gpointer data, gint source, GdkInputCondition condition) 4587 { 4588 struct CDINFO tmpinfo; 4589 int x; 4590 static struct SITE *sp, 4591 *sp_top=NULL, 4592 *sp_end=NULL; 4593 char *p, buffer[80]; 4594 gchar *string; 4595 GtkWidget *button, 4596 *scrolled_win, 4597 *list, 4598 *vbox1, 4599 *label; 4600 static GList *cbitems=NULL; 4601 char *texts[3], 4602 text1[255], 4603 text2[255]; 4604 4605 4606 /* Read back the status structure */ 4607 if( read( cddbd_fd, &tmpinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) ) 4608 { 4609 perror( "CDDBD status read" ); 4610 close( cd_fd ); 4611 close( cddbd_fd ); 4612 exit(-1); 4613 } 4614 4615 switch( tmpinfo.cddbd_stat ) 4616 { 4617 case CDDBD_OPEN_OK : 4618 #ifdef DEBUG3 4619 g_print("Connected to %s ok\n", tmpinfo.server ); 4620 #endif 4621 4622 if( display.plabel != NULL ) 4623 { 4624 sprintf (buffer, "Connected to %s:%d", tmpinfo.server, tmpinfo.port); 4625 gtk_label_set (GTK_LABEL (display.plabel), buffer); 4626 } 4627 break; 4628 4629 case CDDBD_DONE_OK : 4630 display.cddb_lock = 0; 4631 4632 /* Copy the info from the tmpinfo to cdinfo */ 4633 #ifdef DEBUG3 4634 g_print("Got the new data ok\n"); 4635 g_print("tmpinfo.title->str = 0x%X\n", tmpinfo.title->str ); 4636 #endif 4637 4638 #ifdef DUMB 4639 if( display.plabel != NULL ) 4640 { 4641 sprintf (buffer, "Retrieved %s", tmpinfo.title->str ); 4642 gtk_label_set (GTK_LABEL (display.plabel), buffer); 4643 } 4644 #endif 4645 4646 gtk_widget_destroy( display.progress ); 4647 display.plabel = NULL; 4648 4649 /* Read the new data from the database */ 4650 local_cddb(); 4651 4652 /* If the track list window is open, update the list */ 4653 if( display.twindow != NULL ) 4654 { 4655 gtk_clist_freeze (GTK_CLIST (display.tclist)); 4656 4657 /* Clear out the old list first */ 4658 gtk_clist_clear( GTK_CLIST( display.tclist ) ); 4659 4660 /* Set the new title */ 4661 if( cdinfo.title != NULL ) 4662 sprintf( text1, "%s", cdinfo.title->str ); 4663 else 4664 strcpy( text1, "" ); 4665 gtk_label_set( GTK_LABEL( display.ttitle ), text1 ); 4666 4667 /* Add the track names */ 4668 for( x = 0; x < cdinfo.tochdr.cdth_trk1; x++ ) 4669 { 4670 sprintf( text1, "%d", x+1 ); 4671 sprintf( text2, "%d:%02d",cdinfo.track[x].length/60,cdinfo.track[x].length%60 ); 4672 texts[0] = text1; 4673 texts[2] = text2; 4674 if( cdinfo.name[x] != NULL ) 4675 texts[1] = cdinfo.name[x]->str; 4676 else 4677 texts[1] = "(blank)"; 4678 gtk_clist_append (GTK_CLIST (display.tclist), texts); 4679 } 4680 gtk_clist_thaw( GTK_CLIST( display.tclist ) ); 4681 gtk_clist_select_row( GTK_CLIST(display.tclist), display.track-1, -1 ); 4682 } 4683 break; 4684 4685 /* Process the line of text */ 4686 case CDDBD_MOTD_LINE : 4687 4688 if( tmpinfo.line[0] == '.' ) 4689 { 4690 display.cddb_lock = 0; 4691 #ifdef DEBUG3 4692 g_print("End of MOTD\n"); 4693 #endif 4694 4695 gtk_widget_destroy( display.progress ); 4696 display.plabel = NULL; 4697 4698 } else { 4699 #ifdef DEBUG3 4700 /* Do something with the MOTD, for now print it */ 4701 g_print( "%s", tmpinfo.line ); 4702 #endif 4703 4704 if( display.plabel != NULL ) 4705 { 4706 gtk_label_set (GTK_LABEL (display.plabel), tmpinfo.line); 4707 } 4708 } 4709 break; 4710 4711 /* Process the line of text */ 4712 case CDDBD_SITE_LINE : 4713 4714 if( tmpinfo.line[0] == '.' ) 4715 { 4716 display.cddb_lock = 0; 4717 #ifdef DEBUG3 4718 g_print("End of Site listing\n"); 4719 #endif 4720 if( display.plabel != NULL ) 4721 { 4722 sprintf (buffer, "Retrieved Site Listing ok" ); 4723 gtk_label_set (GTK_LABEL (display.plabel), buffer); 4724 } 4725 4726 if( sp_top != NULL ) 4727 { 4728 /* Everything seems okay, erase the old list and add the new one */ 4729 while( config.server != NULL ) 4730 { 4731 sp = config.server; 4732 config.server = config.server->next; 4733 free( sp->name ); 4734 free( sp ); 4735 } 4736 4737 /* Point config to the new list */ 4738 config.server = sp_top; 4739 sp_top = sp_end = NULL; 4740 4741 config.saved = 0; /* Need to save this to disk */ 4742 write_config( &config ); /* Write new list to disk */ 4743 strncpy( cdinfo.device, config.device, 80 ); 4744 4745 /* Need to let the site list in the dialog box be updated if it is 4746 still being shown (user could close it before we finish). 4747 */ 4748 if( display.cb != NULL ) 4749 { 4750 4751 /* Walk the list */ 4752 cbitems = NULL; 4753 sp = config.server; 4754 while( sp != NULL ) 4755 { 4756 cbitems = g_list_append(cbitems, sp->name); 4757 sp = sp->next; 4758 } 4759 4760 gtk_combo_set_popdown_strings (GTK_COMBO (display.cb), cbitems); 4761 cbitems = NULL; 4762 } 4763 4764 } 4765 gtk_widget_destroy( display.progress ); 4766 display.plabel = NULL; 4767 4768 } else { 4769 /* Do something with the SITE, for now print it */ 4770 /* Need to store in a temp. List until complete, then move to config */ 4771 #ifdef DEBUG3 4772 g_print( "%s", tmpinfo.line ); 4773 #endif 4774 4775 if( display.plabel != NULL ) 4776 { 4777 gtk_label_set (GTK_LABEL (display.plabel), tmpinfo.line); 4778 } 4779 4780 /* Reserve some space for this server, add it to the end of the list */ 4781 if( ( sp = (struct SITE *) malloc( sizeof(struct SITE) ) ) == NULL ) 4782 { 4783 perror("malloc - 1"); 4784 } 4785 bzero( sp, sizeof(struct SITE) ); 4786 4787 p = strtok( tmpinfo.line, " \n" ); 4788 4789 /* Reserve space for the name */ 4790 if( ( sp->name = (char *) malloc( strlen(p)+1 ) ) == NULL ) 4791 { 4792 perror("malloc - 2"); 4793 } 4794 strcpy( sp->name, p ); 4795 4796 p = strtok( NULL, " \n" ); 4797 sp->port = atoi(p); 4798 sp->next = NULL; 4799 4800 /* Is it the first in the list? */ 4801 if( sp_top == NULL ) 4802 { 4803 /* Yep, First in the list */ 4804 sp_top = sp; 4805 sp_end = sp; 4806 } else { 4807 /* No, add it to the end of the list */ 4808 sp_end->next = sp; 4809 sp_end = sp; 4810 } 4811 } 4812 break; 4813 4814 4815 /* Process the line of text inexact matches */ 4816 case CDDBD_INEX_LINE : 4817 4818 if( tmpinfo.line[0] == '.' ) 4819 { 4820 cdinfo.revision = -2; 4821 display.cddb_lock = 0; 4822 4823 #ifdef DEBUG3 4824 g_print("End of Inexact Match listing\n"); 4825 #endif 4826 4827 if( display.plabel != NULL ) 4828 { 4829 sprintf (buffer, "Retrieved inexact matches for discid 0x%08lx", cdinfo.discid ); 4830 gtk_label_set (GTK_LABEL (display.plabel), buffer); 4831 } 4832 4833 /* Here we want to add a list of the sites to the progress box, 4834 add a cancel button, and add a signal to use one of the inexact 4835 matches in a new search. 4836 */ 4837 if( cbitems != NULL ) 4838 { 4839 /* Add a vbox to hold the list and cancel button */ 4840 vbox1 = gtk_vbox_new( FALSE, 0 ); 4841 gtk_box_pack_start( GTK_BOX (GTK_DIALOG (display.progress)->action_area), 4842 vbox1, FALSE, TRUE, 1 ); 4843 gtk_widget_show( vbox1 ); 4844 4845 scrolled_win = gtk_scrolled_window_new (NULL, NULL); 4846 gtk_widget_set_usize( scrolled_win, 250, 100 ); 4847 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win), 4848 GTK_POLICY_AUTOMATIC, 4849 GTK_POLICY_AUTOMATIC); 4850 gtk_box_pack_start (GTK_BOX( vbox1 ), scrolled_win, FALSE, FALSE, 0); 4851 gtk_widget_show (scrolled_win); 4852 4853 /* Put a list into the scrolling window */ 4854 list = gtk_list_new (); 4855 gtk_list_set_selection_mode (GTK_LIST (list), GTK_SELECTION_SINGLE); 4856 gtk_container_add (GTK_CONTAINER (scrolled_win), list); 4857 gtk_container_set_focus_vadjustment (GTK_CONTAINER (list), 4858 gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_win))); 4859 gtk_signal_connect(GTK_OBJECT(list), 4860 "selection_changed", 4861 GTK_SIGNAL_FUNC(inexact_selected), 4862 NULL); 4863 gtk_widget_show (list); 4864 4865 /* Add the list of inexact matches to the list from cbitems */ 4866 gtk_list_append_items( GTK_LIST( list ), cbitems ); 4867 4868 button = gtk_button_new_with_label ("Cancel"); 4869 gtk_signal_connect_object (GTK_OBJECT (button), "clicked", 4870 GTK_SIGNAL_FUNC(gtk_widget_destroy), 4871 GTK_OBJECT (display.progress)); 4872 GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); 4873 gtk_box_pack_start (GTK_BOX( vbox1 ), button, TRUE, TRUE, 0); 4874 gtk_widget_grab_default (button); 4875 gtk_widget_show (button); 4876 4877 cbitems = NULL; 4878 } else { 4879 gtk_widget_destroy( display.progress ); 4880 display.plabel = NULL; 4881 } 4882 } else { 4883 /* Need to store in a temp. List until we receive the last line */ 4884 #ifdef DEBUG3 4885 g_print( "%s", tmpinfo.line ); 4886 #endif 4887 4888 /* Show the line in the progress box */ 4889 if( display.plabel != NULL ) 4890 { 4891 gtk_label_set (GTK_LABEL (display.plabel), tmpinfo.line); 4892 } 4893 4894 /* Add it to a list of sites */ 4895 /* Need to detect first line of this type and set cbitems to NULL, or else 4896 set it to null when everything else is finished with it. 4897 */ 4898 if( tmpinfo.line[strlen(tmpinfo.line)-1] == '\n' ) 4899 { 4900 tmpinfo.line[strlen(tmpinfo.line)-1] = 0x00; 4901 } 4902 4903 button=gtk_list_item_new(); 4904 label=gtk_label_new( tmpinfo.line ); 4905 gtk_misc_set_alignment (GTK_MISC(label), 0.0, 0.5); 4906 gtk_container_add (GTK_CONTAINER (button), label); 4907 gtk_widget_show (label); 4908 gtk_widget_show(button); 4909 gtk_label_get(GTK_LABEL(label), &string); 4910 gtk_object_set_data(GTK_OBJECT(button), 4911 "XfreeCDkey", 4912 string); 4913 cbitems = g_list_append(cbitems, button); 4914 4915 } 4916 break; 4917 4918 4919 4920 case CDDBD_MATCH_OK : 4921 #ifdef DEBUG3 4922 g_print("Got a match for 0x%08lx\n", tmpinfo.discid ); 4923 #endif 4924 4925 if( display.plabel != NULL ) 4926 { 4927 sprintf (buffer, "Retrieving data for id 0x%08lx", tmpinfo.discid); 4928 gtk_label_set (GTK_LABEL (display.plabel), buffer); 4929 } 4930 4931 break; 4932 4933 case CDDBD_ENTRY_OK : 4934 #ifdef DEBUG3 4935 g_print("Reading CDDB Database entry from %s\n", tmpinfo.server ); 4936 #endif 4937 4938 if( display.plabel != NULL ) 4939 { 4940 sprintf (buffer, "Reading CDDB info from %s", tmpinfo.server); 4941 gtk_label_set (GTK_LABEL (display.plabel), buffer); 4942 } 4943 break; 4944 4945 case CDDBD_DONE_ERR : 4946 cdinfo.revision = -2; 4947 display.cddb_lock = 0; 4948 4949 4950 #ifdef DEBUG3 4951 g_print("Error reading temporary file\n"); 4952 #endif 4953 4954 if( display.plabel != NULL ) 4955 { 4956 sprintf (buffer, "Error Reading temp. file"); 4957 gtk_label_set (GTK_LABEL (display.plabel), buffer); 4958 } 4959 4960 button = gtk_button_new_with_label ("OK"); 4961 gtk_signal_connect_object (GTK_OBJECT (button), "clicked", 4962 GTK_SIGNAL_FUNC(gtk_widget_destroy), 4963 GTK_OBJECT (display.progress)); 4964 GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); 4965 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (display.progress)->action_area), 4966 button, TRUE, TRUE, 0); 4967 gtk_widget_grab_default (button); 4968 gtk_widget_show (button); 4969 4970 break; 4971 4972 case CDDBD_OPEN_ERR : 4973 cdinfo.revision = -2; 4974 display.cddb_lock = 0; 4975 4976 #ifdef DEBUG3 4977 g_print("Failed to connect to %s\n", tmpinfo.server ); 4978 g_print("%s\n", tmpinfo.line ); 4979 #endif 4980 4981 if( display.plabel != NULL ) 4982 { 4983 sprintf (buffer, "Failed to connect to %s", tmpinfo.server ); 4984 gtk_label_set (GTK_LABEL (display.plabel), buffer); 4985 } 4986 4987 button = gtk_button_new_with_label ("OK"); 4988 gtk_signal_connect_object (GTK_OBJECT (button), "clicked", 4989 GTK_SIGNAL_FUNC(gtk_widget_destroy), 4990 GTK_OBJECT (display.progress)); 4991 GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); 4992 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (display.progress)->action_area), 4993 button, TRUE, TRUE, 0); 4994 gtk_widget_grab_default (button); 4995 gtk_widget_show (button); 4996 4997 break; 4998 4999 case CDDBD_READ_ERR : 5000 cdinfo.revision = -2; 5001 display.cddb_lock = 0; 5002 5003 #ifdef DEBUG3 5004 g_print("Socket read failed\n"); 5005 #endif 5006 5007 if( display.plabel != NULL ) 5008 { 5009 sprintf (buffer, "Socket Read Failed"); 5010 gtk_label_set (GTK_LABEL (display.plabel), buffer); 5011 } 5012 5013 button = gtk_button_new_with_label ("OK"); 5014 gtk_signal_connect_object (GTK_OBJECT (button), "clicked", 5015 GTK_SIGNAL_FUNC(gtk_widget_destroy), 5016 GTK_OBJECT (display.progress)); 5017 GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); 5018 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (display.progress)->action_area), 5019 button, TRUE, TRUE, 0); 5020 gtk_widget_grab_default (button); 5021 gtk_widget_show (button); 5022 5023 break; 5024 5025 case CDDBD_WRITE_ERR : 5026 cdinfo.revision = -2; 5027 display.cddb_lock = 0; 5028 5029 #ifdef DEBUG3 5030 g_print("Socket write failed\n"); 5031 #endif 5032 5033 if( display.plabel != NULL ) 5034 { 5035 sprintf (buffer, "Socket Write Failed"); 5036 gtk_label_set (GTK_LABEL (display.plabel), buffer); 5037 } 5038 5039 button = gtk_button_new_with_label ("OK"); 5040 gtk_signal_connect_object (GTK_OBJECT (button), "clicked", 5041 GTK_SIGNAL_FUNC(gtk_widget_destroy), 5042 GTK_OBJECT (display.progress)); 5043 GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); 5044 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (display.progress)->action_area), 5045 button, TRUE, TRUE, 0); 5046 gtk_widget_grab_default (button); 5047 gtk_widget_show (button); 5048 5049 break; 5050 5051 case CDDBD_TMPF_ERR : 5052 cdinfo.revision = -2; 5053 display.cddb_lock = 0; 5054 5055 #ifdef DEBUG3 5056 g_print("Error, cannot create a temporary filename\n"); 5057 #endif 5058 5059 if( display.plabel != NULL ) 5060 { 5061 sprintf (buffer, "Cannot Create temp. file"); 5062 gtk_label_set (GTK_LABEL (display.plabel), buffer); 5063 } 5064 5065 button = gtk_button_new_with_label ("OK"); 5066 gtk_signal_connect_object (GTK_OBJECT (button), "clicked", 5067 GTK_SIGNAL_FUNC(gtk_widget_destroy), 5068 GTK_OBJECT (display.progress)); 5069 GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); 5070 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (display.progress)->action_area), 5071 button, TRUE, TRUE, 0); 5072 gtk_widget_grab_default (button); 5073 gtk_widget_show (button); 5074 5075 break; 5076 5077 case CDDBD_FOPEN_ERR : 5078 cdinfo.revision = -2; 5079 display.cddb_lock = 0; 5080 5081 #ifdef DEBUG3 5082 g_print("Error opening temporary file\n"); 5083 #endif 5084 5085 if( display.plabel != NULL ) 5086 { 5087 sprintf (buffer, "Error opening temp. file"); 5088 gtk_label_set (GTK_LABEL (display.plabel), buffer); 5089 } 5090 5091 button = gtk_button_new_with_label ("OK"); 5092 gtk_signal_connect_object (GTK_OBJECT (button), "clicked", 5093 GTK_SIGNAL_FUNC(gtk_widget_destroy), 5094 GTK_OBJECT (display.progress)); 5095 GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); 5096 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (display.progress)->action_area), 5097 button, TRUE, TRUE, 0); 5098 gtk_widget_grab_default (button); 5099 gtk_widget_show (button); 5100 5101 break; 5102 5103 default: 5104 cdinfo.revision = -2; 5105 display.cddb_lock = 0; 5106 5107 #ifdef DEBUG3 5108 g_print("Server returned %d\n", tmpinfo.cddbd_stat ); 5109 #endif 5110 5111 if( display.plabel != NULL ) 5112 { 5113 sprintf( buffer, "Server: %s", tmpinfo.line ); 5114 gtk_label_set (GTK_LABEL (display.plabel), buffer ); 5115 } 5116 5117 button = gtk_button_new_with_label ("OK"); 5118 gtk_signal_connect_object (GTK_OBJECT (button), "clicked", 5119 GTK_SIGNAL_FUNC(gtk_widget_destroy), 5120 GTK_OBJECT (display.progress)); 5121 GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); 5122 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (display.progress)->action_area), 5123 button, TRUE, TRUE, 0); 5124 gtk_widget_grab_default (button); 5125 gtk_widget_show (button); 5126 5127 break; 5128 } 5129 } 5130 5131 5132 /* ----------------------------------------------------------------------- 5133 Get the current status of the cdrom and fill in the display info 5134 5135 return -1 = error writing 5136 ----------------------------------------------------------------------- */ 5137 int cdrom_status() 5138 { 5139 /* Get the status of the cd */ 5140 cmnd[0] = CD_STATUS; 5141 cmnd[1] = 0; 5142 if( write( cd_fd, &cmnd, 2 ) < 0 ) 5143 { 5144 perror("write to cd_control error"); 5145 return(-1); 5146 } 5147 5148 return 0; 5149 } 5150 5151 5152 /* ----------------------------------------------------------------------- 5153 Play a track 5154 ----------------------------------------------------------------------- */ 5155 void play_track( int track ) 5156 { 5157 /* Start Playing right away */ 5158 cmnd[0] = CD_PLAY; 5159 cmnd[1] = track; 5160 if( write( cd_fd, &cmnd, 2 ) < 0 ) 5161 { 5162 perror("write to cd_control error"); 5163 } 5164 } 5165 5166 5167 /* ----------------------------------------------------------------------- 5168 Play the next track 5169 ----------------------------------------------------------------------- */ 5170 void play_next() 5171 { 5172 cmnd[0] = CD_PLAY; 5173 cmnd[1] = display.track == cdinfo.tochdr.cdth_trk1 ? display.track = cdinfo.tochdr.cdth_trk0 : ++display.track; 5174 5175 if( write( cd_fd, &cmnd, 2 ) < 0 ) 5176 { 5177 perror("write to cd_control error"); 5178 } 5179 } 5180 5181 5182 /* ----------------------------------------------------------------------- 5183 Play the previous track 5184 ----------------------------------------------------------------------- */ 5185 void play_previous() 5186 { 5187 cmnd[0] = CD_PLAY; 5188 cmnd[1] = display.track == cdinfo.tochdr.cdth_trk0 ? display.track = cdinfo.tochdr.cdth_trk1 : --display.track; 5189 5190 if( write( cd_fd, &cmnd, 2 ) < 0 ) 5191 { 5192 perror("write to cd_control error"); 5193 } 5194 } 5195 5196 5197 /* ----------------------------------------------------------------------- 5198 Eject the cd tray if we are currently playing, otherwise start playing. 5199 5200 This should really be seperated into 2 pieces of code for more positive 5201 control over the cdrom. 5202 ----------------------------------------------------------------------- */ 5203 void eject_cdrom() 5204 { 5205 cmnd[0] = CD_EJECT; 5206 cmnd[1] = 0; 5207 5208 if( write( cd_fd, &cmnd, 2 ) < 0 ) 5209 { 5210 perror("write to cd_control error"); 5211 } 5212 } 5213 5214 5215 /* ----------------------------------------------------------------------- 5216 Pause the cdrom 5217 ----------------------------------------------------------------------- */ 5218 void pause_cdrom() 5219 { 5220 cmnd[0] = CD_PAUSE; 5221 cmnd[1] = 0; 5222 5223 if( write( cd_fd, &cmnd, 2 ) < 0 ) 5224 { 5225 perror("write to cd_control error"); 5226 } 5227 } 5228 5229 5230 /* ----------------------------------------------------------------------- 5231 Resume playing the cdrom 5232 ----------------------------------------------------------------------- */ 5233 void resume_cdrom() 5234 { 5235 cmnd[0] = CD_RESUME; 5236 cmnd[1] = 0; 5237 5238 if( write( cd_fd, &cmnd, 2 ) < 0 ) 5239 { 5240 perror("write to cd_control error"); 5241 } 5242 } 5243 5244 5245 /* ----------------------------------------------------------------------- 5246 Change the volume setting 5247 5248 amount is +/- amount to adjust by 5249 ----------------------------------------------------------------------- */ 5250 void set_vol( int amount ) 5251 { 5252 /* Limit the volume setting to 0 to 255 */ 5253 cdinfo.volume += amount; 5254 cdinfo.volume = cdinfo.volume < 0 ? 0 : cdinfo.volume > 255 ? 255 : cdinfo.volume; 5255 5256 cmnd[0] = CD_VOLUME; 5257 cmnd[1] = (unsigned char) cdinfo.volume; 5258 5259 if( write( cd_fd, &cmnd, 2 ) < 0 ) 5260 { 5261 perror("write to cd_control error"); 5262 } 5263 } 5264 5265 5266 /* ----------------------------------------------------------------------- 5267 Stop playing the cdrom 5268 ----------------------------------------------------------------------- */ 5269 void stop_cdrom() 5270 { 5271 cmnd[0] = CD_STOP; 5272 cmnd[1] = 0; 5273 5274 if( write( cd_fd, &cmnd, 2 ) < 0 ) 5275 { 5276 perror("write to cd_control error"); 5277 } 5278 } 5279 5280 5281 /* ----------------------------------------------------------------------- 5282 Set the Eject CD on exit state 5283 ----------------------------------------------------------------------- */ 5284 void set_eject( int state ) 5285 { 5286 cmnd[0] = CD_SET_EJECT; 5287 cmnd[1] = state; 5288 5289 if( write( cd_fd, &cmnd, 2 ) < 0 ) 5290 { 5291 perror("write to cd_control error"); 5292 } 5293 }