#include <X11/xpm.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xlibint.h>
#include <X11/extensions/shape.h>
#include <WINGs/WINGs.h>
#include <WMaker.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <cdaudio.h>

#include "pixmaps.h"

#define PROGRAM_NAME "CDPlayer.app"
#define PROGRAM_VERSION "1.6"
#define DEFAULT_DEVICE "/dev/cdrom"
#define DEFAULT_SERVER "cddbp://freedb.freedb.org:888"
#define SCROLL_DELAY 500
#define TIMER_INTERVAL 1000

typedef struct
{
   WMWindow *win;
   WMLabel *lblBack;
   WMLabel *lblIcon;
   WMButton *btnTrack[20];
   WMButton *btnPlayAll;
   WMButton *btnPlayShuffle;
   WMButton *btnPlayTrack;
   WMButton *btnRepeat;
   WMLabel *lblTrack;
   WMLabel *lblTime;
   WMButton *btnRec;
   WMButton *btnPlay;
   WMButton *btnPause;
   WMButton *btnStop;
   WMButton *btnPrev;
   WMButton *btnNext;
   WMButton *btnEject;
   WMSlider *sldPos;
   WMFont *boldFont;
   WMHandlerID scroller;
   int tray_open;
   int disc_present;
   int editing;
   int dragging;
   int play_mode;
   int track_mode;
   int last_mode;
   int position;
   int time_mode;
   int play_track;
   int random_track;
   int end_track;
   int total_tracks;
   int play_list[MAX_TRACKS];
   int button_pressed;
   int mini_button;
} cdplayer;

typedef struct
{
   WMWindow *win;
   WMTabView *tabMain;
   WMFrame *frmEntry;
   WMFrame *frmDiscTitle;
   WMTextField *txtDiscTitle;
   WMFrame *frmDiscArtist;
   WMTextField *txtDiscArtist;
   WMFrame *frmDiscExtended;
   WMTextField *txtDiscExtended;
   WMFrame *frmGenre;
   WMPopUpButton *popGenre;
   WMList *lstTrackNames;
   WMFrame *frmTrackName;
   WMTextField *txtTrackName;
   WMFrame *frmTrackArtist;
   WMTextField *txtTrackArtist;
   WMFrame *frmTrackExtended;
   WMTextField *txtTrackExtended;
   WMButton *btnDelete;
   WMButton *btnSubmit;
   WMButton *btnLookup;
   WMButton *btnSaveEntry;
   WMFrame *frmSites;
   WMFrame *frmProxy;
   WMTextField *txtProxyServer;
   WMTextField *txtProxyPort;
   WMList *lstSiteNames;
   WMFrame *frmProtocol;
   WMPopUpButton *popProtocol;
   WMFrame *frmSite;
   WMTextField *txtName;
   WMTextField *txtPort;
   WMFrame *frmAddressing;
   WMTextField *txtAddressing;
   WMButton *btnRemove;
   WMButton *btnAdd;
   WMButton *btnRefresh;
   WMButton *btnSaveSites;
   struct disc_data data;
   int last_track;
   int last_site;
   int busy;
} editor;

typedef struct
{
   WMWindow *win;
   WMList *lstMatches;
   WMButton *btnOK;
   int selection;
   int done;
} matches;

typedef struct
{
   cdplayer *cdplayer;
   editor *editor;
} app;

typedef struct
{
   Pixmap IconPixmap;
   Pixmap IconMask;
   XpmAttributes IconAttributes;
} Icon;

void wAbort(void);
void usage(const char *name);
void version(const char *name);

/* player */

int disc_present(void);
int stopped(void);
void createPixmaps(WMScreen *scr);
void setButtonImages(WMWidget *self, WMPixmap *image, WMPixmap *altimage);
void trackUpdate(cdplayer *w);
void timeUpdate(cdplayer *w);
void zeroOrTotal(cdplayer *w);
void playerStopped(cdplayer *w);
void playerPlaying(cdplayer *w);
void playerPaused(cdplayer *w);
void playTracks(cdplayer *w);
void nextTrack(cdplayer *w);
void changeTrack(cdplayer *w);
void currentInfo(cdplayer *w);
void scrollName(void *clientData);
void lookForDisc(void *clientData);
void updatePlayer(void *clientData);
cdplayer *createPlayer(WMScreen *scr, int start_hidden);
void ClosePlayer(WMWidget *self, cdplayer *w);
void PlayModeButton(WMWidget *self, cdplayer *w);
void TrackButton(WMWidget *self, cdplayer *w);
void PlayButton(WMWidget *self, cdplayer *w);
void PauseButton(WMWidget *self, cdplayer *w);
void StopButton(WMWidget *self, cdplayer *w);
void PrevButton(WMWidget *self, cdplayer *w);
void NextButton(WMWidget *self, cdplayer *w);
void EjectButton(WMWidget *self, cdplayer *w);
static void Drag(XEvent *event, void *clientData);
static void Skip(XEvent *event, void *clientData);
static void IconLabelClick(XEvent *event, void *clientData);
static void TrackLabelClick(XEvent *event, void *clientData);
static void TimeLabelClick(XEvent *event, void *clientData);

/* editor */

int cddb_lookup(struct disc_data *outdata, WMWindow *owner);
int cddb_get_siteslist(struct cddb_host host, WMWindow *owner);
void alert(char *title, char *text, WMWindow *owner);
char *input(char *title, char *text, char *def, WMWindow *owner);
void updateEntry(app *a, struct disc_data indata);
void updateSites(editor *e);
void saveTrack(editor *e, int pos);
void saveSite(editor *e, int pos);
void createEditor(app *a);
void CloseEditor(WMWidget *self, app *a);
void TrackClick(WMWidget *self, editor *e);
void TrackDoubleClick(WMWidget *self, cdplayer *w);
void DeleteButton(WMWidget *self, editor *e);
void SubmitButton(WMWidget *self, app *a);
void LookupButton(WMWidget *self, app *a);
void SaveEntryButton(WMWidget *self, app *a);
void SiteClick(WMWidget *self, editor *e);
void RemoveButton(WMWidget *self, editor *e);
void AddButton(WMWidget *self, editor *e);
void RefreshButton(WMWidget *self, editor *e);
void SaveSitesButton(WMWidget *self, editor *e);
static void ChangedTrack(void *observerData, WMNotification *notification);
static void ChangedSite(void *observerData, WMNotification *notification);

/* matches */

int createMatches(struct cddb_query query, WMWindow *owner);
void CloseMatches(WMWidget *self, matches *m);
void MatchClick(WMWidget *self, matches *m);
void MatchSelect(WMWidget *self, matches *m);

/* mini window */

int whichMiniButton(int x, int y);
void checkMiniButtons(XEvent Event, cdplayer *w);
void createMiniWindow(int argc, char **argv);
void createGC(void);
void loadIcon(Icon *IconXpm, char **icon_xpm);
void drawIcon(Icon *IconXpm, int x, int y);
void redrawMiniWindow(Icon *IconXpm);
void redrawTrackNumber(cdplayer *w);
void miniInitAction(void);
void miniPlayAction(cdplayer *w);
void miniStopAction(cdplayer *w);
void miniPauseAction(cdplayer *w);
void miniBackAction(cdplayer *w);
void miniForwardAction(cdplayer *w);
void miniEjectAction(void);
