From a150899221a5badff9740703b754f901b4f52762 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Thu, 14 Apr 2011 17:27:24 +0000 Subject: fill /acme --- acme/bin/source/acd/README | 33 ++ acme/bin/source/acd/access | 243 +++++++++++ acme/bin/source/acd/acd.h | 171 ++++++++ acme/bin/source/acd/acme.c | 347 ++++++++++++++++ acme/bin/source/acd/cddb | 206 +++++++++ acme/bin/source/acd/cddb.c | 197 +++++++++ acme/bin/source/acd/cddbproto | 894 ++++++++++++++++++++++++++++++++++++++++ acme/bin/source/acd/discid | 159 +++++++ acme/bin/source/acd/mailinglist | 220 ++++++++++ acme/bin/source/acd/main.c | 135 ++++++ acme/bin/source/acd/mkfile | 22 + acme/bin/source/acd/mmc.c | 303 ++++++++++++++ acme/bin/source/acd/outline | 32 ++ acme/bin/source/acd/submit | 220 ++++++++++ acme/bin/source/acd/toc.c | 59 +++ acme/bin/source/acd/util.c | 89 ++++ acme/bin/source/acd/win.c | 320 ++++++++++++++ 17 files changed, 3650 insertions(+) create mode 100644 acme/bin/source/acd/README create mode 100644 acme/bin/source/acd/access create mode 100644 acme/bin/source/acd/acd.h create mode 100644 acme/bin/source/acd/acme.c create mode 100644 acme/bin/source/acd/cddb create mode 100644 acme/bin/source/acd/cddb.c create mode 100644 acme/bin/source/acd/cddbproto create mode 100644 acme/bin/source/acd/discid create mode 100644 acme/bin/source/acd/mailinglist create mode 100644 acme/bin/source/acd/main.c create mode 100644 acme/bin/source/acd/mkfile create mode 100644 acme/bin/source/acd/mmc.c create mode 100644 acme/bin/source/acd/outline create mode 100644 acme/bin/source/acd/submit create mode 100644 acme/bin/source/acd/toc.c create mode 100644 acme/bin/source/acd/util.c create mode 100644 acme/bin/source/acd/win.c (limited to 'acme/bin/source/acd') diff --git a/acme/bin/source/acd/README b/acme/bin/source/acd/README new file mode 100644 index 000000000..4fba5b0c5 --- /dev/null +++ b/acme/bin/source/acd/README @@ -0,0 +1,33 @@ +This is a CD player for use under Acme. + +It is derived from my earlier cdplay, which +was in turn derived from a 2nd edition player +called vcd. I think hardly any of the code from +vcd is left anymore, but it's what got me started. +Vcd was originally by David Hogan with additions +by Alberto Nava. David Hogan claims the only +code left is the definition of struct Msf. + +Run it by executing "acd /dev/sdD0", where +/dev/sdD0 is your CD reader. + +A window with a track list will appear, with +tracks named Track 1, Track 2, etc. +If it can be found in the freedb.org CD database, +real track names will replace the boring +ones before long. + +To start playing a track, right click the number. +A "> " marks the currently playing track. +When that track finishes, acd plays the track +on the next line. This means you can edit +the window as thought it were a play list. + +If the next line is "repeat", acd will start again +at the first song listed in the window. + +CD changes are handled gracefully. + +Russ Cox +9 August 2000 +rsc@plan9.bell-labs.com diff --git a/acme/bin/source/acd/access b/acme/bin/source/acd/access new file mode 100644 index 000000000..9a34399e0 --- /dev/null +++ b/acme/bin/source/acd/access @@ -0,0 +1,243 @@ +TWO FORMS OF ACCESS TO THE FREEDB +--------------------------------- + +In the following document we will refer to CDDB instead of freedb, since +from a technical point of view, freedb is a CDDB-Server as it uses the +CDDB-protocol. + +If you are interested in incorporating the use of freedb in your +software, there are two forms of access that you may consider. + +1. Local access + + In this mode your software simply attempts to open local files on + the computer to access the CDDB. + +2. Remote access + + In this mode the software must connect to a freedb server on the + network to access the CDDB. There is a CDDB server protocol that + the software (also known as the "client") must use to converse with + the server. + +You may choose to support either one, or both of these modes. + + +CDDB DISCID +----------- + +Both forms of CDDB access requires that the software computes a "disc +ID" which is an identifier that is used to access the CDDB. The disc +ID is a 8-digit hexadecimal (base-16) number, computed using data from +a CD's Table-of-Contents (TOC) in MSF (Minute Second Frame) form. The +algorithm is listed below in the DISCID Howto. + +It is crucial that your software compute the disc ID correctly. If it +does not generate the disc ID, it will not be compatible with the +CDDB. Moreover, if your software submits CDDB entries with bad disc +IDs to the freedb archives, it could compromise the integrity of the +freedb. + +If you have access to a UNIX platform that xmcd supports, we suggest +installing xmcd, and then test the disc ID code in your software by +comparing the disc ID generated by xmcd with that of your software, +for as large a number of CDs as possible. + + +LOCAL CDDB ACCESS +----------------- + +There are two forms of the CDDB archive available, the standard form +and the alternate form. Both forms are available for download from +various servers. You can always find an actual list of mirrors on the +freedb-homepage at http://freedb.freedb.org. +The standard form of the CDDB archive is released to the public as +a UNIX tar(1)-format archive, compressed with gzip. The alternate +form archive is in the .zip format that is popular on the Windows +platform. + +Standard Form: +-------------- + +Each CD entry is a separate file in the xmcd CDDB. These files are +organized in several directories, each directory is a category of +music. Currently the "official" categories are listed as follows: + + blues + classical + country + data + folk + jazz + misc + newage + reggae + rock + soundtrack + +The individual CDDB files have a file name that is the 8-digit disc +ID. For example, under the blues directory there may be the following +files: + + 0511c012 + 060e7314 + 0c01e902 + 0f0c3112 + ... + fa0f6f10 + fb0f8814 + fd0e6013 + +To access the CDDB entry associated with a CD, your software simply +opens the appropriate file and reads the information. + +The content of each of these files is in a format described in the +database-format specification. + +Different pressings of a particular CD title may contain differences +in timings that can cause the computed disc ID to be different. +The CDDB allows this by having multiple file names be links to +the same file. The links are implemented as actual filesystem links +(see the ln(1) command) on UNIX systems. For example, the following +files in the rock directory are all links to the same file, and +refer to the CD "Pink Floyd / The Division Bell".: + + 850f740b + 850f950b + 850f970b + 860f960b + 890f970b + +Xmcd and the CD database server use this form of the CDDB archive. The +benefit of the standard form of the CDDB archive is very fast access, +and ease of add/delete/edit operations on entries. + +Alternate Form: +--------------- + +Due to limitations in the FAT file system used on Windows 9x and +Windows ME, it is unfeasible to use the standard format CDDB archive +due to the large number of files. This is because such a filesystem +operates on fixed-size clusters and even a small file (and most CDDB +files are 1KB or less) would consume the space of a full cluster +(Depending upon disk size, a cluster can range from 4KB to 32KB in +size). Thus, a tremendous amount of disk space would be wasted on +these systems if the CDDB archive is used in its standard form. + +An alternate form of the CDDB archives was created for use by software +that must operate on a system with the FAT limitations. + +The alterate form still use the separate category directories as the +standard form, but concatenates many files into a smaller number of +files under each category. The first two digits of the CDDB file names +is used as a key for concatenation, each file is allowed to grow to +approximately 64KB in size before a new file is started. The file name +indicates what range of the digits are included in that file. For +example, under the blues category we may have the following files: + + 01to36 + 37to55 + 56to71 + ... + b2tod7 + d8toff + +The 01to36 file contains all CDDB entries with disc ID 01xxxxxx, +02xxxxxx, 03xxxxxx and so on, up to 36xxxxxx. + +Each entry in the concatenated file begins with the keyword + +#FILENAME=xxxxxxxx + +where discid is the 8-digit hexadecimal disc ID of that entry. Your +software must search through the appropriate file to locate the desired +entry. The CDDB entry is in the format described in Appendix B below. + +The alternate form avoids the problem of inefficient disk space +utilization on FAT-based filesystems, but is slower to access than the +standard form, and it is much more cumbersome to perform add/delete/edit +operations on a CDDB entry. + + +REMOTE CDDB ACCESS +------------------ + +Your software must be able to communicate with a remote CD server +system via TCP/IP or HTTP. +There are a number of public freedb servers operating +on the Internet. The current list of public servers is listed on the +freedb web page at: + + http://freedb.freedb.org. + +It may also be obtained programmatically via the CDDB protocol "sites" +command. + +TCP/IP access: + +All current freedb servers answer at TCP port 888. There may be future +sites that deviate from this convention, however. + +HTTP access: + +The freedb-servers can be accessed via the cddb.cgi. This is resides at the +following path: /~cddb/cddb.cgi +Thus, the URL for accessing the server at freedb.freedb.org is: +http://freedb.freedb.org/~cddb/cddb.cgi + +You should make the freedb server host (or hosts) and port numbers +user-configurable in your software. Do not hard-wire the list of +CD database servers into your code. The list of active servers changes +over time. + +The CDDB server protocol is described in the CDDB-protocol documentation. + +The CDDB entry returned from the server via a "cddb read" command is in +the format described database-format specification. + +You may experiment with the freedb server by connecting to port 888 of +the server host via the "telnet" program, and then typing the cddb +protocol commands by hand. For example: + + telnet freedb.freedb.org 888 + +connects you to the freedb server at freedb.freedb.org. + +Some additional notes for accessing freedb over the Internet: + +Your application should always specify the highest documented protocol +level. The highest level currently supported is "3". Lower protocol +levels will work, but are only provided for compatibility with older +CDDB applications. If you do not use the highest available protocol +level, certain important features will not be available to your +application. + +Make sure to use the proper arguments with the "hello" command. The user +and hostname arguments should be that of the user's email address, not +some fixed hard-coded value. The application name and version should be +that of your application, not that of another existing application. + +We consider the use of the "cddb query" command mandatory for all CDDB +clients. It is not valid to issue a "cddb read" command without issuing +a prior "cddb query" and receiving a good response, as it may yield incorrect +results. In addition, it is clients should support close matches +(aka "fuzzy" matches, or response code 211). + +The proper way to handle multiple fuzzy matches is to present the +entire list of matches to the user and to let the user choose between them. +Matches are listed in the order of best fit for the user's disc, so they +should be presented to the user in the order they are listed by the server. + +The suggested algorithm for obtaining the list of server sites is +as follows. The application should offer to get the list from +freedb.freedb.org with the "sites" command the first time the user runs +the program. Additionally the application should provide the user with +some method of downloading the list on-demand. + +We do strongly suggest that you provide your users with the capability of +choosing freedb server sites as described above. However, for some +applications this may not be feasible. If you do not wish to offer this +functionality, you may safely hard-code "freedb.freedb.org" in your +application as the sole freedb site to access. This will deprive your users +of the option to choose a site near their locale for optimal response, but +that is your choice. diff --git a/acme/bin/source/acd/acd.h b/acme/bin/source/acd/acd.h new file mode 100644 index 000000000..90c4bdb81 --- /dev/null +++ b/acme/bin/source/acd/acd.h @@ -0,0 +1,171 @@ +#include +#include +#include +#include +#include +#include +#include +#include <9p.h> + +/* acme */ +typedef struct Event Event; +typedef struct Window Window; + +enum +{ + STACK = 16384, + EVENTSIZE = 256, + NEVENT = 5, +}; + +struct Event +{ + int c1; + int c2; + int q0; + int q1; + int flag; + int nb; + int nr; + char b[EVENTSIZE*UTFmax+1]; + Rune r[EVENTSIZE+1]; +}; + +struct Window +{ + /* file descriptors */ + int ctl; + int event; + int addr; + int data; + Biobuf *body; + + /* event input */ + char buf[512]; + char *bufp; + int nbuf; + Event e[NEVENT]; + + int id; + int open; + Channel *cevent; /* chan(Event*) */ +}; + +extern Window* newwindow(void); +extern int winopenfile(Window*, char*); +extern void winopenbody(Window*, int); +extern void winclosebody(Window*); +extern void wintagwrite(Window*, char*, int); +extern void winname(Window*, char*); +extern void winwriteevent(Window*, Event*); +extern void winread(Window*, uint, uint, char*); +extern int windel(Window*, int); +extern void wingetevent(Window*, Event*); +extern void wineventproc(void*); +extern void winwritebody(Window*, char*, int); +extern void winclean(Window*); +extern int winselect(Window*, char*, int); +extern int winsetaddr(Window*, char*, int); +extern char* winreadbody(Window*, int*); +extern void windormant(Window*); +extern void winsetdump(Window*, char*, char*); + +extern char* readfile(char*, char*, int*); +extern void ctlprint(int, char*, ...); +extern void* emalloc(uint); +extern char* estrdup(char*); +extern char* estrstrdup(char*, char*); +extern char* egrow(char*, char*, char*); +extern char* eappend(char*, char*, char*); +extern void error(char*, ...); +extern int tokenizec(char*, char**, int, char*); + +/* cd stuff */ +typedef struct Msf Msf; /* minute, second, frame */ +struct Msf { + int m; + int s; + int f; +}; + +typedef struct Track Track; +struct Track { + Msf start; + Msf end; + ulong bstart; + ulong bend; + char *title; +}; + +enum { + MTRACK = 64, +}; +typedef struct Toc Toc; +struct Toc { + int ntrack; + int nchange; + int changetime; + int track0; + Track track[MTRACK]; + char *title; +}; + +extern int msfconv(Fmt*); + +#pragma varargck argpos error 1 +#pragma varargck argpos ctlprint 2 +#pragma varargck type "M" Msf + +enum { /* state */ + Sunknown, + Splaying, + Spaused, + Scompleted, + Serror, +}; + +typedef struct Cdstatus Cdstatus; +struct Cdstatus { + int state; + int track; + int index; + Msf abs; + Msf rel; +}; + +typedef struct Drive Drive; +struct Drive { + Window *w; + Channel *cstatus; /* chan(Cdstatus) */ + Channel *ctocdisp; /* chan(Toc) */ + Channel *cdbreq; /* chan(Toc) */ + Channel *cdbreply; /* chan(Toc) */ + Scsi *scsi; + Toc toc; + Cdstatus status; +}; + +int gettoc(Scsi*, Toc*); +void drawtoc(Window*, Drive*, Toc*); +void redrawtoc(Window*, Toc*); +void tocproc(void*); /* Drive* */ +void cddbproc(void*); /* Drive* */ +void cdstatusproc(void*); /* Drive* */ + +extern int debug; + +#define DPRINT if(debug)fprint +void acmeevent(Drive*, Window*, Event*); + +int playtrack(Drive*, int, int); +int pause(Drive*); +int resume(Drive*); +int stop(Drive*); +int eject(Drive*); +int ingest(Drive*); + +int markplay(Window*, ulong); +int setplaytime(Window*, char*); +void advancetrack(Drive*, Window*); + + diff --git a/acme/bin/source/acd/acme.c b/acme/bin/source/acd/acme.c new file mode 100644 index 000000000..514bdbc6e --- /dev/null +++ b/acme/bin/source/acd/acme.c @@ -0,0 +1,347 @@ +#include "acd.h" + +static int +iscmd(char *s, char *cmd) +{ + int len; + + len = strlen(cmd); + return strncmp(s, cmd, len)==0 && (s[len]=='\0' || s[len]==' ' || s[len]=='\t' || s[len]=='\n'); +} + +static char* +skip(char *s, char *cmd) +{ + s += strlen(cmd); + while(*s==' ' || *s=='\t' || *s=='\n') + s++; + return s; +} + +//#define PLAYSTRING "/^[0-9:]+>" +//#define PLAYSTRINGSPACE "/^[0-9:]+> ?" +//#define INITSTRING "0:00> " + +#define INITSTRING "> " +#define PLAYSTRING "/^>" +#define PLAYSTRINGSPACE "/^> ?" + +/* + * find the playing string, leave in addr + * if q0, q1 are non-nil, set them to the addr of the string. + */ +int +findplay(Window *w, char *s, ulong *q0, ulong *q1) +{ + char xbuf[25]; + if(w->data < 0) + w->data = winopenfile(w, "data"); + + if(!winsetaddr(w, "#0", 1) || !winsetaddr(w, s, 1)) + return 0; + + seek(w->addr, 0, 0); + if(read(w->addr, xbuf, 24) != 24) + return 0; + + xbuf[24] = 0; + if(q0) + *q0 = atoi(xbuf); + if(q1) + *q1 = atoi(xbuf+12); + + return 1; +} + +/* + * find the playing string and replace the time + */ +int +setplaytime(Window *w, char *new) +{ + char buf[40]; + ulong q0, q1; + +return 1; + if(!findplay(w, PLAYSTRING, &q0, &q1)) + return 0; + + q1--; /* > */ + sprint(buf, "#%lud,#%lud", q0, q1); + DPRINT(2, "setaddr %s\n", buf); + if(!winsetaddr(w, buf, 1)) + return 0; + + if(write(w->data, new, strlen(new)) != strlen(new)) + return 0; + + return 1; +} + +/* + * find the playing string, and remove it. + * return the string at the beginning of hte next line in buf + * (presumably a track number). + */ +static int +unmarkplay(Window *w, char *buf, int n, ulong *q0, ulong *q1, ulong *qbegin) +{ + char xbuf[24]; + + if(!findplay(w, PLAYSTRINGSPACE, q0, q1)) + return 0; + + if(write(w->data, "", 0) < 0 || !winsetaddr(w, "+1+#0", 1)) + return 0; + + if(qbegin) { + seek(w->addr, 0, 0); + if(read(w->addr, xbuf, 24) != 24) + return 0; + *qbegin = atoi(xbuf); + } + + if(buf) { + if((n = read(w->data, buf, n-1)) < 0) + return 0; + + buf[n] = '\0'; + } + + return 1; +} + +int +markplay(Window *w, ulong q0) +{ + char buf[20]; + + if(w->data < 0) + w->data = winopenfile(w, "data"); + + sprint(buf, "#%lud", q0); + DPRINT(2, "addr %s\n", buf); + if(!winsetaddr(w, buf, 1) || !winsetaddr(w, "-0", 1)) + return 0; + if(write(w->data, INITSTRING, strlen(INITSTRING)) != strlen(INITSTRING)) + return 0; + return 1; +} + +/* return 1 if handled, 0 otherwise */ +int +cdcommand(Window *w, Drive *d, char *s) +{ + s = skip(s, ""); + + if(iscmd(s, "Del")){ + if(windel(w, 0)) + threadexitsall(nil); + return 1; + } + if(iscmd(s, "Stop")){ + unmarkplay(w, nil, 0, nil, nil, nil); + stop(d); + return 1; + } + if(iscmd(s, "Eject")){ + unmarkplay(w, nil, 0, nil, nil, nil); + eject(d); + return 1; + } + if(iscmd(s, "Ingest")){ + unmarkplay(w, nil, 0, nil, nil, nil); + ingest(d); + return 1; + } + if(iscmd(s, "Pause")){ + pause(d); + return 1; + } + if(iscmd(s, "Resume")){ + resume(d); + return 1; + } + return 0; +} + +void +drawtoc(Window *w, Drive *d, Toc *t) +{ + int i, playing; + + if(w->data < 0) + w->data = winopenfile(w, "data"); + if(!winsetaddr(w, ",", 1)) + return; + + fprint(w->data, "Title\n\n"); + playing = -1; + if(d->status.state == Splaying || d->status.state == Spaused) + playing = d->status.track-t->track0; + + for(i=0; intrack; i++) + fprint(w->data, "%s%d/ Track %d\n", i==playing ? "> " : "", i+1, i+1); + fprint(w->data, ""); +} + +void +redrawtoc(Window *w, Toc *t) +{ + int i; + char old[50]; + + if(w->data < 0) + w->data = winopenfile(w, "data"); + if(t->title) { + if(winsetaddr(w, "/Title", 1)) + write(w->data, t->title, strlen(t->title)); + } + for(i=0; intrack; i++) { + if(t->track[i].title) { + sprint(old, "/Track %d", i+1); + if(winsetaddr(w, old, 1)) + write(w->data, t->track[i].title, strlen(t->track[i].title)); + } + } +} + +void +advancetrack(Drive *d, Window *w) +{ + int n; + ulong q0, q1, qnext; + char buf[20]; + + q0 = q1 = 0; + if(!unmarkplay(w, buf, sizeof(buf), &q0, &q1, &qnext)) { + DPRINT(2, "unmark: %r\n"); + return; + } + + DPRINT(2, "buf: %s\n", buf); + if(strncmp(buf, "repeat", 6) == 0) { + if(!winsetaddr(w, "#0", 1) || !findplay(w, "/^[0-9]+\\/", &qnext, nil)) { + DPRINT(2, "set/find: %r\n"); + return; + } + if(w->data < 0) + w->data = winopenfile(w, "data"); + if((n = read(w->data, buf, sizeof(buf)-1)) <= 0) { + DPRINT(2, "read %d: %r\n", n); + return; + } + buf[n] = 0; + DPRINT(2, "buf: %s\n", buf); + } + + if((n = atoi(buf)) == 0) + return; + + if(!markplay(w, qnext)) + DPRINT(2, "err: %r"); + + playtrack(d, n-1, n-1); +} + +void +acmeevent(Drive *d, Window *w, Event *e) +{ + Event *ea, *e2, *eq; + char *s, *t, *buf; + int n, na; + ulong q0, q1; + + switch(e->c1){ /* origin of action */ + default: + Unknown: + fprint(2, "unknown message %c%c\n", e->c1, e->c2); + break; + + case 'E': /* write to body or tag; can't affect us */ + break; + + case 'F': /* generated by our actions; ignore */ + break; + + case 'K': /* type away; we don't care */ + break; + + case 'M': /* mouse event */ + switch(e->c2){ /* type of action */ + case 'x': /* mouse: button 2 in tag */ + case 'X': /* mouse: button 2 in body */ + ea = nil; + // e2 = nil; + s = e->b; + if(e->flag & 2){ /* null string with non-null expansion */ + e2 = recvp(w->cevent); + if(e->nb==0) + s = e2->b; + } + if(e->flag & 8){ /* chorded argument */ + ea = recvp(w->cevent); /* argument */ + na = ea->nb; + recvp(w->cevent); /* ignore origin */ + }else + na = 0; + + /* append chorded arguments */ + if(na){ + t = emalloc(strlen(s)+1+na+1); + sprint(t, "%s %s", s, ea->b); + s = t; + } + /* if it's a known command, do it */ + /* if it's a long message, it can't be for us anyway */ + DPRINT(2, "exec: %s\n", s); + if(!cdcommand(w, d, s)) /* send it back */ + winwriteevent(w, e); + if(na) + free(s); + break; + + case 'l': /* mouse: button 3 in tag */ + case 'L': /* mouse: button 3 in body */ + // buf = nil; + eq = e; + if(e->flag & 2){ + e2 = recvp(w->cevent); + eq = e2; + } + s = eq->b; + if(eq->q1>eq->q0 && eq->nb==0){ + buf = emalloc((eq->q1-eq->q0)*UTFmax+1); + winread(w, eq->q0, eq->q1, buf); + s = buf; + } + DPRINT(2, "load %s\n", s); + if((n = atoi(s)) != 0) { + DPRINT(2, "mark %d\n", n); + q0 = q1 = 0; + unmarkplay(w, nil, 0, &q0, &q1, nil); + + /* adjust eq->q* for deletion */ + if(eq->q0 > q1) { + eq->q0 -= (q1-q0); + eq->q1 -= (q1-q0); + } + if(!markplay(w, eq->q0)) + DPRINT(2, "err: %r\n"); + + playtrack(d, n-1, n-1); + } else + winwriteevent(w, e); + break; + + case 'i': /* mouse: text inserted in tag */ + case 'I': /* mouse: text inserted in body */ + case 'd': /* mouse: text deleted from tag */ + case 'D': /* mouse: text deleted from body */ + break; + + default: + goto Unknown; + } + } +} diff --git a/acme/bin/source/acd/cddb b/acme/bin/source/acd/cddb new file mode 100644 index 000000000..be909a8f0 --- /dev/null +++ b/acme/bin/source/acd/cddb @@ -0,0 +1,206 @@ + + +::freedb.org:: + + + + +
+ + + + + +
+ + + +
+ + + +
+ + + +
freedb.org
+
a free approach to cddbp +
+
+
+
+
+ +
  

+
+
+freedb.org - a free approach to cddbp

+ + + + + +
+ + + + + + + + +
+ + + + + + + +
Main Menu
+ + + + + + + +
+ + +
+
  • Home +
  • News-Topics +
  • About +
  • Developers +
  • Applications +
  • Download +
  • Forum +
  • Web-based Search +
  • Web Links +
  • Your Account +
  • Submit News + +
  • + + +
    +
    +
    + + +
    + + + + + + + +
    FAQ
    + + + + + + + +
    + + +
    + Our FAQ can be found here.
    +Please read the FAQ before asking questions via email.
    + + +
    +
    +
    + + +
    + + + + + + + +
    Contact
    + + + + + + + +
    + + +
    + General questions:
    +info@freedb.org
    +Databaseupdates:
    +updates@freedb.org
    +(NOT for submission!)
    +Please keep in mind that we are NOT the Nero-Support and please do not send CD-submits to the adresses above.
    +Submits have to go to:
    +freedb-submit@freedb.org
    + + +
    +
    +
    + + + +
    + + + + + + + +
    Downloads
    + + + + + + + +
    + + +
    + The link to the database downloads is here
    + + +
    +
    +
      + + +
    +
    + + + +
    + Database-format specification
    + +

    + Due to problems with using backslashes on our Webpage, we cannot display the database-format specification directly here.
    +But you can find it here as a text-document. +
    +   +
     


    + +

    +
    +
    +
    +
    + + diff --git a/acme/bin/source/acd/cddb.c b/acme/bin/source/acd/cddb.c new file mode 100644 index 000000000..ba1fa7604 --- /dev/null +++ b/acme/bin/source/acd/cddb.c @@ -0,0 +1,197 @@ +#include "acd.h" +#include + +/* see CDDBPROTO */ +static ulong +cddb_sum(int n) +{ + int ret; + ret = 0; + while(n > 0) { + ret += n%10; + n /= 10; + } + return ret; +} + +static ulong +diskid(Toc *t) +{ + int i, n, tmp; + Msf *ms, *me; + + n = 0; + for(i=0; i < t->ntrack; i++) + n += cddb_sum(t->track[i].start.m*60+t->track[i].start.s); + + ms = &t->track[0].start; + me = &t->track[t->ntrack].start; + tmp = (me->m*60+me->s) - (ms->m*60+ms->s); + + /* + * the spec says n%0xFF rather than n&0xFF. it's unclear which is correct. + * most CDs are in the database under both entries. + */ + return ((n & 0xFF) << 24 | (tmp << 8) | t->ntrack); +} + +static void +append(char **d, char *s) +{ + char *r; + if (*d == nil) + *d = estrdup(s); + else { + r = emalloc(strlen(*d) + strlen(s) + 1); + strcpy(r, *d); + strcat(r, s); + free(*d); + *d = r; + } +} + +static int +cddbfilltoc(Toc *t) +{ + int fd; + int i; + char *p, *q; + Biobuf bin; + Msf *m; + char *f[10]; + int nf; + char *id, *categ; + char gottrack[MTRACK]; + int gottitle; + + fd = dial("tcp!freedb.freedb.org!888", 0, 0, 0); + if(fd < 0) { + fprint(2, "cannot dial: %r\n"); + return -1; + } + Binit(&bin, fd, OREAD); + + if((p=Brdline(&bin, '\n')) == nil || atoi(p)/100 != 2) { + died: + close(fd); + Bterm(&bin); + fprint(2, "error talking to server\n"); + if(p) { + p[Blinelen(&bin)-1] = 0; + fprint(2, "server says: %s\n", p); + } + return -1; + } + + fprint(fd, "cddb hello gre plan9 9cd 1.0\r\n"); + if((p = Brdline(&bin, '\n')) == nil || atoi(p)/100 != 2) + goto died; + + fprint(fd, "cddb query %8.8lux %d", diskid(t), t->ntrack); + DPRINT(2, "cddb query %8.8lux %d", diskid(t), t->ntrack); + for(i=0; intrack; i++) { + m = &t->track[i].start; + fprint(fd, " %d", (m->m*60+m->s)*75+m->f); + DPRINT(2, " %d", (m->m*60+m->s)*75+m->f); + } + m = &t->track[t->ntrack-1].end; + fprint(fd, " %d\r\n", m->m*60+m->s); + DPRINT(2, " %d\r\n", m->m*60+m->s); + + if((p = Brdline(&bin, '\n')) == nil || atoi(p)/100 != 2) + goto died; + p[Blinelen(&bin)-1] = 0; + DPRINT(2, "cddb: %s\n", p); + nf = tokenize(p, f, nelem(f)); + if(nf < 1) + goto died; + + switch(atoi(f[0])) { + case 200: /* exact match */ + if(nf < 3) + goto died; + categ = f[1]; + id = f[2]; + break; + case 211: /* close matches */ + if((p = Brdline(&bin, '\n')) == nil) + goto died; + if(p[0] == '.') /* no close matches? */ + goto died; + p[Blinelen(&bin)-1] = '\0'; + + /* accept first match */ + nf = tokenize(p, f, nelem(f)); + if(nf < 2) + goto died; + categ = f[0]; + id = f[1]; + + /* snarf rest of buffer */ + while(p[0] != '.') { + if((p = Brdline(&bin, '\n')) == nil) + goto died; + p[Blinelen(&bin)-1] = '\0'; + DPRINT(2, "cddb: %s\n", p); + } + break; + case 202: /* no match */ + default: + goto died; + } + + /* fetch results for this cd */ + fprint(fd, "cddb read %s %s\r\n", categ, id); + + memset(gottrack, 0, sizeof(gottrack)); + gottitle = 0; + do { + if((p = Brdline(&bin, '\n')) == nil) + goto died; + q = p+Blinelen(&bin)-1; + while(isspace(*q)) + *q-- = 0; +DPRINT(2, "cddb %s\n", p); + if(strncmp(p, "DTITLE=", 7) == 0) { + if (gottitle) + append(&t->title, p + 7); + else + t->title = estrdup(p+7); + gottitle = 1; + } else if(strncmp(p, "TTITLE", 6) == 0 && isdigit(p[6])) { + i = atoi(p+6); + if(i < t->ntrack) { + p += 6; + while(isdigit(*p)) + p++; + if(*p == '=') + p++; + + if (gottrack[i]) + append(&t->track[i].title, p); + else + t->track[i].title = estrdup(p); + gottrack[i] = 1; + } + } + } while(*p != '.'); + + fprint(fd, "quit\r\n"); + close(fd); + Bterm(&bin); + + return 0; +} + +void +cddbproc(void *v) +{ + Drive *d; + Toc t; + + threadsetname("cddbproc"); + d = v; + while(recv(d->cdbreq, &t)) + if(cddbfilltoc(&t) == 0) + send(d->cdbreply, &t); +} diff --git a/acme/bin/source/acd/cddbproto b/acme/bin/source/acd/cddbproto new file mode 100644 index 000000000..d1a278318 --- /dev/null +++ b/acme/bin/source/acd/cddbproto @@ -0,0 +1,894 @@ + + +::freedb.org:: + + + + +
    + + + + + +
    + + + +
    + + + +
    + + + +
    freedb.org
    +
    a free approach to cddbp +
    +
    +
    +
    +
    + +
      

    +
    +
    +freedb.org - a free approach to cddbp

    + + + + + +
    + + + + + + + + +
    + + + + + + + +
    Main Menu
    + + + + + + + +
    + + +
    +
  • Home +
  • News-Topics +
  • About +
  • Developers +
  • Applications +
  • Download +
  • Forum +
  • Web-based Search +
  • Web Links +
  • Your Account +
  • Submit News + +
  • + + +
    +
    +
    + + +
    + + + + + + + +
    FAQ
    + + + + + + + +
    + + +
    + Our FAQ can be found here.
    +Please read the FAQ before asking questions via email.
    + + +
    +
    +
    + + +
    + + + + + + + +
    Contact
    + + + + + + + +
    + + +
    + General questions:
    +info@freedb.org
    +Databaseupdates:
    +updates@freedb.org
    +(NOT for submission!)
    +Please keep in mind that we are NOT the Nero-Support and please do not send CD-submits to the adresses above.
    +Submits have to go to:
    +freedb-submit@freedb.org
    + + +
    +
    +
    + + + +
    + + + + + + + +
    Downloads
    + + + + + + + +
    + + +
    + The link to the database downloads is here
    + + +
    +
    +
      + + +
    +
    + + + +
    + CDDB-protocol documentation
    + +

    +
    +				CDDB Protocol
    +
    +			  By Steve Scherf and Ti Kan
    +		          --------------------------
    +
    +Revision: $Id: CDDBPROTO,v 1.6 1997/05/14 07:53:52 steve Exp steve $
    +
    +
    +Notation:
    +-> : client to server
    +<- : server to client
    +
    +terminating marker: `.' character in the beginning of a line
    +
    +
    +Server response code (three digit code):
    +
    +First digit:
    +1xx	Informative message
    +2xx	Command OK
    +3xx	Command OK so far, continue
    +4xx	Command OK, but cannot be performed for some specified reasons
    +5xx	Command unimplemented, incorrect, or program error
    + 
    +Second digit:
    +x0x	Ready for further commands
    +x1x	More server-to-client output follows (until terminating marker)
    +x2x	More client-to-server input follows (until terminating marker)
    +x3x	Connection will close
    +
    +Third digit:
    +xx[0-9]	Command-specific code
    +
    +
    +CDDB Protocol Level 1:
    +----------------------
    +
    +Server sign-on banner:
    +----------------------
    +<- code hostname CDDBP server version ready at date
    +
    +    code:
    +	200	OK, read/write allowed
    +	201	OK, read only
    +	432	No connections allowed: permission denied
    +	433	No connections allowed: X users allowed, Y currently active
    +	434	No connections allowed: system load too high
    +    hostname:
    +	Server host name.  Example: xyz.fubar.com
    +    version:
    +	Version number of server software.  Example: v1.0PL0
    +    date:
    +	Current date and time.  Example: Wed Mar 13 00:41:34 1996
    +
    +
    +Initial client-server handshake:
    +--------------------------------
    +Note: This handshake must occur before other cddb commands
    +      are accepted by the server.
    +
    +Client command:
    +-> cddb hello username hostname clientname version
    +
    +    username:
    +	Login name of user.  Example: johndoe
    +    hostname:
    +	Host name of client.  Example: abc.fubar.com
    +    clientname:
    +	The name of the connecting client.  Example: xmcd, cda, EasyCD,
    +	et cetera. Do not use the name of another client which already
    +	exists.
    +    version:
    +	Version number of client software.  Example: v1.0PL0
    +
    +Server response:
    +<- code hello and welcome username@hostname running clientname version
    +
    +    code:
    +	200	Handshake successful
    +	431	Handshake not successful, closing connection
    +	402	Already shook hands
    +
    +
    +CDDB query:
    +-----------
    +Client command:
    +-> cddb query discid ntrks off1 off2 ... nsecs
    +
    +    discid:
    +	CD disc ID number.  Example: f50a3b13
    +    ntrks:
    +	Total number of tracks on CD.
    +    off1, off2, ...:
    +	Frame offset of the starting location of each track.
    +    nsecs:
    +	Total playing length of CD in seconds.
    +
    +Server response:
    +<- code categ discid dtitle
    +	or
    +<- code close matches found
    +<- categ discid dtitle
    +<- categ discid dtitle
    +<- (more matches...)
    +<- .
    +
    +    code:
    +	200	Found exact match
    +	211	Found inexact matches, list follows (until terminating marker)
    +	202	No match found
    +	403	Database entry is corrupt
    +	409	No handshake
    +    categ:
    +	CD category.  Example: rock
    +    discid:
    +	CD disc ID number of the found entry.  Example: f50a3b13
    +    dtitle:
    +	The Disc Artist and Disc Title (The DTITLE line).  For example:
    +	Pink Floyd / The Dark Side of the Moon
    +
    +
    +CDDB read:
    +----------
    +Client command:
    +-> cddb read categ discid
    +
    +    categ:
    +	CD category.  Example: rock
    +    discid:
    +	CD disc ID number.  Example: f50a3b13
    +
    +Server response:
    +<- code categ discid
    +<- # xmcd 2.0 CD database file
    +<- # ...
    +<- (CDDB data...)
    +<- .
    +	or
    +<- code categ discid No such CD entry in database
    +
    +    code:
    +	210	OK, CDDB database entry follows (until terminating marker)
    +	401	Specified CDDB entry not found.
    +	402	Server error.
    +	403	Database entry is corrupt.
    +	409	No handshake.
    +    categ:
    +	CD category.  Example: rock
    +    discid:
    +	CD disc ID number.  Example: f50a3b13
    +
    +
    +CDDB search: (command not yet implemented in freedb-serversoftware!)
    +------------
    +Client command:
    +-> cddb srch key search_type ... search_type
    +
    +    key:
    +	Pseudo-regular expression to match. Expressions should meet the
    +	following description:
    +
    +	- No white space.
    +	- Printable characters only.
    +	- Case is ignored.
    +    search_type:
    +	CDDB fields to search through.  Example: title
    +	Supported types: artist, title, extd, ext, trk
    +    categ:
    +	CD category.  Example: rock
    +
    +Server response:
    +<- code matches found
    +<- categ discid dtitle
    +<- categ discid dtitle
    +<- (more matches...)
    +<- .
    +
    +    code:
    +	210	OK, matches found, list follows (until terminating marker)
    +	401	No match found.
    +	409	No handshake.
    +    categ:
    +	CD category.  Example: rock
    +    dtitle:
    +	The Disc Artist and Disc Title (The DTITLE line).  For example:
    +	Pink Floyd / The Dark Side of the Moon
    +
    +
    +CDDB write:
    +-----------
    +Client command:
    +-> cddb write categ discid
    +
    +    categ:
    +	CD category.  Example: rock
    +    discid:
    +	CD disc ID number.  Example: f50a3b13
    +
    +Server response:
    +<- code categ discid
    +
    +    code:
    +	320	OK, input CDDB data (until terminating marker)
    +	401	Permission denied.
    +	402	Server file system full/file access failed.
    +	409	No handshake.
    +	501	Entry rejected: reason for rejection.
    +    categ:
    +	CD category.  Example: rock
    +    discid:
    +	CD disc ID number.  Example: f50a3b13
    +
    +Client data:
    +-> # xmcd 2.0 CD database file
    +-> # ...
    +-> (CDDB data)
    +-> .
    +
    +Server response:
    +<- code message
    +
    +    code:
    +	200	CDDB entry accepted
    +	401	CDDB entry rejected: reason why
    +    message:
    +	Message string to indicate write status:
    +	CDDB entry accepted, or CDDB entry rejected.
    +
    +
    +Help information:
    +-----------------
    +Client command:
    +-> help
    +	or
    +-> help cmd
    +
    +    cmd:
    +	CDDB command.  Example: quit
    +
    +	or
    +
    +-> help cmd subcmd
    +
    +    cmd:
    +	CDDB command.  Example: cddb
    +    subcmd:
    +	CDDB command argument.  Example: query
    +
    +Server response:
    +<- code Help information follows
    +<- (help data ...)
    +<- .
    +	or
    +<- code no help information available
    +
    +    code:
    +	210	OK, help information follows (until terminating marker)
    +	401	No help information available
    +
    +
    +Log statistics:
    +---------------
    +Client command:
    +-> log [[-l lines] [start date [end date]] | [day [days]] | [get"]]
    +
    +    lines:
    +	The maximum number of lines to print for each data list in the
    +	log statistics.
    +    start date:
    +	The date after which statistics should be calculated. Date is
    +	of the format: hh[mm[ss[MM[DD[[CC]YY]]]]]
    +
    +	E.g.:	201200053196 for 8:12 PM on May 31, 1996.
    +		20120005312096 for 8:12 PM on May 31, 2096.
    +		080530 for today at at 8:15 and 30 seconds.
    +
    +	If the century ("CC") is omitted, a reasonable guess is made. If
    +	this argument is omitted, all messages are considered.
    +    end date:
    +	The date after which statistics should not be calculated. If
    +	omitted, the end date is assumed to be the current date.
    +    day:
    +	The string "day". This solitary argument will cause a log search
    +	of messages generated within the last day.
    +    days:
    +	A positive numerical argument which modifies the number of days'
    +        messages to searh. If this argument is left out, the default is 1.
    +    get:
    +	The string "get". This solitary argument will cause the server
    +	to send the contents of the log file.
    +
    +Server response:
    +<- code Log summary follows
    +<- (log stats)
    +<- .
    +	or
    +<- code Log follows
    +<- (log stats)
    +<- .
    +
    +    code:
    +	210	OK, log summary follows (until terminating marker)
    +	211	OK, log follows (until terminating marker)
    +	401	Permission denied
    +	402	No log information available
    +	501	Invalid start/end date
    +
    +
    +Message of the day:
    +------------------
    +Client command:
    +-> motd
    +
    +Server response:
    +<- code Last modified: date MOTD follows (until terminating marker)
    +<- (message text)
    +<- .
    +
    +    code:
    +	210	Last modified: 05/31/96 06:31:14 MOTD follows (until terminating marker)
    +	401	No message of the day available
    +    date:
    +	The date the text of the message of the day was modified. The date
    +	appears in the following format:
    +
    +		05/31/96 06:31:14
    +
    +	This value may be used by client software as a message timestamp
    +	for purposes of determining if it has already been displayed. This
    +	format was chosen because it is more easily parsed than the standard
    +	ctime() format.
    +
    +
    +Server protocol level:
    +----------------------
    +Client command:
    +-> proto [level]
    +
    +    level:
    +	The (numerical) protocol level to set the server to.
    +
    +Server response:
    +<- code CDDB protocol level: current cur_level, supported supported_level
    +	or
    +<- code OK, protocol version now: cur_level
    +
    +    code:
    +	200	CDDB protocol level: current cur_level, supported supp_level
    +	201	OK, protocol version now: cur_level
    +	501	Illegal protocol level.
    +	502	Protocol level already cur_level.
    +    cur_level:
    +	The current protocol level at which the server is running.
    +    supported_level:
    +	The maximum supported protocol level.
    +
    +
    +Server sites:
    +--------------
    +Client command:
    +-> sites
    +
    +Server response:
    +<- code OK, site information follows (until terminating `.')
    +<- (data)
    +<- .
    +
    +    code:
    +	210	Ok, site information follows
    +	401	No site information available.
    +
    +    The data format is as follows:
    +	site port latitude longitude description
    +
    +    The fields are as follows:
    +	site:
    +	    The Internet address of the remote site.
    +	port:
    +	    The port at which the server resides on that site.
    +	latitude:
    +	    The latitude of the server site. The format is as follows:
    +		CDDD.MM
    +	    Where "C" is the compass direction (N, S), "DDD" is the
    +	    degrees, and "MM" is the minutes.
    +	longitude:
    +	    The longitude of the server site. Format is as above, except
    +	    the compass direction must be one of (E, W).
    +	description:
    +	    A short description of the geographical location of the site.
    +
    +    Example:
    +	cddb.moonsoft.com 888 N037.23 W122.01 Fremont, CA USA
    +
    +
    +Server status:
    +--------------
    +Client command:
    +-> stat
    +
    +Server response:
    +<- code OK, status information follows (until terminating `.')
    +<- (data)
    +<- .
    +
    +    code:
    +	210	Ok, status information follows
    +
    +    The possible data is as follows:
    +	current proto: <current_level>
    +	    An integer representing the server's current operating protocol
    +	    level.
    +	max proto:     <max_level>
    +	    The maximum supported protocol level.
    +	gets:          <yes | no>
    +	    Whether or not the client is allowed to get log information,
    +	    according to the string "yes" or "no".
    +	updates:       <yes | no>
    +	    Whether or not the client is allowed to initiate a database
    +	    update, according to the string "yes" or "no".
    +	posting:       <yes | no>
    +	    Whether or not the client is allowed to post new entries,
    +	    according to the string "yes" or "no".
    +	quotes:        <yes | no>
    +	    Whether or not quoted arguments are enabled, according to
    +	    the string "yes" or "no".
    +	current users: <num_users>
    +	    The number of users currently connected to the server.
    +	max users:     <num_max_users>
    +	    The number of users that can concurrently connect to the server.
    +	strip ext:	<yes | no>
    +	    Whether or not extended data is stripped by the server before
    +	    presented to the user.
    +	Database entries: <num_db_entries>
    +	    The total number of entries in the database.
    +	Database entries by category:
    +	    This field is followed by a list of catgories and the number
    +	    of entries in that category. Each entry is of the following
    +	    format:
    +
    +		<white space>catgory: <num_db_entries>
    +
    +	    The list of entries is terminated by the first line that does
    +	    not begin with white space.
    +
    +	Pending file transmissions:
    +	    This field is followed by a list of sites that are fed new
    +	    database entries at periodic intervals, and the number of
    +	    entries that have yet to be transmitted to that site.
    +	    Each entry is of the following format:
    +
    +		<white space>site: <num_db_entries>
    +
    +	    The list of entries is terminated by the first line that does
    +	    not begin with white space.
    +
    +	This list may grow as needed, so clients must expect possible
    +	unrecognizable data. Also, additional fields may be added to
    +	the currently existing lines, although no existing fields will
    +	be removed or change position.
    +	
    +
    +Server version:
    +---------------
    +Client command:
    +-> ver
    +
    +Server response:
    +<- code servername version copyright
    +	or
    +<- code Version information follows
    +
    +    code:
    +	200	Version information.
    +	211	OK, version information follows (until terminating marker)
    +    version:
    +	Server version.  Example: v1.0PL0
    +    copyright:
    +	Copyright string.  Example: Copyright (c) 1996 Steve Scherf
    +
    +
    +Database update:
    +----------------
    +Client command:
    +-> update
    +
    +Server response:
    +<- code Updating the database.
    +	or
    +<- code Permission denied.
    +	or
    +<- code Unable to update the database.
    +
    +    code:
    +	200 Updating the database.
    +	401 Permission denied.
    +	402 Unable to update the database.
    +
    +
    +Server users:
    +-------------
    +Client command:
    +-> whom
    +
    +Server response:
    +<- code User list follows
    +
    +    code:
    +	210	OK, user list follows (until terminating marker)
    +	401	No user information available.
    +
    +
    +Client sign-off:
    +----------------
    +Client command:
    +-> quit
    +
    +Server response:
    +<- code hostname closing connection.  Goodbye.
    +
    +    code:
    +	230	OK, goodbye.
    +    hostname:
    +	Server host name.  Example: xyz.fubar.com
    +
    +
    +General errors:
    +---------------
    +
    +Server response:
    +<- code error
    +    code:
    +	402	Server error.
    +	408	CGI environment error.
    +	500	Command syntax error, command unknown, command unimplemented.
    +	530	Server error, server timeout.
    +
    +
    +Reserved errors:
    +----------------
    +
    +The following error codes are reserved, and will never be returned as a
    +response to a CDDB protocol command. They are intended to be used internally
    +by clients that have a need for generating pseudo-responses.
    +
    +	600-699
    +
    +
    +CDDB Protocol Level 2:
    +----------------------
    +
    +In all respects, protocol level 2 is the same as level 1, with the exceptions
    +listed below.
    +
    +Arguments to commands may be surrounded by double quotes. All characters
    +within the quotes, including white space, are included in the argument. All
    +white space is replaced by the `_' (2Dh) character by the server. White space
    +is defined as ` ' (20h) and `^I' (control-I, or 09h).
    +
    +Arguments containing quotes that should not be interpreted with the special
    +meaning described above should be escaped with a preceding backslash character,
    +or '' (5Ch). If an actual backslash appears in an argument, it should be
    +escaped with a preceding backslash. In both cases, the preceding backslash
    +will be removed from the input before being interpreted.
    +
    +
    +CDDB Protocol Level 3:
    +----------------------
    +
    +Protocol level 3 is the same as level 2, with the exception listed below.
    +
    +The output of the "sites" command has changed to meet the folowing description:
    +
    +    The data format is as follows:
    +	site protocol port address latitude longitude description
    +
    +    The fields are as follows:
    +	site:
    +	    The Internet address of the remote site.
    +	protocol:
    +	    The transfer protocol used to access the site.
    +	port:
    +	    The port at which the server resides on that site.
    +	address:
    +	    Any additional addressing information needed to access the
    +	    server. For example, for HTTP protocol servers, this would be
    +	    the path to the CDDB server CGI script. This field will be
    +	    "-" if no additional addressing information is needed.
    +	latitude:
    +	    The latitude of the server site. The format is as follows:
    +		CDDD.MM
    +	    Where "C" is the compass direction (N, S), "DDD" is the
    +	    degrees, and "MM" is the minutes.
    +	longitude:
    +	    The longitude of the server site. Format is as above, except
    +	    the compass direction must be one of (E, W).
    +	description:
    +	    A short description of the geographical location of the site.
    +
    +    Example:
    +	cddb.moonsoft.com cddbp 888 - N037.23 W122.01 Fremont, CA USA
    +	cddb.moonsoft.com http 80 /~cddb/cddb.cgi N037.23 W122.01 Fremont,CA USA
    +
    +Note that a site may appear once for each type of protocol it supports for
    +accessing the server.
    +
    +
    +Addendum A: Proper use of CDDBP:
    +--------------------------------
    +
    +There are a few guidelines that must be followed in order to make proper use
    +of CDDBP:
    +
    +- When handshaking with the server via the "cddb hello" command, the client
    +  must specify its own name and version, not that of some other client (such
    +  as xmcd). Also, the "username" and "hostname" must be that of the actual
    +  user running the program, not some hardwired value.
    +
    +- Before performing a "cddb read", the client program MUST perform a
    +  "cddb query". Failure to do so may result in the client program receiving
    +  incorrect CDDB data from the server. Also, without performing a query, the
    +  client program will not benefit from close matches in the event of the
    +  lack of an exact match in the database.
    +
    +- For accounting purposes, it is best if client programs only perform a single
    +  "cddb query" for a particular disc before performing a "cddb read" for that
    +  disc.
    +
    +
    +Addendum B: CDDBP under HTTP:
    +-----------------------------
    +
    +Accessing a server as a CGI script is done in much the same way as through
    +direct interaction. The command set is identical, though the method of
    +communication is through CDDBP commands encapsulated in the HTTP protocol.
    +The only limitation is that a single command may be executed per connection,
    +since HTTP is not truly interactive. For the server to be accessed in this
    +way, it must reside on the target host at a known URL which is accessible by
    +the host HTTP server. The client program must connect to the HTTP server on
    +the target host and issue an HTTP command with the appropriate CDDBP command
    +encapsulated within.
    +
    +Commands may be submitted to servers in CGI mode using either the "GET" or
    +"POST" HTTP commands. Both methods are supported, and there is no real
    +difference between how both are to be used other than the syntactical
    +difference between the two methods. The "POST" method may provide the ability
    +to issue longer commands, though, depending on the architecture of the system
    +on which the server resides.
    +
    +The server command must be sent as part of the "Request-URI" in the case
    +of the "GET" method, and as the "Entity-Body" in the case of the "POST"
    +method. In both cases, the command must be of the following form:
    +
    +cmd=server+command&hello=joe+my.host.com+clientname+version&proto=1
    +
    +Where the text following the "cmd=" represents the CDDBP command to be
    +executed, the text following the "hello=" represents the arguments to
    +the "cddb hello" command that is implied by this operation, and the
    +text following the "proto=" represents the argument to the "proto" command
    +that is implied by this operation.
    +
    +The "+" characters in the input represent spaces, and will be translated
    +by the server before performing the request. Special characters may be
    +represented by the sequence "%XX" where "XX" is a two-digit hex number
    +corresponding to the ASCII (ISO-8859-1) sequence of that character. The
    +"&" characters denote separations between the command, hello and proto
    +arguments. Newlines and carriage returns must not appear anywhere in the
    +string except at the end.
    +
    +All CDDBP commands are supported under HTTP, except for "cddb hello",
    +"cddb write", "proto" and "quit".
    +
    +For example, should user "joe" on system "my.host.com" be running xmcd 2.1,
    +a read request for his currenly playing CD might look like this:
    +
    +cmd=cddb+read+rock+12345678&hello=joe+my.host.com+xmcd+2.1&proto=1
    +
    +The server will perform the implied "proto" and "cddb hello" commands,
    +and then perform the requested "cddb read" command.
    +
    +Server response to the command is encapsulated in the HTTP server response,
    +and appears in the "Entity-Body" exactly as it would appear using the CDDBP
    +protocol. Note that the HTTP response "Entity-Header" is not guaranteed to
    +contain a "Content-Length" field, so clients should be prepared to accept
    +variable length input. This is no different from operation under CDDBP. The
    +header will always contain a Mime "Content-Type" field which describes the
    +body of data as "text/plain".
    +
    +For more detailed information on HTTP and Mime, see RFC 1945 and RFC 1521.
    +
    +
    +   +
     


    + +

    +
    +
    +
    +
    + + diff --git a/acme/bin/source/acd/discid b/acme/bin/source/acd/discid new file mode 100644 index 000000000..1bc9dbf66 --- /dev/null +++ b/acme/bin/source/acd/discid @@ -0,0 +1,159 @@ + +CDDB DISCID +----------- + +Both forms of CDDB access require that the software compute a "disc +ID" which is an identifier that is used to access the CDDB. The disc +ID is a 8-digit hexadecimal (base-16) number, computed using data from +a CD's Table-of-Contents (TOC) in MSF (Minute Second Frame) form. The +algorithm is listed below in Appendix A. + +It is crucial that your software compute the disc ID correctly. If it +does not generate the correct disc ID, it will not be compatible with CDDB. +Moreover, if your software submits CDDB entries with bad disc IDs to the +CDDB archives, it could compromise the integrity of the CDDB. + +[...] + +APPENDIX A - CDDB DISCID ALGORITHM +---------------------------------- + +The following is a C code example that illustrates how to generate the +CDDB disc ID. [...] A text description +of the algorithm follows, which should contain the necessary information +to code the algorithm in any programming language. + + +struct toc { + int min; + int sec; + int frame; +}; + +struct toc cdtoc[100]; + +int +read_cdtoc_from_drive(void) +{ + /* Do whatever is appropriate to read the TOC of the CD + * into the cdtoc[] structure array. + */ + return (tot_trks); +} + +int +cddb_sum(int n) +{ + int ret; + + /* For backward compatibility this algorithm must not change */ + + ret = 0; + + while (n > 0) { + ret = ret + (n % 10); + n = n / 10; + } + + return (ret); +} + +unsigned long +cddb_discid(int tot_trks) +{ + int i, + t = 0, + n = 0; + + /* For backward compatibility this algorithm must not change */ + + i = 0; + + while (i < tot_trks) { + n = n + cddb_sum((cdtoc[i].min * 60) + cdtoc[i].sec); + i++; + } + + t = ((cdtoc[tot_trks].min * 60) + cdtoc[tot_trks].sec) - + ((cdtoc[0].min * 60) + cdtoc[0].sec); + + return ((n % 0xff) << 24 | t << 8 | tot_trks); +} + +main() +{ + int tot_trks; + + tot_trks = read_cdtoc_from_drive(); + printf("The discid is %08x", cddb_discid(tot_trks)); +} + + +This code assumes that your compiler and architecture support 32-bit +integers. + +The cddb_discid function computes the discid based on the CD's TOC data +in MSF form. The frames are ignored for this purpose. The function is +passed a parameter of tot_trks (which is the total number of tracks on +the CD), and returns the discid integer number. + +It is assumed that cdtoc[] is an array of data structures (records) +containing the fields min, sec and frame, which are the minute, second +and frame offsets (the starting location) of each track. This +information is read from the TOC of the CD. There are actually +tot_trks + 1 "active" elements in the array, the last one being the +offset of the lead-out (also known as track 0xAA). + +The function loops through each track in the TOC, and for each track +it takes the (M * 60) + S (total offset in seconds) of the track and +feeds it to cddb_sum() function, which simply adds the value of each digit +in the decimal string representation of the number. A running sum of this +result for each track is kept in the variable n. + +At the end of the loop: +1. t is calculated by subtracting the (M * 60) + S offset of the lead-out +minus the (M * 60) + S offset of first track (yielding the length of +the disc in seconds). + +2. The result of (n modulo FFh) is left-shifted by 24 bits. + +3. t is left shifted by 8. + +The bitwise-OR operation of result 2., 3. and the tot_trks number is +used as the discid. + +The discid is represented in hexadecimal form for the purpose of +xmcd cddb file names and the DISCID= field in the xmcd cddb file itself. +If the hexadecimal string is less than 8 characters long, it is +zero-padded to 8 characters (i.e., 3a8f07 becomes 003a8f07). All +alpha characters in the string should be in lower case, where +applicable. + +Important note for clients using the MS-Windows MCI interface: + +The Windows MCI interface does not provide the MSF location of the +lead-out. Thus, you must compute the lead-out location by taking the +starting position of the last track and add the length of the last track +to it. However, the MCI interface returns the length of the last track +as ONE FRAME SHORT of the actual length found in the CD's TOC. In most +cases this does not affect the disc ID generated, because we truncate +the frame count when computing the disc ID anyway. However, if the +lead-out track has an actual a frame count of 0, the computed quantity +(based on the MSF data returned from the MCI interface) would result in +the seconds being one short and the frame count be 74. For example, +a CD with the last track at an offset of 48m 32s 12f and having a +track length of 2m 50s 63f has a lead-out offset of 51m 23s 0f. Windows +MCI incorrectly reports the length as 2m 50s 62f, which would yield a +lead-out offset of 51m 22s 74f, which causes the resulting truncated +disc length to be off by one second. This will cause an incorrect disc +ID to be generated. You should thus add one frame to the length of the +last track when computing the location of the lead-out. + +The easiest way for Windows clients to compute the lead-out given information +in MSF format is like this: + +(offset_minutes * 60 * 75) + (offset_seconds * 75) + offset_frames + +(length_minutes * 60 * 75) + (length_seconds * 75) + length_frames + 1 = X + +Where X is the offset of the lead-out in frames. To find the lead-out in +seconds, simply divide by 75 and discard the remainder. diff --git a/acme/bin/source/acd/mailinglist b/acme/bin/source/acd/mailinglist new file mode 100644 index 000000000..002fd8da8 --- /dev/null +++ b/acme/bin/source/acd/mailinglist @@ -0,0 +1,220 @@ + + +::freedb.org:: + + + + +
    + + + + + +
    + + + +
    + + + +
    + + + +
    freedb.org
    +
    a free approach to cddbp +
    +
    +
    +
    +
    + +
      

    +
    +
    +freedb.org - a free approach to cddbp

    + + + + + +
    + + + + + + + + +
    + + + + + + + +
    Main Menu
    + + + + + + + +
    + + +
    +
  • Home +
  • News-Topics +
  • About +
  • Developers +
  • Applications +
  • Download +
  • Forum +
  • Web-based Search +
  • Web Links +
  • Your Account +
  • Submit News + +
  • + + +
    +
    +
    + + +
    + + + + + + + +
    FAQ
    + + + + + + + +
    + + +
    + Our FAQ can be found here.
    +Please read the FAQ before asking questions via email.
    + + +
    +
    +
    + + +
    + + + + + + + +
    Contact
    + + + + + + + +
    + + +
    + General questions:
    +info@freedb.org
    +Databaseupdates:
    +updates@freedb.org
    +(NOT for submission!)
    +Please keep in mind that we are NOT the Nero-Support and please do not send CD-submits to the adresses above.
    +Submits have to go to:
    +freedb-submit@freedb.org
    + + +
    +
    +
    + + + +
    + + + + + + + +
    Downloads
    + + + + + + + +
    + + +
    + The link to the database downloads is here
    + + +
    +
    +
      + + +
    +
    + + + +
    + Mailinglists
    + +

    + There are a couple of mailinglists available: + +

    fdb-apps@freedb.org

    + +This mailinglist is intended for all developers that want to +exchange tips and tricks, codesnippets and so on. Subcribe +to this list by sending an email to
    +fdb-apps-request@freedb.org
    +with the word "subscribe" in the body of the email. +

    fdb-dev@freedb.org

    + +This list is for anyone interested in developing the freedb.org +server software. Subcribe +to this list by sending an email to
    +fdb-dev-request@freedb.org
    +with the word "subscribe" in the body of the email. +
    +   +
     


    + +

    +
    +
    +
    +
    + + diff --git a/acme/bin/source/acd/main.c b/acme/bin/source/acd/main.c new file mode 100644 index 000000000..2ac388f56 --- /dev/null +++ b/acme/bin/source/acd/main.c @@ -0,0 +1,135 @@ +#include "acd.h" + +int debug; + +void +usage(void) +{ + fprint(2, "usage: acd dev\n"); + threadexitsall("usage"); +} + +Alt +mkalt(Channel *c, void *v, int op) +{ + Alt a; + + memset(&a, 0, sizeof(a)); + a.c = c; + a.v = v; + a.op = op; + return a; +} + +void +freetoc(Toc *t) +{ + int i; + + free(t->title); + for(i=0; intrack; i++) + free(t->track[i].title); +} + +void +eventwatcher(Drive *d) +{ + enum { STATUS, WEVENT, TOCDISP, DBREQ, DBREPLY, NALT }; + Alt alts[NALT+1]; + Toc nt, tdb; + Event *e; + Window *w; + Cdstatus s; + char buf[40]; + + w = d->w; + + alts[STATUS] = mkalt(d->cstatus, &s, CHANRCV); + alts[WEVENT] = mkalt(w->cevent, &e, CHANRCV); + alts[TOCDISP] = mkalt(d->ctocdisp, &nt, CHANRCV); + alts[DBREQ] = mkalt(d->cdbreq, &tdb, CHANNOP); + alts[DBREPLY] = mkalt(d->cdbreply, &nt, CHANRCV); + alts[NALT] = mkalt(nil, nil, CHANEND); + for(;;) { + switch(alt(alts)) { + case STATUS: + //DPRINT(2, "s..."); + d->status = s; + if(s.state == Scompleted) { + s.state = Sunknown; + advancetrack(d, w); + } + //DPRINT(2, "status %d %d %d %M %M\n", s.state, s.track, s.index, s.abs, s.rel); + sprint(buf, "%d:%2.2d", s.rel.m, s.rel.s); + setplaytime(w, buf); + break; + case WEVENT: + //DPRINT(2, "w..."); + acmeevent(d, w, e); + break; + case TOCDISP: + //DPRINT(2,"td..."); + freetoc(&d->toc); + d->toc = nt; + drawtoc(w, d, &d->toc); + tdb = nt; + alts[DBREQ].op = CHANSND; + break; + case DBREQ: /* sent */ + //DPRINT(2,"dreq..."); + alts[DBREQ].op = CHANNOP; + break; + case DBREPLY: + //DPRINT(2,"drep..."); + freetoc(&d->toc); + d->toc = nt; + redrawtoc(w, &d->toc); + break; + } + } +} + +void +threadmain(int argc, char **argv) +{ + Scsi *s; + Drive *d; + char buf[80]; + + ARGBEGIN{ + case 'v': + debug++; + scsiverbose++; + }ARGEND + + if(argc != 1) + usage(); + + fmtinstall('M', msfconv); + + if((s = openscsi(argv[0])) == nil) + error("opening scsi: %r"); + + d = malloc(sizeof(*d)); + if(d == nil) + error("out of memory"); + memset(d, 0, sizeof d); + + d->scsi = s; + d->w = newwindow(); + d->ctocdisp = chancreate(sizeof(Toc), 0); + d->cdbreq = chancreate(sizeof(Toc), 0); + d->cdbreply = chancreate(sizeof(Toc), 0); + d->cstatus = chancreate(sizeof(Cdstatus), 0); + + proccreate(wineventproc, d->w, STACK); + proccreate(cddbproc, d, STACK); + proccreate(cdstatusproc, d, STACK); + + cleanname(argv[0]); + snprint(buf, sizeof(buf), "%s/", argv[0]); + winname(d->w, buf); + + wintagwrite(d->w, "Stop Pause Resume Eject Ingest ", 5+6+7+6+7); + eventwatcher(d); +} diff --git a/acme/bin/source/acd/mkfile b/acme/bin/source/acd/mkfile new file mode 100644 index 000000000..7b549a6c5 --- /dev/null +++ b/acme/bin/source/acd/mkfile @@ -0,0 +1,22 @@ +args, Msf); + fmtprint(fp, "%d.%d.%d", m.m, m.s, m.f); + return 0; +} + +static int +status(Drive *d) +{ + uchar cmd[12]; + + memset(cmd, 0, sizeof cmd); + cmd[0] = 0xBD; + return scsi(d->scsi, cmd, sizeof cmd, nil, 0, Snone); +} + +static int +playmsf(Drive *d, Msf start, Msf end) +{ + uchar cmd[12]; + + memset(cmd, 0, sizeof cmd); + cmd[0] = 0x47; + cmd[3] = start.m; + cmd[4] = start.s; + cmd[5] = start.f; + cmd[6] = end.m; + cmd[7] = end.s; + cmd[8] = end.f; + + return scsi(d->scsi, cmd, sizeof cmd, nil, 0, Snone); +} + +int +playtrack(Drive *d, int start, int end) +{ + Toc *t; + + t = &d->toc; + + if(t->ntrack == 0) + return -1; + + if(start < 0) + start = 0; + if(end >= t->ntrack) + end = t->ntrack-1; + if(end < start) + end = start; + + return playmsf(d, t->track[start].start, t->track[end].end); +} + +int +resume(Drive *d) +{ + uchar cmd[12]; + + memset(cmd, 0, sizeof cmd); + cmd[0] = 0x4B; + cmd[8] = 0x01; + return scsi(d->scsi, cmd, sizeof cmd, nil, 0, Snone); +} + +int +pause(Drive *d) +{ + uchar cmd[12]; + + memset(cmd, 0, sizeof cmd); + cmd[0] = 0x4B; + return scsi(d->scsi, cmd, sizeof cmd, nil, 0, Snone); +} + +int +stop(Drive *d) +{ + uchar cmd[12]; + + memset(cmd, 0, sizeof cmd); + cmd[0] = 0x4E; + return scsi(d->scsi, cmd, sizeof cmd, nil, 0, Snone); +} + +int +eject(Drive *d) +{ + uchar cmd[12]; + + memset(cmd, 0, sizeof cmd); + cmd[0] = 0x1B; + cmd[1] = 1; + cmd[4] = 2; + return scsi(d->scsi, cmd, sizeof cmd, nil, 0, Snone); +} + +int +ingest(Drive *d) +{ + uchar cmd[12]; + + memset(cmd, 0, sizeof cmd); + cmd[0] = 0x1B; + cmd[1] = 1; + cmd[4] = 3; + return scsi(d->scsi, cmd, sizeof cmd, nil, 0, Snone); +} + +static Msf +rdmsf(uchar *p) +{ + Msf msf; + + msf.m = p[0]; + msf.s = p[1]; + msf.f = p[2]; + return msf; +} + +static ulong +rdlba(uchar *p) +{ + return (p[0]<<16) | (p[1]<<8) | p[2]; +} + +/* not a Drive, so that we don't accidentally touch Drive.toc */ +int +gettoc(Scsi *s, Toc *t) +{ + int i, n; + uchar cmd[12]; + uchar resp[1024]; + +Again: + memset(t, 0, sizeof(*t)); + memset(cmd, 0, sizeof cmd); + cmd[0] = 0x43; + cmd[1] = 0x02; + cmd[7] = sizeof(resp)>>8; + cmd[8] = sizeof(resp); + + s->changetime = 1; + /* scsi sets nchange, changetime */ + if(scsi(s, cmd, sizeof cmd, resp, sizeof(resp), Sread) < 4) + return -1; + + if(s->changetime == 0) { + t->ntrack = 0; + werrstr("no media"); + return -1; + } + + if(t->nchange == s->nchange && t->changetime != 0) + return 0; + + t->nchange = s->nchange; + t->changetime = s->changetime; + + if(t->ntrack > MTRACK) + t->ntrack = MTRACK; + +DPRINT(2, "%d %d\n", resp[3], resp[2]); + t->ntrack = resp[3]-resp[2]+1; + t->track0 = resp[2]; + + n = ((resp[0]<<8) | resp[1])+2; + if(n < 4+8*(t->ntrack+1)) { + werrstr("bad read0 %d %d", n, 4+8*(t->ntrack+1)); + return -1; + } + + for(i=0; i<=t->ntrack; i++) /* <=: track[ntrack] = end */ + t->track[i].start = rdmsf(resp+4+i*8+5); + + for(i=0; intrack; i++) + t->track[i].end = t->track[i+1].start; + + memset(cmd, 0, sizeof cmd); + cmd[0] = 0x43; + cmd[7] = sizeof(resp)>>8; + cmd[8] = sizeof(resp); + if(scsi(s, cmd, sizeof cmd, resp, sizeof(resp), Sread) < 4) + return -1; + + if(s->changetime != t->changetime || s->nchange != t->nchange) { + fprint(2, "disk changed underfoot; repeating\n"); + goto Again; + } + + n = ((resp[0]<<8) | resp[1])+2; + if(n < 4+8*(t->ntrack+1)) { + werrstr("bad read"); + return -1; + } + + for(i=0; i<=t->ntrack; i++) + t->track[i].bstart = rdlba(resp+4+i*8+5); + + for(i=0; intrack; i++) + t->track[i].bend = t->track[i+1].bstart; + + return 0; +} + +static void +dumptoc(Toc *t) +{ + int i; + + fprint(1, "%d tracks\n", t->ntrack); + for(i=0; intrack; i++) + print("%d. %M-%M (%lud-%lud)\n", i+1, + t->track[i].start, t->track[i].end, + t->track[i].bstart, t->track[i].bend); +} + +static void +ping(Drive *d) +{ + uchar cmd[12]; + + memset(cmd, 0, sizeof cmd); + cmd[0] = 0x43; + scsi(d->scsi, cmd, sizeof(cmd), nil, 0, Snone); +} + +static int +playstatus(Drive *d, Cdstatus *stat) +{ + uchar cmd[12], resp[16]; + + memset(cmd, 0, sizeof cmd); + cmd[0] = 0x42; + cmd[1] = 0x02; + cmd[2] = 0x40; + cmd[3] = 0x01; + cmd[7] = sizeof(resp)>>8; + cmd[8] = sizeof(resp); + if(scsi(d->scsi, cmd, sizeof(cmd), resp, sizeof(resp), Sread) < 0) + return -1; + + switch(resp[1]){ + case 0x11: + stat->state = Splaying; + break; + case 0x12: + stat->state = Spaused; + break; + case 0x13: + stat->state = Scompleted; + break; + case 0x14: + stat->state = Serror; + break; + case 0x00: /* not supported */ + case 0x15: /* no current status to return */ + default: + stat->state = Sunknown; + break; + } + + stat->track = resp[6]; + stat->index = resp[7]; + stat->abs = rdmsf(resp+9); + stat->rel = rdmsf(resp+13); + return 0; +} + +void +cdstatusproc(void *v) +{ + Drive *d; + Toc t; + Cdstatus s; + + t.changetime = ~0; + t.nchange = ~0; + + threadsetname("cdstatusproc"); + d = v; + DPRINT(2, "cdstatus %d\n", getpid()); + for(;;) { + ping(d); + //DPRINT(2, "d %d %d t %d %d\n", d->scsi->changetime, d->scsi->nchange, t.changetime, t.nchange); + if(playstatus(d, &s) == 0) + send(d->cstatus, &s); + if(d->scsi->changetime != t.changetime || d->scsi->nchange != t.nchange) { + if(gettoc(d->scsi, &t) == 0) { + DPRINT(2, "sendtoc...\n"); + if(debug) dumptoc(&t); + send(d->ctocdisp, &t); + } else + DPRINT(2, "error: %r\n"); + } + sleep(1000); + } +} diff --git a/acme/bin/source/acd/outline b/acme/bin/source/acd/outline new file mode 100644 index 000000000..5ab337d9c --- /dev/null +++ b/acme/bin/source/acd/outline @@ -0,0 +1,32 @@ +acd is composed of four procs + +wineventproc (win.c:/^wineventproc) + reads acme window events, sends them along w->cevent. + +cdstatusproc (mmc.c:/^cdstatusproc) + reads cd status once per second, sending + status updates to d->cstatus. + detects disk changes, sends new tocs to d->ctocdisp. + +cddbproc (cddb.c:/^cddbproc) + reads tocs from d->cdbreq, if it finds + translations in the cddb, sends new tocs to d->cdbreply. + +eventwatcher (main.c:/^eventwatcher) + the main event loop. + reads status from d->cstatus. + reads events from w->cevent. + reads new tocs to display from d->ctocdisp. + sends new tocs to translate to d->cdbreq. + reads new translated tocs from d->cdbreply. + +an interesting bug in the original design: + both cdstatusproc and the eventwatcher proc + issue scsi commands. (the eventwatcher responds to + things such as Play, Stop, etc., as well as advancing the track.) + + the sd(3) driver did not expect overlapped commands, + and crashed. + + this has been fixed by making the scsi(2) commands threadsafe, + and making the sd(3) driver more robust. diff --git a/acme/bin/source/acd/submit b/acme/bin/source/acd/submit new file mode 100644 index 000000000..49aaf1662 --- /dev/null +++ b/acme/bin/source/acd/submit @@ -0,0 +1,220 @@ +CDDB SUBMISSION +--------------- + +Your software may allow users to enter CDDB data and then submit them +to the freedb archive. +There are two methods of submission: via e-mail or via http using submit.cgi + +1. Submission via e-mail +------------------------ + +Your software has to send the entry to the +following address: + + freedb-submit@freedb.org + +You may implement a button or somesuch in your software's user-interface +to facilitate this. The destination e-mail address should be made +user-configurable. + +There should be one e-mail message per freedb entry. The mail Subject +line should be in the form "cddb category discid". For example: + +Subject: cddb rock 850f970b + +The body of the e-mail message should be in the format of a CDDB file +entry as described here. The messages should contain only +plain ASCII text. Do not attach encoded information or add special +escape sequences. + +Note that the disc ID specified in the mail Subject line should +also appear in the list of disc IDs in the DISCID= field of the +CDDB file entry. If not, it is considered an error and the submission +will be rejected. + +You should only allow categories that are currently supported by the +freedb (blues, classical, country, data, folk, jazz, misc, newage, +reggae, rock, soundtrack). Submissions specifying unsupported +categories will be rejected. + +Please do not allow a user to submit CD database entries that +have completely unfilled contents (i.e., blank information in the +disc artist/title as well as the track titles, or filled with +useless default information like "track 1", "track 2", etc.). +While the current CD database server checks and rejects submissions +that have a blank DTITLE line, it doesn't (and can't feasibly) check +the track titles effectively, nor can it check any of these fields +if they are filled with a default string. If it were, it would +have to be hacked to know about the default strings of every possible +client. + +Thus, please design your client with this in mind. This is a somewhat +tricky thing to do, as some CDs contain blank tracks with no titles +and you need to allow for that. An example minimum requirement +that a CD player client should meet is listed below: + +1. Don't allow the "send" or "submit" feature to be activated if + the CD database information form is not edited at all. +2. Check that the disc artist/title contains something (that the user + typed in). +3. Check that all of the tracks have a title filled in by the user + (some (but not all!) may be blank, but not the default string). + +This should minimize the number of useless garbage being submitted +into the CD database. + +Before you release your software, please be sure that it produces +submissions that adheres to the CDDB file format, and that the frame +offset, disc length, and disc ID information are correctly computed. +For testing, please make your software send submissions to the +following e-mail address (rather than the real submission site at +freedb-submit@freedb.org): + + test-submit@freedb.org + +The test address performs sanity checking on the CDDB submission and +sends back pass/fail confirmation, but does not actually deposit the +entry in the CD database. + +2. Submission via http +---------------------- + +For submit via http, your application has to transmit the entry to the +database through a CGI program at the following URL: + +http://freedb.freedb.org/~cddb/submit.cgi + +Submissions are made through the CGI program as follows. You must only use +the "POST" method of sending data; "GET" is not supported. There are several +HTTP "Entity-Header" fields that must be included in the data followed by a +blank line, followed by the "Entity-Body" (a.k.a the CDDB entry) in the +format described in Appendix B below. The required header fields are: + +Category: CDDB_category +Discid: CDDB_discid +User-Email: user@domain +Submit-Mode: test_or_submit +Content-Length: length_of_CDDB_entry + +Where: + +- "CDDB_category" is one of the valid CDDB categories (blues, classical, + country, data, folk, jazz, misc, newage, reggae, rock, soundtrack). + Invalid categories will result in the entry being rejected. + +- "CDDB_discid" is the 8-digit hex CDDB disc ID of the entry as described in + the "Discid howto" section. This must be the same disc ID that appears + in the "DISCID=" section of the entry being submitted. If not, the entry + will be rejected. + +- "user@domain" is the valid email address of the user submitting the entry. + This is required in case a submission failure notice must be sent to the + user. + +- "test_or_submit" is the word "test" or "submit" (without the surrounding + quotes) to indicate whether the submission is a test submission or a real + submission to the database, respectively. See below for an explanation of + test submissions. + +- "length_of_CDDB_entry" is the size in bytes of the CDDB entry being + submitted. This number does not include the length of the header or the + blank line separating the HTTP header and the CDDB entry. + +There are several additional optional HTTP header fields that may also +be specified (but which are currently not used by the freedb): + +Charset: character_set_of_CDDB_entry +X-Cddbd-Note: message for user + +Where: + +- "character_set_of_CDDB_entry" is one of ISO-8859-1 or US-ASCII (lower case + may be used if desired). This specifies to the CDDB server which character + set the CDDB entry has been encoded in. If your application knows the + user's character set, then you should specify it here. Only these two + character sets are supported currently. DO NOT specify the character set + if your application does not have any way of verifying the user's character + set (i.e. do not guess; it's better not to specify it at all). + +- "message for user" is an arbitrary message to be included at the top of + any rejection notice that may be sent to the submitting user. + +An example submission showing the HTTP command, "Entity-Header" and "Entity- +Body" follows: + +POST /~cddb/submit.cgi HTTP/1.0 +Category: rock +Discid: 2a09310a +User-Email: joe@joeshost.joesdomain.com +Submit-Mode: submit +Charset: ISO-8859-1 +X-Cddbd-Note: Problems with Super CD Player? Send email to support@supercd.com. +Content-Length: 820 + +# xmcd +# +# Track frame offsets: +[ data omitted in this example for brevity ] +PLAYORDER= + +Note the blank line between the "Content-Length" header field and the +"# xmcd" which marks the beginning of the CDDB entry. + +When your application submits an entry through the CGI program, it will +respond with a 3-digit response code indicating whether or not the entry has +been forwarded to the freedb server for inclusion in the database, followed +by a textual description of the response code. For example: + +200 OK, submission has been sent. +400 Internal error: failed to forward submission. +500 Missing required header information. + +These are but a few of the possible responses. +See the description of the CDDB server protocol for more information on +handling response codes. + +The body of the freedb entry being submitted should be sent verbatim as +described in the database-format specification. DO NOT encode the data in any +way before transmitting it; data must be sent as raw text. For example, +Windows programmers should not use the Windows URL encode function prior to +calling the submit CGI program. Doing so may lead to corrupt data being sent +and also possibly to rejected submissions. + +You may implement a button or somesuch in your software's user interface +to initiate submissions. Rejected submissions are automatically returned +via email to the sender specified in the "User-Email" header field with an +explanation of the reason for the rejection. + +Please do not allow a user to submit CD database entries that +have completely unfilled contents (i.e., blank information in the +disc artist/title as well as the track titles, or filled with +useless default information like "track 1", "track 2", etc.). +While the current CD database server checks and rejects submissions +that have a blank DTITLE line, it doesn't (and can't feasibly) check +the track titles effectively, nor can it check any of these fields +if they are filled with a default string. If it were, it would +have to be hacked to know about the default strings of every possible +client. + +Thus, please design your client with this in mind. This is a somewhat +tricky thing to do, as some CDs contain blank tracks with no titles +and you need to allow for that. An example minimum requirement +that a CD player client should meet is listed below: + +1. Don't allow the "send" or "submit" feature to be activated if + the CD database information form is not edited at all. +2. Check that the disc artist/title contains something (that the user + typed in). +3. Check that all of the tracks have a title filled in by the user. + (some (but not all!) may be blank, but not the default string). + +Before you release your software, please be sure that it produces +submissions that adhere to the CDDB file format, and that the frame +offset, disc length, and disc ID information are correctly computed. +For testing, please make your software send submissions with the +"Submit-Mode" HTTP header field set to "test". + +CDDB submissions sent in test mode will be sanity-checked by the freedb server +and pass/fail confirmation sent back to the submitter, but will not actually +be deposited in the CD database. Please DO NOT send submisions in "submit" +mode until you have tested your program with several different CD's. diff --git a/acme/bin/source/acd/toc.c b/acme/bin/source/acd/toc.c new file mode 100644 index 000000000..c447949e6 --- /dev/null +++ b/acme/bin/source/acd/toc.c @@ -0,0 +1,59 @@ +#include "acd.h" + +Toc thetoc; + +void +tocthread(void *v) +{ + Drive *d; + + threadsetname("tocthread"); + d = v; + DPRINT(2, "recv ctocdisp?..."); + while(recv(d->ctocdisp, &thetoc) == 1) { + DPRINT(2, "recv ctocdisp!..."); + drawtoc(d->w, &thetoc); + DPRINT(2, "send dbreq...\n"); + send(d->ctocdbreq, &thetoc); + } +} + +void +freetoc(Toc *t) +{ + int i; + + free(t->title); + for(i=0; intrack; i++) + free(t->track[i].title); +} + +void +cddbthread(void *v) +{ + Drive *d; + Toc t; + + threadsetname("cddbthread"); + d = v; + while(recv(d->ctocdbreply, &t) == 1) { + if(thetoc.nchange == t.nchange) { + freetoc(&thetoc); + thetoc = t; + redrawtoc(d->w, &thetoc); + } + } +} + +void +cdstatusthread(void *v) +{ + Drive *d; + Cdstatus s; + + d = v; + + for(;;) + recv(d->cstat, &s); + +} diff --git a/acme/bin/source/acd/util.c b/acme/bin/source/acd/util.c new file mode 100644 index 000000000..2b300fc12 --- /dev/null +++ b/acme/bin/source/acd/util.c @@ -0,0 +1,89 @@ +#include "acd.h" + +void* +emalloc(uint n) +{ + void *p; + + p = malloc(n); + if(p == nil) + error("can't malloc: %r"); + memset(p, 0, n); + return p; +} + +char* +estrdup(char *s) +{ + char *t; + + t = emalloc(strlen(s)+1); + strcpy(t, s); + return t; +} + +char* +estrstrdup(char *s, char *t) +{ + char *u; + + u = emalloc(strlen(s)+strlen(t)+1); + strcpy(u, s); + strcat(u, t); + return u; +} + +char* +eappend(char *s, char *sep, char *t) +{ + char *u; + + if(t == nil) + u = estrstrdup(s, sep); + else{ + u = emalloc(strlen(s)+strlen(sep)+strlen(t)+1); + strcpy(u, s); + strcat(u, sep); + strcat(u, t); + } + free(s); + return u; +} + +char* +egrow(char *s, char *sep, char *t) +{ + s = eappend(s, sep, t); + free(t); + return s; +} + +void +error(char *fmt, ...) +{ + int n; + va_list arg; + char buf[256]; + + fprint(2, "Mail: "); + va_start(arg, fmt); + n = vsnprint(buf, sizeof buf, fmt, arg); + va_end(arg); + write(2, buf, n); + write(2, "\n", 1); + threadexitsall(fmt); +} + +void +ctlprint(int fd, char *fmt, ...) +{ + int n; + va_list arg; + char buf[256]; + + va_start(arg, fmt); + n = vsnprint(buf, sizeof buf, fmt, arg); + va_end(arg); + if(write(fd, buf, n) != n) + error("control file write error: %r"); +} diff --git a/acme/bin/source/acd/win.c b/acme/bin/source/acd/win.c new file mode 100644 index 000000000..2f378961c --- /dev/null +++ b/acme/bin/source/acd/win.c @@ -0,0 +1,320 @@ +#include "acd.h" + +Window* +newwindow(void) +{ + char buf[12]; + Window *w; + + w = emalloc(sizeof(Window)); + w->ctl = open("/mnt/wsys/new/ctl", ORDWR|OCEXEC); + if(w->ctl<0 || read(w->ctl, buf, 12)!=12) + error("can't open window ctl file: %r"); + ctlprint(w->ctl, "noscroll\n"); + w->id = atoi(buf); + w->event = winopenfile(w, "event"); + w->addr = -1; /* will be opened when needed */ + w->body = nil; + w->data = -1; + w->cevent = chancreate(sizeof(Event*), 0); + if(w->cevent == nil) + error("cevent is nil: %r"); + return w; +} + +void +winsetdump(Window *w, char *dir, char *cmd) +{ + if(dir != nil) + ctlprint(w->ctl, "dumpdir %s\n", dir); + if(cmd != nil) + ctlprint(w->ctl, "dump %s\n", cmd); +} + +void +wineventproc(void *v) +{ + Window *w; + int i; + + threadsetname("wineventproc"); + w = v; + for(i=0; ; i++){ + if(i >= NEVENT) + i = 0; + wingetevent(w, &w->e[i]); + sendp(w->cevent, &w->e[i]); + } +} + +int +winopenfile(Window *w, char *f) +{ + char buf[64]; + int fd; + + sprint(buf, "/mnt/wsys/%d/%s", w->id, f); + fd = open(buf, ORDWR|OCEXEC); + if(fd < 0) + error("can't open window file %s: %r", f); + return fd; +} + +void +wintagwrite(Window *w, char *s, int n) +{ + int fd; + + fd = winopenfile(w, "tag"); + if(write(fd, s, n) != n) + error("tag write: %r"); + close(fd); +} + +void +winname(Window *w, char *s) +{ + ctlprint(w->ctl, "name %s\n", s); +} + +void +winopenbody(Window *w, int mode) +{ + char buf[256]; + + sprint(buf, "/mnt/wsys/%d/body", w->id); + w->body = Bopen(buf, mode|OCEXEC); + if(w->body == nil) + error("can't open window body file: %r"); +} + +void +winclosebody(Window *w) +{ + if(w->body != nil){ + Bterm(w->body); + w->body = nil; + } +} + +void +winwritebody(Window *w, char *s, int n) +{ + if(w->body == nil) + winopenbody(w, OWRITE); + if(Bwrite(w->body, s, n) != n) + error("write error to window: %r"); +} + +int +wingetec(Window *w) +{ + if(w->nbuf == 0){ + w->nbuf = read(w->event, w->buf, sizeof w->buf); + if(w->nbuf <= 0){ + /* probably because window has exited, and only called by wineventproc, so just shut down */ + threadexits(nil); + } + w->bufp = w->buf; + } + w->nbuf--; + return *w->bufp++; +} + +int +wingeten(Window *w) +{ + int n, c; + + n = 0; + while('0'<=(c=wingetec(w)) && c<='9') + n = n*10+(c-'0'); + if(c != ' ') + error("event number syntax"); + return n; +} + +int +wingeter(Window *w, char *buf, int *nb) +{ + Rune r; + int n; + + r = wingetec(w); + buf[0] = r; + n = 1; + if(r >= Runeself) { + while(!fullrune(buf, n)) + buf[n++] = wingetec(w); + chartorune(&r, buf); + } + *nb = n; + return r; +} + +void +wingetevent(Window *w, Event *e) +{ + int i, nb; + + e->c1 = wingetec(w); + e->c2 = wingetec(w); + e->q0 = wingeten(w); + e->q1 = wingeten(w); + e->flag = wingeten(w); + e->nr = wingeten(w); + if(e->nr > EVENTSIZE) + error("event string too long"); + e->nb = 0; + for(i=0; inr; i++){ + e->r[i] = wingeter(w, e->b+e->nb, &nb); + e->nb += nb; + } + e->r[e->nr] = 0; + e->b[e->nb] = 0; + if(wingetec(w) != '\n') + error("event syntax error"); +} + +void +winwriteevent(Window *w, Event *e) +{ + fprint(w->event, "%c%c%d %d\n", e->c1, e->c2, e->q0, e->q1); +} + +static int +nrunes(char *s, int nb) +{ + int i, n; + Rune r; + + n = 0; + for(i=0; iaddr < 0) + w->addr = winopenfile(w, "addr"); + if(w->data < 0) + w->data = winopenfile(w, "data"); + m = q0; + while(m < q1){ + n = sprint(buf, "#%d", m); + if(write(w->addr, buf, n) != n) + error("error writing addr: %r"); + n = read(w->data, buf, sizeof buf); + if(n <= 0) + error("reading data: %r"); + nr = nrunes(buf, n); + while(m+nr >q1){ + do; while(n>0 && (buf[--n]&0xC0)==0x80); + --nr; + } + if(n == 0) + break; + memmove(data, buf, n); + data += n; + *data = 0; + m += nr; + } +} + +void +windormant(Window *w) +{ + if(w->addr >= 0){ + close(w->addr); + w->addr = -1; + } + if(w->body != nil){ + Bterm(w->body); + w->body = nil; + } + if(w->data >= 0){ + close(w->data); + w->data = -1; + } +} + + +int +windel(Window *w, int sure) +{ + if(sure) + write(w->ctl, "delete\n", 7); + else if(write(w->ctl, "del\n", 4) != 4) + return 0; + /* event proc will die due to read error from event file */ + windormant(w); + close(w->ctl); + w->ctl = -1; + close(w->event); + w->event = -1; + return 1; +} + +void +winclean(Window *w) +{ + if(w->body) + Bflush(w->body); + ctlprint(w->ctl, "clean\n"); +} + +int +winsetaddr(Window *w, char *addr, int errok) +{ + if(w->addr < 0) + w->addr = winopenfile(w, "addr"); + if(write(w->addr, addr, strlen(addr)) < 0){ + if(!errok) + error("error writing addr(%s): %r", addr); + return 0; + } + return 1; +} + +int +winselect(Window *w, char *addr, int errok) +{ + if(winsetaddr(w, addr, errok)){ + ctlprint(w->ctl, "dot=addr\n"); + return 1; + } + return 0; +} + +char* +winreadbody(Window *w, int *np) /* can't use readfile because acme doesn't report the length */ +{ + char *s; + int m, na, n; + + if(w->body != nil) + winclosebody(w); + winopenbody(w, OREAD); + s = nil; + na = 0; + n = 0; + for(;;){ + if(na < n+512){ + na += 1024; + s = realloc(s, na+1); + } + m = Bread(w->body, s+n, na-n); + if(m <= 0) + break; + n += m; + } + s[n] = 0; + winclosebody(w); + *np = n; + return s; +} -- cgit v1.2.3