ref: c613382caf1c0bffa38dc09f113d8c11dbc47628
parent: c6cdee420da18fc02c44c257505f3c43a331c7a4
author: Sigrid <ftrvxmtrx@gmail.com>
date: Tue Apr 13 07:25:24 EDT 2021
remove juke (use play or zuke instead)
--- a/rc/bin/juke
+++ /dev/null
@@ -1,57 +1,0 @@
-#!/bin/rc
-rfork e
-wide=`{echo $vgasize | sed 's/(.*)x.*x.*/\1 > 240/' | hoc}
-debug=0
-tflag=''
-wflag=''
-host=''
-flags=()
-sname=$user
-if (! ~ $wide 1) {
- flags=($flags -t)
-}
-while(! ~ $#* 0) {
- switch ($1) {
- case -d
- debug=$2
- shift
- case -t
- tflag='-t'
- case -h
- host=$2
- shift
- case -w
- wflags='-w'
- case -s
- sname=$2
- shift
- case -*
- echo usage: juke [-d level] [-tw] [-s srv] [-h srvhost] >[1=2]
- exit usage
- }
- shift
-}
-if (! test -f /mnt/playlist) {
- if (! ~ $debug '0') echo mounting playlistfs
- if (! test -e /srv/playlist.$sname && ! ~ $host ''){
- import -a $host /srv /srv
- }
- if (! mount -b /srv/playlist.$sname /mnt >/dev/null >[2]/dev/null){
- rm -f /srv/playlist.$sname
- if (! ~ $debug '0') echo starting playlistfs
- games/playlistfs -s $sname -d $debug
- }
-}
-if (~ `{ls /mnt/juke >[2]/dev/null | sed '1q'} '') {
- if (! test -e /srv/jukefs.$sname && ! ~ $host ''){
- import -a $host /srv /srv
- }
- if (! mount -b /srv/jukefs.$sname /mnt >/dev/null >[2]/dev/null){
- if (! ~ $debug '0') echo games/jukefs
- games/jukefs -s $sname
- }
-}
-if (~ $wflags '-w') {
- exec games/jukebox -w -d $debug $tflag &
-}
-exec games/jukebox -d $debug $tflag
--- a/sys/man/7/juke
+++ /dev/null
@@ -1,368 +1,0 @@
-.TH JUKE 7
-.SH NAME
-juke \- music jukebox
-.SH SYNOPSIS
-.B juke
-[
-.B \-t
-]
-[
-.B \-w
-]
-[
-.B \-h
-.I srvhost
-]
-[
-.B \-s
-.I srvname
-]
-.ift .sp 0.5
-.ifn .sp
-.B games/jukebox
-[
-.B \-t
-]
-[
-.B \-w
-]
-.ift .sp 0.5
-.ifn .sp
-.B games/jukefs
-[
-.B \-m
-.I mountpoint
-]
-[
-.B \-s
-.I srvname
-]
-[
-.I mapfile
-]
-.SH DESCRIPTION
-.I Jukebox
-controls a playlist server
-(see
-.IR playlistfs (7))
-through a graphical user interface. It connects to a music database server which reads a set of
-.I map
-files that describe recordings and their location. Currently, there is
-one set of maps, mostly for classical music, with some jazz and other stuff
-thrown in. These are served by
-.BR jukefs ,
-which presents a file system conventionally mounted at
-.BR /mnt/juke .
-The playlist, explained below, is managed by a file system implemented by
-.IR playlistfs (7)
-and normally mounted on
-.BR /mnt .
-.PP
-.I Jukebox
-is most easily started through the
-.I juke
-shell script.
-.PP
-.I Jukebox
-has four windows, which can be selected by clicking the appropriate tab
-at the top of the window.
-.PP
-Above the tab are nine buttons and a volume slider. The
-.ift buttons, shown below,
-.ifn buttons
-are named, from left to right,
-.IR Exit ,
-.IR Pause ,
-.IR Play ,
-.IR Halt ,
-.IR Back ,
-.IR Forward ,
-.IR Root ,
-.IR Delete ,
-and
-.IR Help .
-The buttons are
-.I active
-when they are displayed in dark green (or red). When they are pale blue
-they are
-.IR inactive .
-The Exit button is always active; it exits the program (but leaves the playlist and music database
-servers running).
-.PP
-The
-.I browse
-window is for browsing through the music and selecting music to play.
-Browsing down in the music hierarchy is done by clicking button one on
-an item. Clicking button three goes back up.
-Clicking button two recursively adds all files below the selected item to
-the
-.IR "play list" .
-.PP
-The selected music is displayed in the
-.I playlist
-window.
-The track currently playing is shown in the
-.I playing
-window.
-.PP
-The
-.I Root
-button browses back to the root.
-.PP
-The
-.I Delete
-button empties the playlist.
-.PP
-The
-.I Help
-displays a minimal on-line manual.
-.PP
-.I Play
-starts playing at the beginning of the play list, or at the selected track in
-the play list.
-.PP
-During play,
-.IR Pause ,
-.IR Stop ,
-.IR Back ,
-and
-.I Forward
-are active.
-.I Back
-and
-.I Forward
-go back or forward a track at a time. The other buttons do the obvious thing.
-.PP
-The
-.B \-t
-flag chooses a tiny font, useful for handhelds.
-.PP
-The
-.B \-w
-flag creates the jukebox in a new window. Normally, the jukebox takes over
-the window in which it is invoked.
-.PP
-The
-.B \-s
-flag specifies the name under which the file descriptors of the playlist and databse servers are posted
-in /srv. This allows two or more play list servers to exist on one platform, e.g., when
-there are several audio devices. The default value of the flag is
-.B $\f2user\fP
-for a playlist server at
-.B /srv/playlistfs.$\f2user\fP
-and a database server at
-.BR /srv/jukefs.$\f2user\fP .
-.sp
-.LP
-.B Jukefs
-reads a set of
-.I maps
-describing the music data, builds an in-memory database, and provides
-lookup service to
-.IR jukebox .
-The default map is
-.BR /sys/lib/music/map .
-It consists of a hierarchical set of
-.IR objects .
-Each object has a type, a value, zero or more attribute-value
-pairs and zero or more subobjects. An object consists of the
-type, followed by its contents between curly brackets.
-Attribute value pairs consist
-of a single line containing an attribute name, an equals sign, and
-a value.
-The value of an object is any text not containing curly brackets or equals
-signs. Here is an example:
-.EX
-.ps -2
-.vs -2p
-.sp
-category {
- composer = mahler
-
- Gustav Mahler
- (1860 — 1911)
-
- work {
- path {classic/mahler}
- class = symphonic
- orchestra = rfo
- conductor = Waart,~Edo~de
-
- Symphony Nº 5 in c♯ (RFO, Vienna)
- performance{
- Radio Filharmonisch Orkest Holland
- Edo de Waart, conductor
-
- recorded: Musikverein, Vienna, May 6, 1996
- }
- command {number}
- track {
- Trauermarsch (In gemessenem Schritt. Streng. Wie ein Kondukt)
- time {13:55}
- file {034.pac}
- }
- track {
- Stürmisch bewegt, mit größter Vehemenz
- time {15:34}
- file {035.pac}
- }
- track {
- Scherzo (Kräftig, nicht zu schnell)
- time {18:54}
- file {036.pac}
- }
- track {
- Adagietto (Sehr Langsam)
- time {10:01}
- file {037.pac}
- }
- track {
- Rondo–Finale (Allegro)
- time {15:44}
- file {038.pac}
- }
- }
-}
-.EE
-.LP
-This example shows a
-.I category
-object for the composer Gustav Mahler (the value consists of the two
-lines `Gustav Mahler' and `(1860 — 1911)') with one subobject, a
-.I work
-object whose value is `Symphony Nº 5 in c♯ (RFO, Vienna)'. The work object
-contains six subobjects: one
-.I performance
-object and five
-.I track
-objects.
-.PP
-.I Category
-objects must contain exactly one attribute-value pair. The attribute
-names a subobject of the root under which this category object will
-be placed. Gustav Mahler, thus, will be placed in
-Root→composer.
-.IR Work ,
-.IR Recording ,
-.IR Part ,
-and
-.IR Track ,
-objects all describe named containers for subunits.
-A
-.IR Lyrics ,
-.IR Performance ,
-or
-.IR Soloists
-object adds information to a
-.IR Work ,
-.IR Recording ,
-.IR Part ,
-or
-.IR Track ,
-object. It should only contain text.
-The same is true for a
-.I Time
-object; however, it should only be used adjacent to
-.I File
-objects and it should contain the running time of that file (this
-is for future use).
-.PP
-A
-.I File
-object specifies a file to be played. When the
-.I Select
-button is pressed, all file objects contained hierarchically in the
-selected object are added to the playlist.
-.PP
-There are a number of pseudo objects:
-.I Command
-may contain either
-.I sort
-or
-.IR number .
-The
-.I sort
-command sorts the subobjects of the object it appears in by
-.I key
-or textual content.
-The
-.I number
-commands prepends numbers to the texts of its subobjects
-(e.g., for the parts in a symphony)
-.PP
-An
-.I Include
-object is replaced by the contents of the named file.
-.PP
-A
-.I Key
-object specifies a key for sorting subobjects.
-.PP
-Finally, a
-.I Path
-object specifies a path to be prepended to the files named in
-hierarchically contained
-.I File
-objects.
-.PP
-The attribute-value value pairs arrange for entries to be made of the
-current object in a
-.I Category
-object named by the attribute directly under the root.
-.sp
-.LP
-The interface to the browsing database is through a file system
-implemented by
-.BR jukefs .
-The file system synthesises a directory per object. Each directory contains a set of files
-describing the object's attributes:
-.TP
-.B children
-contains a new-line separated list of subobject names. For each name,
-.I x
-the directory
-.BI /mnt/juke/ x
-describes the subobject.
-.TP
-.B digest
-contains a one-line summary of the object
-.TP
-.B files
-is a new-line separated list of file objects contained in this object.
-Each line consists of object name and file name.
-.TP
-.B fulltext
-is the fulltextual value of the object.
-.TP
-.B key
-contains the key by which objects are sorted
-.TP
-.B miniparentage
-is a one-line summary of the objects and the path leading to it from the root.
-This is the line displayed in the playlist and bottom browse windows of
-.BR games/jukebox .
-.TP
-.B parent
-is the object reference to the parent of this object.
-.TP
-.B parentage
-is a full description of the path leading to this object and the object itself.
-This is the string displayed in the top of the Browse and Playing windows
-of
-.BR games/jukebox .
-.TP
-.B text
-is the text field of the object.
-.TP
-.B type
-is the type of the object
-.LP
-.SH FILES
-.BR /sys/lib/music/map :
-Default map file
-.BR /mnt/juke :
-Default mount point for the music database.
-.SH SOURCE
-.B /sys/src/games/music
-.SH SEE ALSO
-.IR playlistfs (7).
--- a/sys/man/7/playlistfs
+++ /dev/null
@@ -1,147 +1,0 @@
-.TH PLAYLISTFS 7
-.SH NAME
-playlistfs \- playlist file system
-.SH SYNOPSIS
-.B games/playlistfs
-[
-.B \-s
-.I postname
-]
-[
-.B \-m
-.I mountpoint
-]
-[
-.B \-a
-]
-.SH DESCRIPTION
-.B Playlistfs
-implements an audio player which plays files from a built-in play list.
-The player is controlled through three files, usually mounted at
-.BR /mnt .
-The files are
-.B /playctl
-for controlling play: start, stop, pause, skip, etc.;
-.B /playvol
-for controlling the playout volume; and
-.B /playlist
-for controlling the play list itself.
-.PP
-All three files can be written to control the player and read to obtain player
-status information.
-.PP
-When read, the files report the current status of the player, volume and playlist,
-respectively. End of file is indicated by a read that returns zero bytes, as usual.
-However, in all three files, subsequent read operations will block until the status
-of the file changes and then report the changed state. When the changed state has
-been read, another end-of-file indication is given, after which another read
-can be issued to wait for state changes.
-.PP
-The
-.B /playctl
-file returns strings of the form `\f2cmd n\fP'
-where
-.I cmd
-is one of
-.IR stop ,
-.IR pause ,
-or
-.I play
-and
-.I n
-is an index (or offset) into the playlist; indices start at zero.
-.PP
-The commands that can be written to
-.B /playctl
-take the same form; however, the index is an optional argument. If the
-index is omitted, the current value is used. The commands are
-.IR play ,
-.IR stop ,
-.IR pause ,
-.IR resume ,
-and
-.IR skip .
-.I Play
-starts playing at the index.
-.I Stop
-stops playing. If an index is given, the current index is set to it and
-can be used in future commands.
-.I Pause
-and
-.I Resume
-interrupt and continue play, respectively. The index argument is always ignored and
-the whole command is ignored if the state in which they occur does not
-make sense.
-.I Skip
-adds the argument to the current index (adds one if no argument is given)
-and starts play at that index, stopping current play, if necessary.
-.PP
-Reads of
-.B /playvol
-return strings of the form
-.BR "`volume \f2n\fP'" ,
-where
-.I n
-is a number or, if there is more than one channel, a quoted set of numbers, between 0
-(minimum) and 100 (maximum).
-Writes to
-.B /playvol
-take the same form.
-.PP
-The
-.B /playlist
-file is an append-only file which accepts lines with one or two fields
-per line (parsed using
-.BR tokenize ).
-The first, compulsory, field is a file name, the optional second argument
-may contain a reference to, or a description of, the item, for instance in a graphical
-user interface.
-.B /playlist
-is append-only, individual lines cannot be removed. However, the playlist
-can be cleared by opening the file with the
-.B OTRUNC
-flag. A process that has
-.B /playlist
-open while the file is truncated will receive an error on the next read with
-.B errstr
-set to
-.IR "reading past eof" .
-When this error occurs, clients can seek to the beginning of the file and reread its contents.
-.PP
-After starting up,
-.B Playlistfs
-puts itself in the background. When called with the
-.B \-s
-flag, it posts a mountable file descriptor in
-.BR /srv/playlist.\f2postname\fP .
-The
-.B \-m
-flag can be used to specify a mount point other than
-.BR /mnt .
-.PP
-.B Playlistfs
-uses the
-.IR audio (1)
-decoders by running
-.IR play (1)
-for format detection and conversion to pcm.
-.SH FILES
-.BR /srv/playlistfs.\f2user\fP :
-default
-.B playlistfs
-mountable file descriptor used by juke(7).
-.br
-.BR /mnt/playctl :
-Control file
-.br
-.BR /mnt/playlist :
-Playlist file
-.br
-.BR /mnt/playvol :
-Volume control file
-.SH SOURCE
-.B /sys/src/games/music/playlistfs
-.SH SEE ALSO
-.IR play (1),
-.IR audio (1),
-.IR juke (7).
--- a/sys/src/games/mkfile
+++ b/sys/src/games/mkfile
@@ -40,7 +40,6 @@
mahjongg\
mines\
mix\
- music\
md\
nes\
opl3\
--- a/sys/src/games/music/Readme
+++ /dev/null
@@ -1,12 +1,0 @@
-The Plan 9 Jukebox consists of three applications: a play-list server, a browse server
-and a GUI:
- playlist server: playlistfs
- browse server: jukefs
- GUI: jukebox
-The juke.rc script (installed, by default, in /rc/bin/juke) starts them all up.
-
-To configure, adjust the DEFAULTMAP and ICONPATH in the central mkfile.
-The default map is used by jukefs as the root of the descriptive database.
-The iconpath is used by jukebox to find the icons.
-
-Report problems to sape@plan9.bell-labs.com
--- a/sys/src/games/music/debug.h
+++ /dev/null
@@ -1,13 +1,0 @@
-extern int debug;
-
-enum {
- DBGSERVER = 0x01,
- DBGCONTROL = 0x02,
- DBGCTLGRP = 0x04,
- DBGPICKLE = 0x08,
- DBGSTATE = 0x10,
- DBGPLAY = 0x20,
- DBGPUMP = 0x40,
- DBGTHREAD = 0x80,
- DBGFILEDUMP = 0x100,
-};
binary files a/sys/src/games/music/icon/next.bit /dev/null differ
binary files a/sys/src/games/music/icon/pause.bit /dev/null differ
binary files a/sys/src/games/music/icon/play.bit /dev/null differ
binary files a/sys/src/games/music/icon/prev.bit /dev/null differ
binary files a/sys/src/games/music/icon/question.bit /dev/null differ
binary files a/sys/src/games/music/icon/root.bit /dev/null differ
binary files a/sys/src/games/music/icon/skull.bit /dev/null differ
binary files a/sys/src/games/music/icon/stop.bit /dev/null differ
binary files a/sys/src/games/music/icon/trash.bit /dev/null differ
--- a/sys/src/games/music/juke.rc
+++ /dev/null
@@ -1,57 +1,0 @@
-#!/bin/rc
-rfork e
-wide=`{echo $vgasize | sed 's/(.*)x.*x.*/\1 > 240/' | hoc}
-debug=0
-tflag=''
-wflag=''
-host=''
-flags=()
-sname=$user
-if (! ~ $wide 1) {
- flags=($flags -t)
-}
-while(! ~ $#* 0) {
- switch ($1) {
- case -d
- debug=$2
- shift
- case -t
- tflag='-t'
- case -h
- host=$2
- shift
- case -w
- wflags='-w'
- case -s
- sname=$2
- shift
- case -*
- echo Usage: classical [-d level] [-t] [-h srvhost]
- exit usage
- }
- shift
-}
-if (! test -f /mnt/playlist) {
- if (! ~ $debug '0') echo mounting playlistfs
- if (! test -e /srv/playlist.$sname && ! ~ $host ''){
- import -a $host /srv /srv
- }
- if (! mount -b /srv/playlist.$sname /mnt >/dev/null >[2]/dev/null){
- rm -f /srv/playlist.$sname
- if (! ~ $debug '0') echo starting playlistfs
- games/playlistfs -s $sname -d $debug
- }
-}
-if (~ `{ls /mnt/juke >[2]/dev/null | sed '1q'} '') {
- if (! test -e /srv/jukefs.$sname && ! ~ $host ''){
- import -a $host /srv /srv
- }
- if (! mount -b /srv/jukefs.$sname /mnt >/dev/null >[2]/dev/null){
- if (! ~ $debug '0') echo games/jukefs
- games/jukefs -s $sname
- }
-}
-if (~ $wflags '-w') {
- exec games/jukebox -w -d $debug $tflag &
-}
-exec games/jukebox -d $debug $tflag
--- a/sys/src/games/music/jukebox/client.c
+++ /dev/null
@@ -1,157 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include <bio.h>
-#include "client.h"
-#include "playlist.h"
-#include "../debug.h"
-
-char *srvmount = "/mnt/juke";
-
-char*
-getroot(void)
-{
- return "root";
-}
-
-void
-fillbrowsebot(char *onum)
-{
- char *name, *p, *q;
- Biobuf *b, *d;
- int c;
-
- name = smprint("%s/%s/children", srvmount, onum);
- b = Bopen(name, OREAD);
- if(b == nil)
- sysfatal("getchildren: %s: %r", name);
- free(name);
- while(p = Brdline(b, '\n')){
- c = strtol(p, &q, 0);
- assert(*q == '\n');
- *q = 0;
- name = smprint("%s/%d/type", srvmount, c);
- d = Bopen(name, OREAD);
- if(d == nil)
- sysfatal("getchildren: %s: %r", name);
- free(name);
- q = Brdstr(d, '\n', 1);
- if(q == nil){
- abort();
- }
- Bterm(d);
- if(strcmp(q, "performance") == 0)
- continue;
- name = smprint("%s/%d/digest", srvmount, c);
- d = Bopen(name, OREAD);
- if(d == nil)
- sysfatal("getchildren: %s: %r", name);
- free(name);
- q = Brdstr(d, '\n', 1);
- if(q == nil){
- Bterm(d);
- continue;
- }
- addchild(strdup(p), q);
- Bterm(d);
- }
- Bterm(b);
-}
-
-void
-doplay(char *onum){
- char *name, *p, *q;
- Biobuf *b;
- int m;
-
- name = smprint("%s/%s/files", srvmount, onum);
- b = Bopen(name, OREAD);
- if(b == nil)
-abort();// sysfatal("doplay: %s: %r", name);
- while(p = Brdline(b, '\n')){
- m = Blinelen(b);
- assert(p[m-1] == '\n');
- p[m-1] = '\0';
- q = strchr(p, ' ');
- if(q == nil)
- sysfatal("doplay: %s: format", name);
- *q++ = '\0';
- sendplaylist(strdup(q), strdup(p));
- }
- free(name);
- Bterm(b);
-}
-
-void
-fillbrowsetop(char *onum)
-{
- char *name, *p;
- Biobuf *b;
- int m;
-
- name = smprint("%s/%s/parentage", srvmount, onum);
- b = Bopen(name, OREAD);
- if(b == nil)
-abort();// sysfatal("gettopwin: %s: %r", name);
- free(name);
- while(p = Brdline(b, '\n')){
- m = Blinelen(b);
- assert(p[m-1] == '\n');
- p[m-1] = '\0';
- addparent(p);
- }
- Bterm(b);
-}
-
-void
-fillplaytext(char *onum)
-{
- char *name, *p;
- Biobuf *b;
- int m;
-
- name = smprint("%s/%s/parentage", srvmount, onum);
- b = Bopen(name, OREAD);
- if(b == nil)
- sysfatal("fillplaytext: %s: %r", name);
- free(name);
- while(p = Brdline(b, '\n')){
- m = Blinelen(b);
- assert(p[m-1] == '\n');
- p[m-1] = '\0';
- addplaytext(p);
- }
- Bterm(b);
-}
-
-char *
-getoneliner(char *onum)
-{
- char *name, *p;
- Biobuf *b;
-
- name = smprint("%s/%s/miniparentage", srvmount, onum);
- b = Bopen(name, OREAD);
- if(b == nil)
- sysfatal("gettopwin: %s: %r", name);
- free(name);
- p = Brdstr(b, '\n', 1);
- Bterm(b);
- return p;
-}
-
-char *
-getparent(char *onum)
-{
- char *name, *p;
- Biobuf *b;
-
- name = smprint("%s/%s/parent", srvmount, onum);
- b = Bopen(name, OREAD);
- if(b == nil)
-abort();// sysfatal("gettopwin: %s: %r", name);
- free(name);
- p = Brdstr(b, '\n', 1);
- Bterm(b);
- return p;
-}
--- a/sys/src/games/music/jukebox/client.h
+++ /dev/null
@@ -1,10 +1,0 @@
-char* getroot(void);
-void doplay(char*);
-void fillbrowsebot(char*);
-void fillbrowsetop(char*);
-void fillplaytext(char*);
-void addchild(char*, char*);
-void addparent(char*);
-char *getoneliner(char*);
-char *getparent(char*);
-void addplaytext(char*);
--- a/sys/src/games/music/jukebox/colors.c
+++ /dev/null
@@ -1,120 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include <draw.h>
-#include <keyboard.h>
-#include <mouse.h>
-#include <control.h>
-#include "colors.h"
-
-Font *boldfont;
-Font *romanfont;
-
-Image *background;
-Image *bordercolor;
-Image *black;
-Image *blue;
-Image *darkblue;
-Image *darkgrey;
-Image *darkgreen;
-Image *darkmagenta;
-Image *green;
-Image *grey;
-Image *high;
-Image *land;
-Image *lightblue;
-Image *lightgreen;
-Image *lightgrey;
-Image *lightmagenta;
-Image *low;
-Image *magenta;
-Image *oceanblue;
-Image *pale;
-Image *paleblue;
-Image *paleyellow;
-Image *red;
-Image *sea;
-Image *white;
-Image *yellow;
-
-static ulong
-rgba(ulong rgba)
-{
- uchar r, g, b, a;
-
- a = rgba & 0xff;
- b = (rgba >>= 8) & 0xff;
- g = (rgba >>= 8) & 0xff;
- r = (rgba >> 8) & 0xff;
- rgba = ((r * a / 0xff) & 0xff);
- rgba = ((g * a / 0xff) & 0xff) | (rgba << 8);
- rgba = ((b * a / 0xff) & 0xff) | (rgba << 8);
- rgba = (a & 0xff) | (rgba << 8);
- return rgba;
-}
-
-void
-colorinit(char *roman, char *bold)
-{
- Rectangle r = Rect(0, 0, 1, 1);
-
- white = display->white;
- black = display->black;
- blue = allocimage(display, r, screen->chan, 1, rgba(0x0000ffff));
- darkblue = allocimage(display, r, screen->chan, 1, rgba(0x0000ccff));
- darkgrey = allocimage(display, r, screen->chan, 1, rgba(0x444444ff));
- darkgreen = allocimage(display, r, screen->chan, 1, rgba(0x008800ff));
- darkmagenta = allocimage(display, r, screen->chan, 1, rgba(0x770077ff));
- green = allocimage(display, r, screen->chan, 1, rgba(0x00ff00ff));
- grey = allocimage(display, r, screen->chan, 1, rgba(0x888888ff));
- high = allocimage(display, r, screen->chan, 1, rgba(0x00ccccff));
- land = allocimage(display, r, screen->chan, 1, rgba(0xe0ffe0ff));
- lightblue = allocimage(display, r, screen->chan, 1, rgba(0x88ccccff));
- lightgreen = allocimage(display, r, screen->chan, 1, rgba(0xaaffaaff));
- lightgrey = allocimage(display, r, screen->chan, 1, rgba(0xddddddff));
- lightmagenta = allocimage(display, r, screen->chan, 1, rgba(0xff88ffff));
- low = allocimage(display, r, screen->chan, 1, rgba(0xddddddff));
- magenta = allocimage(display, r, screen->chan, 1, rgba(0xbb00bbff));
- oceanblue = allocimage(display, r, screen->chan, 1, rgba(0x93ddddff));
- pale = allocimage(display, r, screen->chan, 1, rgba(0xffffaaff));
- paleblue = allocimage(display, r, screen->chan, 1, rgba(0xddffffff));
- paleyellow = allocimage(display, r, screen->chan, 1, rgba(0xeeee9eff));
- red = allocimage(display, r, screen->chan, 1, rgba(0xff0000ff));
- sea = allocimage(display, r, screen->chan, 1, rgba(0xe0e0ffff));
- yellow = allocimage(display, r, screen->chan, 1, rgba(0xffff00ff));
- background = sea;
- bordercolor = darkgreen;
-
- namectlimage(background, "background");
- namectlimage(bordercolor, "border");
- namectlimage(black, "black");
- namectlimage(blue, "blue");
- namectlimage(darkblue, "darkblue");
- namectlimage(darkgreen, "darkgreen");
- namectlimage(darkmagenta, "darkmagenta");
- namectlimage(green, "green");
- namectlimage(grey, "grey");
- namectlimage(high, "high");
- namectlimage(land, "land");
- namectlimage(lightblue, "lightblue");
- namectlimage(lightgreen, "lightgreen");
- namectlimage(lightgrey, "lightgrey");
- namectlimage(lightmagenta, "lightmagenta");
- namectlimage(low, "low");
- namectlimage(magenta, "magenta");
- namectlimage(oceanblue, "oceanblue");
- namectlimage(pale, "pale");
- namectlimage(paleblue, "paleblue");
- namectlimage(paleyellow, "paleyellow");
- namectlimage(red, "red");
- namectlimage(sea, "sea");
- namectlimage(white, "white");
- namectlimage(yellow, "yellow");
-
- if ((romanfont = openfont(display, roman)) == nil)
- sysfatal("openfont %s: %r", roman);
- namectlfont(romanfont, "romanfont");
- if ((boldfont = openfont(display, bold)) == nil)
- sysfatal("openfont %s: %r", bold);
- namectlfont(boldfont, "boldfont");
-}
--- a/sys/src/games/music/jukebox/colors.h
+++ /dev/null
@@ -1,30 +1,0 @@
-extern Image *background;
-extern Image *bordercolor;
-extern Image *black;
-extern Image *blue;
-extern Image *darkblue;
-extern Image *darkgrey;
-extern Image *darkgreen;
-extern Image *darkmagenta;
-extern Image *green;
-extern Image *grey;
-extern Image *high;
-extern Image *land;
-extern Image *lightblue;
-extern Image *lightgreen;
-extern Image *lightgrey;
-extern Image *lightmagenta;
-extern Image *low;
-extern Image *magenta;
-extern Image *oceanblue;
-extern Image *pale;
-extern Image *paleblue;
-extern Image *paleyellow;
-extern Image *red;
-extern Image *sea;
-extern Image *white;
-extern Image *yellow;
-
-extern Font *romanfont, *boldfont;
-
-void colorinit(char*, char*);
--- a/sys/src/games/music/jukebox/mk.dep
+++ /dev/null
@@ -1,4 +1,0 @@
-client.$O: /$objtype/include/u.h /sys/include/libc.h /sys/include/thread.h /sys/include/bio.h client.h playlist.h
-colors.$O: /$objtype/include/u.h /sys/include/libc.h /sys/include/thread.h /sys/include/draw.h /sys/include/keyboard.h /sys/include/mouse.h /sys/include/control.h colors.h
-music.$O: /$objtype/include/u.h /sys/include/libc.h /sys/include/thread.h /sys/include/draw.h /sys/include/keyboard.h /sys/include/mouse.h /sys/include/control.h colors.h client.h playlist.h
-playlist.$O: /$objtype/include/u.h /sys/include/libc.h /sys/include/thread.h /sys/include/draw.h /sys/include/keyboard.h /sys/include/mouse.h /sys/include/control.h playlist.h
--- a/sys/src/games/music/jukebox/mkfile
+++ /dev/null
@@ -1,16 +1,0 @@
-</$objtype/mkfile
-<../mkinc
-
-CFLAGS = -DDEFAULTMAP="$DEFAULTMAP" -DICONPATH="$ICONPATH"
-TARG = jukebox
-BIN = /$objtype/bin/games
-
-CFILES=\
- client.c\
- colors.c\
- music.c\
- playlist.c\
-
-OFILES = ${CFILES:%.c=%.$O}
-
-</sys/src/cmd/mkone
--- a/sys/src/games/music/jukebox/music.c
+++ /dev/null
@@ -1,1091 +1,0 @@
-#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 [-d mask] [-t] [-w]\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,
-
- Browsedepth = 63,
-};
-
-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,
- Browsebotscr,
- 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,
-};
-
-struct Browsestack {
- char *onum;
- int scrollpos;
-} browsestack[Browsedepth];
-int browsesp; /* browse stack pointer */
-int browseline; /* current browse position */
-
-Control *vol;
-Control *browsetopwin;
-Control *browsebotwin;
-Control *playlistwin;
-Control *errortext;
-Control *browsetopscr;
-Control *browsebotscr;
-
-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;
-
- 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, "playlistwin topline 0");
- 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, int line)
-{
- onum = strdup(onum);
- setparent(onum);
- clearchildren();
- fillbrowsetop(onum);
- chanprint(cs->ctl, "browsetop show");
- fillbrowsebot(onum);
- if(line){
- chanprint(cs->ctl, "browsebotscr value %d", line);
- chanprint(cs->ctl, "browsebotwin topline %d", line);
- }
- chanprint(cs->ctl, "browsebot show");
- free(onum);
-}
-
-void
-browsedown(char *onum)
-{
- if(browsesp == 0){
- /* Make room for an entry by deleting the last */
- free(browsestack[Browsedepth-1].onum);
- memmove(browsestack + 1, browsestack, (Browsedepth-1) * sizeof(browsestack[0]));
- browsesp++;
- }
- /* Store current position in current stack frame */
- assert(browsesp > 0 && browsesp < Browsedepth);
- browsestack[browsesp].onum = strdup(parent.address);
- browsestack[browsesp].scrollpos = browseline;
- browsesp--;
- browseline = 0;
- if(browsestack[browsesp].onum && strcmp(browsestack[browsesp].onum, onum) == 0)
- browseline = browsestack[browsesp].scrollpos;
- browseto(onum, browseline);
-}
-
-void
-browseup(char *onum)
-{
- if(browsesp == Browsedepth){
- /* Make room for an entry by deleting the first */
- free(browsestack[0].onum);
- memmove(browsestack, browsestack + 1, browsesp * sizeof(browsestack[0]));
- browsesp--;
- }
- /* Store current position in current stack frame */
- assert(browsesp >= 0 && browsesp < Browsedepth);
- browsestack[browsesp].onum = strdup(parent.address);
- browsestack[browsesp].scrollpos = browseline;
- browsesp++;
- browseline = 0;
- if(browsestack[browsesp].onum && strcmp(browsestack[browsesp].onum, onum) == 0)
- browseline = browsestack[browsesp].scrollpos;
- browseto(onum, browseline);
-}
-
-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},
- [Browsebotscr] = {browsebotscr->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);
- browsedown(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){
- browseup(children[selected].address);
- }else if(strcmp(args[3], "2") == 0)
- doplay(children[selected].address);
- else if(strcmp(args[3], "4") == 0)
- browsedown(getparent(parent.address));
- break;
- case Browsebotscr:
- browseline = atoi(args[2]);
- chanprint(cs->ctl, "browsebotwin topline %d", browseline);
- 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);
- threadexitsall(nil);
-}
--- a/sys/src/games/music/jukebox/playlist.c
+++ /dev/null
@@ -1,297 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include <draw.h>
-#include <keyboard.h>
-#include <mouse.h>
-#include <control.h>
-#include "playlist.h"
-#include "../debug.h"
-
-char *playlistfile = "/mnt/playlist";
-char *playctlfile = "/mnt/playctl";
-char *playvolfile = "/mnt/playvol";
-char *volumefile = "/dev/audioctl";
-
-Playlist playlist;
-int playctlfd;
-
-void
-playlistproc(void*)
-{
- int fd, m, n, nf;
- static char buf[8192+1];
- char *p, *q, *fields[4];
-
- threadsetname("playlistproc");
- fd = open(playlistfile, OREAD);
- if(fd < 0)
- sysfatal("%s: %r", playlistfile);
- p = buf;
- n = 0;
- if(debug & DBGPLAY)
- fprint(2, "playlistproc: starting\n");
- for(;;){
- m = read(fd, buf+n, sizeof buf - 1 - n);
- if(m == 0){
- if(debug & DBGPLAY)
- fprint(2, "playlistproc: empty read\n");
- continue;
- }
- if(m < 0){
- rerrstr(buf, sizeof(buf));
- if(strcmp(buf, "reading past eof"))
- sysfatal("%s: %r", playlistfile);
- for(n = 0; n < playlist.nentries; n++){
- free(playlist.entry[n].file);
- free(playlist.entry[n].onum);
- }
- if(debug & DBGPLAY)
- fprint(2, "playlistproc: trunc\n");
- playlist.nentries = 0;
- free(playlist.entry);
- playlist.entry = nil;
- updateplaylist(1);
- seek(fd, 0, 0);
- p = buf;
- n = 0;
- continue;
- }
- if(debug & DBGPLAY)
- fprint(2, "playlistproc: read %d bytes\n", m);
- n += m;
- p[n] = '\0';
- while(q = strchr(p, '\n')){
- *q = 0;
- nf = tokenize(p, fields, nelem(fields));
- if(nf){
- playlist.entry = realloc(playlist.entry, (playlist.nentries+1)*sizeof playlist.entry[0]);
- if(playlist.entry == nil)
- sysfatal("realloc %r");
- playlist.entry[playlist.nentries].file = strdup(fields[0]);
- if(nf > 1){
- playlist.entry[playlist.nentries].onum = strdup(fields[1]);
- if(debug & DBGPLAY)
- fprint(2, "playlistproc: [%d]: %q %q\n", playlist.nentries,
- playlist.entry[playlist.nentries].file,
- playlist.entry[playlist.nentries].onum);
- }else{
- playlist.entry[playlist.nentries].onum = nil;
- if(debug & DBGPLAY)
- fprint(2, "playlistproc: [%d]: %q nil\n", playlist.nentries,
- playlist.entry[playlist.nentries].file);
- }
- updateplaylist(0); // this will also update nentries
- }
- q++;
- n -= q-p;
- p = q;
- }
- if(n)
- memmove(buf, p, n);
- p = buf;
- }
-}
-
-void
-sendplaylist(char *file, char *onum)
-{
- static int fd = -1;
- char *b;
-
- if(file == nil){
- if(fd >= 0)
- close(fd);
- fd = open(playlistfile, OWRITE|OTRUNC);
- if(fd < 0)
- sysfatal("%s: truncate: %r", playlistfile);
- return;
- }
- if(fd < 0){
- fd = open(playlistfile, OWRITE);
- if(fd < 0)
- sysfatal("%s: %r", playlistfile);
- }
- b = smprint("%q %q\n", file, onum);
- if(debug & DBGPLAY)
- fprint(2, "sendplaylist @%s@\n", b);
- if(write(fd , b, strlen(b)) != strlen(b))
- sysfatal("sendplaylist: %r");
-}
-
-void
-playctlproc(void*a)
-{
- int fd, n, nf;
- static char buf[512+1];
- char *fields[4];
- Channel *chan;
-
- threadsetname("playctlproc");
- chan = a;
- fd = open(playctlfile, OREAD);
- if(fd < 0)
- sysfatal("%s: %r", playctlfile);
- for(;;){
- n = read(fd, buf, sizeof buf -1);
- if(n == 0)
- continue;
- if(n < 0)
- sysfatal("%s: %r", playctlfile);
- buf[n] = '\0';
- nf = tokenize(buf, fields, nelem(fields));
- if(nf == 0)
- continue;
- switch (nf){
- default:
- sysfatal("playctlproc: [%d]: %s", nf, fields[0]);
- case 3:
- chanprint(chan, "playctlproc: error %lud %q", strtoul(fields[1], nil, 0), fields[2]);
- if(strcmp(fields[0], "error") == 0)
- break;
- // fall through
- case 2:
- chanprint(chan, "playctlproc: %s %lud", fields[0], strtoul(fields[1], nil, 0));
- }
- }
-}
-
-void
-sendplayctl(char *fmt, ...)
-{
- va_list arg;
- static int fd = -1;
-
- va_start(arg, fmt);
- if(debug & DBGPLAY){
- fprint(2, "sendplayctl: fmt=%s: ", fmt);
- fprint(2, fmt, arg);
- fprint(2, "\n");
- }
- fprint(fd, fmt, arg);
- va_end(arg);
-}
-
-void
-setvolume(char *volume)
-{
- static int fd;
-
- if(fd == 0){
- fd = open(playvolfile, OWRITE);
- if(fd < 0){
- fprint(2, "can't open %s, (%r) opening %s instead\n", playvolfile, "/dev/volume");
- if((fd = open("/dev/volume", OWRITE)) < 0){
- fprint(2, "setvolume: open: %r\n");
- return;
- }
- }
- }
- if(fd < 0)
- return;
- fprint(fd, "volume %s", volume);
-}
-
-void
-volumeproc(void *arg)
-{
- int fd, n, nf, nnf, i, nlines;
- static char buf[1024];
- char *lines[32];
- char *fields[8];
- char *subfields[8];
- Channel *ctl;
- int volume, minvolume, maxvolume, nvolume;
-
- ctl = arg;
- threadsetname("volumeproc");
- fd = open(volumefile, OREAD);
- if(fd < 0){
- fprint(2, "%s: %r\n", volumefile);
- threadexits(nil);
- }
- for(;;){
- n = read(fd, buf, sizeof buf -1);
- if(n == 0)
- continue;
- if(n < 0){
- fprint(2, "volumeproc: read: %r\n");
- threadexits("volumeproc");
- }
- buf[n] = '\0';
- nlines = getfields(buf, lines, nelem(lines), 1, "\n");
- for(i = 0; i < nlines; i++){
- nf = tokenize(lines[i], fields, nelem(fields));
- if(nf == 0)
- continue;
- if(nf != 6 || strcmp(fields[0], "volume") || strcmp(fields[1], "out"))
- continue;
- minvolume = strtol(fields[3], nil, 0);
- maxvolume = strtol(fields[4], nil, 0);
- if(minvolume >= maxvolume)
- continue;
- nnf = tokenize(fields[2], subfields, nelem(subfields));
- if(nnf <= 0 || nnf > 8){
- fprint(2, "volume format error\n");
- threadexits(nil);
- }
- volume = 0;
- nvolume = 0;
- for(i = 0; i < nnf; i++){
- volume += strtol(subfields[i], nil, 0);
- nvolume++;
- }
- volume /= nvolume;
- volume = 100*(volume - minvolume)/(maxvolume-minvolume);
- chanprint(ctl, "volume value %d", volume);
- }
- }
-}
-
-void
-playvolproc(void*a)
-{
- int fd, n, nf, volume, nvolume, i;
- static char buf[256+1];
- static errors;
- char *fields[3], *subfields[9];
- Channel *chan;
-
- threadsetname("playvolproc");
- chan = a;
- fd = open(playvolfile, OREAD);
- if(fd < 0)
- sysfatal("%s: %r", playvolfile);
- for(;;){
- n = read(fd, buf, sizeof buf -1);
- if(n == 0)
- continue;
- if(n < 0){
- fprint(2, "%s: %r\n", playvolfile);
- threadexits("playvolproc");
- }
- buf[n] = '\0';
- if(debug) fprint(2, "volumestring: %s\n", buf);
- nf = tokenize(buf, fields, nelem(fields));
- if(nf == 0)
- continue;
- if(nf != 2 || strcmp(fields[0], "volume")){
- fprint(2, "playvolproc: [%d]: %s\n", nf, fields[0]);
- if(errors++ > 32)
- threadexits("playvolproc");
- continue;
- }
- nvolume = tokenize(fields[1], subfields, nelem(subfields));
- if(nvolume <= 0 || nvolume > 8){
- fprint(2, "volume format error\n");
- if(errors++ > 32)
- threadexits("playvolproc");
- continue;
- }
- volume = 0;
- for(i = 0; i < nvolume; i++)
- volume += strtol(subfields[i], nil, 0);
- volume /= nvolume;
- chanprint(chan, "volume value %d", volume);
- }
-}
--- a/sys/src/games/music/jukebox/playlist.h
+++ /dev/null
@@ -1,26 +1,0 @@
-
-typedef struct Playlistentry {
- char *file;
- char *onum;
-} Playlistentry;
-
-typedef struct Playlist {
- QLock;
- int nentries;
- int selected;
- Playlistentry *entry;
-} Playlist;
-
-extern Playlist playlist;
-extern char *playctlfile;
-extern char *srvmount;
-extern int playctlfd;
-
-void playctlproc(void*a);
-void playlistproc(void*);
-void playvolproc(void*a);
-void sendplayctl(char *fmt, ...);
-void sendplaylist(char*, char*);
-void setvolume(char *volume);
-void updateplaylist(int);
-void volumeproc(void *arg);
--- a/sys/src/games/music/jukefs/catset.c
+++ /dev/null
@@ -1,152 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-
-#include "object.h"
-#include "catset.h"
-
-static int debug = 0;
-
-int
-catsetneeded(int v)
-{
- return (v / 8) + 1;
-}
-
-static void
-catsetprint(int f, Catset*cs)
-{
- int i;
- fprint(2, "(%p %d:", cs->bitpiece, cs->nbitpiece);
- for (i = 0; i < cs->nbitpiece; i++)
- fprint(f, "[%d]=%x", i, cs->bitpiece[i]);
- fprint(2, ")");
-}
-
-void
-catsetrealloc(Catset *cs, int sz)
-{
- if (debug) fprint(2, "catsetrealloc %p %d (%p %d)", cs, sz, cs->bitpiece, cs->nbitpiece);
- if (sz > cs->nbitpiece) {
- cs->bitpiece = realloc(cs->bitpiece, sz*sizeof(uchar));
- memset(cs->bitpiece + cs->nbitpiece, 0, sz - cs->nbitpiece);
- cs->nbitpiece = sz;
- }
- if (debug) fprint(2, " -> %p %d\n", cs->bitpiece, cs->nbitpiece);
-}
-
-void
-catsetfree(Catset *cs)
-{
- free(cs->bitpiece);
- cs->bitpiece = 0;
- cs->nbitpiece = 0;
-}
-
-void
-catsetinit(Catset*cs, int v)
-{
- int n;
-
- n = catsetneeded(v);
- if (debug) fprint(2, "catsetinit %p %d -> ", cs, v);
- catsetrealloc(cs, n);
- catsetset(cs, v);
- if (debug) catsetprint(2, cs);
- if (debug) fprint(2, "\n");
-}
-
-void
-catsetcopy(Catset*dst, Catset*src)
-{
- if (debug) fprint(2, "catsetcopy %p %p ", dst, src);
- if (debug) catsetprint(2, dst);
- if (debug) fprint(2, " ");
- if (debug) catsetprint(2, src);
- if (dst->nbitpiece < src->nbitpiece)
- catsetrealloc(dst, src->nbitpiece);
- else
- memset(dst->bitpiece, 0, dst->nbitpiece);
- memcpy(dst->bitpiece, src->bitpiece, src->nbitpiece);
- dst->nbitpiece = src->nbitpiece;
- if (debug) fprint(2, "-> ");
- if (debug) catsetprint(2, dst);
- if (debug) fprint(2, "\n");
-}
-
-void
-catsetset(Catset*cs, int v)
-{
- int p = v / 8;
- int b = v % 8;
- if (debug) fprint(2, "catsetset %p %d ", cs, v);
- if (debug) catsetprint(2, cs);
- cs->bitpiece[p] = 1 << b;
- if (debug) fprint(2, "-> ");
- if (debug) catsetprint(2, cs);
- if (debug) fprint(2, "\n");
-}
-
-int
-catsetisset(Catset*cs)
-{
- int i;
-
- if (debug) fprint(2, "catsetisset %p ", cs);
- if (debug) catsetprint(2, cs);
- if (debug) fprint(2, "\n");
- for (i =0; i < cs->nbitpiece; i++) {
- if (cs->bitpiece[i])
- return 1;
- }
- return 0;
-}
-
-void
-catsetorset(Catset*dst, Catset*src)
-{
- int i;
-
- if (debug) fprint(2, "catsetorset %p %p ", dst, src);
- if (debug) catsetprint(2, dst);
- if (debug) fprint(2, " ");
- if (debug) catsetprint(2, src);
- if (src->nbitpiece > dst->nbitpiece)
- catsetrealloc(dst, src->nbitpiece);
-
- for (i =0; i < src->nbitpiece; i++) {
- dst->bitpiece[i] |= src->bitpiece[i];
- }
- if (debug) fprint(2, "-> ");
- if (debug) catsetprint(2, dst);
- if (debug) fprint(2, "\n");
-}
-
-int
-catseteq(Catset*cs1, Catset*cs2)
-{
- int i;
- Catset *css, * csl;
-
- if (debug) fprint(2, "catseteq %p %p ", cs1, cs2);
- if (debug) catsetprint(2, cs1);
- if (debug) fprint(2, " ");
- if (debug) catsetprint(2, cs2);
- if (debug) fprint(2, "\n");
- if (cs1->nbitpiece > cs2->nbitpiece) {
- csl = cs1;
- css = cs2;
- } else {
- csl = cs2;
- css = cs1;
- }
- for (i =0; i < css->nbitpiece; i++) {
- if (css->bitpiece[i] != csl->bitpiece[i])
- return 0;
- }
- for (i = css->nbitpiece; i < csl->nbitpiece; i++) {
- if (csl->bitpiece[i])
- return 0;
- }
- return 1;
-}
--- a/sys/src/games/music/jukefs/catset.h
+++ /dev/null
@@ -1,8 +1,0 @@
-void catsetrealloc(Catset*, int);
-void catsetinit(Catset*, int);
-void catsetfree(Catset*t);
-void catsetcopy(Catset*, Catset*);
-void catsetset(Catset*, int);
-int catsetisset(Catset*);
-void catsetorset(Catset*, Catset*);
-int catseteq(Catset*, Catset*);
--- a/sys/src/games/music/jukefs/fs.c
+++ /dev/null
@@ -1,747 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include <bio.h>
-#include <fcall.h>
-#include "object.h"
-
-extern int debug;
-
-extern int mfd[];
-
-enum {
- DbgFs = 0x1000
-};
-
-typedef struct Fid Fid;
-
-enum {
- Busy = 0x01,
- Open = 0x02,
- Endf = 0x04,
-};
-
-struct Fid
-{
- QLock;
- Qid qid;
- int fid;
- ushort flags;
- vlong offset; // offset of data[0]
- Fid *next;
-};
-
-Fcall thdr;
-Fcall rhdr;
-
-enum {
- /* Files making up an object */
- Qchildren, /* Each of these must be in dirtab */
- Qdigest,
- Qfiles,
- Qfulltext,
- Qkey,
- Qminiparentage,
- Qparent,
- Qparentage,
- Qtext,
- Qtype,
-
- /* Other files */
- Qtop, /* Must follow Qtype */
- Qclassical,
- Qdir,
- Qroot,
- Qctl,
-};
-
-#define PATH(id, f) (((id)<<8) | (f))
-#define FILE(p) ((p) & 0xff)
-#define NUM(p) ((p) >> 8)
-
-char *dirtab[] =
-{
-[Qchildren] "children",
-[Qdigest] "digest",
-[Qdir] ".",
-[Qfiles] "files",
-[Qfulltext] "fulltext",
-[Qkey] "key",
-[Qminiparentage]"miniparentage",
-[Qparent] "parent",
-[Qparentage] "parentage",
-[Qtext] "text",
-[Qtype] "type",
-[Qtop] nil,
-};
-
-char *rflush(Fid*), *rauth(Fid*),
- *rattach(Fid*), *rwalk(Fid*),
- *ropen(Fid*), *rcreate(Fid*),
- *rread(Fid*), *rwrite(Fid*), *rclunk(Fid*),
- *rremove(Fid*), *rstat(Fid*), *rwstat(Fid*),
- *rversion(Fid*);
-
-char *(*fcalls[])(Fid*) = {
- [Tflush] rflush,
- [Tversion] rversion,
- [Tauth] rauth,
- [Tattach] rattach,
- [Twalk] rwalk,
- [Topen] ropen,
- [Tcreate] rcreate,
- [Tread] rread,
- [Twrite] rwrite,
- [Tclunk] rclunk,
- [Tremove] rremove,
- [Tstat] rstat,
- [Twstat] rwstat,
-};
-
-int messagesize = 8*1024+IOHDRSZ;
-uchar mdata[8*1024+IOHDRSZ];
-uchar mbuf[8*1024+IOHDRSZ];
-char bigbuf[1<<23]; /* 8 megabytes */
-Fid *fids;
-
-char Eperm[] = "permission denied";
-char Enotdir[] = "not a directory";
-char Enoauth[] = "no authentication required";
-char Enotexist[] = "file does not exist";
-char Einuse[] = "file in use";
-char Eexist[] = "file exists";
-char Enotowner[] = "not owner";
-char Eisopen[] = "file already open for I/O";
-char Excl[] = "exclusive use file already open";
-char Ename[] = "illegal name";
-char Ebadctl[] = "unknown control message";
-
-Fid *newfid(int fid);
-
-static int
-lookup(char *cmd, char *list[])
-{
- int i;
-
- for (i = 0; list[i] != nil; i++)
- if (strcmp(cmd, list[i]) == 0)
- return i;
- return -1;
-}
-
-char*
-rversion(Fid *)
-{
- Fid *f;
-
- if(thdr.msize < 256)
- return "max messagesize too small";
- if(thdr.msize < messagesize)
- messagesize = thdr.msize;
- rhdr.msize = messagesize;
- if(strncmp(thdr.version, "9P2000", 6) != 0)
- return "unknown 9P version";
- else
- rhdr.version = "9P2000";
- for(f = fids; f; f = f->next)
- if(f->flags & Busy)
- rclunk(f);
- return nil;
-}
-
-char*
-rauth(Fid*)
-{
- return Enoauth;
-}
-
-char*
-rflush(Fid *)
-{
- return 0;
-}
-
-char*
-rattach(Fid *f)
-{
- f->flags |= Busy;
- f->qid.type = QTDIR;
- f->qid.vers = 0;
- f->qid.path = PATH(0, Qtop);
- rhdr.qid = f->qid;
- return 0;
-}
-
-static Fid*
-doclone(Fid *f, int nfid)
-{
- Fid *nf;
-
- nf = newfid(nfid);
- nf->qid = f->qid;
- if(nf->flags & Busy)
- return nil;
- nf->flags |= Busy;
- nf->flags &= ~Open;
- return nf;
-}
-
-char*
-dowalk(Fid *f, char *name)
-{
- int t, n, m;
- char *rv, *p;
-
- t = FILE(f->qid.path); /* Type */
-
- rv = Enotexist;
-
- if(strcmp(name, ".") == 0 && f->qid.type == QTDIR)
- return nil;
- if(strcmp(name, "..") == 0){
- switch(t){
- case Qtop:
- case Qclassical:
- f->qid.path = PATH(0, Qtop);
- f->qid.type = QTDIR;
- f->qid.vers = 0;
- rv = nil;
- break;
- case Qdir:
- case Qroot:
- f->qid.path = PATH(0, Qclassical);
- f->qid.type = QTDIR;
- f->qid.vers = 0;
- rv = nil;
- break;
- }
- return rv;
- }
- switch(t){
- case Qtop:
- /* Contains classical */
- if(strcmp(name, "juke") == 0){
- f->qid.path = PATH(root->tabno, Qclassical);
- f->qid.type = QTDIR;
- f->qid.vers = 0;
- rv = nil;
- break;
- }
- break;
- case Qclassical:
- /* main dir, contains `root' and object dirs */
- if(strcmp(name, "root") == 0){
- f->qid.path = PATH(root->tabno, Qroot);
- f->qid.type = QTDIR;
- f->qid.vers = 0;
- rv = nil;
- break;
- }
- if(strcmp(name, "ctl") == 0){
- f->qid.path = PATH(root->tabno, Qctl);
- f->qid.type = QTFILE;
- f->qid.vers = 0;
- rv = nil;
- break;
- }
- n = strtol(name, &p, 0);
- if(*p)
- break; /* Not a number */
- if(n < 0 || n >= notab)
- break; /* Outside range */
- if(otab[n] == nil)
- break; /* Not in object table */
- f->qid.path = PATH(n, Qdir);
- f->qid.type = QTDIR;
- f->qid.vers = 0;
- rv = nil;
- break;
- case Qroot: /* Root of the object hierarchy */
- case Qdir: /* Object directory */
- if((m = lookup(name, dirtab)) < 0)
- break;
- n = NUM(f->qid.path);
- f->qid.path = PATH(n, m);
- f->qid.type = QTFILE;
- f->qid.vers = 0;
- rv = nil;
- break;
- }
- return rv;
-}
-
-char*
-rwalk(Fid *f)
-{
- Fid *nf;
- char *rv;
- int i;
-
- if(f->flags & Open)
- return Eisopen;
-
- rhdr.nwqid = 0;
- nf = nil;
-
- /* clone if requested */
- if(thdr.newfid != thdr.fid){
- nf = doclone(f, thdr.newfid);
- if(nf == nil)
- return "new fid in use";
- f = nf;
- }
-
- /* if it's just a clone, return */
- if(thdr.nwname == 0 && nf != nil)
- return nil;
-
- /* walk each element */
- rv = nil;
- for(i = 0; i < thdr.nwname; i++){
- rv = dowalk(f, thdr.wname[i]);
- if(rv != nil){
- if(nf != nil)
- rclunk(nf);
- break;
- }
- rhdr.wqid[i] = f->qid;
- }
- rhdr.nwqid = i;
-
- /* we only error out if no walk */
- if(i > 0)
- rv = nil;
-
- return rv;
-}
-
-char *
-ropen(Fid *f)
-{
- if(f->flags & Open)
- return Eisopen;
-
- if(thdr.mode != OREAD && FILE(f->qid.path) != Qctl)
- return Eperm;
- rhdr.iounit = 0;
- rhdr.qid = f->qid;
- f->flags |= Open;
- f->flags &= ~Endf;
- return nil;
-}
-
-char *
-rcreate(Fid*)
-{
- return Eperm;
-}
-
-static long
-fileinfo(char *buf, int bufsize, int onum, int t)
-{
- long n;
-
- n = 0;
- switch(t){
- case Qchildren:
- n = printchildren(buf, bufsize, otab[onum]);
- break;
- case Qdigest:
- n = printdigest(buf, bufsize, otab[onum]);
- break;
- case Qfulltext:
- n = printfulltext(buf, bufsize, otab[onum]);
- break;
- case Qkey:
- n = printkey(buf, bufsize, otab[onum]);
- break;
- case Qparent:
- n = printparent(buf, bufsize, otab[onum]);
- break;
- case Qtext:
- n = printtext(buf, bufsize, otab[onum]);
- break;
- case Qtype:
- n = printtype(buf, bufsize, otab[onum]);
- break;
- case Qfiles:
- n = printfiles(buf, bufsize, otab[onum]);
- break;
- case Qparentage:
- n = printparentage(buf, bufsize, otab[onum]);
- break;
- case Qminiparentage:
- n = printminiparentage(buf, bufsize, otab[onum]);
- break;
- default:
- sysfatal("rread: %d", t);
- }
- return n;
-}
-
-static void
-mkstat(Dir *d, int n, int t)
-{
- static char buf[16];
-
- d->uid = user;
- d->gid = user;
- d->muid = user;
- d->qid.vers = 0;
- d->qid.type = QTFILE;
- d->type = 0;
- d->dev = 0;
- d->atime = time(0);
- d->mtime = d->atime;
- switch(t){
- case Qtop:
- d->name = ".";
- d->mode = DMDIR|0555;
- d->atime = d->mtime = time(0);
- d->length = 0;
- d->qid.path = PATH(0, Qtop);
- d->qid.type = QTDIR;
- break;
- case Qclassical:
- d->name = "juke";
- d->mode = DMDIR|0555;
- d->atime = d->mtime = time(0);
- d->length = 0;
- d->qid.path = PATH(0, Qclassical);
- d->qid.type = QTDIR;
- break;
- case Qdir:
- snprint(buf, sizeof buf, "%d", n);
- d->name = buf;
- d->mode = DMDIR|0555;
- d->length = 0;
- d->qid.path = PATH(n, Qdir);
- d->qid.type = QTDIR;
- break;
- case Qroot:
- d->name = "root";
- d->mode = DMDIR|0555;
- d->length = 0;
- d->qid.path = PATH(0, Qroot);
- d->qid.type = QTDIR;
- break;
- case Qctl:
- d->name = "ctl";
- d->mode = 0666;
- d->length = 0;
- d->qid.path = PATH(0, Qctl);
- break;
- d->name = "ctl";
- d->mode = 0666;
- d->length = 0;
- d->qid.path = PATH(0, Qctl);
- break;
- case Qchildren:
- case Qdigest:
- case Qfiles:
- case Qfulltext:
- case Qkey:
- case Qminiparentage:
- case Qparent:
- case Qparentage:
- case Qtext:
- case Qtype:
- d->name = dirtab[t];
- d->mode = 0444;
- d->length = fileinfo(bigbuf, sizeof bigbuf, n, t);
- d->qid.path = PATH(n, t);
- break;
- default:
- sysfatal("mkstat: %d", t);
- }
-}
-
-int
-readtopdir(Fid*, uchar *buf, long off, int cnt, int blen)
-{
- int m, n;
- Dir d;
-
- n = 0;
- mkstat(&d, 0, Qclassical);
- m = convD2M(&d, &buf[n], blen);
- if(off <= 0){
- if(m <= BIT16SZ || m > cnt)
- return n;
- n += m;
- }
- return n;
-}
-
-int
-readclasdir(Fid*, uchar *buf, long off, int cnt, int blen)
-{
- int m, n;
- long pos;
- Dir d;
- Fid *fid;
-
- n = 0;
- pos = 0;
- mkstat(&d, 0, Qctl);
- m = convD2M(&d, &buf[n], blen);
- if(off <= pos){
- if(m <= BIT16SZ || m > cnt)
- return 0;
- n += m;
- cnt -= m;
- }
- pos += m;
- mkstat(&d, 0, Qroot);
- m = convD2M(&d, &buf[n], blen);
- if(off <= pos){
- if(m <= BIT16SZ || m > cnt)
- return n;
- n += m;
- cnt -= m;
- }
- pos += m;
- for (fid = fids; fid; fid = fid->next){
- if(FILE(fid->qid.path) != Qdir)
- continue;
- mkstat(&d, NUM(fid->qid.path), Qdir);
- m = convD2M(&d, &buf[n], blen-n);
- if(off <= pos){
- if(m <= BIT16SZ || m > cnt)
- break;
- n += m;
- cnt -= m;
- }
- pos += m;
- }
- return n;
-}
-
-int
-readdir(Fid *f, uchar *buf, long off, int cnt, int blen)
-{
- int i, m, n;
- long pos;
- Dir d;
-
- n = 0;
- pos = 0;
- for (i = 0; i < Qtop; i++){
- mkstat(&d, NUM(f->qid.path), i);
- m = convD2M(&d, &buf[n], blen-n);
- if(off <= pos){
- if(m <= BIT16SZ || m > cnt)
- break;
- n += m;
- cnt -= m;
- }
- pos += m;
- }
- return n;
-}
-
-void
-readbuf(char *s, long n)
-{
- rhdr.count = thdr.count;
- if(thdr.offset >= n){
- rhdr.count = 0;
- return;
- }
- if(thdr.offset+rhdr.count > n)
- rhdr.count = n - thdr.offset;
- rhdr.data = s + thdr.offset;
-}
-
-char*
-rread(Fid *f)
-{
- long off;
- int n, cnt, t;
-
- rhdr.count = 0;
- off = thdr.offset;
- cnt = thdr.count;
-
- if(cnt > messagesize - IOHDRSZ)
- cnt = messagesize - IOHDRSZ;
-
- rhdr.data = (char*)mbuf;
-
- n = 0;
- t = FILE(f->qid.path);
- switch(t){
- case Qtop:
- n = readtopdir(f, mbuf, off, cnt, messagesize - IOHDRSZ);
- rhdr.count = n;
- return nil;
- case Qclassical:
- n = readclasdir(f, mbuf, off, cnt, messagesize - IOHDRSZ);
- rhdr.count = n;
- return nil;
- case Qdir:
- case Qroot:
- n = readdir(f, mbuf, off, cnt, messagesize - IOHDRSZ);
- rhdr.count = n;
- return nil;
- case Qctl:
- snprint(bigbuf, sizeof bigbuf, "%d objects in tree (%d holes)\n", notab, hotab);
- break;
- case Qchildren:
- case Qdigest:
- case Qfiles:
- case Qfulltext:
- case Qkey:
- case Qminiparentage:
- case Qparent:
- case Qparentage:
- case Qtext:
- case Qtype:
- n = fileinfo(bigbuf, sizeof bigbuf, NUM(f->qid.path), t);
- break;
- default:
- sysfatal("rread: %d", t);
- }
- readbuf(bigbuf, n);
- return nil;
-}
-
-char*
-rwrite(Fid *f)
-{
- long cnt;
- char *p;
-
- if(FILE(f->qid.path) != Qctl)
- return Eperm;
- rhdr.count = 0;
- cnt = thdr.count;
- if(p = strchr(thdr.data, '\n'))
- *p = '\0';
- if(strncmp(thdr.data, "quit", cnt) == 0)
- threadexitsall(nil);
- else if(strncmp(thdr.data, "reread", cnt) == 0)
- reread();
- else
- return "illegal command";
- rhdr.count = thdr.count;
- return nil;
-}
-
-char *
-rclunk(Fid *f)
-{
- f->flags &= ~(Open|Busy);
- return 0;
-}
-
-char *
-rremove(Fid *)
-{
- return Eperm;
-}
-
-char *
-rstat(Fid *f)
-{
- Dir d;
-
- mkstat(&d, NUM(f->qid.path), FILE(f->qid.path));
- rhdr.nstat = convD2M(&d, mbuf, messagesize - IOHDRSZ);
- rhdr.stat = mbuf;
- return 0;
-}
-
-char *
-rwstat(Fid*)
-{
- return Eperm;
-}
-
-Fid *
-newfid(int fid)
-{
- Fid *f, *ff;
-
- ff = nil;
- for(f = fids; f; f = f->next)
- if(f->fid == fid){
- return f;
- }else if(ff == nil && (f->flags & Busy) == 0)
- ff = f;
- if(ff == nil){
- ff = malloc(sizeof *ff);
- if (ff == nil)
- sysfatal("malloc: %r");
- memset(ff, 0, sizeof *ff);
- ff->next = fids;
- fids = ff;
- }
- ff->fid = fid;
- return ff;
-}
-
-void
-io(void *)
-{
- char *err;
- int n;
- extern int p[];
- Fid *f;
-
- threadsetname("file server");
- close(p[1]);
- while((n = read9pmsg(mfd[0], mdata, messagesize)) != 0){
- if(n < 0){
- char e[32];
- rerrstr(e, sizeof e);
- if (strcmp(e, "interrupted") == 0){
- if (debug & DbgFs) fprint(2, "read9pmsg interrupted\n");
- continue;
- }
- sysfatal("mount read: %s", e);
- }
- if(convM2S(mdata, n, &thdr) != n)
- sysfatal("convM2S format error: %r");
-
- if(debug & DbgFs)
- fprint(2, "io:<-%F\n", &thdr);
-
- rhdr.data = (char*)mbuf;
-
- if(!fcalls[thdr.type])
- err = "bad fcall type";
- else {
- f = newfid(thdr.fid);
- err = (*fcalls[thdr.type])(f);
- }
- if(err){
- rhdr.type = Rerror;
- rhdr.ename = err;
- }else{
- rhdr.type = thdr.type + 1;
- rhdr.fid = thdr.fid;
- }
- rhdr.tag = thdr.tag;
- if(debug & DbgFs)
- fprint(2, "io:->%F\n", &rhdr);/**/
- n = convS2M(&rhdr, mdata, messagesize);
- if(write(mfd[1], mdata, n) != n)
- sysfatal("mount write");
- }
- threadexitsall("die yankee pig dog");
-}
-
-int
-newid(void)
-{
- int rv;
- static int id;
- static Lock idlock;
-
- lock(&idlock);
- rv = ++id;
- unlock(&idlock);
-
- return rv;
-}
--- a/sys/src/games/music/jukefs/mk.dep
+++ /dev/null
@@ -1,6 +1,0 @@
-catset.$O: /$objtype/include/u.h /sys/include/libc.h /sys/include/bio.h object.h catset.h
-fs.$O: /$objtype/include/u.h /sys/include/libc.h /sys/include/thread.h /sys/include/bio.h /sys/include/fcall.h object.h
-parse.$O: /$objtype/include/u.h /sys/include/libc.h /sys/include/thread.h /sys/include/bio.h /sys/include/ctype.h object.h catset.h parse.h
-print.$O: /$objtype/include/u.h /sys/include/libc.h /sys/include/ctype.h /sys/include/bio.h /sys/include/thread.h object.h parse.h catset.h
-search.$O: /$objtype/include/u.h /sys/include/libc.h /sys/include/bio.h /sys/include/thread.h object.h parse.h search.h
-server.$O: /$objtype/include/u.h /sys/include/libc.h /sys/include/thread.h /sys/include/bio.h /sys/include/fcall.h object.h parse.h print.h catset.h
--- a/sys/src/games/music/jukefs/mkfile
+++ /dev/null
@@ -1,18 +1,0 @@
-</$objtype/mkfile
-<../mkinc
-
-CFLAGS = -DDEFAULTMAP="/sys/lib/music/map"
-TARG = jukefs
-BIN = /$objtype/bin/games
-
-CFILES=\
- catset.c\
- fs.c\
- parse.c\
- print.c\
- search.c\
- server.c\
-
-OFILES = ${CFILES:%.c=%.$O}
-
-</sys/src/cmd/mkone
--- a/sys/src/games/music/jukefs/object.h
+++ /dev/null
@@ -1,117 +1,0 @@
-/* Keywords */
-
-typedef enum {
- Category,
- Cddata,
- Cmd,
- File,
- Include,
- Key,
- Lyrics,
- Part,
- Path,
- Performance,
- Recording,
- Root,
- Search,
- Soloists,
- Time,
- Track,
- Work,
- Ntoken, /* Initializer for ntoken */
- Eof = -1,
- Txt = -2,
- BraceO = -3,
- BraceC = -4,
- Equals = -5,
- Newcat = -6,
-} Type;
-
-typedef struct Object Object;
-typedef struct Catset Catset;
-typedef struct Token Token;
-typedef struct Cmdlist Cmdlist;
-
-/* Token-only types */
-
-typedef enum {
- Obj,
- Cat,
-} Kind;
-
-struct Catset {
- uchar *bitpiece; /* mallocated */
- int nbitpiece;
-};
-
-
-struct Token {
- char *name;
- Kind kind;
- long value;
- char *kname;
- Catset categories;
-};
-
-typedef enum {
- Hierarchy,
- Typelist,
- Nlisttype,
-} Listtype;
-
-struct Cmdlist {
- int flag;
- char *name;
-};
-
-#define KEYLEN 128
-
-struct Object {
- Type type;
- int tabno; /* entry in object table */
- Object *parent;
- Object **children; /* mallocated */
- Object **catparents;
- Object *orig; /* back pointer from search object */
- int nchildren;
- int ncatparents;
- Catset categories; /* was int */
- int flags;
- int num; /* for enumerations */
- char *value; /* mallocated */
- char key[KEYLEN];
- char *path; /* mallocated */
-};
-
-#define Sort 0x01
-#define Enum 0x02
-#define Hier 0x04
-#define Elab 0x10 /* elaborated rune string */
-
-extern Token *tokenlist;
-extern int ncat;
-extern Object **catobjects;
-extern Biobuf *f;
-extern char *file;
-extern Object *root;
-extern int ntoken;
-
-extern Object **otab; // object table
-extern int notab; // no of entries used
-extern int sotab; // no of entries mallocated
-extern int hotab; // no of holes in tab
-extern char *user;
-
-void io(void *);
-long printchildren(char*, int, Object*);
-long printdigest(char*, int, Object*);
-long printfiles(char*, int, Object*);
-long printfulltext(char*, int, Object*);
-long printkey(char*, int, Object*);
-long printminiparentage(char*, int, Object*);
-long printparent(char*, int, Object*);
-long printparentage(char*, int, Object*);
-long printtext(char*, int, Object*);
-long printtype(char*, int, Object*);
-void reread(void);
-void listfiles(Object *o);
--- a/sys/src/games/music/jukefs/parse.c
+++ /dev/null
@@ -1,616 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include <bio.h>
-#include <ctype.h>
-#include "object.h"
-#include "catset.h"
-#include "parse.h"
-
-#define MAXTOKEN 1024
-
-Biobuf *f;
-static int str;
-char *file;
-
-Token tokenlistinit[] = {
- { "category", Obj, Category , "music" , {nil,0}},
- { "cddata", Obj, Cddata , nil , {nil,0}},
- { "command", Obj, Cmd , nil , {nil,0}},
- { "file", Obj, File , "file" , {nil,0}},
- { "include", Obj, Include , nil , {nil,0}},
- { "key", Obj, Key , nil , {nil,0}},
- { "lyrics", Obj, Lyrics , "lyrics" , {nil,0}},
- { "part", Obj, Part , "title" , {nil,0}},
- { "path", Obj, Path , nil , {nil,0}},
- { "performance",Obj, Performance , "artist" , {nil,0}},
- { "recording", Obj, Recording , "title" , {nil,0}},
- { "root", Obj, Root , nil , {nil,0}},
- { "search", Obj, Search , nil , {nil,0}},
- { "soloists", Obj, Soloists , "artist" , {nil,0}},
- { "time", Obj, Time , "time" , {nil,0}},
- { "track", Obj, Track , "title" , {nil,0}},
- { "work", Obj, Work , "title" , {nil,0}},
-};
-Token *tokenlist;
-int ntoken = nelem(tokenlistinit);
-int catnr = 0;
-
-Cmdlist cmdlist[] = {
- { Sort, "sort" },
- { Enum, "number" },
- { 0x00, 0 },
-};
-
-static char *curtext;
-
-void
-inittokenlist(void)
-{
- int i;
-
- ntoken = nelem(tokenlistinit);
- tokenlist = malloc(sizeof(tokenlistinit));
- memmove(tokenlist, tokenlistinit, sizeof(tokenlistinit));
- for(i = 0; i< ntoken; i++){
- tokenlist[i].name = strdup(tokenlist[i].name);
- catsetinit(&tokenlist[i].categories, tokenlist[i].value);
- }
- curtext = smprint("{");
-}
-
-Type
-gettoken(char *token)
-{
- char *p, *q;
- int i, n;
- Token *t;
-
- for(;;){
- if(curtext){
- p = &curtext[strspn(curtext, " \t")];
- if(*p && *p != '\n')
- break;
- }
- do {
- str++;
- free(curtext);
- if((curtext = Brdstr(f, '\n', 0)) == nil)
- return Eof;
- } while(curtext[0] == '#');
- }
- if(*p == '{'){
- *token++ = *p;
- *token = 0;
- *p = ' ';
- return BraceO;
- }
- if(*p == '}'){
- *token++ = *p;
- *token = 0;
- *p = ' ';
- return BraceC;
- }
- if(*p == '='){
- *token++ = *p;
- *token = 0;
- *p = ' ';
- return Equals;
- }
- t = nil;
- n = 0;
- for(i = 0; i < ntoken; i++){
- t = &tokenlist[i];
- if(strncmp(p, t->name, n=strlen(t->name)) == 0){
- q = &p[n];
- if(isalnum(*q) || *q == '-') continue;
- q += strspn(q, " \t");
- if(t->kind == Obj && *q == '{')
- break;
- if(t->kind == Cat && *q == '=')
- break;
- }
- }
- if(i < ntoken){
- strcpy(token, t->name);
- memset(p, ' ', n);
- return i;
- }
- assert(strlen(token) < MAXTOKEN);
- if(strchr(p, '{'))
- sysfatal("Illegal keyword or parse error: %s", p);
- if((q = strchr(p, '='))){
- if(q == p) goto tx;
- *q = 0;
- strcpy(token, p);
- assert(strlen(token) < MAXTOKEN);
- memset(p, ' ', q-p);
- *q = '=';
- for(q = token; *q; q++)
- if(!isalnum(*q) && !isspace(*q)) break;
- if(*q) return Txt;
- while(isspace(*--q)) *q = 0;
- return Newcat;
- }
-tx: if((q = strchr(p, '}'))){
- *q = 0;
- strcpy(token, p);
- assert(strlen(token) < MAXTOKEN);
- memset(p, ' ', q-p);
- *q = '}';
- return Txt;
- }
- strcpy(token, p);
- assert(strlen(token) < MAXTOKEN);
- free(curtext);
- curtext = nil;
- return Txt;
-}
-
-Object *
-getobject(Type t, Object *parent)
-{
- char *token;
- char *textbuf;
- char *tp, *p, *q;
- int i;
- Object *o, *oo, *child;
- Token *ot;
- Type nt;
-
- token = malloc(MAXTOKEN);
- textbuf = malloc(8192);
-
- tp = textbuf;
- o = newobject(t, parent);
- o->flags |= Hier;
- if(parent == nil){
- root = o;
- o->path = strdup(startdir);
- setmalloctag(o->path, 0x100001);
- }
- if(gettoken(token) != BraceO)
- sysfatal("Parse error: no brace, str %d", str);
- for(;;){
- t = gettoken(token);
- if(t >= 0)
- switch(tokenlist[t].kind){
- case Obj:
- switch(t){
- case Key:
- case Cmd:
- case Path:
- if(getobject(t, o) != nil)
- sysfatal("Non-null child?");
- break;
- case Include:
- case Category:
- child = getobject(t, o);
- if(child) addchild(o, child, "case Category");
- break;
- default:
- /* subobject */
- child = getobject(t, o);
- if(child == nil)
- sysfatal("Null child?");
- addchild(o, child, "default");
- break;
- }
- break;
- case Cat:
- catcase: nt = gettoken(token);
- if(nt != Equals)
- sysfatal("Expected Equals, not %s", token);
- nt = gettoken(token);
- if(nt != Txt)
- sysfatal("Expected Text, not %s", token);
- if((p = strchr(token, '\n'))) *p = 0;
- p = token;
- if(o->type == Category){
- if(catsetisset(&o->categories)){
- fprint(2, "Category object must have one category\n");
- }
- catsetcopy(&o->categories, &tokenlist[t].categories);
- strncpy(o->key, p, KEYLEN);
- if(catobjects[t] == 0)
- sysfatal("Class %s not yet defined", tokenlist[t].name);
- for(i = 0; i < catobjects[t]->nchildren; i++)
- if(strcmp(catobjects[t]->children[i]->key, p) == 0)
- break;
- if(i == catobjects[t]->nchildren){
- /* It's a new key for the category */
- addchild(catobjects[t], o, "new key for cat");
- }else{
- /* Key already existed */
- oo = catobjects[t]->children[i];
- if(oo->value)
- sysfatal("Duplicate category object for %s", oo->value);
- catobjects[t]->children[i] = o;
- if(oo->nchildren){
- for(i = 0; i < oo->nchildren; i++){
- if(oo->children[i]->parent == oo)
- oo->children[i]->parent = o;
- addchild(o, oo->children[i], "key already existed");
- }
- }
- freeobject(oo, "a");
- }
- o->parent = catobjects[t];
- }else{
- catsetorset(&o->categories, &tokenlist[t].categories);
- for(i = 0; i < catobjects[t]->nchildren; i++)
- if(strcmp(catobjects[t]->children[i]->key, p) == 0)
- break;
- if(i == catobjects[t]->nchildren){
- oo = newobject(Category, catobjects[t]);
-/*
- oo->value = strdup(token);
-*/
- strncpy(oo->key, p, KEYLEN);
- catsetcopy(&oo->categories, &tokenlist[t].categories);
- addchild(catobjects[t], oo, "catobjects[t],oo");
- }
- addchild(catobjects[t]->children[i], o, "children[i]");
- }
- break;
- }
- else
- switch(t){
- case Eof:
- if(o->type == Root){
- free(token);
- free(textbuf);
- return o;
- }
- sysfatal("Unexpected Eof in %s, file %s", tokenlist[o->type].name, file);
- case Newcat:
- /* New category, make an entry in the tokenlist */
- tokenlist = realloc(tokenlist, (ntoken+1)*sizeof(Token));
- ot = &tokenlist[ntoken];
- ot->name = strdup(token);
- setmalloctag(ot->name, 0x100002);
- ot->kind = Cat;
- ot->value = -1;
- memset(&ot->categories, 0, sizeof(Catset));
- catsetinit(&ot->categories, catnr++);
- /* And make an entry in the catobjects table */
- if(ncat <= ntoken){
- catobjects = realloc(catobjects, (ntoken+1)*sizeof(Object*));
- while(ncat <= ntoken) catobjects[ncat++] = nil;
- }
- if(catobjects[ntoken] != nil)
- sysfatal("Class %s already defined in %s:%d", token, file, str);
- if(0) fprint(2, "newcat: token %s catnr %d ntoken %d ncat %d\n",
- token, catnr, ntoken, ncat);
- catobjects[ntoken] = newobject(Category, root);
- if(o->type == Category)
- catobjects[ntoken]->flags = o->flags&Hier;
- catobjects[ntoken]->flags |= Sort;
- strncpy(catobjects[ntoken]->key, token, KEYLEN);
- catsetcopy(&catobjects[ntoken]->categories, &ot->categories);
- addchild(root, catobjects[ntoken], "root");
- t = ntoken;
- ntoken++;
- goto catcase;
- case Txt:
- strcpy(tp, token);
- tp += strlen(token);
- break;
- case BraceC:
- while(tp > textbuf && tp[-1] == '\n') *--tp = 0;
- if((o->type == File || o->type == Include) && o->path){
- o->value = smprint("%s/%s", o->path, textbuf);
- }else if(tp > textbuf){
- o->value = strdup(textbuf);
- setmalloctag(o->value, 0x100003);
- }
- switch(o->type){
- case Cmd:
- q = strtok(o->value, " \t,;\n");
- while(q){
- if(*q) for(i = 0; cmdlist[i].name; i++){
- if(strcmp(q, cmdlist[i].name) == 0){
- o->parent->flags |= cmdlist[i].flag;
- break;
- }
- if(cmdlist[i].name == 0)
- fprint(2, "Unknown command: %s\n", q);
- }
- q = strtok(nil, " \t,;\n");
- }
- freeobject(o, "b");
- free(token);
- free(textbuf);
- return nil;
- case Path:
- p = o->value;
- free(o->parent->path);
- if(p[0] == '/' || o->path == nil){
- o->parent->path = strdup(p);
- setmalloctag(o->parent->path, 0x100004);
- }else{
- o->parent->path = smprint("%s/%s", o->path, p);
- setmalloctag(o->parent->path, 0x100005);
- }
- freeobject(o, "b");
- free(token);
- free(textbuf);
- return nil;
- case Include:
- free(token);
- free(textbuf);
- return getinclude(o);
- case Category:
- /*
- if(o->nchildren) break;
- */
- free(token);
- free(textbuf);
- return nil;
- case Key:
- strncpy(o->parent->key, o->value, KEYLEN);
- freeobject(o, "d");
- free(token);
- free(textbuf);
- return nil;
- default:
- break;
- }
- free(token);
- free(textbuf);
- return o;
- default:
- fprint(2, "Unexpected token: %s\n", token);
- free(token);
- free(textbuf);
- return nil;
- }
- }
-}
-
-Object *
-getinclude(Object *o)
-{
- char *savetext;
- Biobuf *savef = f;
- char *savefile, fname[256];
- Object *oo;
- int savestr = str;
- char token[MAXTOKEN], *dirname, *filename;
- Type t;
-
- str = 0;
- if(curtext){
- savetext = strdup(curtext);
- setmalloctag(savetext, 0x100006);
- }else
- savetext = nil;
- if((f = Bopen(o->value, OREAD)) == nil)
- sysfatal("getinclude: %s: %r", o->value);
- savefile = file;
- file = strdup(o->value);
- strncpy(fname, o->value, 256);
- if((filename = strrchr(fname, '/'))){
- *filename = 0;
- dirname = fname;
- filename++;
- }else{
- dirname = "";
- filename = fname;
- }
- while((t = gettoken(token)) != Eof){
- if(t < 0){
- if(*dirname)
- sysfatal("Bad include file %s/%s, token %s, str %d",
- dirname, filename, token, str);
- else
- sysfatal("Bad include file %s, token %s, str %d",
- filename, token, str);
- }
- free(o->path);
- o->path = strdup(dirname);
- setmalloctag(o->path, 0x100007);
- oo = getobject(t, o->parent);
- if(oo) addchild(o->parent, oo, "o->parent, oo");
- }
- freeobject(o, "e");
- free(curtext);
- curtext = nil;
- if(savetext)
- curtext = savetext;
- free(file);
- file = savefile;
- str = savestr;
- Bterm(f);
- f = savef;
- return nil;
-}
-
-void
-addchild(Object *parent, Object *child, char *where)
-{
- int i;
-
- /* First check if child's already been added
- * This saves checking elsewhere
- */
- for(i = 0; i < parent->nchildren; i++)
- if(parent->children[i] == child) return;
- parent->children = realloc(parent->children, (i+1)*sizeof(Object*));
- parent->children[i] = child;
- parent->nchildren++;
- if(parent->type == Category && child->type == Category)
- return;
- if(parent->type == Work && child->type == Work)
- return;
- if(parent->type == Work && child->type == Track)
- return;
- if(parent->type == Track && child->type == File)
- return;
- if(child->parent == child)
- return;
- if(parent->type == Root)
- return;
- if(parent->parent->type == Root)
- return;
-// addcatparent(parent, child);
- i = child->ncatparents;
- if(0) fprint(2, "addcatparent %s parent %d type %d child %d type %d\n",where,
- parent->tabno, parent->type, child->tabno, child->type);
- child->catparents = realloc(child->catparents, (i+1)*sizeof(Object*));
- child->catparents[i] = parent;
- child->ncatparents++;
-}
-
-void
-addcatparent(Object *parent, Object *child)
-{
- int i;
-
- /* First check if child's already been added
- * This saves checking elsewhere
- */
- if(child->parent == child)
- return;
-// for(i = 0; i < child->ncatparents; i++)
-// if(child->catparents[i] == parent) return;
- i = child->ncatparents;
- fprint(2, "addcatparent parent %d child %d\n", parent->tabno, child->tabno);
- child->catparents = realloc(child->catparents, (i+1)*sizeof(Object*));
- child->catparents[i] = parent;
- child->ncatparents++;
-}
-
-void
-sortprep(char *out, int n, Object *o)
-{
- char *p, *q;
-
- if(*o->key)
- q = o->key;
- else if (o->value)
- q = o->value;
- else
- q = "";
- if(p = strchr(q, '~'))
- p++;
- else
- p = q;
- for(q = out; *p && q < out+n-1; q++)
- *q = tolower(*p++);
- *q = 0;
-}
-
-void
-childsort(Object *o)
-{
- Object *oo;
- int i, j, n;
- char si[256], sj[256];
- /* sort the kids by key or by value */
-
- n = o->nchildren;
- if(n > 1){
- for(i = 0; i < n-1; i++){
- sortprep(si, nelem(si), o->children[i]);
- for(j = i+1; j < n; j++){
- sortprep(sj, nelem(sj), o->children[j]);
- if(strncmp(si, sj, sizeof(si)) > 0){
- oo = o->children[i];
- o->children[i] = o->children[j];
- o->children[j] = oo;
- strncpy(si, sj, sizeof(si));
- }
- }
- }
- }
-}
-
-void
-childenum(Object *o){
- Object *oo;
- int i, n = 1;
-
- for(i = 0; i < o->nchildren; i++){
- oo = o->children[i];
- if(tokenlist[oo->type].kind == Cat)
- oo->num = n++;
- else
- switch(oo->type){
- case Category:
- case Part:
- case Recording:
- case Track:
- case Work:
- oo->num = n++;
- default:
- break;
- }
- }
-}
-
-Object *
-newobject(Type t, Object *parent){
- Object *o;
- int tabno;
-
- if(hotab){
- for(tabno = 0; tabno < notab; tabno++)
- if(otab[tabno] == nil)
- break;
- if(tabno == notab)
- sysfatal("lost my hole");
- hotab--;
- }else{
- if(sotab < notab+1){
- sotab += 512;
- otab = realloc(otab, sizeof(Object*)*sotab);
- if(otab == nil)
- sysfatal("realloc: %r");
- }
- tabno = notab++;
- }
- o = mallocz(sizeof(Object), 1);
- o->tabno = tabno;
- otab[tabno] = o;
- o->type = t;
- o->parent = parent;
- if(parent && parent->path){
- o->path = strdup(parent->path);
- setmalloctag(o->path, 0x100008);
- }
- return o;
-}
-
-void
-freeobject(Object *o, char*){
-
- free(o->children);
- if(o->orig == nil)
- free(o->value);
- free(o->path);
- free(o->catparents);
- catsetfree(&o->categories);
- otab[o->tabno] = nil;
- hotab++;
- free(o);
-}
-
-void
-freetree(Object *o)
-{
- int i;
-
- for(i = 0; i < o->nchildren; i++)
- if(o->children[i]->parent == o)
- freetree(o->children[i]);
- free(o->children);
- if(o->orig == nil)
- free(o->value);
- free(o->path);
- free(o->catparents);
- catsetfree(&o->categories);
- otab[o->tabno] = nil;
- hotab++;
- free(o);
-}
--- a/sys/src/games/music/jukefs/parse.h
+++ /dev/null
@@ -1,15 +1,0 @@
-Object *getobject(Type, Object *);
-Object *getinclude(Object *);
-void childsort(Object *);
-void childenum(Object *);
-Object *newobject(Type, Object *);
-void freeobject(Object *, char *);
-void freetree(Object *);
-void *mymalloc(void *old, int size);
-void addchild(Object *, Object *, char*);
-void addcatparent(Object *, Object *);
-void inittokenlist(void);
-void initparse(void);
-void exit(int);
-
-extern char *startdir;
--- a/sys/src/games/music/jukefs/print.c
+++ /dev/null
@@ -1,489 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <ctype.h>
-#include <bio.h>
-#include <thread.h>
-#include "object.h"
-#include "parse.h"
-#include "catset.h"
-
-int fflag;
-
-void
-listfiles(Object *o)
-{
- int i;
-
- if(o->type == File){
- print("%s\n", o->value);
- return;
- }
- for(i = 0; i < o->nchildren; i++)
- if(o->children[i]->parent == o)
- listfiles(o->children[i]);
-}
-
-int
-indent(char *lp, int ln, int n, char *buf) {
- int sln;
- char *p, c;
-
- sln = ln;
- if (ln <= 0)
- return 0;
- if (n < 0)
- n = -n;
- else {
- if (ln < 4*n)
- goto out;
- memset(lp, ' ', 4*n);
- lp += 4*n;
- ln -= 4*n;
- }
- if(p = buf) while (ln > 1) {
- c = *p++;
- if(c == '\0')
- break;
- if(c == '~')
- continue;
- *lp++ = c;
- ln--;
- if (c == '\n' && p[1]) {
- if (ln < 4*n)
- break;
- memset(lp, ' ', 4*n);
- lp += 4*n;
- ln -= 4*n;
- }
- }
- *lp = '\0';
-out:
- return sln - ln;
-}
-
-long
-printchildren(char *lp, int ln, Object *o) {
- int i, r;
- char *sp;
-
- sp = lp;
- if (o->flags & Sort) {
- childsort(o);
- o->flags &= ~Sort;
- }
- for(i = 0; i < o->nchildren && ln > 0; i++){
- r = snprint(lp, ln, "%d\n", o->children[i]->tabno);
- lp += r;
- ln -= r;
- }
- return lp - sp;
-}
-
-long
-printminiparentage(char *lp, int ln, Object *o) {
- char *p, c;
- int r, sln;
-
- if (ln <= 0) return 0;
- *lp = '\0';
- if (o == 0 || o->type == Root)
- return 0;
- sln = ln;
- if(o->orig) o = o->orig;
- r = printminiparentage(lp, ln, o->parent);
- lp += r;
- ln -= r;
- if (ln <= 0) return 0;
- if(o->value && o->type != File){
- if(r && o->value && ln > 1){
- *lp++ = '/';
- ln--;
- }
- p = o->value;
- while(ln > 0){
- c = *p++;
- if(c == '\n' || c == '\0')
- break;
- if(c == '~')
- continue;
- *lp++ = c;
- ln--;
- }
- }
- if(ln > 0)
- *lp = '\0';
- return sln - ln;
-}
-
-long
-printparentage(char *lp, int ln, Object *o) {
- int i;
- int r, k, sln;
-
- if(ln <= 0)
- return 0;
- *lp = '\0';
- if(o == 0 || o->type == Root)
- return 0;
- if(0)fprint(2, "parentage 0x%p %d type %d value 0x%p parent 0x%p %d\n", o, o->tabno, o->type, o->value, o->parent, o->parent->tabno);
- if(o->orig){
- if(0)fprint(2, "parentage 0x%p %d type %d orig %d type %d parent 0x%p %d\n", o, o->tabno, o->type, o->orig->tabno, o->orig->type, o->orig->parent, o->orig->parent->tabno);
- o = o->orig;
- }
- sln = ln;
- r = printparentage(lp, ln, o->parent);
- lp += r; ln -= r;
- if(o->type == File && fflag == 0){
- if(ln > 0)
- *lp = '\0';
- return sln - ln;
- }
- if(o->value && *o->value && ln > 0){
- if(o->type == Category){
- if(o->parent == root){
- r = snprint(lp, ln, "category: ");
- lp += r; ln -= r;
- }else{
- for(k = Ntoken; k < ntoken; k++)
- if(catseteq(&o->categories,&tokenlist[k].categories)){
- r = snprint(lp, ln, "%s: ", tokenlist[k].name);
- lp += r; ln -= r;
- break;
- }
- }
- }else{
- r = snprint(lp, ln, "%s: ", tokenlist[o->type].name);
- lp += r; ln -= r;
- }
- if(ln <= 0)
- return sln - ln;
- if(o->num){
- r = snprint(lp, ln, "%2d. ", o->num);
- lp += r; ln -= r;
- }
- if(ln <= 0)
- return sln - ln;
- r = indent(lp, ln, -1, o->value);
- lp += r; ln -= r;
- if(ln > 1){
- *lp++ = '\n';
- ln--;
- }
- }else{
- if(0)fprint(2, "parentage 0x%p %d type %d no value\n", o, o->tabno, o->type);
- }
- for(i = 0; i < o->nchildren && ln > 0; i++)
- switch(o->children[i]->type){
- case Performance:
- case Soloists:
- case Lyrics:
- r = snprint(lp, ln, "%s: ", tokenlist[o->children[i]->type].name);
- lp += r; ln -= r;
- if(ln <= 0)
- break;
- r = indent(lp, ln, -1, o->children[i]->value);
- lp += r; ln -= r;
- if(ln > 1){
- *lp++ = '\n';
- ln--;
- }
- break;
- case Time:
- r = snprint(lp, ln, "%s: %s\n", "duration", o->children[i]->value);
- lp += r; ln -= r;
- break;
- case File:
- if(fflag){
- r = snprint(lp, ln, "%s: %s\n", "file", o->children[i]->value);
- lp += r; ln -= r;
- }
- break;
- default:
- break;
- }
- if(ln > 0)
- *lp = '\0';
- return sln - ln;
-}
-
-long
-printparent(char *lp, int ln, Object *o) {
- return snprint(lp, ln, "%d", o->parent->tabno);
-}
-
-long
-printkey(char *lp, int ln, Object *o) {
- return snprint(lp, ln, "%s", o->key?o->key:o->value);
-}
-
-long
-printtype(char *lp, int ln, Object *o) {
- return snprint(lp, ln, "%s", tokenlist[o->type].name);
-}
-
-long
-printtext(char *lp, int ln, Object *o) {
- return snprint(lp, ln, "%s", o->value?o->value:o->key);
-}
-
-long
-printfulltext(char *lp, int ln, Object *o) {
- char *sp, *p, *q;
- int i, j, k, c, depth;
- Object *oo;
-
- depth = 0;
- sp = lp;
- switch(o->type){
- case Category:
- if(o->parent == root){
- j = snprint(lp, ln, "category:");
- lp += j; ln -= j;
- }else{
- for(k = Ntoken; k < ntoken; k++)
- if(catseteq(&o->categories, &tokenlist[k].categories)){
- j = snprint(lp, ln, "%s:", tokenlist[k].name);
- lp += j; ln -= j;
- break;
- }
- }
- if(ln <= 0)
- return lp - sp;
- p = o->value;
- if(p == nil)
- p = o->key;
- if((q = strchr(p, '\n')) && q[1] != '\0'){
- // multiple lines
- *lp++ = '\n'; ln--;
- if(ln <= 0)
- break;
- j = indent(lp, ln, depth+1, p);
- lp += j; ln -= j;
- }else{
- *lp++ = ' '; ln--;
- while((c=*p++) && ln > 0){
- if(c == '~')
- continue;
- *lp++ = c;
- ln--;
- if(c == '\n')
- break;
- }
- }
- break;
- case Track:
- case Part:
- case Recording:
- case Root:
- case Search:
- case Work:
- j = snprint(lp, ln, "%s:", tokenlist[o->type].name);
- lp += j; ln -= j;
- if(ln <= 0)
- break;
- if(o->num){
- j = snprint(lp, ln, " %2d.", o->num);
- lp += j; ln -= j;
- }
- if(ln <= 0)
- break;
- p = o->value;
- if(p == nil)
- p = o->key;
- if((q = strchr(p, '\n')) && q[1] != '\0'){
- // multiple lines
- *lp++ = '\n'; ln--;
- if(ln <= 0)
- break;
- j = indent(lp, ln, depth+1, p);
- lp += j; ln -= j;
- }else{
- *lp++ = ' '; ln--;
- while((c =*p++) && ln > 0){
- if(c == '~')
- continue;
- *lp++ = c;
- ln--;
- if(c == '\n')
- break;
- }
- }
- default:
- break;
- }
- depth++;
- for(i = 0; i < o->nchildren && ln > 0; i++){
- oo = o->children[i];
- switch(oo->type){
- case Lyrics:
- case Performance:
- case Soloists:
- case Time:
- if (ln <= 4*depth + 1)
- break;
- *lp++ = '\n'; ln--;
- memset(lp, ' ', 4*depth);
- lp += 4*depth;
- ln -= 4*depth;
- if(ln <= 0)
- break;
- j = snprint(lp, ln, "%s:", tokenlist[oo->type].name);
- lp += j; ln -= j;
- if(ln <= 0)
- break;
- p = oo->value;
- if(ln <= 1)
- break;
- if((q = strchr(p, '\n')) && q[1] != '\0'){
- // multiple lines
- *lp++ = '\n'; ln--;
- j = indent(lp, ln, depth+1, p);
- lp += j; ln -= j;
- }else{
- *lp++ = ' '; ln--;
- while((c =*p++) && ln > 0){
- if(c == '~')
- continue;
- *lp++ = c;
- ln--;
- if(c == '\n')
- break;
- }
- }
- }
- }
- *lp = '\0';
- return lp - sp;
-}
-
-long
-printfiles(char *lp, int ln, Object *o) {
- int i, r;
- char *sp;
-
- sp = lp;
- if (o->type == File)
- lp += snprint(lp, ln, "%d %s\n", o->tabno, o->value);
- else {
- for (i = 0; i < o->nchildren && ln > 0; i++){
- r = printfiles(lp, ln, o->children[i]);
- lp += r;
- ln -= r;
- }
- }
- return lp - sp;
-}
-
-long
-printdigest(char *lp, int ln, Object *o) {
- char *p;
- int j, c, k;
- char *sp;
-
- sp = lp;
- switch(o->type){
- case Category:
- if (o->parent == root) {
- j = snprint(lp, ln, "category: ");
- lp += j; ln -= j;
- } else {
- for (k = Ntoken; k < ntoken; k++)
- if (catseteq(&o->categories,& tokenlist[k].categories)) {
- j = snprint(lp, ln, "%s: ", tokenlist[k].name);
- lp += j; ln -= j;
-// break;
- }
- }
- p = o->value;
- if (p == 0) p = o->key;
- while ((c=*p++) && c != '\n' && ln > 0) {
- if(c == '~')
- continue;
- *lp++ = c;
- ln--;
- }
- break;
- case Track:
- case Part:
- case Recording:
- case Root:
- case Search:
- case Work:
- j = snprint(lp, ln, "%s: ", tokenlist[o->type].name);
- lp += j; ln -= j;
- if (o->num) {
- j = snprint(lp, ln, "%2d. ", o->num);
- lp += j; ln -= j;
- }
- p = o->value;
- if (p == 0) p = o->key;
- while ((c = *p++) && c != '\n' && ln > 0) {
- if(c == '~')
- continue;
- *lp++ = c;
- ln--;
- }
- default:
- break;
- }
- if(ln)
- *lp = '\0';
- return lp - sp;
-}
-
-#ifdef UNDEF
-
-void
-printtree(Object *o, int ind) {
- char *p;
- char buf[2048];
- int i;
-
- sprintf(buf, "%s {\n", tokenlist[o->type].name);
- indent(ind, buf);
- ind++;
- if ((p = o->value)) {
- sprintf(buf, "%s\n", p);
- indent(ind, buf);
- }
- for (i = 0; i < o->nchildren; i++)
- printtree(o->children[i], ind);
- indent(--ind, "}\n");
-}
-
-void
-mapdump(Object *o, int depth, char *inheritance) {
- Object *oo;
- char *data;
- int n, l;
-
- if (o == root) {
- depth = 0;
- inheritance = "";
- data = NULL;
- } else {
- if (o->value) {
- l = nlines(o->value);
- n = strlen(inheritance) +
- l * (strlen(tokenlist[o->type].name) + 2) +
- strlen(o->value) + 2;
- data = mymalloc(NULL, n);
- strcpy(data, inheritance);
- p = data + strlen(inheritance);
- q = o->value;
- while (*q) {
- p += sprintf(p, "%s:\t", tokenlist[o->type].name);
- do {
- *p++ = *q;
- while (*q++ != '\n');
- }
- if (p[-1] != '\n') *p++ = '\n';
- *p = 0;
- inheritance = data;
- }
- indent(depth, inheritance);
- }
- c = 0;
-}
-
-#endif
--- a/sys/src/games/music/jukefs/print.h
+++ /dev/null
@@ -1,6 +1,0 @@
-extern int fflag;
-
-void printtree(Object *, int);
-int parentage(char *, int, Object *);
-int miniparentage(char *, int, Object *);
-int indent(char *, int, int n, char *buf);
--- a/sys/src/games/music/jukefs/search.c
+++ /dev/null
@@ -1,44 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <thread.h>
-#include "object.h"
-#include "parse.h"
-#include "search.h"
-
-Object *
-search(Object *rt, Object *parent, Reprog *preg) {
- /* Create a `search object', a subtree of rt containing
- * only objects with s in their value of key fields plus
- * their parentage.
- *
- * Algorithm: depth-first traversal of rt. On the way down,
- * copy rt to nr (new root), on the way back up, delete
- * subtrees without match.
- *
- * returns null when there are no matches in rt's subtree
- */
- Object *o, *nr;
- char *s;
- int i;
- int yes = 0;
-
- nr = newobject(rt->type, parent);
- nr->orig = rt->orig?rt->orig:rt;
- nr->value = rt->value;
- strncpy(nr->key, rt->key, KEYLEN);
-
- if((((s = nr->value)) && regexec(preg, s, nil, 0) == 1)
- || (((s = nr->value)) && regexec(preg, s, nil, 0) == 1))
- yes = 1;
- for(i = 0; i < rt->nchildren; i++)
- if((o = search((Object*)rt->children[i], nr, preg))){
- yes = 1;
- addchild(nr, o, "search");
- }
- if(yes == 0){
- freeobject(nr, "s");
- return nil;
- }
- return nr;
-}
--- a/sys/src/games/music/jukefs/search.h
+++ /dev/null
@@ -1,5 +1,0 @@
-#include <regexp.h>
-
-extern Object *sobj;
-
-Object *search(Object *rt, Object *parent, Reprog *preg);
--- a/sys/src/games/music/jukefs/server.c
+++ /dev/null
@@ -1,214 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include <bio.h>
-#include <fcall.h>
-#include "object.h"
-#include "parse.h"
-#include "print.h"
-#include "catset.h"
-#include "../debug.h"
-
-char *user, *mapname, *svrname;
-int p[2];
-int mfd[2];
-int debug = 0; //DBGSERVER|DBGSTATE|DBGPICKLE|DBGPLAY;
-Biobuf *f;
-char *file;
-
-Object *root;
-
-Object ** otab; // object table
-int notab; // no of entries used
-int sotab; // no of entries mallocated (invariant sotab >= notab)
-int hotab; // no of holes in otab;
-
-char usage[] = "Usage: %s [-f] [-l] [mapfile]\n";
-
-char *startdir;
-
-Object **catobjects; /* for quickly finding category objects */
-int ncat = 0;
-
-void
-post(char *name, char *envname, int srvfd)
-{
- int fd;
- char buf[32];
-
- fd = create(name, OWRITE, 0666);
- if(fd < 0)
- return;
- sprint(buf, "%d",srvfd);
- if(write(fd, buf, strlen(buf)) != strlen(buf))
- sysfatal("srv write: %r");
- close(fd);
- putenv(envname, name);
-}
-
-int
-robusthandler(void*, char *s)
-{
- if (debug) fprint(2, "inthandler: %s\n", s);
- return (s && (strstr(s, "interrupted") || strstr(s, "hangup")));
-}
-
-long
-robustread(int fd, void *buf, long sz)
-{
- long r;
- char err[32];
-
- do {
- r = read(fd , buf, sz);
- if (r < 0)
- rerrstr(err, sizeof(err));
- } while (r < 0 && robusthandler(nil, err));
- return r;
-}
-
-void
-delobject(Object *o)
-{
- /* Free an object and all its descendants */
- Object *oo;
- int i;
-
- for (i = 0; i < o->nchildren; i++){
- oo = o->children[i];
- if (oo->parent == o)
- delobject(oo);
- }
- freeobject(o, "r");
-}
-
-void
-threadmain(int argc, char *argv[]) {
- char *q;
- char *srvname;
- char *mntpt;
- int list;
-
- mntpt = "/mnt";
- user = strdup(getuser());
- srvname = nil;
- list = 0;
-
- ARGBEGIN{
- case 'l':
- list = 1;
- break;
- case 'm':
- mntpt = ARGF();
- break;
- case 'd':
- debug = strtoul(ARGF(), nil, 0);
- break;
- case 's':
- srvname = ARGF();
- break;
- case 'f':
- fflag = 1;
- break;
- default:
- fprint(2, usage, argv0);
- exits("usage");
- }ARGEND
-
- switch (argc) {
- default:
- fprint(2, usage, argv0);
- exits("usage");
- case 0:
- mapname = DEFAULTMAP;
- break;
- case 1:
- mapname = argv[0];
- break;
- }
-
- quotefmtinstall();
-
- if((f = Bopen(mapname, OREAD)) == nil)
- sysfatal("%s: %r", mapname);
- free(file);
- file = strdup(mapname);
- free(startdir);
- startdir = strdup(mapname);
- if ((q = strrchr(startdir, '/')))
- *q = '\0';
- else
- startdir[0] = '\0';
- inittokenlist();
- getobject(Root, nil);
- Bterm(f);
- f = nil;
- root->parent = root;
-
- if(list){
- listfiles(root);
- threadexits(nil);
- }
-
- if(pipe(p) < 0)
- sysfatal("pipe failed: %r");
- mfd[0] = p[0];
- mfd[1] = p[0];
-
- threadnotify(robusthandler, 1);
- user = strdup(getuser());
-
- if(debug)
- fmtinstall('F', fcallfmt);
-
- procrfork(io, nil, 8192, RFFDG); //RFNOTEG?
-
- close(p[0]); /* don't deadlock if child fails */
-
- if(srvname){
- srvname = smprint("/srv/jukefs.%s", srvname);
- remove(srvname);
- post(srvname, "jukefs", p[1]);
- }
- if(mount(p[1], -1, mntpt, MBEFORE, "") < 0)
- sysfatal("mount failed: %r");
- threadexits(nil);
-}
-
-void
-reread(void)
-{
- int i;
- extern int catnr;
- char *q;
-
- assert(f == nil);
- if((f = Bopen(mapname, OREAD)) == nil)
- fprint(2, "reread: %s: %r\n", mapname);
- freetree(root);
- root = nil;
- for(i = 0; i< ntoken; i++){
- free(tokenlist[i].name);
- catsetfree(&tokenlist[i].categories);
- }
- catnr = 0;
- free(tokenlist);
- free(catobjects);
- catobjects = nil;
- ncat = 0;
- tokenlist = nil;
- ntoken = Ntoken;
- inittokenlist();
- free(file);
- file = strdup(mapname);
- free(startdir);
- startdir = strdup(mapname);
- if ((q = strrchr(startdir, '/')))
- *q = '\0';
- else
- startdir[0] = '\0';
- getobject(Root, nil);
- root->parent = root;
- Bterm(f);
- f = nil;
-}
--- a/sys/src/games/music/mkfile
+++ /dev/null
@@ -1,51 +1,0 @@
-dirs = playlistfs jukefs jukebox
-
-# DEFAULTMAP = /lib/audio/map
-ICONPATH = /lib/audio/icon
-
-ICONS = \
- next.bit\
- pause.bit\
- play.bit\
- prev.bit\
- question.bit\
- root.bit\
- skull.bit\
- stop.bit\
- trash.bit\
-
-ICONFILES = ${ICONS:%.bit=icon/%.bit}
-
-default:V: all
-
-all dep clean nuke:V:
- for (i in $dirs) @ {
- echo $i
- cd $i
- mk $MKFLAGS $target
- }
-
-rcinstall:V: juke.rc
- cp juke.rc /rc/bin/juke
- chmod +x /rc/bin/juke
-
-$ICONPATH:
- mkdir $ICONPATH
-
-iconinstall:V: $ICONFILES $ICONPATH
- for (i in $ICONS)
- cp $ICONFILES $ICONPATH
-
-install:V:
- for (i in $dirs) @ {
- echo $i
- cd $i
- mk $MKFLAGS $target
- }
- mk rcinstall
- mk iconinstall
-
-installall:V:
- for(objtype in $CPUS)
- mk $MKFLAGS install
- mk rcinstall
--- a/sys/src/games/music/mkinc
+++ /dev/null
@@ -1,9 +1,0 @@
-base = ..
-CFLAGS=$CFLAGS $DEFINES
-
-all:
-
-dep:Q:
- mkdep $INCLUDES $CFILES > mk.dep
-
-< mk.dep
--- a/sys/src/games/music/playlistfs/boilerplate.c
+++ /dev/null
@@ -1,100 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include <fcall.h>
-#include "playlist.h"
-
-static Channel *reqs;
-
-Req*
-reqalloc(void)
-{
- Req *r;
-
- if(reqs == nil)
- reqs = chancreate(sizeof(Req*), 256);
- if(r = nbrecvp(reqs))
- return r;
- r = malloc(sizeof(Req));
- return r;
-}
-
-void
-reqfree(Req *r)
-{
- if(!nbsendp(reqs, r))
- free(r);
-}
-
-Wmsg
-waitmsg(Worker *w, Channel *q)
-{
- Wmsg m;
-
- sendp(q, w);
- recv(w->eventc, &m);
- return m;
-}
-
-int
-sendmsg(Channel *q, Wmsg *m)
-{
- Worker *w;
-
- while(w = nbrecvp(q)){
- /* Test for markerdom (see bcastmsg) */
- if(w->eventc){
- send(w->eventc, m);
- return 1;
- }
- sendp(q, w); /* put back */
- }
- return 0;
-}
-
-void
-bcastmsg(Channel *q, Wmsg *m)
-{
- Worker *w, marker;
- void *a;
-
- a = m->arg;
- /*
- * Use a marker to mark the end of the queue.
- * This prevents workers from getting the
- * broadcast and putting themselves back on the
- * queue before the broadcast has finished
- */
- marker.eventc = nil; /* Only markers have eventc == nil */
- sendp(q, &marker);
- while((w = recvp(q)) != &marker){
- if(w->eventc == nil){
- /* somebody else's marker, put it back */
- sendp(q, w);
- }else{
- if(a) m->arg = strdup(a);
- send(w->eventc, m);
- }
- }
- free(a);
- m->arg = nil;
-}
-
-void
-readbuf(Req *r, void *s, long n)
-{
- r->ofcall.count = r->ifcall.count;
- if(r->ifcall.offset >= n){
- r->ofcall.count = 0;
- return;
- }
- if(r->ifcall.offset+r->ofcall.count > n)
- r->ofcall.count = n - r->ifcall.offset;
- memmove(r->ofcall.data, (char*)s+r->ifcall.offset, r->ofcall.count);
-}
-
-void
-readstr(Req *r, char *s)
-{
- readbuf(r, s, strlen(s));
-}
--- a/sys/src/games/music/playlistfs/fs.c
+++ /dev/null
@@ -1,882 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include <fcall.h>
-#include "pool.h"
-#include "playlist.h"
-
-typedef struct Wmsg Wmsg;
-
-enum {
- Busy = 0x01,
- Open = 0x02,
- Trunc = 0x04,
- Eof = 0x08,
-};
-
-File files[] = {
-[Qdir] = {.dir = {0,0,{Qdir, 0,QTDIR}, 0555|DMDIR, 0,0,0, "."}},
-[Qplayctl] = {.dir = {0,0,{Qplayctl, 0,QTFILE}, 0666, 0,0,0, "playctl"}},
-[Qplaylist] = {.dir = {0,0,{Qplaylist, 0,QTFILE}, 0666|DMAPPEND, 0,0,0, "playlist"}},
-[Qplayvol] = {.dir = {0,0,{Qplayvol, 0,QTFILE}, 0666, 0,0,0, "playvol"}},
-[Qplaystat] = {.dir = {0,0,{Qplaystat, 0,QTFILE}, 0444, 0,0,0, "playstat"}},
-};
-
-Channel *reqs;
-Channel *workers;
-Channel *volumechan;
-Channel *playchan;
-Channel *playlistreq;
-Playlist playlist;
-int volume[8];
-
-char *statetxt[] = {
- [Nostate] = "panic!",
- [Error] = "error",
- [Stop] = "stop",
- [Pause] = "pause",
- [Play] = "play",
- [Resume] = "resume",
- [Skip] = "skip",
- nil
-};
-
-// low-order bits: position in play list, high-order: play state:
-Pmsg playstate = {Stop, 0};
-
-char *rflush(Worker*), *rauth(Worker*),
- *rattach(Worker*), *rwalk(Worker*),
- *ropen(Worker*), *rcreate(Worker*),
- *rread(Worker*), *rwrite(Worker*), *rclunk(Worker*),
- *rremove(Worker*), *rstat(Worker*), *rwstat(Worker*),
- *rversion(Worker*);
-
-char *(*fcalls[])(Worker*) = {
- [Tflush] rflush,
- [Tversion] rversion,
- [Tauth] rauth,
- [Tattach] rattach,
- [Twalk] rwalk,
- [Topen] ropen,
- [Tcreate] rcreate,
- [Tread] rread,
- [Twrite] rwrite,
- [Tclunk] rclunk,
- [Tremove] rremove,
- [Tstat] rstat,
- [Twstat] rwstat,
-};
-
-int messagesize = Messagesize;
-Fid *fids;
-
-
-char Eperm[] = "permission denied";
-char Enotdir[] = "not a directory";
-char Enoauth[] = "authentication not required";
-char Enotexist[] = "file does not exist";
-char Einuse[] = "file in use";
-char Eexist[] = "file exists";
-char Enotowner[] = "not owner";
-char Eisopen[] = "file already open for I/O";
-char Excl[] = "exclusive use file already open";
-char Ename[] = "illegal name";
-char Ebadctl[] = "unknown control message";
-char Epast[] = "reading past eof";
-
-Fid *oldfid(int);
-Fid *newfid(int);
-void volumeupdater(void*);
-void playupdater(void*);
-
-char *playerror;
-
-static int
-lookup(char *cmd, char *list[])
-{
- int i;
-
- for (i = 0; list[i] != nil; i++)
- if (strcmp(cmd, list[i]) == 0)
- return i;
- return -1;
-}
-
-char*
-rversion(Worker *w)
-{
- Req *r;
- Fid *f;
-
- r = w->r;
- if(r->ifcall.msize < 256)
- return "max messagesize too small";
- if(r->ifcall.msize < messagesize)
- messagesize = r->ifcall.msize;
- r->ofcall.msize = messagesize;
- if(strncmp(r->ifcall.version, "9P2000", 6) != 0)
- return "unknown 9P version";
- else
- r->ofcall.version = "9P2000";
- for(f = fids; f; f = f->next)
- if(f->flags & Busy)
- f->flags &= ~(Open|Busy);
- return nil;
-}
-
-char*
-rauth(Worker*)
-{
- return Enoauth;
-}
-
-char*
-rflush(Worker *w)
-{
- Wmsg m;
- int i;
- Req *r;
-
- r = w->r;
- m.cmd = Flush;
- m.off = r->ifcall.oldtag;
- m.arg = nil;
- for(i = 1; i < nelem(files); i++)
- bcastmsg(files[i].workers, &m);
- if (debug & DbgWorker)
- fprint(2, "flush done on tag %d\n", r->ifcall.oldtag);
- return 0;
-}
-
-char*
-rattach(Worker *w)
-{
- Fid *f;
- Req *r;
-
- r = w->r;
- r->fid = newfid(r->ifcall.fid);
- f = r->fid;
- f->flags |= Busy;
- f->file = &files[Qdir];
- r->ofcall.qid = f->file->dir.qid;
- if(!aflag && strcmp(r->ifcall.uname, user) != 0)
- return Eperm;
- return 0;
-}
-
-static Fid*
-doclone(Fid *f, int nfid)
-{
- Fid *nf;
-
- nf = newfid(nfid);
- if(nf->flags & Busy)
- return nil;
- nf->flags |= Busy;
- nf->flags &= ~(Open);
- nf->file = f->file;
- return nf;
-}
-
-char*
-dowalk(Fid *f, char *name)
-{
- int t;
-
- if (strcmp(name, ".") == 0)
- return nil;
- if (strcmp(name, "..") == 0){
- f->file = &files[Qdir];
- return nil;
- }
- if(f->file != &files[Qdir])
- return Enotexist;
- for (t = 1; t < Nqid; t++){
- if(strcmp(name, files[t].dir.name) == 0){
- f->file = &files[t];
- return nil;
- }
- }
- return Enotexist;
-}
-
-char*
-rwalk(Worker *w)
-{
- Fid *f, *nf;
- char *rv;
- int i;
- File *savefile;
- Req *r;
-
- r = w->r;
- r->fid = oldfid(r->ifcall.fid);
- if((f = r->fid) == nil)
- return Enotexist;
- if(f->flags & Open)
- return Eisopen;
-
- r->ofcall.nwqid = 0;
- nf = nil;
- savefile = f->file;
- /* clone if requested */
- if(r->ifcall.newfid != r->ifcall.fid){
- nf = doclone(f, r->ifcall.newfid);
- if(nf == nil)
- return "new fid in use";
- f = nf;
- }
-
- /* if it's just a clone, return */
- if(r->ifcall.nwname == 0 && nf != nil)
- return nil;
-
- /* walk each element */
- rv = nil;
- for(i = 0; i < r->ifcall.nwname; i++){
- rv = dowalk(f, r->ifcall.wname[i]);
- if(rv != nil){
- if(nf != nil)
- nf->flags &= ~(Open|Busy);
- else
- f->file = savefile;
- break;
- }
- r->ofcall.wqid[i] = f->file->dir.qid;
- }
- r->ofcall.nwqid = i;
-
- /* we only error out if no walk */
- if(i > 0)
- rv = nil;
-
- return rv;
-}
-
-char *
-ropen(Worker *w)
-{
- Fid *f, *ff;
- Wmsg m;
- Req *r;
-
- r = w->r;
- r->fid = oldfid(r->ifcall.fid);
- if((f = r->fid) == nil)
- return Enotexist;
- if(f->flags & Open)
- return Eisopen;
-
- if(r->ifcall.mode != OREAD)
- if((f->file->dir.mode & 0x2) == 0)
- return Eperm;
- if((r->ifcall.mode & OTRUNC) && f->file == &files[Qplaylist]){
- playlist.nlines = 0;
- playlist.ndata = 0;
- free(playlist.lines);
- free(playlist.data);
- playlist.lines = nil;
- playlist.data = nil;
- f->file->dir.length = 0;
- f->file->dir.qid.vers++;
- /* Mark all fids for this file `Trunc'ed */
- for(ff = fids; ff; ff = ff->next)
- if(ff->file == &files[Qplaylist] && (ff->flags & Open))
- ff->flags |= Trunc;
- m.cmd = Check;
- m.off = 0;
- m.arg = nil;
- bcastmsg(f->file->workers, &m);
- }
- r->ofcall.iounit = 0;
- r->ofcall.qid = f->file->dir.qid;
- f->flags |= Open;
- return nil;
-}
-
-char *
-rcreate(Worker*)
-{
- return Eperm;
-}
-
-int
-readtopdir(Fid*, uchar *buf, long off, int cnt, int blen)
-{
- int i, m, n;
- long pos;
-
- n = 0;
- pos = 0;
- for (i = 1; i < Nqid; i++){
- m = convD2M(&files[i].dir, &buf[n], blen-n);
- if(off <= pos){
- if(m <= BIT16SZ || m > cnt)
- break;
- n += m;
- cnt -= m;
- }
- pos += m;
- }
- return n;
-}
-
-char*
-rread(Worker *w)
-{
- Fid *f;
- Req *r;
- long off, cnt;
- int n, i;
- Wmsg m;
- char *p;
-
- r = w->r;
- r->fid = oldfid(r->ifcall.fid);
- if((f = r->fid) == nil)
- return Enotexist;
- r->ofcall.count = 0;
- off = r->ifcall.offset;
- cnt = r->ifcall.count;
-
- if(cnt > messagesize - IOHDRSZ)
- cnt = messagesize - IOHDRSZ;
-
- if(f->file == &files[Qdir]){
- n = readtopdir(f, r->indata, off, cnt, messagesize - IOHDRSZ);
- r->ofcall.count = n;
- return nil;
- }
-
- if(f->file == files + Qplaystat){
- p = getplaystat(r->ofcall.data, r->ofcall.data + sizeof r->indata);
- readbuf(r, r->ofcall.data, p - r->ofcall.data);
- return nil;
- }
-
- m.cmd = 0;
- while(f->vers == f->file->dir.qid.vers && (f->flags & Eof)){
- /* Wait until file state changes (f->file->dir.qid.vers is incremented) */
- m = waitmsg(w, f->file->workers);
- if(m.cmd == Flush && m.off == r->ifcall.tag)
- return (char*)~0; /* no answer needed */
- assert(m.cmd != Work);
- yield();
- }
- if(f->file == files + Qplaylist){
- f->flags &= ~Eof;
- if((f->flags & Trunc) && r->ifcall.offset != 0){
- f->flags &= ~Trunc;
- return Epast;
- }
- f->flags &= ~Trunc;
- if(r->ifcall.offset < playlist.ndata)
- readbuf(r, playlist.data, playlist.ndata);
- else if(r->ifcall.offset == playlist.ndata){
- r->ofcall.count = 0;
- /* Arrange for this fid to wait next time: */
- f->vers = f->file->dir.qid.vers;
- f->flags |= Eof;
- }else{
- /* Beyond eof, bad seek? */
- return Epast;
- }
- }else if(f->file == files + Qplayctl){
- f->flags &= ~Eof;
- if(m.cmd == Error){
- snprint(r->ofcall.data, sizeof r->indata, "%s %ud %q",
- statetxt[m.cmd], m.off, m.arg);
- free(m.arg);
- }else if(f->vers == f->file->dir.qid.vers){
- r->ofcall.count = 0;
- /* Arrange for this fid to wait next time: */
- f->flags |= Eof;
- return nil;
- }else{
- snprint(r->ofcall.data, sizeof r->indata, "%s %ud",
- statetxt[playstate.cmd], playstate.off);
- f->vers = f->file->dir.qid.vers;
- }
- r->ofcall.count = strlen(r->ofcall.data);
- if(r->ofcall.count > r->ifcall.count)
- r->ofcall.count = r->ifcall.count;
- }else if(f->file == files + Qplayvol){
- f->flags &= ~Eof;
- if(f->vers == f->file->dir.qid.vers){
- r->ofcall.count = 0;
- /* Arrange for this fid to wait next time: */
- f->flags |= Eof;
- }else{
- p = seprint(r->ofcall.data, r->ofcall.data + sizeof r->indata, "volume '");
- for(i = 0; i < nelem(volume); i++){
- if(volume[i] == Undef)
- break;
- p = seprint(p, r->ofcall.data + sizeof r->indata, "%d ", volume[i]);
- }
- p = seprint(p, r->ofcall.data + sizeof r->indata, "'");
- r->ofcall.count = p - r->ofcall.data;
- if(r->ofcall.count > r->ifcall.count)
- r->ofcall.count = r->ifcall.count;
- f->vers = f->file->dir.qid.vers;
- }
- }else
- abort();
- return nil;
-}
-
-char*
-rwrite(Worker *w)
-{
- long cnt, i, nf, cmd;
- Pmsg newstate;
- char *fields[3], *p, *q;
- Wmsg m;
- Fid *f;
- Req *r;
-
- r = w->r;
- r->fid = oldfid(r->ifcall.fid);
- if((f = r->fid) == nil)
- return Enotexist;
- r->ofcall.count = 0;
- cnt = r->ifcall.count;
-
- if(cnt > messagesize - IOHDRSZ)
- cnt = messagesize - IOHDRSZ;
-
- if(f->file == &files[Qplayctl]){
- r->ifcall.data[cnt] = '\0';
- if (debug & DbgPlayer)
- fprint(2, "rwrite playctl: %s\n", r->ifcall.data);
- nf = tokenize(r->ifcall.data, fields, 4);
- if (nf == 0){
- r->ofcall.count = r->ifcall.count;
- return nil;
- }
- if (nf == 2)
- i = strtol(fields[1], nil, 0);
- else
- i = playstate.off;
- newstate = playstate;
- if ((cmd = lookup(fields[0], statetxt)) < 0)
- return Ebadctl;
- switch(cmd){
- case Play:
- newstate.cmd = cmd;
- newstate.off = i;
- break;
- case Pause:
- if (playstate.cmd != Play)
- break;
- // fall through
- case Stop:
- newstate.cmd = cmd;
- newstate.off = playstate.off;
- break;
- case Resume:
- if(playstate.cmd == Stop)
- break;
- newstate.cmd = Resume;
- newstate.off = playstate.off;
- break;
- case Skip:
- if (nf == 2)
- i += playstate.off;
- else
- i = playstate.off +1;
- if(i < 0)
- i = 0;
- else if (i >= playlist.nlines)
- i = playlist.nlines - 1;
- newstate.cmd = Play;
- newstate.off = i;
- }
- if (newstate.off >= playlist.nlines){
- newstate.cmd = Stop;
- newstate.off = playlist.nlines;
- }
- if (debug & DbgPlayer)
- fprint(2, "new state %s-%ud\n",
- statetxt[newstate.cmd], newstate.off);
- if (newstate.m != playstate.m)
- sendul(playc, newstate.m);
- f->file->dir.qid.vers++;
- } else if(f->file == &files[Qplayvol]){
- char *subfields[nelem(volume)];
- int v[nelem(volume)];
-
- r->ifcall.data[cnt] = '\0';
- if (debug & DbgPlayer)
- fprint(2, "rwrite playvol: %s\n", r->ifcall.data);
- nf = tokenize(r->ifcall.data, fields, 4);
- if (nf == 0){
- r->ofcall.count = r->ifcall.count;
- return nil;
- }
- if (nf != 2 || strcmp(fields[0], "volume") != 0)
- return Ebadctl;
- if (debug & DbgPlayer)
- fprint(2, "new volume '");
- nf = tokenize(fields[1], subfields, nelem(subfields));
- if (nf <= 0 || nf > nelem(volume))
- return "volume";
- for (i = 0; i < nf; i++){
- v[i] = strtol(subfields[i], nil, 0);
- if (debug & DbgPlayer)
- fprint(2, " %d", v[i]);
- }
- if (debug & DbgPlayer)
- fprint(2, "'\n");
- while (i < nelem(volume))
- v[i++] = Undef;
- volumeset(v);
- r->ofcall.count = r->ifcall.count;
- return nil;
- } else if(f->file == &files[Qplaylist]){
- if (debug & DbgPlayer){
- fprint(2, "rwrite playlist: `");
- write(2, r->ifcall.data, cnt);
- fprint(2, "'\n");
- }
- playlist.data = realloc(playlist.data, playlist.ndata + cnt + 2);
- if (playlist.data == 0)
- sysfatal("realloc: %r");
- memmove(playlist.data + playlist.ndata, r->ifcall.data, cnt);
- if (playlist.data[playlist.ndata + cnt-1] != '\n')
- playlist.data[playlist.ndata + cnt++] = '\n';
- playlist.data[playlist.ndata + cnt] = '\0';
- p = playlist.data + playlist.ndata;
- while (*p){
- playlist.lines = realloc(playlist.lines, (playlist.nlines+1)*sizeof(playlist.lines[0]));
- if(playlist.lines == nil)
- sysfatal("realloc: %r");
- playlist.lines[playlist.nlines] = playlist.ndata;
- q = strchr(p, '\n');
- if (q == nil)
- break;
- if(debug & DbgPlayer)
- fprint(2, "[%lud]: ", playlist.nlines);
- playlist.nlines++;
- q++;
- if(debug & DbgPlayer)
- write(2, p, q-p);
- playlist.ndata += q - p;
- p = q;
- }
- f->file->dir.length = playlist.ndata;
- f->file->dir.qid.vers++;
- }else
- return Eperm;
- r->ofcall.count = r->ifcall.count;
- m.cmd = Check;
- m.off = 0;
- m.arg = nil;
- bcastmsg(f->file->workers, &m);
- return nil;
-}
-
-char *
-rclunk(Worker *w)
-{
- Fid *f;
-
- f = oldfid(w->r->ifcall.fid);
- if(f == nil)
- return Enotexist;
- f->flags &= ~(Open|Busy);
- return 0;
-}
-
-char *
-rremove(Worker*)
-{
- return Eperm;
-}
-
-char *
-rstat(Worker *w)
-{
- Req *r;
-
- r = w->r;
- r->fid = oldfid(r->ifcall.fid);
- if(r->fid == nil)
- return Enotexist;
- r->ofcall.nstat = convD2M(&r->fid->file->dir, r->indata, messagesize - IOHDRSZ);
- r->ofcall.stat = r->indata;
- return 0;
-}
-
-char *
-rwstat(Worker*)
-{
- return Eperm;
-}
-
-Fid *
-oldfid(int fid)
-{
- Fid *f;
-
- for(f = fids; f; f = f->next)
- if(f->fid == fid)
- return f;
- return nil;
-}
-
-Fid *
-newfid(int fid)
-{
- Fid *f, *ff;
-
- ff = nil;
- for(f = fids; f; f = f->next)
- if(f->fid == fid){
- return f;
- }else if(ff == nil && (f->flags & Busy) == 0)
- ff = f;
- if(ff == nil){
- ff = mallocz(sizeof *ff, 1);
- if (ff == nil)
- sysfatal("malloc: %r");
- ff->next = fids;
- ff->readers = 0;
- fids = ff;
- }
- ff->fid = fid;
- ff->file = nil;
- ff->vers = ~0;
- return ff;
-}
-
-void
-work(Worker *w)
-{
- Req *r;
- char *err;
- int n;
-
- r = w->r;
- r->ofcall.data = (char*)r->indata;
- if(!fcalls[r->ifcall.type])
- err = "bad fcall type";
- else
- err = (*fcalls[r->ifcall.type])(w);
- if(err != (char*)~0){ /* ~0 indicates Flush received */
- if(err){
- r->ofcall.type = Rerror;
- r->ofcall.ename = err;
- }else{
- r->ofcall.type = r->ifcall.type + 1;
- r->ofcall.fid = r->ifcall.fid;
- }
- r->ofcall.tag = r->ifcall.tag;
- if(debug & DbgFs)
- fprint(2, "io:->%F\n", &r->ofcall);/**/
- n = convS2M(&r->ofcall, r->outdata, messagesize);
- if(write(srvfd[0], r->outdata, n) != n)
- sysfatal("mount write");
- }
- reqfree(r);
- w->r = nil;
-}
-
-void
-worker(void *arg)
-{
- Worker *w;
- Wmsg m;
-
- w = arg;
- recv(w->eventc, &m);
- for(;;){
- assert(m.cmd == Work);
- w->r = m.arg;
- if(debug & DbgWorker)
- fprint(2, "worker 0x%p:<-%F\n", w, &w->r->ifcall);
- work(w);
- if(debug & DbgWorker)
- fprint(2, "worker 0x%p wait for next\n", w);
- m = waitmsg(w, workers);
- }
-}
-
-void
-allocwork(Req *r)
-{
- Worker *w;
- Wmsg m;
-
- m.cmd = Work;
- m.off = 0;
- m.arg = r;
- if(sendmsg(workers, &m))
- return;
- /* No worker ready to accept request, allocate one */
- w = malloc(sizeof(Worker));
- w->eventc = chancreate(sizeof(Wmsg), 1);
- if(debug & DbgWorker)
- fprint(2, "new worker 0x%p\n", w);/**/
- threadcreate(worker, w, 4096);
- send(w->eventc, &m);
-}
-
-void
-srvio(void *arg)
-{
- int n;
- Req *r;
- Channel *dispatchc;
-
- threadsetname("file server IO");
- dispatchc = arg;
-
- r = reqalloc();
- while((n = read9pmsg(srvfd[0], r->indata, messagesize)) != 0){
- if(n < 0){
- char e[32];
- rerrstr(e, sizeof e);
- if (strcmp(e, "interrupted") == 0){
- if (debug & DbgFs) fprint(2, "read9pmsg interrupted\n");
- continue;
- }
- sysfatal("srvio: read: %s", e);
- }
- if(convM2S(r->indata, n, &r->ifcall) != n)
- sysfatal("srvio: convM2S: %r");
-
- if(debug & DbgFs)
- fprint(2, "io:<-%F\n", &r->ifcall);
- sendp(dispatchc, r);
- r = reqalloc();
- }
- threadexitsall(nil);
-}
-
-char *
-getplaylist(int n)
-{
- Wmsg m;
-
- m.cmd = Preq;
- m.off = n;
- m.arg = nil;
- send(playlistreq, &m);
- recv(playlistreq, &m);
- if(m.cmd == Error)
- return nil;
- assert(m.cmd == Prep);
- assert(m.arg);
- return m.arg;
-}
-
-void
-playlistsrv(void*)
-{
- Wmsg m;
- char *p, *q, *r;
- char *fields[2];
- int n;
- /* Runs in the srv proc */
-
- threadsetname("playlistsrv");
- while(recv(playlistreq, &m)){
- assert(m.cmd == Preq);
- m.cmd = Error;
- if(m.off < playlist.nlines){
- p = playlist.data + playlist.lines[m.off];
- q = strchr(p, '\n');
- if (q == nil)
- sysfatal("playlistsrv: no newline character found");
- n = q-p;
- r = malloc(n+1);
- memmove(r, p, n);
- r[n] = 0;
- tokenize(r, fields, nelem(fields));
- assert(fields[0] == r);
- m.cmd = Prep;
- m.arg = r;
- }
- send(playlistreq, &m);
- }
-}
-
-void
-srv(void*)
-{
- Req *r;
- Channel *dispatchc;
- /*
- * This is the proc with all the action.
- * When a file request comes in, it is dispatched to this proc
- * for processing. Two extra threads field changes in play state
- * and volume state.
- * By keeping all the action in this proc, we won't need locks
- */
-
- threadsetname("srv");
- close(srvfd[1]);
-
- dispatchc = chancreate(sizeof(Req*), 1);
- procrfork(srvio, dispatchc, 4096, RFFDG);
-
- threadcreate(volumeupdater, nil, 4096);
- threadcreate(playupdater, nil, 4096);
- threadcreate(playlistsrv, nil, 4096);
-
- while(r = recvp(dispatchc))
- allocwork(r);
-
-}
-
-void
-playupdater(void*)
-{
- Wmsg m;
- /* This is a thread in the srv proc */
-
- while(recv(playchan, &m)){
- if(debug & DbgPlayer)
- fprint(2, "playupdate: %s %d %s\n", statetxt[m.cmd], m.off, m.arg?m.arg:"");
- if(playstate.m == m.m)
- continue;
- if(m.cmd == Stop && m.off == 0xffff)
- m.off = playlist.nlines;
- if(m.cmd != Error){
- playstate.m = m.m;
- m.cmd = Check;
- assert(m.arg == nil);
- }
- files[Qplayctl].dir.qid.vers++;
- bcastmsg(files[Qplayctl].workers, &m);
- }
-}
-
-void
-volumeupdater(void*)
-{
- Wmsg m;
- int v[nelem(volume)];
- /* This is a thread in the srv proc */
-
- while(recv(volumechan, v)){
- if(debug & DbgPlayer)
- fprint(2, "volumeupdate: volume now %d %d %d %d\n", volume[0], volume[1], volume[2], volume[3]);
- memmove(volume, v, sizeof(volume));
- files[Qplayvol].dir.qid.vers++;
- m.cmd = Check;
- m.arg = nil;
- bcastmsg(files[Qplayvol].workers, &m);
- }
-}
-
-void
-playupdate(Pmsg p, char *s)
-{
- Wmsg m;
-
- m.m = p.m;
- m.arg = s ? strdup(s) : nil;
- send(playchan, &m);
-}
--- a/sys/src/games/music/playlistfs/main.c
+++ /dev/null
@@ -1,94 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include <fcall.h>
-#include "playlist.h"
-
-int debug;
-char *user;
-int srvfd[2];
-int aflag;
-
-void
-usage(void)
-{
- sysfatal("usage: %s [-d bitmask] [-s] [-m mountpoint]", argv0);
-}
-
-void
-post(char *name, int sfd)
-{
- int fd;
- char buf[32];
-
- fd = create(name, OWRITE, 0666);
- if(fd < 0)
- return;
- sprint(buf, "%d", sfd);
- if(write(fd, buf, strlen(buf)) != strlen(buf))
- sysfatal("srv write: %r");
- close(fd);
-}
-
-void
-threadmain(int argc, char *argv[])
-{
- char *srvfile;
- char *srvpost;
- char *mntpt;
- int i;
-
- mntpt = "/mnt";
- srvpost = nil;
-
- rfork(RFNOTEG);
-
- ARGBEGIN{
- case 'a':
- aflag = 1;
- break;
- case 'm':
- mntpt = ARGF();
- break;
- case 'd':
- debug = strtoul(ARGF(), nil, 0);
- break;
- case 's':
- srvpost = ARGF();
- break;
- default:
- usage();
- }ARGEND
-
- user = strdup(getuser());
-
- quotefmtinstall();
-
- if(debug)
- fmtinstall('F', fcallfmt);
-
- volumechan = chancreate(sizeof(volume), 1);
- playchan = chancreate(sizeof(Wmsg), 1);
- playlistreq = chancreate(sizeof(Wmsg), 0); /* No storage! requires rendez-vous */
- workers = chancreate(sizeof(Worker*), 256);
- for(i = 1; i < Nqid; i++)
- files[i].workers = chancreate(sizeof(Worker*), 256);
-
- if(pipe(srvfd) < 0)
- sysfatal("pipe failed: %r");
- procrfork(srv, nil, 8192, RFFDG);
- close(srvfd[0]); /* don't deadlock if child fails */
-
- procrfork(volumeproc, nil, 8192, RFFDG);
- playinit();
-
- if(srvpost){
- srvfile = smprint("/srv/playlist.%s", srvpost);
- remove(srvfile);
- post(srvfile, srvfd[1]);
- free(srvfile);
- }
- if(mount(srvfd[1], -1, mntpt, MBEFORE, "") < 0)
- sysfatal("mount failed: %r");
- threadexits(nil);
-}
--- a/sys/src/games/music/playlistfs/mk.dep
+++ /dev/null
@@ -1,5 +1,0 @@
-main.$O: /$objtype/include/u.h /sys/include/libc.h /sys/include/thread.h /sys/include/fcall.h playlist.h
-fs.$O: /$objtype/include/u.h /sys/include/libc.h /sys/include/thread.h /sys/include/fcall.h /sys/include/pool.h playlist.h
-player.$O: /$objtype/include/u.h /sys/include/libc.h /sys/include/thread.h /sys/include/fcall.h /sys/include/pool.h playlist.h
-volume.$O: /$objtype/include/u.h /sys/include/libc.h /sys/include/thread.h /sys/include/fcall.h /sys/include/pool.h playlist.h
-boilerplate.$O: /$objtype/include/u.h /sys/include/libc.h /sys/include/thread.h /sys/include/fcall.h playlist.h
--- a/sys/src/games/music/playlistfs/mkfile
+++ /dev/null
@@ -1,16 +1,0 @@
-</$objtype/mkfile
-<../mkinc
-
-TARG = playlistfs
-BIN = /$objtype/bin/games
-
-CFILES=\
- main.c\
- fs.c\
- player.c\
- volume.c\
- boilerplate.c\
-
-OFILES = ${CFILES:%.c=%.$O}
-
-</sys/src/cmd/mkone
--- a/sys/src/games/music/playlistfs/player.c
+++ /dev/null
@@ -1,373 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include <fcall.h>
-#include "pool.h"
-#include "playlist.h"
-
-typedef struct Playfd Playfd;
-
-struct Playfd {
- /* Describes a file to play for starting up pac4dec/mp3,... */
- char *filename; /* mallocated */
- int fd; /* filedesc to use */
- int cfd; /* fildesc to close */
-};
-
-Channel *full, *empty, *playout, *spare;
-Channel *playc, *pacc;
-
-ulong totbytes, totbuffers;
-
-static char curfile[8192];
-
-void
-decexec(void *a)
-{
- char buf[256];
- Playfd *pfd;
- Pacbuf *pb;
-
- threadsetname("decexec");
- pfd = a;
- close(pfd->cfd); /* read fd */
- if(pfd->fd != 1){
- dup(pfd->fd, 1);
- close(pfd->fd);
- }
- close(0); open("/dev/null", OREAD);
- close(2); open("/dev/null", OWRITE);
- strncpy(buf, pfd->filename, sizeof(buf)-1);
- buf[sizeof(buf)-1] = 0;
- free(pfd->filename);
- free(pfd);
- procexecl(nil, "/bin/play", "play", "-o", "/fd/1", buf, nil);
- if((pb = nbrecvp(spare)) == nil)
- pb = malloc(sizeof(Pacbuf));
- pb->cmd = Error;
- pb->off = 0;
- pb->len = snprint(pb->data, sizeof(pb->data), "startplay: exec play failed");
- sendp(full, pb);
- threadexits("exec");
-}
-
-static int
-startplay(ushort n)
-{
- int fd[2];
- Playfd *pfd;
- char *file;
-
- file = getplaylist(n);
- if(file == nil)
- return Undef;
- if (debug & DbgPlayer)
- fprint(2, "startplay: file is `%s'\n", file);
- if(pipe(fd) < 0)
- sysfatal("pipe: %r");
- pfd = malloc(sizeof(Playfd));
- pfd->filename = file; /* mallocated already */
- pfd->fd = fd[1];
- pfd->cfd = fd[0];
- procrfork(decexec, pfd, 4096, RFFDG|RFENVG);
- close(fd[1]); /* write fd, for pac4dec */
- return fd[0]; /* read fd */
-}
-
-static void
-rtsched(void)
-{
- int fd;
- char *ctl;
-
- ctl = smprint("/proc/%ud/ctl", getpid());
- if((fd = open(ctl, OWRITE)) < 0)
- sysfatal("%s: %r", ctl);
- if(fprint(fd, "period 20ms") < 0)
- sysfatal("%s: %r", ctl);
- if(fprint(fd, "cost 100µs") < 0)
- sysfatal("%s: %r", ctl);
- if(fprint(fd, "sporadic") < 0)
- sysfatal("%s: %r", ctl);
- if(fprint(fd, "admit") < 0)
- sysfatal("%s: %r", ctl);
- close(fd);
- free(ctl);
-}
-
-static void
-boost(void)
-{
- int fd;
- char *ctl;
-
- ctl = smprint("/proc/%ud/ctl", getpid());
- if((fd = open(ctl, OWRITE)) >= 0) {
- fprint(fd, "pri 13");
- close(fd);
- }
- free(ctl);
-}
-
-void
-decproc(void*)
-{
- Pmsg playstate, newstate;
- int fd;
- Pacbuf *pb;
- Alt a[3] = {
- {empty, &pb, CHANNOP},
- {playc, &newstate.m, CHANRCV},
- {nil, nil, CHANEND},
- };
-
- threadsetname("decproc");
- close(srvfd[1]);
- newstate.cmd = playstate.cmd = Stop;
- newstate.off = playstate.off = 0;
- fd = -1;
- for(;;){
- switch(alt(a)){
- case 0:
- /* Play out next buffer (pb points to one already) */
- assert(fd >= 0); /* Because we must be in Play mode */
- pb->m = playstate.m;
- pb->len = read(fd, pb->data, sizeof pb->data);
- if(pb->len > 0){
- sendp(full, pb);
- break;
- }
- if(pb->len < 0){
- if(debug & DbgPlayer)
- fprint(2, "pac, error: %d\n", playstate.off);
- pb->cmd = Error;
- pb->len = snprint(pb->data, sizeof pb->data, "%s: %r", curfile);
- sendp(full, pb);
- }else{
- /* Simple end of file */
- sendp(empty, pb); /* Don't need buffer after all */
- }
- close(fd);
- fd = -1;
- if(debug & DbgPlayer)
- fprint(2, "pac, eof: %d\n", playstate.off);
- /* End of file, do next by falling through */
- newstate.cmd = playstate.cmd;
- newstate.off = playstate.off + 1;
- case 1:
- if((debug & DbgPac) && newstate.cmd)
- fprint(2, "Pacproc: newstate %s-%d, playstate %s-%d\n",
- statetxt[newstate.cmd], newstate.off,
- statetxt[playstate.cmd], playstate.off);
- /* Deal with an incoming command */
- if(newstate.cmd == Pause || newstate.cmd == Resume){
- /* Just pass them on, don't change local state */
- pb = recvp(spare);
- pb->m = newstate.m;
- sendp(full, pb);
- break;
- }
- /* Stop whatever we're doing */
- if(fd >= 0){
- if(debug & DbgPlayer)
- fprint(2, "pac, stop\n");
- /* Stop any active (pac) decoders */
- close(fd);
- fd = -1;
- }
- a[0].op = CHANNOP;
- switch(newstate.cmd){
- default:
- sysfatal("decproc: unexpected newstate %d", newstate.cmd);
- case Stop:
- /* Wait for state to change */
- break;
- case Skip:
- case Play:
- fd = startplay(newstate.off);
- if(fd >=0){
- playstate = newstate;
- a[0].op = CHANRCV;
- continue; /* Start reading */
- }
- newstate.cmd = Stop;
- }
- pb = recvp(spare);
- pb->m = newstate.m;
- sendp(full, pb);
- playstate = newstate;
- }
- }
-}
-
-void
-pcmproc(void*)
-{
- Pmsg localstate, newstate, prevstate;
- int fd, n;
- Pacbuf *pb, *b;
- Alt a[3] = {
- {full, &pb, CHANRCV},
- {playout, &pb, CHANRCV},
- {nil, nil, CHANEND},
- };
-
- /*
- * This is the real-time proc.
- * It gets its input from two sources, full data/control buffers from the decproc
- * which mixes decoded data with control messages, and data buffers from the pcmproc's
- * (*this* proc's) own internal playout buffer.
- * When a command is received on the `full' channel containing a command that warrants
- * an immediate change of audio source (e.g., to silence or to another number), we just
- * toss everything in the pipeline -- i.e., the playout channel
- * Finally, we report all state changes using `playupdate' (another message channel)
- */
- threadsetname("pcmproc");
- close(srvfd[1]);
- fd = -1;
- localstate.cmd = 0; /* Force initial playupdate */
- newstate.cmd = Stop;
- newstate.off = 0;
-// rtsched();
- boost();
- for(;;){
- if(newstate.m != localstate.m){
- playupdate(newstate, nil);
- localstate = newstate;
- }
- switch(alt(a)){
- case 0:
- /* buffer received from decproc */
- if((debug & DbgPcm) && localstate.m != prevstate.m){
- fprint(2, "pcm, full: %s-%d, local state is %s-%d\n",
- statetxt[pb->cmd], pb->off,
- statetxt[localstate.cmd], localstate.off);
- prevstate.m = localstate.m;
- }
- switch(pb->cmd){
- default:
- sysfatal("pcmproc: unknown newstate: %s-%d", statetxt[pb->cmd], pb->off);
- case Resume:
- a[1].op = CHANRCV;
- newstate.cmd = Play;
- break;
- case Pause:
- a[1].op = CHANNOP;
- newstate.cmd = Pause;
- if(fd >= 0){
- close(fd);
- fd = -1;
- }
- break;
- case Stop:
- /* Dump all data in the buffer */
- while(b = nbrecvp(playout))
- if(b->cmd == Error){
- playupdate(b->Pmsg, b->data);
- sendp(spare, b);
- }else
- sendp(empty, b);
- newstate.m = pb->m;
- a[1].op = CHANRCV;
- if(fd >= 0){
- close(fd);
- fd = -1;
- }
- break;
- case Skip:
- /* Dump all data in the buffer, then fall through */
- while(b = nbrecvp(playout))
- if(b->cmd == Error){
- playupdate(pb->Pmsg, pb->data);
- sendp(spare, pb);
- }else
- sendp(empty, b);
- a[1].op = CHANRCV;
- newstate.cmd = Play;
- case Error:
- case Play:
- /* deal with at playout, just requeue */
- sendp(playout, pb);
- pb = nil;
- localstate = newstate;
- break;
- }
- /* If we still have a buffer, free it */
- if(pb)
- sendp(spare, pb);
- break;
- case 1:
- /* internal buffer */
- if((debug & DbgPlayer) && localstate.m != prevstate.m){
- fprint(2, "pcm, playout: %s-%d, local state is %s-%d\n",
- statetxt[pb->cmd], pb->off,
- statetxt[localstate.cmd], localstate.off);
- prevstate.m = localstate.m;
- }
- switch(pb->cmd){
- default:
- sysfatal("pcmproc: unknown newstate: %s-%d", statetxt[pb->cmd], pb->off);
- case Error:
- playupdate(pb->Pmsg, pb->data);
- localstate = newstate;
- sendp(spare, pb);
- break;
- case Play:
- if(fd < 0 && (fd = open("/dev/audio", OWRITE)) < 0){
- a[1].op = CHANNOP;
- newstate.cmd = Pause;
- pb->cmd = Error;
- snprint(pb->data, sizeof(pb->data),
- "/dev/audio: %r");
- playupdate(pb->Pmsg, pb->data);
- sendp(empty, pb);
- break;
- }
- /* play out this buffer */
- totbytes += pb->len;
- totbuffers++;
- n = write(fd, pb->data, pb->len);
- if (n != pb->len){
- if (debug & DbgPlayer)
- fprint(2, "pcmproc: file %d: %r\n", pb->off);
- if (n < 0)
- sysfatal("pcmproc: write: %r");
- }
- newstate.m = pb->m;
- sendp(empty, pb);
- break;
- }
- break;
- }
- }
-}
-
-void
-playinit(void)
-{
- int i;
-
- full = chancreate(sizeof(Pacbuf*), 1);
- empty = chancreate(sizeof(Pacbuf*), NPacbuf);
- spare = chancreate(sizeof(Pacbuf*), NSparebuf);
- playout = chancreate(sizeof(Pacbuf*), NPacbuf+NSparebuf);
- for(i = 0; i < NPacbuf; i++)
- sendp(empty, malloc(sizeof(Pacbuf)));
- for(i = 0; i < NSparebuf; i++)
- sendp(spare, malloc(sizeof(Pacbuf)));
-
- playc = chancreate(sizeof(ulong), 1);
- procrfork(decproc, nil, 32*1024, RFFDG);
- procrfork(pcmproc, nil, 32*1024, RFFDG);
-}
-
-char *
-getplaystat(char *p, char *e)
-{
- p = seprint(p, e, "empty buffers %d of %d\n", empty->n, empty->s);
- p = seprint(p, e, "full buffers %d of %d\n", full->n, full->s);
- p = seprint(p, e, "playout buffers %d of %d\n", playout->n, playout->s);
- p = seprint(p, e, "spare buffers %d of %d\n", spare->n, spare->s);
- p = seprint(p, e, "bytes %lud / buffers %lud played\n", totbytes, totbuffers);
- return p;
-}
--- a/sys/src/games/music/playlistfs/playlist.h
+++ /dev/null
@@ -1,147 +1,0 @@
-typedef struct Worker Worker;
-typedef struct Req Req;
-typedef struct Fid Fid;
-typedef struct File File;
-typedef struct Playlist Playlist;
-typedef struct Wmsg Wmsg;
-typedef union Pmsg Pmsg;
-typedef struct Pacbuf Pacbuf;
-
-enum {
- Qdir,
- Qplayctl,
- Qplaylist,
- Qplayvol,
- Qplaystat,
- Nqid,
-};
-
-enum {
- DbgPcm = 0x01000,
- DbgPac = 0x02000,
- DbgFs = 0x10000,
- DbgWorker = 0x20000,
- DbgPlayer = 0x40000,
- DbgError = 0x80000,
-};
-
-enum {
- Messagesize = 8*1024+IOHDRSZ,
- Undef = 0x80000000,
- /* 256 buffers of 4096 bytes represents 5.9 seconds
- * of playout at 44100 Hz (2*16bit samples)
- */
- NPacbuf = 256,
- Pacbufsize = 4096,
- NSparebuf = 16, /* For in-line commands (Pause, Resume, Error) */
-};
-
-enum {
- /* Named commands (see fs.c): */
- Nostate, // can't use zero for state
- Error,
- Stop,
- Pause,
- Play,
- Resume,
- Skip,
- /* Unnamed commands */
- Work,
- Check,
- Flush,
- Prep,
- Preq,
-};
-
-union Pmsg {
- ulong m;
- struct{
- ushort cmd;
- ushort off;
- };
-};
-
-struct Wmsg {
- Pmsg;
- void *arg; /* if(cmd != Work) mallocated by sender, freed by receiver */
-};
-
-struct Playlist {
- /* The play list consists of a sequence of {objectref, filename}
- * entries. Object ref and file name are separated by a tab.
- * An object ref may not contain a tab. Entries are seperated
- * by newline characters. Neither file names, nor object refs
- * may contain newlines.
- */
- ulong *lines;
- ulong nlines;
- char *data;
- ulong ndata;
-};
-
-struct File {
- Dir dir;
- Channel *workers;
-};
-
-struct Worker
-{
- Req *r;
- Channel *eventc;
-};
-
-struct Fid
-{
- int fid;
- File *file;
- ushort flags;
- short readers;
- ulong vers; /* set to file's version when completely read */
- Fid *next;
-};
-
-struct Req
-{
- uchar indata[Messagesize];
- uchar outdata[Messagesize];
- Fcall ifcall;
- Fcall ofcall;
- Fid* fid;
-};
-
-struct Pacbuf {
- Pmsg;
- int len;
- char data[Pacbufsize];
-};
-
-void allocwork(Req*);
-Wmsg waitmsg(Worker*, Channel*);
-int sendmsg(Channel*, Wmsg*);
-void bcastmsg(Channel*, Wmsg*);
-void reqfree(Req*);
-Req *reqalloc(void);
-void readbuf(Req*, void*, long);
-void readstr(Req*, char*);
-void volumeset(int *v);
-void playupdate(Pmsg, char*);
-void playinit(void);
-void volumeproc(void*);
-void srv(void *);
-long robustread(int, void*, long);
-void volumeupdate(int*);
-char *getplaylist(int);
-char *getplaystat(char*, char*);
-
-extern int debug, aflag;
-extern char *user;
-extern Channel *playc;
-extern char *statetxt[];
-extern int volume[8];
-extern Playlist playlist;
-extern Channel *workers;
-extern Channel *volumechan;
-extern Channel *playchan;
-extern Channel *playlistreq;
-extern File files[];
-extern int srvfd[];
--- a/sys/src/games/music/playlistfs/playplumb.c
+++ /dev/null
@@ -1,20 +1,0 @@
-#include <u.h>
-#include <libc.h>
-
-void
-main(int argc, char *argv[])
-{
- Plumbmsg *m;
- int fd;
-
- fd = plumbopen("audioplay", OREAD);
- if (fd < 0)
- sysfatal("port audioplay: %r");
- for (;;) {
- m = plumbrecv(fd);
- if (m == nil)
- sysfatal("plumrecv: %r");
-
- plumbfree(m);
- }
-}
--- a/sys/src/games/music/playlistfs/volume.c
+++ /dev/null
@@ -1,91 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include <fcall.h>
-#include "pool.h"
-#include "playlist.h"
-
-int minvolume, maxvolume;
-
-void
-volumeproc(void *)
-{
- int fd, n, nf, i, nlines;
- static char buf[1024];
- char *lines[32];
- char *fields[8];
- char *subfields[9];
- int volume[8], nvolumes;
-
- threadsetname("volumeproc");
- close(srvfd[1]);
- fd = open("/dev/audioctl", OREAD);
- if (fd < 0)
- threadexits(nil);
- for(;;){
- n = read(fd, buf, sizeof buf -1);
- if (n == 0)
- continue;
- if (n < 0){
- fprint(2, "volumeproc: read: %r\n");
- threadexits("volumeproc");
- }
- buf[n] = '\0';
- nlines = getfields(buf, lines, nelem(lines), 1, "\n");
- for(i = 0; i < nlines; i++){
- nf = tokenize(lines[i], fields, nelem(fields));
- if (nf == 0)
- continue;
- if (nf != 6 || strcmp(fields[0], "volume") || strcmp(fields[1], "out"))
- continue;
- minvolume = strtol(fields[3], nil, 0);
- maxvolume = strtol(fields[4], nil, 0);
- if (minvolume >= maxvolume)
- continue;
- nvolumes = tokenize(fields[2], subfields, nelem(subfields));
- if (nvolumes <= 0 || nvolumes > 8)
- sysfatal("bad volume data");
- if (debug)
- fprint(2, "volume changed to '");
- for (i = 0; i < nvolumes; i++){
- volume[i] = strtol(subfields[i], nil, 0);
- volume[i]= 100*(volume[i]- minvolume)/(maxvolume-minvolume);
- if (debug)
- fprint(2, " %d", volume[i]);
- }
- if (debug)
- fprint(2, "'\n");
- while (i < 8)
- volume[i++] = Undef;
- send(volumechan, volume);
- }
- }
-}
-
-void
-volumeset(int *v)
-{
- int fd, i;
- char buf[256], *p;
-
- fd = open("/dev/audioctl", OWRITE);
- if (fd < 0){
- fd = open("/dev/volume", OWRITE);
- if (fd < 0){
- fprint(2, "Can't set volume: %r");
- return;
- }
- fprint(fd, "audio out %d", v[0]);
- send(volumechan, v);
- } else {
- p = buf;
- for (i = 0; i < 8; i++){
- if (v[i] == Undef) break;
- p = seprint(p, buf+sizeof buf, (p==buf)?"volume out '%d":" %d",
- minvolume + v[i] * (maxvolume-minvolume) / 100);
- }
- p = seprint(p, buf+sizeof buf, "'\n");
- write(fd, buf, p-buf);
- }
- close(fd);
-}
--- a/sys/src/games/music/readcd
+++ /dev/null
@@ -1,46 +1,0 @@
-#!/bin/rc
-
-cdrom=/dev/sdC1
-
-switch($#*){
-case 3
- starttrack = `{echo $1 - 1 | hoc}
- endtrack = `{echo $2 - 1 | hoc}
- desttrack = $3
-case *
- echo Usage readcd starttrack endtrack desttrack
-}
-
-if(test -e /mnt/cd/ctl){
- echo -n ingest >/mnt/cd/ctl >[2]/dev/null
-}
-if not {
- if (~ $cdrom '') cdfs
- if not cdfs -d $cdrom
-}
-
->/tmp/readcd
->/tmp/map
-cat /mnt/cd/ctl
-sed 1q /mnt/cd/ctl | rc
-echo $starttrack $endtrack $desttrack | awk '{
- start = $1
- finish = $2
- dest = $3
- print "read cd tracks " start "-" finish " starting at " dest
- for (i = start; i <= finish; i++) {
- cmd = sprintf("ls -l /mnt/cd/a%3.3d | awk ''{print $6}''>>/tmp/readcd", i)
- system(cmd)
- getline x<"/tmp/readcd"
- sec = x/44100/4
- min = sec/60
- sec = sec%60
- printf("track {\n\t\n\tfile {%3.3d}\n\ttime {%d:%2.2d}\n}\n",i+dest-start,min,sec)>"/tmp/map"
- }
- for (i = start; i <= finish; i++) {
- cmd = sprintf("/bin/games/pacenc /mnt/cd/a%3.3d %3.3d",i,i+dest-start)
- print cmd
- system(cmd)
- }
-}'
-echo eject >/mnt/cd/ctl