|
@@ -0,0 +1,1030 @@
|
|
|
+#include <u.h>
|
|
|
+#include <libc.h>
|
|
|
+#include <thread.h>
|
|
|
+#include <draw.h>
|
|
|
+#include <keyboard.h>
|
|
|
+#include <mouse.h>
|
|
|
+#include <control.h>
|
|
|
+#include "colors.h"
|
|
|
+#include "client.h"
|
|
|
+#include "playlist.h"
|
|
|
+#include "../debug.h"
|
|
|
+
|
|
|
+int debug = 0; //DBGSERVER|DBGPUMP|DBGSTATE|DBGPICKLE|DBGPLAY;
|
|
|
+
|
|
|
+char usage[] = "Usage: %s [-t]\n";
|
|
|
+
|
|
|
+typedef struct But {
|
|
|
+ char *name;
|
|
|
+ Control *ctl;
|
|
|
+} But;
|
|
|
+
|
|
|
+typedef struct Simpleitem {
|
|
|
+ char *address;
|
|
|
+ char *data;
|
|
|
+} Simpleitem;
|
|
|
+
|
|
|
+typedef struct Multiitem {
|
|
|
+ char *address;
|
|
|
+ int ndata;
|
|
|
+ char **data;
|
|
|
+} Multiitem;
|
|
|
+
|
|
|
+enum {
|
|
|
+ WinBrowse,
|
|
|
+ WinPlay,
|
|
|
+ WinPlaylist,
|
|
|
+ WinError,
|
|
|
+ Topselect = 0x7fffffff
|
|
|
+};
|
|
|
+
|
|
|
+typedef enum {
|
|
|
+ PlayIdle,
|
|
|
+ PlayStart,
|
|
|
+ Playing,
|
|
|
+ PlayPause,
|
|
|
+} Playstate;
|
|
|
+
|
|
|
+typedef enum {
|
|
|
+ User,
|
|
|
+ Troot,
|
|
|
+ Rroot,
|
|
|
+ Tchildren,
|
|
|
+ Rchildren,
|
|
|
+ Tparent,
|
|
|
+ Rparent,
|
|
|
+ Tinfo,
|
|
|
+ Rinfo,
|
|
|
+ Tparentage,
|
|
|
+ Rparentage,
|
|
|
+ Tplay,
|
|
|
+ Rplay,
|
|
|
+} Srvstate;
|
|
|
+
|
|
|
+enum {
|
|
|
+ Exitbutton,
|
|
|
+ Pausebutton,
|
|
|
+ Playbutton,
|
|
|
+ Stopbutton,
|
|
|
+ Prevbutton,
|
|
|
+ Nextbutton,
|
|
|
+ Rootbutton,
|
|
|
+ Deletebutton,
|
|
|
+ Helpbutton,
|
|
|
+ Volume,
|
|
|
+ Browsetopwin,
|
|
|
+ Browsebotwin,
|
|
|
+ Playevent,
|
|
|
+ Playlistwin,
|
|
|
+ Nalt,
|
|
|
+};
|
|
|
+
|
|
|
+But buts[] = {
|
|
|
+ [Exitbutton] = {"skull", nil},
|
|
|
+ [Pausebutton] = {"pause", nil},
|
|
|
+ [Playbutton] = {"play", nil},
|
|
|
+ [Stopbutton] = {"stop", nil},
|
|
|
+ [Prevbutton] = {"prev", nil},
|
|
|
+ [Nextbutton] = {"next", nil},
|
|
|
+ [Rootbutton] = {"root", nil},
|
|
|
+ [Deletebutton] = {"trash", nil},
|
|
|
+ [Helpbutton] = {"question", nil},
|
|
|
+};
|
|
|
+
|
|
|
+struct tab {
|
|
|
+ char *tabname;
|
|
|
+ char *winname;
|
|
|
+ Control *tab;
|
|
|
+ Control *win;
|
|
|
+} tabs[4] = {
|
|
|
+ [WinBrowse] = {"Browse", "browsewin", nil, nil},
|
|
|
+ [WinPlay] = {"Playing", "playwin", nil, nil},
|
|
|
+ [WinPlaylist] = {"Playlist", "listwin", nil, nil},
|
|
|
+ [WinError] = {"Errors", "errorwin", nil, nil},
|
|
|
+};
|
|
|
+
|
|
|
+char *helptext[] = {
|
|
|
+ "Buttons, left to right:",
|
|
|
+ " Exit: exit jukebox",
|
|
|
+ " Pause: pause/resume playback",
|
|
|
+ " Play: play selection in Playlist",
|
|
|
+ " Stop: stop playback",
|
|
|
+ " Prev: play previous item in Playlist",
|
|
|
+ " Next: play next item in Playlist",
|
|
|
+ " Root: browse to root of database tree",
|
|
|
+ " Delete: empty Playlist, reread database",
|
|
|
+ " Help: show this window",
|
|
|
+ "",
|
|
|
+ "Browse window: (click tab to bring forward)",
|
|
|
+ " Top window displays current item",
|
|
|
+ " Bottom window displays selectable subitems",
|
|
|
+ " Mouse commands:",
|
|
|
+ " Left: selected subitem becomes current",
|
|
|
+ " Right: parent of current item becomes current",
|
|
|
+ " Middle: add item or subitem to Playlist",
|
|
|
+ "",
|
|
|
+ "Playing window",
|
|
|
+ " Displays item currently playing",
|
|
|
+ "",
|
|
|
+ "Playlist window",
|
|
|
+ " Displays contents of Playlist",
|
|
|
+ " Mouse commands:",
|
|
|
+ " Left: select item",
|
|
|
+ " (then click the play button)",
|
|
|
+ "",
|
|
|
+ "Error window",
|
|
|
+ " Displays error messages received from player",
|
|
|
+ " (e.g., can't open file)",
|
|
|
+ nil,
|
|
|
+};
|
|
|
+
|
|
|
+Control *vol;
|
|
|
+Control *browsetopwin;
|
|
|
+Control *browsebotwin;
|
|
|
+Control *playlistwin;
|
|
|
+Control *errortext;
|
|
|
+
|
|
|
+Playstate playstate;
|
|
|
+
|
|
|
+ulong playingbuts = 1<<Pausebutton | 1<<Stopbutton | 1<<Prevbutton | 1<<Nextbutton;
|
|
|
+ulong activebuts;
|
|
|
+
|
|
|
+int tabht;
|
|
|
+Image *vol1img;
|
|
|
+Image *vol2img;
|
|
|
+
|
|
|
+int resizeready;
|
|
|
+int borderwidth = 1;
|
|
|
+int butht, butwid;
|
|
|
+int errorlines;
|
|
|
+
|
|
|
+int tflag;
|
|
|
+int pflag;
|
|
|
+
|
|
|
+Controlset *cs;
|
|
|
+
|
|
|
+char *root;
|
|
|
+Multiitem parent;
|
|
|
+Simpleitem children[2048];
|
|
|
+int nchildren;
|
|
|
+
|
|
|
+int selected;
|
|
|
+
|
|
|
+Channel *playevent;
|
|
|
+
|
|
|
+void
|
|
|
+readbuts(void)
|
|
|
+{
|
|
|
+ static char str[32], file[64];
|
|
|
+ But *b;
|
|
|
+ int fd;
|
|
|
+ Image *img, *mask;
|
|
|
+
|
|
|
+ for(b = buts; b < &buts[nelem(buts)]; b++){
|
|
|
+ sprint(file, "%s/%s.bit", ICONPATH, b->name);
|
|
|
+ if((fd = open(file, OREAD)) < 0)
|
|
|
+ sysfatal("open: %s: %r", file);
|
|
|
+ mask = readimage(display, fd, 0);
|
|
|
+ close(fd);
|
|
|
+ butwid = Dx(mask->r);
|
|
|
+ butht = Dy(mask->r);
|
|
|
+ b->ctl = createbutton(cs, b->name);
|
|
|
+ chanprint(cs->ctl, "%q align center", b->name);
|
|
|
+ chanprint(cs->ctl, "%q border 0", b->name);
|
|
|
+
|
|
|
+ img = allocimage(display, mask->r, screen->chan, 0, 0xe0e0ffff);
|
|
|
+ draw(img, img->r, darkgreen, mask, mask->r.min);
|
|
|
+ sprint(str, "%s.active", b->name);
|
|
|
+ namectlimage(img, str);
|
|
|
+
|
|
|
+ img = allocimage(display, mask->r, screen->chan, 0, 0xe0e0ffff);
|
|
|
+ draw(img, img->r, lightblue, mask, mask->r.min);
|
|
|
+ sprint(str, "%s.passive", b->name);
|
|
|
+ namectlimage(img, str);
|
|
|
+
|
|
|
+ chanprint(cs->ctl, "%q image %q", b->name, str);
|
|
|
+ sprint(str, "%s.mask", b->name);
|
|
|
+ namectlimage(mask, str);
|
|
|
+ chanprint(cs->ctl, "%q mask %q", b->name, str);
|
|
|
+ chanprint(cs->ctl, "%q light red", b->name);
|
|
|
+ chanprint(cs->ctl, "%q size %d %d %d %d", b->name, butwid, butht, butwid, butht);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+activatebuttons(ulong mask)
|
|
|
+{ // mask bit i corresponds to buts[i];
|
|
|
+ ulong bit;
|
|
|
+ But *b;
|
|
|
+ static char str[40];
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for(i = 0; i < nelem(buts); i++){
|
|
|
+ b = &buts[i];
|
|
|
+ bit = 1 << i;
|
|
|
+ if((mask & bit) && (activebuts & bit) == 0){
|
|
|
+ // button was `deactive'
|
|
|
+ activate(b->ctl);
|
|
|
+ activebuts |= bit;
|
|
|
+ sprint(str, "%s.active", b->name);
|
|
|
+ chanprint(cs->ctl, "%q image %q", b->name, str);
|
|
|
+ chanprint(cs->ctl, "%q show", b->name);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+deactivatebuttons(ulong mask)
|
|
|
+{ // mask bit i corresponds with buts[i];
|
|
|
+ ulong bit;
|
|
|
+ But *b;
|
|
|
+ static char str[40];
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for(i = 0; i < nelem(buts); i++){
|
|
|
+ b = &buts[i];
|
|
|
+ bit = 1 << i;
|
|
|
+ if((mask & bit) && (activebuts & bit)){
|
|
|
+ // button was active
|
|
|
+ deactivate(b->ctl);
|
|
|
+ activebuts &= ~bit;
|
|
|
+ sprint(str, "%s.passive", b->name);
|
|
|
+ chanprint(cs->ctl, "%q image %q", b->name, str);
|
|
|
+ chanprint(cs->ctl, "%q show", b->name);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+resizecontrolset(Controlset *){
|
|
|
+ static Point pol[3];
|
|
|
+ char *p;
|
|
|
+
|
|
|
+ if(getwindow(display, Refbackup) < 0)
|
|
|
+ sysfatal("getwindow");
|
|
|
+ draw(screen, screen->r, bordercolor, nil, screen->r.min);
|
|
|
+ if(!resizeready)
|
|
|
+ return;
|
|
|
+#ifndef REPLACESEMANTICS
|
|
|
+ if(vol1img)
|
|
|
+ chanprint(cs->ctl, "volume image darkgreen");
|
|
|
+ if(vol2img)
|
|
|
+ chanprint(cs->ctl, "volume indicatorcolor red");
|
|
|
+ chanprint(cs->ctl, "wholewin size");
|
|
|
+ chanprint(cs->ctl, "wholewin rect %R", screen->r);
|
|
|
+
|
|
|
+ chanprint(cs->ctl, "sync");
|
|
|
+ p = recvp(cs->data);
|
|
|
+ if(strcmp(p, "sync"))
|
|
|
+ sysfatal("huh?");
|
|
|
+ free(p);
|
|
|
+
|
|
|
+ if(vol1img){
|
|
|
+ freectlimage("volume.img");
|
|
|
+ freeimage(vol1img);
|
|
|
+ }
|
|
|
+ if(vol2img){
|
|
|
+ freectlimage("indicator.img");
|
|
|
+ freeimage(vol2img);
|
|
|
+ }
|
|
|
+ vol1img = allocimage(display, vol->rect, screen->chan, 0, 0xe0e0ffff);
|
|
|
+ vol2img = allocimage(display, vol->rect, screen->chan, 0, 0xe0e0ffff);
|
|
|
+ pol[0] = Pt(vol->rect.min.x, vol->rect.max.y);
|
|
|
+ pol[1] = Pt(vol->rect.max.x, vol->rect.min.y);
|
|
|
+ pol[2] = vol->rect.max;
|
|
|
+ fillpoly(vol1img, pol, 3, 0, darkgreen, ZP);
|
|
|
+ fillpoly(vol2img, pol, 3, 0, red, ZP);
|
|
|
+ namectlimage(vol1img, "volume.img");
|
|
|
+ namectlimage(vol2img, "indicator.img");
|
|
|
+ chanprint(cs->ctl, "volume image volume.img");
|
|
|
+ chanprint(cs->ctl, "volume indicatorcolor indicator.img");
|
|
|
+#else
|
|
|
+ chanprint(cs->ctl, "wholewin size");
|
|
|
+ chanprint(cs->ctl, "wholewin rect %R", screen->r);
|
|
|
+
|
|
|
+ chanprint(cs->ctl, "sync");
|
|
|
+ p = recvp(cs->data);
|
|
|
+ if(strcmp(p, "sync"))
|
|
|
+ sysfatal("huh?");
|
|
|
+ free(p);
|
|
|
+
|
|
|
+ new1img = allocimage(display, vol->rect, screen->chan, 0, 0xe0e0ffff);
|
|
|
+ new2img = allocimage(display, vol->rect, screen->chan, 0, 0xe0e0ffff);
|
|
|
+ pol[0] = Pt(vol->rect.min.x, vol->rect.max.y);
|
|
|
+ pol[1] = Pt(vol->rect.max.x, vol->rect.min.y);
|
|
|
+ pol[2] = vol->rect.max;
|
|
|
+ fillpoly(new1img, pol, 3, 0, darkgreen, ZP);
|
|
|
+ fillpoly(new2img, pol, 3, 0, red, ZP);
|
|
|
+ namectlimage(new1img, "volume.img");
|
|
|
+ namectlimage(new2img, "indicator.img");
|
|
|
+ if(vol1img)
|
|
|
+ freeimage(vol1img);
|
|
|
+ else
|
|
|
+ chanprint(cs->ctl, "volume image volume.img");
|
|
|
+ if(vol2img)
|
|
|
+ freeimage(vol2img);
|
|
|
+ else
|
|
|
+ chanprint(cs->ctl, "volume indicatorcolor indicator.img");
|
|
|
+ vol1img = new1img;
|
|
|
+ vol2img = new2img;
|
|
|
+#endif
|
|
|
+ chanprint(cs->ctl, "browsetopscr vis '%d'",
|
|
|
+ Dy(controlcalled("browsetopscr")->rect)/romanfont->height);
|
|
|
+ chanprint(cs->ctl, "browsebotscr vis '%d'",
|
|
|
+ Dy(controlcalled("browsebotscr")->rect)/romanfont->height);
|
|
|
+ chanprint(cs->ctl, "playscr vis '%d'",
|
|
|
+ Dy(controlcalled("playscr")->rect)/romanfont->height);
|
|
|
+ chanprint(cs->ctl, "playlistscr vis '%d'",
|
|
|
+ Dy(controlcalled("playlistscr")->rect)/romanfont->height);
|
|
|
+ chanprint(cs->ctl, "wholewin show");
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+maketab(void)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ tabht = boldfont->height + 1 + borderwidth;
|
|
|
+
|
|
|
+ createtab(cs, "tabs");
|
|
|
+
|
|
|
+ for(i = 0; i < nelem(tabs); i++){
|
|
|
+ tabs[i].tab = createtextbutton(cs, tabs[i].tabname);
|
|
|
+ chanprint(cs->ctl, "%q size %d %d %d %d", tabs[i].tab->name,
|
|
|
+ stringwidth(boldfont, tabs[i].tabname), tabht, 1024, tabht);
|
|
|
+ chanprint(cs->ctl, "%q align uppercenter", tabs[i].tab->name);
|
|
|
+ chanprint(cs->ctl, "%q font boldfont", tabs[i].tab->name);
|
|
|
+ chanprint(cs->ctl, "%q image background", tabs[i].tab->name);
|
|
|
+ chanprint(cs->ctl, "%q light background", tabs[i].tab->name);
|
|
|
+ chanprint(cs->ctl, "%q pressedtextcolor red", tabs[i].tab->name);
|
|
|
+ chanprint(cs->ctl, "%q textcolor darkgreen", tabs[i].tab->name);
|
|
|
+ chanprint(cs->ctl, "%q mask transparent", tabs[i].tab->name);
|
|
|
+ chanprint(cs->ctl, "%q text %q", tabs[i].tab->name, tabs[i].tabname);
|
|
|
+
|
|
|
+ chanprint(cs->ctl, "tabs add %s %s", tabs[i].tabname, tabs[i].winname);
|
|
|
+ }
|
|
|
+
|
|
|
+ chanprint(cs->ctl, "tabs separation %d", 2);
|
|
|
+ chanprint(cs->ctl, "tabs image background");
|
|
|
+ chanprint(cs->ctl, "tabs value 0");
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+makeplaycontrols(void)
|
|
|
+{
|
|
|
+ int w;
|
|
|
+ Control *playscr;
|
|
|
+
|
|
|
+ w = stringwidth(romanfont, "Roll over Beethoven");
|
|
|
+ playscr = createslider(cs, "playscr");
|
|
|
+ chanprint(cs->ctl, "playscr size 12, 24, 12, 1024");
|
|
|
+ createtext(cs, "playtext");
|
|
|
+ chanprint(cs->ctl, "playtext size %d %d %d %d",
|
|
|
+ w, 5*romanfont->height, 2048, 1024);
|
|
|
+
|
|
|
+ chanprint(cs->ctl, "playscr format '%%s: playtext topline %%d'");
|
|
|
+ controlwire(playscr, "event", cs->ctl);
|
|
|
+
|
|
|
+ tabs[WinPlay].win = createrow(cs, tabs[WinPlay].winname);
|
|
|
+ chanprint(cs->ctl, "%q add playscr playtext", tabs[WinPlay].win->name);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+makebrowsecontrols(void)
|
|
|
+{
|
|
|
+ int w;
|
|
|
+ Control *browsetopscr, *browsebotscr;
|
|
|
+
|
|
|
+ w = stringwidth(romanfont, "Roll over Beethoven");
|
|
|
+ browsetopscr = createslider(cs, "browsetopscr");
|
|
|
+ chanprint(cs->ctl, "browsetopscr size 12, 24, 12, %d", 12*romanfont->height);
|
|
|
+ browsetopwin = createtext(cs, "browsetopwin");
|
|
|
+ chanprint(cs->ctl, "browsetopwin size %d %d %d %d",
|
|
|
+ w, 3*romanfont->height, 2048, 12*romanfont->height);
|
|
|
+ createrow(cs, "browsetop");
|
|
|
+ chanprint(cs->ctl, "browsetop add browsetopscr browsetopwin");
|
|
|
+
|
|
|
+ browsebotscr = createslider(cs, "browsebotscr");
|
|
|
+ chanprint(cs->ctl, "browsebotscr size 12, 24, 12, 1024");
|
|
|
+ browsebotwin = createtext(cs, "browsebotwin");
|
|
|
+ chanprint(cs->ctl, "browsebotwin size %d %d %d %d",
|
|
|
+ w, 3*romanfont->height, 2048, 1024);
|
|
|
+ createrow(cs, "browsebot");
|
|
|
+ chanprint(cs->ctl, "browsebot add browsebotscr browsebotwin");
|
|
|
+
|
|
|
+ chanprint(cs->ctl, "browsetopscr format '%%s: browsetopwin topline %%d'");
|
|
|
+ controlwire(browsetopscr, "event", cs->ctl);
|
|
|
+ chanprint(cs->ctl, "browsebotscr format '%%s: browsebotwin topline %%d'");
|
|
|
+ controlwire(browsebotscr, "event", cs->ctl);
|
|
|
+
|
|
|
+ tabs[WinBrowse].win = createcolumn(cs, tabs[WinBrowse].winname);
|
|
|
+ chanprint(cs->ctl, "%q add browsetop browsebot", tabs[WinBrowse].win->name);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+makeplaylistcontrols(void)
|
|
|
+{
|
|
|
+ int w;
|
|
|
+ Control *playlistscr;
|
|
|
+
|
|
|
+ w = stringwidth(romanfont, "Roll over Beethoven");
|
|
|
+ playlistscr = createslider(cs, "playlistscr");
|
|
|
+ chanprint(cs->ctl, "playlistscr size 12, 24, 12, 1024");
|
|
|
+ playlistwin = createtext(cs, "playlistwin");
|
|
|
+ chanprint(cs->ctl, "playlistwin size %d %d %d %d",
|
|
|
+ w, 5*romanfont->height, 2048, 1024);
|
|
|
+// chanprint(cs->ctl, "playlistwin selectmode multi");
|
|
|
+
|
|
|
+ chanprint(cs->ctl, "playlistscr format '%%s: playlistwin topline %%d'");
|
|
|
+ controlwire(playlistscr, "event", cs->ctl);
|
|
|
+
|
|
|
+ tabs[WinPlaylist].win = createrow(cs, tabs[WinPlaylist].winname);
|
|
|
+ chanprint(cs->ctl, "%q add playlistscr playlistwin", tabs[WinPlaylist].win->name);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+makeerrorcontrols(void)
|
|
|
+{
|
|
|
+ int w;
|
|
|
+ Control *errorscr;
|
|
|
+
|
|
|
+ w = stringwidth(romanfont, "Roll over Beethoven");
|
|
|
+ errorscr = createslider(cs, "errorscr");
|
|
|
+ chanprint(cs->ctl, "errorscr size 12, 24, 12, 1024");
|
|
|
+ errortext = createtext(cs, "errortext");
|
|
|
+ chanprint(cs->ctl, "errortext size %d %d %d %d",
|
|
|
+ w, 5*romanfont->height, 2048, 1024);
|
|
|
+ chanprint(cs->ctl, "errortext selectmode multi");
|
|
|
+
|
|
|
+ chanprint(cs->ctl, "errorscr format '%%s: errortext topline %%d'");
|
|
|
+ controlwire(errorscr, "event", cs->ctl);
|
|
|
+
|
|
|
+ tabs[WinError].win = createrow(cs, tabs[WinError].winname);
|
|
|
+ chanprint(cs->ctl, "%q add errorscr errortext", tabs[WinError].win->name);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+makecontrols(void)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ cs = newcontrolset(screen, nil, nil, nil);
|
|
|
+
|
|
|
+ // make shared buttons
|
|
|
+ readbuts();
|
|
|
+
|
|
|
+ vol = createslider(cs, "volume");
|
|
|
+ chanprint(cs->ctl, "volume size %d %d %d %d", 2*butwid, butht, 2048, butht);
|
|
|
+ chanprint(cs->ctl, "volume absolute 1");
|
|
|
+ chanprint(cs->ctl, "volume indicatorcolor red");
|
|
|
+ chanprint(cs->ctl, "volume max 100");
|
|
|
+ chanprint(cs->ctl, "volume orient hor");
|
|
|
+ chanprint(cs->ctl, "volume clamp low 1");
|
|
|
+ chanprint(cs->ctl, "volume clamp high 0");
|
|
|
+ chanprint(cs->ctl, "volume format '%%s volume %%d'");
|
|
|
+
|
|
|
+ createrow(cs, "buttonrow");
|
|
|
+ for(i = 0; i < nelem(buts); i++)
|
|
|
+ chanprint(cs->ctl, "buttonrow add %s", buts[i].name);
|
|
|
+ chanprint(cs->ctl, "buttonrow add volume");
|
|
|
+ chanprint(cs->ctl, "buttonrow separation %d", borderwidth);
|
|
|
+ chanprint(cs->ctl, "buttonrow image darkgreen");
|
|
|
+
|
|
|
+ makebrowsecontrols();
|
|
|
+ makeplaycontrols();
|
|
|
+ makeplaylistcontrols();
|
|
|
+ makeerrorcontrols();
|
|
|
+
|
|
|
+ maketab();
|
|
|
+
|
|
|
+ chanprint(cs->ctl, "%q image background", "text slider");
|
|
|
+ chanprint(cs->ctl, "text font romanfont");
|
|
|
+ chanprint(cs->ctl, "slider indicatorcolor darkgreen");
|
|
|
+ chanprint(cs->ctl, "row separation %d", borderwidth);
|
|
|
+ chanprint(cs->ctl, "row image darkgreen");
|
|
|
+ chanprint(cs->ctl, "column separation %d", 2);
|
|
|
+ chanprint(cs->ctl, "column image darkgreen");
|
|
|
+
|
|
|
+ createcolumn(cs, "wholewin");
|
|
|
+ chanprint(cs->ctl, "wholewin separation %d", borderwidth);
|
|
|
+ chanprint(cs->ctl, "wholewin add buttonrow tabs");
|
|
|
+ chanprint(cs->ctl, "wholewin image darkgreen");
|
|
|
+ chanprint(cs->ctl, "%q image darkgreen", "column row");
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+makewindow(int dx, int dy, int wflag){
|
|
|
+ int mountfd, fd, n;
|
|
|
+ static char aname[128];
|
|
|
+ static char rio[128] = "/mnt/term";
|
|
|
+ char *args[6];
|
|
|
+
|
|
|
+ if(wflag){
|
|
|
+ /* find out screen size */
|
|
|
+ fd = open("/mnt/wsys/screen", OREAD);
|
|
|
+ if(fd >= 0 && read(fd, aname, 60) == 60){
|
|
|
+ aname[60] = '\0';
|
|
|
+ n = tokenize(aname, args, nelem(args));
|
|
|
+ if(n != 5)
|
|
|
+ fprint(2, "Not an image: /mnt/wsys/screen\n");
|
|
|
+ else{
|
|
|
+ n = atoi(args[3]) - atoi(args[1]);
|
|
|
+ if(n <= 0 || n > 2048)
|
|
|
+ fprint(2, "/mnt/wsys/screen very wide: %d\n", n);
|
|
|
+ else
|
|
|
+ if(n < dx) dx = n-1;
|
|
|
+ n = atoi(args[4]) - atoi(args[2]);
|
|
|
+ if(n <= 0 || n > 2048)
|
|
|
+ fprint(2, "/mnt/wsys/screen very high: %d\n", n);
|
|
|
+ else
|
|
|
+ if(n < dy) dy = n-1;
|
|
|
+ }
|
|
|
+ close(fd);
|
|
|
+ }
|
|
|
+ n = 0;
|
|
|
+ if((fd = open("/env/wsys", OREAD)) < 0){
|
|
|
+ n = strlen(rio);
|
|
|
+ fd = open("/mnt/term/env/wsys", OREAD);
|
|
|
+ if(fd < 0)
|
|
|
+ sysfatal("/env/wsys");
|
|
|
+ }
|
|
|
+ if(read(fd, rio+n, sizeof(rio)-n-1) <= 0)
|
|
|
+ sysfatal("/env/wsys");
|
|
|
+ mountfd = open(rio, ORDWR);
|
|
|
+ if(mountfd < 0)
|
|
|
+ sysfatal("open %s: %r", rio);
|
|
|
+ snprint(aname, sizeof aname, "new -dx %d -dy %d", dx, dy);
|
|
|
+ rfork(RFNAMEG);
|
|
|
+ if(mount(mountfd, -1, "/mnt/wsys", MREPL, aname) < 0)
|
|
|
+ sysfatal("mount: %r");
|
|
|
+ if(bind("/mnt/wsys", "/dev", MBEFORE) < 0)
|
|
|
+ sysfatal("mount: %r");
|
|
|
+ }
|
|
|
+
|
|
|
+ if(initdraw(nil, nil, "music") < 0)
|
|
|
+ sysfatal("initdraw: %r");
|
|
|
+
|
|
|
+ initcontrols();
|
|
|
+ if(dx <= 320)
|
|
|
+ colorinit("/lib/font/bit/lucidasans/unicode.6.font",
|
|
|
+ "/lib/font/bit/lucidasans/boldunicode.8.font");
|
|
|
+ else
|
|
|
+ colorinit("/lib/font/bit/lucidasans/unicode.8.font",
|
|
|
+ "/lib/font/bit/lucidasans/boldunicode.10.font");
|
|
|
+ makecontrols();
|
|
|
+ resizeready = 1;
|
|
|
+
|
|
|
+ resizecontrolset(cs);
|
|
|
+ if(debug & DBGCONTROL)
|
|
|
+ fprint(2, "resize done\n");
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+setparent(char *addr)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ if(parent.address)
|
|
|
+ free(parent.address);
|
|
|
+ parent.address = strdup(addr);
|
|
|
+ for(i = 0; i < parent.ndata; i++)
|
|
|
+ if(parent.data[i])
|
|
|
+ free(parent.data[i]);
|
|
|
+ parent.ndata = 0;
|
|
|
+ if(parent.data){
|
|
|
+ free(parent.data);
|
|
|
+ parent.data = nil;
|
|
|
+ }
|
|
|
+ chanprint(cs->ctl, "browsetopwin clear");
|
|
|
+ chanprint(cs->ctl, "browsetopscr max 0");
|
|
|
+ chanprint(cs->ctl, "browsetopscr value 0");
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+addparent(char *str)
|
|
|
+{
|
|
|
+ parent.data = realloc(parent.data, (parent.ndata+1)*sizeof(char*));
|
|
|
+ parent.data[parent.ndata] = strdup(str);
|
|
|
+ parent.ndata++;
|
|
|
+ chanprint(cs->ctl, "browsetopwin accumulate %q", str);
|
|
|
+ chanprint(cs->ctl, "browsetopscr max %d", parent.ndata);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+clearchildren(void)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for(i = 0; i < nchildren; i++){
|
|
|
+ if(children[i].address)
|
|
|
+ free(children[i].address);
|
|
|
+ if(children[i].data)
|
|
|
+ free(children[i].data);
|
|
|
+ }
|
|
|
+ nchildren= 0;
|
|
|
+ chanprint(cs->ctl, "browsebotwin clear");
|
|
|
+ chanprint(cs->ctl, "browsebotwin topline 0");
|
|
|
+ chanprint(cs->ctl, "browsebotscr max 0");
|
|
|
+ chanprint(cs->ctl, "browsebotscr value 0");
|
|
|
+ selected = -1;
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+addchild(char *addr, char *data)
|
|
|
+{
|
|
|
+ children[nchildren].address = addr;
|
|
|
+ children[nchildren].data = data;
|
|
|
+ nchildren++;
|
|
|
+ chanprint(cs->ctl, "browsebotwin accumulate %q", data);
|
|
|
+ chanprint(cs->ctl, "browsebotscr max %d", nchildren);
|
|
|
+}
|
|
|
+
|
|
|
+static void
|
|
|
+playlistselect(int n)
|
|
|
+{
|
|
|
+ if(playlist.selected >= 0 && playlist.selected < playlist.nentries){
|
|
|
+ chanprint(cs->ctl, "playlistwin select %d 0", playlist.selected);
|
|
|
+ deactivatebuttons(1<<Playbutton);
|
|
|
+ }
|
|
|
+ playlist.selected = n;
|
|
|
+ if(playlist.selected < 0 || playlist.selected >= playlist.nentries)
|
|
|
+ return;
|
|
|
+ activatebuttons(1<<Playbutton);
|
|
|
+ chanprint(cs->ctl, "playlistwin select %d 1", n);
|
|
|
+ if(n >= 0 && n <= playlist.nentries - Dy(playlistwin->rect)/romanfont->height)
|
|
|
+ n--;
|
|
|
+ else
|
|
|
+ n = playlist.nentries - Dy(playlistwin->rect)/romanfont->height + 1;
|
|
|
+ if(n < 0) n = 0;
|
|
|
+ if(n < playlist.nentries){
|
|
|
+ chanprint(cs->ctl, "playlistwin topline %d", n);
|
|
|
+ chanprint(cs->ctl, "playlistscr value %d", n);
|
|
|
+ }
|
|
|
+ chanprint(cs->ctl, "playlist show");
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+updateplaylist(int trunc)
|
|
|
+{
|
|
|
+ char *s;
|
|
|
+ int fd;
|
|
|
+
|
|
|
+ while(cs->ctl->s - cs->ctl->n < cs->ctl->s/4)
|
|
|
+ sleep(100);
|
|
|
+ if(trunc){
|
|
|
+ playlistselect(-1);
|
|
|
+ chanprint(cs->ctl, "playlistwin clear");
|
|
|
+ chanprint(cs->ctl, "playlistscr max 0");
|
|
|
+ chanprint(cs->ctl, "playlistscr value 0");
|
|
|
+ deactivatebuttons(1<<Playbutton | 1<<Deletebutton);
|
|
|
+ chanprint(cs->ctl, "playlistwin show");
|
|
|
+ chanprint(cs->ctl, "playlistscr show");
|
|
|
+ s = smprint("%s/ctl", srvmount);
|
|
|
+ if((fd = open(s, OWRITE)) >= 0){
|
|
|
+ fprint(fd, "reread");
|
|
|
+ close(fd);
|
|
|
+ }
|
|
|
+ free(s);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if(playlist.entry[playlist.nentries].onum){
|
|
|
+ s = getoneliner(playlist.entry[playlist.nentries].onum);
|
|
|
+ chanprint(cs->ctl, "playlistwin accumulate %q", s);
|
|
|
+ free(s);
|
|
|
+ }else
|
|
|
+ chanprint(cs->ctl, "playlistwin accumulate %q", playlist.entry[playlist.nentries].file);
|
|
|
+ playlist.nentries++;
|
|
|
+ chanprint(cs->ctl, "playlistscr max %d", playlist.nentries);
|
|
|
+ if(playlist.selected == playlist.nentries - 1)
|
|
|
+ playlistselect(playlist.selected);
|
|
|
+ activatebuttons(1<<Playbutton|1<<Deletebutton);
|
|
|
+ chanprint(cs->ctl, "playlistscr show");
|
|
|
+ chanprint(cs->ctl, "playlistwin show");
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+browseto(char *onum)
|
|
|
+{
|
|
|
+ onum = strdup(onum);
|
|
|
+ setparent(onum);
|
|
|
+ clearchildren();
|
|
|
+ fillbrowsetop(onum);
|
|
|
+ chanprint(cs->ctl, "browsetop show");
|
|
|
+ fillbrowsebot(onum);
|
|
|
+ chanprint(cs->ctl, "browsebot show");
|
|
|
+ free(onum);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+addplaytext(char *s)
|
|
|
+{
|
|
|
+ chanprint(cs->ctl, "playtext accumulate %q", s);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+work(void)
|
|
|
+{
|
|
|
+ static char *eventstr, *args[64], *s;
|
|
|
+ static char buf[4096];
|
|
|
+ int a, n, i;
|
|
|
+ Alt alts[] = {
|
|
|
+ [Exitbutton] = {buts[Exitbutton].ctl->event, &eventstr, CHANRCV},
|
|
|
+ [Pausebutton] = {buts[Pausebutton].ctl->event, &eventstr, CHANRCV},
|
|
|
+ [Playbutton] = {buts[Playbutton].ctl->event, &eventstr, CHANRCV},
|
|
|
+ [Stopbutton] = {buts[Stopbutton].ctl->event, &eventstr, CHANRCV},
|
|
|
+ [Prevbutton] = {buts[Prevbutton].ctl->event, &eventstr, CHANRCV},
|
|
|
+ [Nextbutton] = {buts[Nextbutton].ctl->event, &eventstr, CHANRCV},
|
|
|
+ [Rootbutton] = {buts[Rootbutton].ctl->event, &eventstr, CHANRCV},
|
|
|
+ [Deletebutton] = {buts[Deletebutton].ctl->event, &eventstr, CHANRCV},
|
|
|
+ [Helpbutton] = {buts[Helpbutton].ctl->event, &eventstr, CHANRCV},
|
|
|
+ [Volume] = {vol->event, &eventstr, CHANRCV},
|
|
|
+ [Browsetopwin] = {browsetopwin->event, &eventstr, CHANRCV},
|
|
|
+ [Browsebotwin] = {browsebotwin->event, &eventstr, CHANRCV},
|
|
|
+ [Playevent] = {playevent, &eventstr, CHANRCV},
|
|
|
+ [Playlistwin] = {playlistwin->event, &eventstr, CHANRCV},
|
|
|
+ [Nalt] = {nil, nil, CHANEND}
|
|
|
+ };
|
|
|
+
|
|
|
+ activate(vol);
|
|
|
+ activate(controlcalled("tabs"));
|
|
|
+ activatebuttons(1 << Exitbutton | 1 << Rootbutton | 1 << Helpbutton);
|
|
|
+
|
|
|
+ root = getroot();
|
|
|
+ setparent(root);
|
|
|
+ clearchildren();
|
|
|
+ addparent("Root");
|
|
|
+ chanprint(cs->ctl, "browsetop show");
|
|
|
+ fillbrowsebot(root);
|
|
|
+ chanprint(cs->ctl, "browsebot show");
|
|
|
+
|
|
|
+ eventstr = nil;
|
|
|
+ selected = -1;
|
|
|
+
|
|
|
+ for(;;){
|
|
|
+ a = alt(alts);
|
|
|
+ if(debug & DBGCONTROL)
|
|
|
+ fprint(2, "Event: %s\n", eventstr);
|
|
|
+ n = tokenize(eventstr, args, nelem(args));
|
|
|
+ switch(a){
|
|
|
+ default:
|
|
|
+ sysfatal("Illegal event %d in work", a);
|
|
|
+ case Volume:
|
|
|
+ if(n != 3 || strcmp(args[0], "volume") || strcmp(args[1], "volume"))
|
|
|
+ sysfatal("Bad Volume event[%d]: %s %s", n, args[0], args[1]);
|
|
|
+ setvolume(args[2]);
|
|
|
+ break;
|
|
|
+ case Exitbutton:
|
|
|
+ return;
|
|
|
+ case Pausebutton:
|
|
|
+ if(n != 3 || strcmp(args[0], "pause:") || strcmp(args[1], "value"))
|
|
|
+ sysfatal("Bad Pausebutton event[%d]: %s %s", n, args[0], args[1]);
|
|
|
+ if(strcmp(args[2], "0") == 0)
|
|
|
+ fprint(playctlfd, "resume");
|
|
|
+ else
|
|
|
+ fprint(playctlfd, "pause");
|
|
|
+ break;
|
|
|
+ case Playbutton:
|
|
|
+ if(n != 3 || strcmp(args[0], "play:") || strcmp(args[1], "value"))
|
|
|
+ sysfatal("Bad Playbutton event[%d]: %s %s", n, args[0], args[1]);
|
|
|
+ if(playlist.selected >= 0){
|
|
|
+ fprint(playctlfd, "play %d", playlist.selected);
|
|
|
+ }else
|
|
|
+ fprint(playctlfd, "play");
|
|
|
+ break;
|
|
|
+ case Stopbutton:
|
|
|
+ if(n != 3 || strcmp(args[0], "stop:") || strcmp(args[1], "value"))
|
|
|
+ sysfatal("Bad Stopbutton event[%d]: %s %s", n, args[0], args[1]);
|
|
|
+ if(strcmp(args[2], "0") == 0)
|
|
|
+ chanprint(cs->ctl, "%q value 1", buts[Stopbutton].ctl->name);
|
|
|
+ fprint(playctlfd, "stop");
|
|
|
+ break;
|
|
|
+ case Prevbutton:
|
|
|
+ if(n != 3 || strcmp(args[0], "prev:") || strcmp(args[1], "value"))
|
|
|
+ sysfatal("Bad Prevbutton event[%d]: %s %s", n, args[0], args[1]);
|
|
|
+ if(strcmp(args[2], "0") == 0)
|
|
|
+ break;
|
|
|
+ chanprint(cs->ctl, "%q value 0", buts[Prevbutton].ctl->name);
|
|
|
+ fprint(playctlfd, "skip -1");
|
|
|
+ break;
|
|
|
+ case Nextbutton:
|
|
|
+ if(n != 3 || strcmp(args[0], "next:") || strcmp(args[1], "value"))
|
|
|
+ sysfatal("Bad Nextbutton event[%d]: %s %s", n, args[0], args[1]);
|
|
|
+ if(strcmp(args[2], "0") == 0)
|
|
|
+ break;
|
|
|
+ chanprint(cs->ctl, "%q value 0", buts[Nextbutton].ctl->name);
|
|
|
+ fprint(playctlfd, "skip 1");
|
|
|
+ break;
|
|
|
+ case Playlistwin:
|
|
|
+ if(debug & (DBGCONTROL|DBGPLAY))
|
|
|
+ fprint(2, "Playlistevent: %s %s\n", args[0], args[1]);
|
|
|
+ if(n != 4 || strcmp(args[0], "playlistwin:") || strcmp(args[1], "select"))
|
|
|
+ sysfatal("Bad Playlistwin event[%d]: %s %s", n, args[0], args[1]);
|
|
|
+ n = atoi(args[2]);
|
|
|
+ if(n < 0 || n >= playlist.nentries)
|
|
|
+ sysfatal("Selecting line %d of %d", n, playlist.nentries);
|
|
|
+ if(playlist.selected >= 0 && playlist.selected < playlist.nentries){
|
|
|
+ chanprint(cs->ctl, "playlistwin select %d 0", playlist.selected);
|
|
|
+ chanprint(cs->ctl, "playlistwin show");
|
|
|
+ }
|
|
|
+ playlist.selected = -1;
|
|
|
+ deactivatebuttons(1<<Playbutton);
|
|
|
+ if(strcmp(args[3], "1") == 0)
|
|
|
+ playlistselect(n);
|
|
|
+ break;
|
|
|
+ case Rootbutton:
|
|
|
+ chanprint(cs->ctl, "%q value 0", buts[Rootbutton].ctl->name);
|
|
|
+ setparent(root);
|
|
|
+ clearchildren();
|
|
|
+ addparent("Root");
|
|
|
+ chanprint(cs->ctl, "browsetop show");
|
|
|
+ fillbrowsebot(root);
|
|
|
+ chanprint(cs->ctl, "browsebot show");
|
|
|
+ break;
|
|
|
+ case Deletebutton:
|
|
|
+ if(n != 3 || strcmp(args[0], "trash:") || strcmp(args[1], "value"))
|
|
|
+ sysfatal("Bad Deletebutton event[%d]: %s %s", n, args[0], args[1]);
|
|
|
+ if(strcmp(args[2], "0") == 0)
|
|
|
+ break;
|
|
|
+ chanprint(cs->ctl, "%q value 0", buts[Deletebutton].ctl->name);
|
|
|
+ sendplaylist(nil, nil);
|
|
|
+ break;
|
|
|
+ case Helpbutton:
|
|
|
+ chanprint(cs->ctl, "%q value 0", buts[Helpbutton].ctl->name);
|
|
|
+ if(errorlines > 0){
|
|
|
+ chanprint(cs->ctl, "errortext clear");
|
|
|
+ chanprint(cs->ctl, "errortext topline 0");
|
|
|
+ chanprint(cs->ctl, "errorscr max 0");
|
|
|
+ chanprint(cs->ctl, "errorscr value 0");
|
|
|
+ }
|
|
|
+ if(errorlines >= 0){
|
|
|
+ for(i = 0; helptext[i]; i++)
|
|
|
+ chanprint(cs->ctl, "errortext accumulate %q", helptext[i]);
|
|
|
+ chanprint(cs->ctl, "errorscr max %d", i);
|
|
|
+ }
|
|
|
+ chanprint(cs->ctl, "errortext topline 0");
|
|
|
+ chanprint(cs->ctl, "errorscr value 0");
|
|
|
+ errorlines = -1;
|
|
|
+ chanprint(cs->ctl, "tabs value %d", WinError);
|
|
|
+ break;
|
|
|
+ case Browsetopwin:
|
|
|
+ if(n != 4 || strcmp(args[0], "browsetopwin:") || strcmp(args[1], "select"))
|
|
|
+ sysfatal("Bad Browsetopwin event[%d]: %s %s", n, args[0], args[1]);
|
|
|
+ if(strcmp(args[3], "0") == 0)
|
|
|
+ break;
|
|
|
+ chanprint(cs->ctl, "browsetopwin select %s 0", args[2]);
|
|
|
+ selected = -1;
|
|
|
+ if(strcmp(args[3], "2") == 0)
|
|
|
+ doplay(parent.address);
|
|
|
+ else if(strcmp(args[3], "4") == 0){
|
|
|
+ s = getparent(parent.address);
|
|
|
+ browseto(s);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case Browsebotwin:
|
|
|
+ if(n != 4 || strcmp(args[0], "browsebotwin:") || strcmp(args[1], "select"))
|
|
|
+ sysfatal("Bad Browsebotwin event[%d]: %s %s", n, args[0], args[1]);
|
|
|
+ n = atoi(args[2]);
|
|
|
+ if(n < 0 || n >= nchildren)
|
|
|
+ sysfatal("Selection out of range: %d [%d]", n, nchildren);
|
|
|
+ if(strcmp(args[3], "0") == 0){
|
|
|
+ selected = -1;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if(n < 0)
|
|
|
+ break;
|
|
|
+ chanprint(cs->ctl, "browsebotwin select %d 0", n);
|
|
|
+ selected = n;
|
|
|
+ if(selected >= nchildren)
|
|
|
+ sysfatal("Select out of range: %d [0⋯%d)", selected, nchildren);
|
|
|
+ if(strcmp(args[3], "1") == 0){
|
|
|
+ browseto(children[selected].address);
|
|
|
+ }else if(strcmp(args[3], "2") == 0)
|
|
|
+ doplay(children[selected].address);
|
|
|
+ else if(strcmp(args[3], "4") == 0)
|
|
|
+ browseto(getparent(parent.address));
|
|
|
+ break;
|
|
|
+ case Playevent:
|
|
|
+ if(n < 3 || strcmp(args[0], "playctlproc:"))
|
|
|
+ sysfatal("Bad Playevent event[%d]: %s", n, args[0]);
|
|
|
+ if(debug & (DBGCONTROL|DBGPLAY))
|
|
|
+ fprint(2, "Playevent: %s %s\n", args[1], args[2]);
|
|
|
+ if(strcmp(args[1], "error") ==0){
|
|
|
+ if(n != 4){
|
|
|
+ fprint(2, "Playevent: %s: arg count: %d\n", args[1], n);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if(errorlines < 0){
|
|
|
+ chanprint(cs->ctl, "errortext clear");
|
|
|
+ chanprint(cs->ctl, "errortext topline 0");
|
|
|
+ chanprint(cs->ctl, "errorscr max 0");
|
|
|
+ chanprint(cs->ctl, "errorscr value 0");
|
|
|
+ errorlines = 0;
|
|
|
+ }
|
|
|
+ n = errorlines;
|
|
|
+ chanprint(cs->ctl, "errortext accumulate %q", args[3]);
|
|
|
+ chanprint(cs->ctl, "errorscr max %d", ++errorlines);
|
|
|
+ if(n >= 0 && n <= errorlines - Dy(errortext->rect)/romanfont->height)
|
|
|
+ n--;
|
|
|
+ else
|
|
|
+ n = errorlines - Dy(errortext->rect)/romanfont->height + 1;
|
|
|
+ if(n < 0) n = 0;
|
|
|
+ if(n < errorlines){
|
|
|
+ chanprint(cs->ctl, "errortext topline %d", n);
|
|
|
+ chanprint(cs->ctl, "errorscr value %d", n);
|
|
|
+ }
|
|
|
+ chanprint(cs->ctl, "tabs value %d", WinError);
|
|
|
+ }else if(strcmp(args[1], "play") ==0){
|
|
|
+ chanprint(cs->ctl, "%q value 1", buts[Playbutton].ctl->name);
|
|
|
+ chanprint(cs->ctl, "%q value 0", buts[Stopbutton].ctl->name);
|
|
|
+ chanprint(cs->ctl, "%q value 0", buts[Pausebutton].ctl->name);
|
|
|
+ playlistselect(strtoul(args[2], nil, 0));
|
|
|
+ chanprint(cs->ctl, "playtext clear");
|
|
|
+ chanprint(cs->ctl, "playtext topline 0");
|
|
|
+ chanprint(cs->ctl, "playscr max 0");
|
|
|
+ chanprint(cs->ctl, "playscr value 0");
|
|
|
+ playstate = Playing;
|
|
|
+ activatebuttons(playingbuts);
|
|
|
+ qlock(&playlist);
|
|
|
+ if(playlist.selected < playlist.nentries){
|
|
|
+ fillplaytext(playlist.entry[playlist.selected].onum);
|
|
|
+ chanprint(cs->ctl, "playscr max %d", n);
|
|
|
+ }
|
|
|
+ qunlock(&playlist);
|
|
|
+ chanprint(cs->ctl, "playwin show");
|
|
|
+ }else if(strcmp(args[1], "stop") ==0){
|
|
|
+ chanprint(cs->ctl, "%q value 0", buts[Playbutton].ctl->name);
|
|
|
+ chanprint(cs->ctl, "%q value 1", buts[Stopbutton].ctl->name);
|
|
|
+ chanprint(cs->ctl, "%q value 0", buts[Pausebutton].ctl->name);
|
|
|
+ playlistselect(strtoul(args[2], nil, 0));
|
|
|
+ chanprint(cs->ctl, "%q show", tabs[WinPlaylist].winname);
|
|
|
+ playstate = PlayIdle;
|
|
|
+ deactivatebuttons(playingbuts);
|
|
|
+ }else if(strcmp(args[1], "pause") ==0){
|
|
|
+ activatebuttons(playingbuts);
|
|
|
+ chanprint(cs->ctl, "%q value 1", buts[Playbutton].ctl->name);
|
|
|
+ chanprint(cs->ctl, "%q value 0", buts[Stopbutton].ctl->name);
|
|
|
+ if(playstate == PlayPause){
|
|
|
+ chanprint(cs->ctl, "%q value 0", buts[Pausebutton].ctl->name);
|
|
|
+ playstate = Playing;
|
|
|
+ }else{
|
|
|
+ chanprint(cs->ctl, "%q value 1", buts[Pausebutton].ctl->name);
|
|
|
+ playstate = PlayPause;
|
|
|
+ }
|
|
|
+ }else if(strcmp(args[1], "exits") ==0){
|
|
|
+ threadexits("exitevent");
|
|
|
+ }else{
|
|
|
+ fprint(2, "Unknown play event:");
|
|
|
+ for(i=0; i<n; i++)
|
|
|
+ fprint(2, " %s", args[i]);
|
|
|
+ fprint(2, "\n");
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if(eventstr){
|
|
|
+ free(eventstr);
|
|
|
+ eventstr = nil;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+threadmain(int argc, char *argv[]){
|
|
|
+ int wflag;
|
|
|
+
|
|
|
+ wflag = 0;
|
|
|
+ ARGBEGIN{
|
|
|
+ case 'd':
|
|
|
+ debug = strtol(ARGF(), nil, 0);
|
|
|
+ break;
|
|
|
+ case 't':
|
|
|
+ tflag = 1;
|
|
|
+ break;
|
|
|
+ case 'w':
|
|
|
+ wflag = 1;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ sysfatal(usage, argv0);
|
|
|
+ }ARGEND
|
|
|
+
|
|
|
+ quotefmtinstall();
|
|
|
+
|
|
|
+ if(tflag)
|
|
|
+ makewindow(320, 320, wflag);
|
|
|
+ else
|
|
|
+ makewindow(480, 480, wflag);
|
|
|
+
|
|
|
+ playlist.selected = -1;
|
|
|
+
|
|
|
+ playctlfd = open(playctlfile, OWRITE);
|
|
|
+ if(playctlfd < 0)
|
|
|
+ sysfatal("%s: %r", playctlfile);
|
|
|
+ proccreate(playlistproc, nil, 8192);
|
|
|
+ playevent = chancreate(sizeof(char *), 1);
|
|
|
+ proccreate(playctlproc, playevent, 8192);
|
|
|
+ proccreate(playvolproc, cs->ctl, 8192);
|
|
|
+
|
|
|
+ work();
|
|
|
+
|
|
|
+ closecontrolset(cs);
|
|
|
+ sysfatal("");
|
|
|
+}
|