ascd-0.13.2.orig/0040755000175000017500000000000006764326157013006 5ustar hallonhallonascd-0.13.2.orig/libworkman/0040700000175000017500000000000006764326157015141 5ustar hallonhallonascd-0.13.2.orig/libworkman/Config0100644000175000017500000000405206661514631016271 0ustar hallonhallonXCOMM ------------------------------------------------------------------- XCOMM libworkman installation configuration XCOMM ------------------------------------------------------------------- XCOMM XCOMM This file is part of LibWorkMan, the civilized CD player library XCOMM (c) 1991-1997 by Steven Grimm (original author) XCOMM (c) by Dirk Försterling (current 'author' = maintainer) XCOMM The maintainer can be contacted by his e-mail address: XCOMM milliByte@DeathsDoor.com XCOMM XCOMM This library is free software; you can redistribute it and/or XCOMM modify it under the terms of the GNU Library General Public XCOMM License as published by the Free Software Foundation; either XCOMM version 2 of the License, or (at your option) any later version. XCOMM XCOMM This library is distributed in the hope that it will be useful, XCOMM but WITHOUT ANY WARRANTY; without even the implied warranty of XCOMM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU XCOMM Library General Public License for more details. XCOMM XCOMM You should have received a copy of the GNU Library General Public XCOMM License along with this library; if not, write to the Free XCOMM Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA XCOMM XCOMM ------------------------------------------------------------------- XCOMM XCOMM This configures the compilation and installation XCOMM processes only. To configure libworkman to your XCOMM needs, please review the file include/wm_config.h XCOMM XCOMM XCOMM ------------------------------------------------------------------- XCOMM Directory Prefix XCOMM ------------------------------------------------------------------- DESTDIR=/usr/local/ XCOMM ------------------------------------------------------------------- XCOMM LibWorkMan include file target relative to DSTDIR XCOMM ------------------------------------------------------------------- WMINCDIR=include/workman XCOMM ------------------------------------------------------------------- #define SHARED_LIBWORKMAN LIBDIR=lib ascd-0.13.2.orig/libworkman/Imakefile0100600000175000017500000000512106724006101016724 0ustar hallonhallonXCOMM ------------------------------------------------------------------- XCOMM libworkman Imakefile XCOMM ------------------------------------------------------------------- XCOMM XCOMM This file is part of LibWorkMan, the civilized CD player library XCOMM (c) 1991-1997 by Steven Grimm (original author) XCOMM (c) by Dirk Försterling (current 'author' = maintainer) XCOMM The maintainer can be contacted by his e-mail address: XCOMM milliByte@DeathsDoor.com XCOMM XCOMM This library is free software; you can redistribute it and/or XCOMM modify it under the terms of the GNU Library General Public XCOMM License as published by the Free Software Foundation; either XCOMM version 2 of the License, or (at your option) any later version. XCOMM XCOMM This library is distributed in the hope that it will be useful, XCOMM but WITHOUT ANY WARRANTY; without even the implied warranty of XCOMM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU XCOMM Library General Public License for more details. XCOMM XCOMM You should have received a copy of the GNU Library General Public XCOMM License along with this library; if not, write to the Free XCOMM Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA XCOMM XCOMM ------------------------------------------------------------------- XCOMM XCOMM Please edit the file "Config" for paths. XCOMM #include #include "include/wm_version.h" WM_LIBVER=WM_LIBVER_MAJOR.WM_LIBVER_MINOR.WM_LIBVER_PL SRCS = cddb.c cdrom.c cdinfo.c plat_freebsd.c plat_sun.c plat_hpux.c \ plat_ultrix.c plat_news.c plat_bsd386.c plat_osf1.c plat_linux.c \ plat_aix.c plat_openbsd.c plat_irix.c plat_svr4.c \ drv_sony.c drv_toshiba.c scsi.c database.c index.c \ wm_helpers.c OBJS = cddb.o cdrom.o cdinfo.o plat_freebsd.o plat_sun.o plat_hpux.o \ plat_ultrix.o plat_news.o plat_bsd386.o plat_osf1.o plat_linux.o \ plat_aix.o plat_openbsd.o plat_irix.o plat_svr4.o \ drv_sony.o drv_toshiba.o scsi.o database.o index.o \ wm_helpers.o HEADERS= \ include/wm_cdda.h \ include/wm_cdinfo.h \ include/wm_cdrom.h \ include/wm_config.h \ include/wm_database.h \ include/wm_helpers.h \ include/wm_index.h \ include/wm_platform.h \ include/wm_scsi.h \ include/wm_struct.h \ include/wm_version.h \ include/workman.h \ include/workman_defs.h #include #ifdef SHARED_LIBWORKMAN SharedLibraryTarget(workman,$(WM_LIBVER),$(OBJS),.,.) InstallSharedLibrary(workman,$(WM_LIBVER),$(LIBDIR)) #else NormalLibraryTarget(workman, $(OBJS)) #endif InstallMultiple($(HEADERS),$(WMINCDIR)) ascd-0.13.2.orig/libworkman/scsi.c0100644000175000017500000003110006732115043016231 0ustar hallonhallon/* * $Id: scsi.c,v 1.8 1999/06/17 06:48:03 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * Frontend functions for sending raw SCSI commands to the CD-ROM drive. * These depend on wm_scsi(), which should be defined in each platform * module. */ static char scsi_id[] = "$Id: scsi.c,v 1.8 1999/06/17 06:48:03 dirk Exp $"; #include #include #include #include "include/wm_config.h" #include "include/wm_struct.h" #include "include/wm_scsi.h" #include "include/wm_platform.h" #include "include/wm_helpers.h" #include "include/wm_cdrom.h" #define SCMD_INQUIRY 0x12 #define SCMD_MODE_SELECT 0x15 #define SCMD_MODE_SENSE 0x1a #define SCMD_START_STOP 0x1b #define SCMD_PREVENT 0x1e #define SCMD_READ_SUBCHANNEL 0x42 #define SCMD_READ_TOC 0x43 #define SCMD_PLAY_AUDIO_MSF 0x47 #define SCMD_PAUSE_RESUME 0x4b #define SUBQ_STATUS_INVALID 0x00 #define SUBQ_STATUS_PLAY 0x11 #define SUBQ_STATUS_PAUSE 0x12 #define SUBQ_STATUS_DONE 0x13 #define SUBQ_STATUS_ERROR 0x14 #define SUBQ_STATUS_NONE 0x15 #define SUBQ_STATUS_NO_DISC 0x17 /* Illegal, but Toshiba returns it. */ #define SUBQ_ILLEGAL 0xff #define PAGE_AUDIO 0x0e #define LEADOUT 0xaa #define WM_MSG_CLASS WM_MSG_CLASS_SCSI /* * Send a SCSI command over the bus, with all the CDB bytes specified * as unsigned char parameters. This doesn't use varargs because some * systems have stdargs instead and the number of bytes in a CDB is * limited to 12 anyway. * * d Drive structure * buf Buffer for data, both sending and receiving * len Size of buffer * dir TRUE if the command expects data to be returned in the buffer. * a0- CDB bytes. Either 6, 10, or 12 of them, depending on the command. */ /*VARARGS4*/ int sendscsi( struct wm_drive *d, void *buf, unsigned int len, int dir, unsigned char a0, unsigned char a1, unsigned char a2, unsigned char a3, unsigned char a4, unsigned char a5, unsigned char a6, unsigned char a7, unsigned char a8, unsigned char a9, unsigned char a10, unsigned char a11 ) { int cdblen = 0; unsigned char cdb[12]; cdb[0] = a0; cdb[1] = a1; cdb[2] = a2; cdb[3] = a3; cdb[4] = a4; cdb[5] = a5; switch ((a0 >> 5) & 7) { case 0: cdblen = 6; break; case 5: cdb[10] = a10; cdb[11] = a11; cdblen = 12; case 1: case 2: case 6: /* assume 10-byte vendor-specific codes for now */ cdb[6] = a6; cdb[7] = a7; cdb[8] = a8; cdb[9] = a9; if (! cdblen) cdblen = 10; break; } return (wm_scsi(d, cdb, cdblen, buf, len, dir)); } /* * Send a MODE SENSE command and return the results (minus header cruft) * in a user buffer. * * d Drive structure * page Number of page to query (plus page control bits, if any) * buf Result buffer */ int wm_scsi_mode_sense( struct wm_drive *d, unsigned char page, unsigned char *buf ) { unsigned char pagebuf[255]; int status, i, len, offset; status = sendscsi(d, pagebuf, sizeof(pagebuf), 1, SCMD_MODE_SENSE, 0, page, 0, sizeof(pagebuf), 0,0,0,0,0,0,0); if (status < 0) return (status); /* * The first byte of the returned data is the transfer length. Then * two more bytes and the length of whatever header blocks are in * front of the page we want. */ len = pagebuf[0] - pagebuf[3] - 3; offset = pagebuf[3] + 4; for (i = 0; i < len; i++) buf[i] = pagebuf[offset + i]; return (0); } /* * Send a MODE SELECT command. * * d Drive structure * buf Page buffer (no need to put on block descriptors) * len Size of page */ int wm_scsi_mode_select(d, buf, len) struct wm_drive *d; unsigned char *buf; unsigned char len; { unsigned char pagebuf[255]; int i; pagebuf[0] = pagebuf[1] = pagebuf[2] = pagebuf[3] = 0; for (i = 0; i < (int) len; i++) pagebuf[i + 4] = buf[i]; return (sendscsi(d, pagebuf, len + 4, 0, SCMD_MODE_SELECT, 0x10, 0, 0, len + 4, 0,0,0,0,0,0,0)); } /* * Send an INQUIRY command to get the drive type. * * d Drive structure * vendor Buffer for vendor name (8 bytes + null) * model Buffer for model name (16 bytes + null) * rev Buffer for revision level (4 bytes + null) * * The above string lengths apply to the SCSI INQUIRY command. The * actual WorkMan drive structure reserves 31 bytes + NULL per entry. * * If the model name begins with "CD-ROM" and zero or more spaces, that will * all be stripped off since it's just extra junk to WorkMan. */ int wm_scsi_get_drive_type( struct wm_drive *d, char *vendor, char *model, char *rev ) { /* removed unsigned*/ char *s, *t, buf[36]; wm_lib_message(WM_MSG_LEVEL_INFO|WM_MSG_CLASS, "Sending SCSI inquiry command..."); if (sendscsi(d, buf, sizeof(buf), 1, SCMD_INQUIRY, 0, 0, 0, sizeof(buf), 0,0,0,0,0,0,0)) { sprintf( vendor, WM_STR_GENVENDOR); sprintf( model, WM_STR_GENMODEL); sprintf( rev, WM_STR_GENREV); wm_lib_message(WM_MSG_LEVEL_ERROR|WM_MSG_CLASS, "\nSCSI inquiry command not supported by the hardware\n"); return (WM_ERR_SCSI_INQUIRY_FAILED); } wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "sent.\n"); memcpy(vendor, buf + 8, 8); vendor[8] = '\0'; memcpy(model, buf + 16, 16); model[16] = '\0'; memcpy(rev, buf + 32, 4); rev[4] = '\0'; wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "SCSI Inquiry result: [%s|%s|%s]\n", vendor, model, rev); /* Remove "CD-ROM " from the model. */ if (! strncmp(model, "CD-ROM", 6)) { s = model + 6; t = model; while (*s == ' ' || *s == '\t') s++; while( (*t++ = *s++) ) ; } wm_lib_message(WM_MSG_LEVEL_INFO|WM_MSG_CLASS, "Cooked data: %s %s rev. %s\n", vendor, model,rev); return (0); } /* wm_scsi_get_drive_type() */ /* * Send a SCSI-2 PAUSE/RESUME command. "resume" is 1 to resume, 0 to pause. */ int wm_scsi2_pause_resume(d, resume) struct wm_drive *d; int resume; { return (sendscsi(d, NULL, 0, 0, SCMD_PAUSE_RESUME, 0, 0, 0, 0, 0, 0, 0, resume ? 1 : 0, 0,0,0)); } /* * Send a SCSI-2 "prevent media removal" command. "prevent" is 1 to lock * caddy in. */ int wm_scsi2_prevent(d, prevent) struct wm_drive *d; int prevent; { return (sendscsi(d, NULL, 0, 0, SCMD_PREVENT, 0, 0, 0, 0, 0, 0, 0, prevent ? 1 : 0, 0,0,0)); } /* * Send a SCSI-2 PLAY AUDIO MSF command. Pass the starting and ending * frame numbers. */ int wm_scsi2_play(d, sframe, eframe) struct wm_drive *d; int sframe, eframe; { return (sendscsi(d, NULL, 0, 0, SCMD_PLAY_AUDIO_MSF, 0, 0, sframe / (60 * 75), (sframe / 75) % 60, sframe % 75, eframe / (60 * 75), (eframe / 75) % 60, eframe % 75, 0,0,0)); } /* * Send a SCSI-2 READ TOC command to get the data for a particular track. * Fill in track information from the returned data. */ int wm_scsi2_get_trackinfo(d, track, data, startframe) struct wm_drive *d; int track, *data, *startframe; { unsigned char buf[12]; /* one track's worth of info */ if (sendscsi(d, buf, sizeof(buf), 1, SCMD_READ_TOC, 2, 0, 0, 0, 0, track, sizeof(buf) / 256, sizeof(buf) % 256, 0,0,0)) return (-1); *data = buf[5] & 4 ? 1 : 0; *startframe = buf[9] * 60 * 75 + buf[10] * 75 + buf[11]; return (0); } /* * Get the starting frame for the leadout area (which should be the same as * the length of the disc as far as WorkMan is concerned). */ int wm_scsi2_get_cdlen(d, frames) struct wm_drive *d; int *frames; { int tmp; return (wm_scsi2_get_trackinfo(d, LEADOUT, &tmp, frames)); } /* * Get the current status of the drive by sending the appropriate SCSI-2 * READ SUB-CHANNEL command. */ int wm_scsi2_get_drive_status(d, oldmode, mode, pos, track, index) struct wm_drive *d; enum wm_cd_modes oldmode, *mode; int *pos, *track, *index; { unsigned char buf[48]; /* If we can't get status, the CD is ejected, so default to that. */ *mode = WM_CDM_EJECTED; /* Is the device open? */ if (d->fd < 0) { /* * stupid somehow, but necessary this time */ switch( wmcd_open( d ) ) { case -1: /* error */ return (-1); case 1: /* retry */ return (0); } } /* If we can't read status, the CD has been ejected. */ buf[1] = SUBQ_ILLEGAL; if (sendscsi(d, buf, sizeof(buf), 1, SCMD_READ_SUBCHANNEL, 2, 64, 1, 0, 0, 0, sizeof(buf) / 256, sizeof(buf) % 256, 0,0,0)) return (0); switch (buf[1]) { case SUBQ_STATUS_PLAY: *mode = WM_CDM_PLAYING; *track = buf[6]; *index = buf[7]; *pos = buf[9] * 60 * 75 + buf[10] * 75 + buf[11]; break; case SUBQ_STATUS_PAUSE: if (oldmode == WM_CDM_PLAYING || oldmode == WM_CDM_PAUSED) { *mode = WM_CDM_PAUSED; *track = buf[6]; *index = buf[7]; *pos = buf[9] * 60 * 75 + buf[10] * 75 + buf[11]; } else *mode = WM_CDM_STOPPED; break; /* * SUBQ_STATUS_DONE is sometimes returned when the CD is idle, * even though the spec says it should only be returned when an * audio play operation finishes. */ case SUBQ_STATUS_DONE: case SUBQ_STATUS_NONE: case SUBQ_STATUS_INVALID: if (oldmode == WM_CDM_PLAYING) *mode = WM_CDM_TRACK_DONE; else *mode = WM_CDM_STOPPED; break; /* * This usually means there's no disc in the drive. */ case SUBQ_STATUS_NO_DISC: break; /* * This usually means the user ejected the CD manually. */ case SUBQ_STATUS_ERROR: break; case SUBQ_ILLEGAL: /* call didn't really succeed */ break; default: *mode = WM_CDM_UNKNOWN; #ifdef DEBUG if( getenv( "WORKMAN_DEBUG" ) != NULL ) printf("wm_scsi2_get_drive_status: status is 0x%x\n", buf[1]); #endif break; } return (0); } /* * Get the number of tracks on the CD using the SCSI-2 READ TOC command. */ int wm_scsi2_get_trackcount(d, tracks) struct wm_drive *d; int *tracks; { unsigned char buf[4]; if (sendscsi(d, buf, sizeof(buf), 1, SCMD_READ_TOC, 0, 0, 0, 0, 0, 0, sizeof(buf) / 256, sizeof(buf) % 256, 0,0,0)) return (-1); *tracks = buf[3] - buf[2] + 1; return (0); } /* * Pause the CD. */ int wm_scsi2_pause(d) struct wm_drive *d; { return (wm_scsi2_pause_resume(d, 0)); } /* * Resume playing after a pause. */ int wm_scsi2_resume(d) struct wm_drive *d; { return (wm_scsi2_pause_resume(d, 1)); } /* * Stop playing the CD by sending a START STOP UNIT command. */ int wm_scsi2_stop(d) struct wm_drive *d; { return (sendscsi(d, NULL, 0, 0, SCMD_START_STOP, 0, 0,0,0,0,0,0,0,0,0,0)); } /* * Eject the CD by sending a START STOP UNIT command. */ int wm_scsi2_eject(struct wm_drive *d) { /* Unlock the disc (possibly unnecessary). */ if (wm_scsi2_prevent(d, 0)) return (-1); wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "Issuing START_STOP for ejecting...\n"); return (sendscsi(d, NULL, 0, 0, SCMD_START_STOP, 2, 0,0,0,0,0,0,0,0,0,0)); } /* * Something like a dummy. The SCSI-2 specs are too hard for me to * understand here... * * If you have the correct command handy, please send the code to * milliByte@DeathsDoor.com */ int wm_scsi2_closetray(struct wm_drive *d) { wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "Issuing START_STOP for closing...\n"); return (sendscsi(d, NULL, 0,0, SCMD_START_STOP, 2, 0,0,0,0,0,0,0,0,0,0)); } /* * Get the volume by doing a MODE SENSE command. */ int wm_scsi2_get_volume(d, left, right) struct wm_drive *d; int *left, *right; { unsigned char mode[16]; *left = *right = -1; /* Get the current audio parameters first. */ if (wm_scsi_mode_sense(d, PAGE_AUDIO, mode)) return (-1); *left = ((int) mode[9] * 100) / 255; *right = ((int) mode[11] * 100) / 255; return (0); } /* * Set the volume by doing a MODE SELECT command. */ int wm_scsi2_set_volume(d, left, right) struct wm_drive *d; int left, right; { unsigned char mode[16]; /* Get the current audio parameters first. */ if (wm_scsi_mode_sense(d, PAGE_AUDIO, mode)) return (-1); /* Tweak the volume part of the parameters. */ mode[9] = (left * 255) / 100; mode[11] = (right * 255) / 100; /* And send them back to the drive. */ return (wm_scsi_mode_select(d, mode, sizeof(mode))); } ascd-0.13.2.orig/libworkman/COPYING.LIB0100644000175000017500000006127306661514165016613 0ustar hallonhallon GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Library General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! ascd-0.13.2.orig/libworkman/README0100644000175000017500000000026406661516462016026 0ustar hallonhallon$Id: README,v 1.2 1999/02/14 09:53:54 dirk Exp $ This directory contains the WorkMan library. libworkman is a multi-plaform CD-Player library for creating various CD-Player-UIs. ascd-0.13.2.orig/libworkman/buildindex.c0100644000175000017500000001163206661516162017437 0ustar hallonhallon/* * $Id: buildindex.c,v 1.2 1999/02/14 09:50:42 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * Build a WorkMan database index file from a flat text file. Requires * 4.4BSD libdb library. */ static char buildindex_id[] = "$Id: buildindex.c,v 1.2 1999/02/14 09:50:42 dirk Exp $"; #include #include #include #include #include /* for htonl() */ #include #include #include #include static char buildindex_id[]="$Id: buildindex.c,v 1.2 1999/02/14 09:50:42 dirk Exp $"; char *strrchr(); main(argc, argv) int argc; char **argv; { DB *db; DBT key, data; FILE *fp; int lock = 1, i = 0, locked, frame; char buf[1000], indname[MAXPATHLEN + 100], framebuf[8], *c; unsigned long pos; BTREEINFO bt; struct stat st; if (argc > 2 && !strcmp(argv[1], "-n")) { lock = 0; i++; } if (argc < i + 2) { fprintf(stderr, "Usage: %s [-n] dbfile [dbfile ...]\n", argv[0]); exit(1); } data.data = &pos; data.size = sizeof(pos); key.data = framebuf; key.size = 7; /* %07d */ while (++i < argc) { fprintf(stderr, "Building index for %s\n", argv[i]); if ((fp = fopen(argv[i], "r")) == NULL) { perror(argv[i]); continue; } /* * Figure out the file's mode, uid, gid, so we can set the * permissions on the index file to the same thing. */ if (fstat(fileno(fp), &st)) { sprintf(indname, "%s: fstat", argv[i]); perror(indname); fclose(fp); continue; } if (lock && lockit(fileno(fp), F_WRLCK)) { sprintf(indname, "%s: Warning: Couldn't lock", argv[i]); perror(indname); locked = 0; } else locked = 1; /* * Create a database file. */ bt.flags = R_DUP; /* allow duplicate keys */ bt.cachesize = 0; bt.psize = 0; bt.lorder = 4321; bt.minkeypage = 0; bt.compare = NULL; /* use lexical comparison */ bt.prefix = NULL; /* no prefix comparisons */ /* Index files have ".ind" extensions */ sprintf(indname, "%s.ind", argv[i]); if ((db = dbopen(indname, O_CREAT | O_RDWR | O_TRUNC, st.st_mode, DB_BTREE, &bt)) == NULL) { perror(indname); if (locked) lockit(fileno(fp), F_UNLCK); fclose(fp); continue; } /* * Now loop through the text file, inserting a record into * the index file for each "tracks" line. */ while (! feof(fp)) { pos = ftell(fp); buf[0] = '\0'; if (fgets(buf, sizeof(buf), fp) == NULL || ! buf[0]) { /* End of file? */ if (feof(fp)) break; /* Nope. A read error. Unlink the database. */ perror(argv[i]); (void) unlink(indname); break; } if (strncmp(buf, "tracks ", 7)) continue; /* * Found the start of a record. Figure out the start * time of the last track and put an entry in the * index file with that as the key. */ c = strrchr(buf, ' '); /* this will always succeed */ *c = '\0'; c = strrchr(buf, ' '); /* this should too, but... */ if (c == NULL) { fprintf(stderr, "%s: Malformed tracks line at %lu\n", argv[i], pos); continue; } sscanf(c+1, "%d", &frame); sprintf(framebuf, "%07d", frame); pos = htonl(pos); if ((db->put)(db, &key, &data, 0)) { perror(indname); unlink(indname); break; } } /* * Clean up. */ (void) (db->close)(db); if (locked) lockit(fileno(fp), F_UNLCK); } } /* * Lock a file. Time out after a little while if we can't get a lock; * this usually means the locking system is broken. * * Unfortunately, if there are lots of people contending for a lock, * this can result in the file not getting locked when it probably should. */ int lockit(fd, type) int fd; int type; { struct flock fl; int result, timer = 0; fl.l_type = type; fl.l_whence = 0; fl.l_start = 0; fl.l_len = 0; while ((result = fcntl(fd, F_SETLK, &fl)) < 0) { if (errno != EACCES || errno != EAGAIN) break; if (timer++ == 30) { errno = ETIMEDOUT; break; } sleep(1); } return (result); } ascd-0.13.2.orig/libworkman/cddaslave.c0100644000175000017500000003033406661644720017240 0ustar hallonhallon/* * $id$ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ****************************************************************** * * Digital audio manipulator for WorkMan. * * The CDDA architecture looks like this: * * WorkMan (or another UI!) * ^^^ * ||| (separate processes connected by pipe) * vvv * +------------- cddaslave -------------+ * | | | * command module CDDA reader audio output * (portable) (per platform) (per platform) * * This source file has the command module and some of the scaffolding * to hold cddaslave together, plus some non-system-dependent audio * processing code. Look in plat_*_cdda.c for system-specific stuff. * */ #include "config.h" #ifdef BUILD_CDDA static char cddaslave_id[] = "$Id: cddaslave.c,v 1.3 1999/02/14 22:10:24 dirk Exp $"; #include #include #include #include "include/wm_cdda.h" #include "include/wm_platform.h" int playing = 0; /* Should the CD be playing now? */ /* * Loudness setting, plus the floating volume multiplier and decaying-average * volume level. */ int loudness = 0; unsigned int volume = 32768; unsigned int level; /* * Playback speed (0 = slow) */ int speed = 128; /* * This is non-null if we're saving audio to a file. */ FILE *output = NULL; /* * Audio file header format. */ typedef unsigned long u_32; struct auheader { u_32 magic; u_32 hdr_size; u_32 data_size; u_32 encoding; u_32 sample_rate; u_32 channels; }; /* had to change #ifdef to #if -> see wm_cdda.h */ #if WM_BIG_ENDIAN # ifndef htonl # define htonl(x) (x) # endif #else extern unsigned long htonl(x); #endif void *malloc(); long cdda_transform(); /* * Send status information upstream. */ void send_status(blk) struct cdda_block *blk; { write(1, blk, sizeof(*blk)); } /* * Accept a command from our master. * * The protocol is byte-oriented: * PmsfMSFxyz Play from msf to MSF (MSF can be 0,0,0 to play to end) * xyz is the msf of the start of this chunk, i.e., the * ending boundary for reverse play. * S Stop. * E Eject. This means we just close the CD device and * open it again later. * Q Quit. * Vn Set volume level (0-255). * Bn Set balance level (0-255). * EnL Set an equalizer level (n = 0 for bass, 255 for treble) * G Get current status. * sn Set speed multiplier to n. * dn Set direction to forward (n = 0) or reverse. * Fllllx... Start saving to a file (length = l, followed by name) * F0000 Stop saving. * Ln Set loudness level (0-255). */ int command(cd_fd, blk) int cd_fd; struct cdda_block *blk; { unsigned char inbuf[10]; char *filename; int namelen; struct auheader hdr; if (read(0, inbuf, 1) <= 0) /* Parent died. */ { wmcdda_close(); wmaudio_close(); exit(0); } switch (inbuf[0]) { case 'E': playing = 0; wmaudio_stop(); wmcdda_close(cd_fd); cd_fd = -1; blk->status = WMCDDA_ACK; send_status(blk); break; case 'P': read(0, inbuf, 9); playing = 1; wmaudio_stop(); wmcdda_setup(inbuf[0] * 60 * 75 + inbuf[1] * 75 + inbuf[2], inbuf[3] * 60 * 75 + inbuf[4] * 75 + inbuf[5], inbuf[6] * 60 * 75 + inbuf[7] * 75 + inbuf[8]); wmaudio_ready(); level = 2500; volume = 1 << 15; blk->status = WMCDDA_ACK; send_status(blk); break; case 'S': playing = 0; wmaudio_stop(); blk->status = WMCDDA_ACK; send_status(blk); blk->status = WMCDDA_STOPPED; send_status(blk); break; case 'B': read(0, inbuf, 1); wmaudio_balance(inbuf[0]); blk->status = WMCDDA_ACK; send_status(blk); break; case 'V': read(0, inbuf, 1); wmaudio_volume(inbuf[0]); blk->status = WMCDDA_ACK; send_status(blk); break; case 'G': blk->status = WMCDDA_ACK; send_status(blk); if (playing) blk->status = WMCDDA_PLAYED; else blk->status = WMCDDA_STOPPED; wmaudio_state(blk); send_status(blk); break; case 'Q': blk->status = WMCDDA_ACK; send_status(blk); wmcdda_close(); wmaudio_close(); exit(0); case 's': read(0, inbuf, 1); speed = inbuf[0]; wmcdda_speed(speed); blk->status = WMCDDA_ACK; send_status(blk); break; case 'd': read(0, inbuf, 1); wmcdda_direction(inbuf[0]); blk->status = WMCDDA_ACK; send_status(blk); break; case 'L': read(0, inbuf, 1); loudness = inbuf[0]; blk->status = WMCDDA_ACK; send_status(blk); break; case 'F': read(0, &namelen, sizeof(namelen)); if (output != NULL) { fclose(output); output = NULL; } if (namelen) { filename = malloc(namelen + 1); if (filename == NULL) { perror("cddaslave"); wmcdda_close(); wmaudio_close(); exit(1); } read(0, filename, namelen); filename[namelen] = '\0'; output = fopen(filename, "w"); if (output == NULL) perror(filename); else { /* Write an .au file header. */ hdr.magic = htonl(0x2e736e64); hdr.hdr_size = htonl(sizeof(hdr) + 28); hdr.data_size = htonl(~0); hdr.encoding = htonl(3); /* linear-16 */ hdr.sample_rate = htonl(44100); hdr.channels = htonl(2); fwrite(&hdr, sizeof(hdr), 1, output); fwrite("Recorded from CD by WorkMan", 28, 1, output); } free(filename); } blk->status = WMCDDA_ACK; send_status(blk); } return(cd_fd); } /* * Transform some CDDA data. */ long wmcdda_transform(unsigned char *rawbuf, long buflen, struct cdda_block *block) { long i; long *buf32 = (long *)rawbuf; register short *buf16 = (short *)rawbuf; register int aval; /* * Loudness transformation. Basically this is a self-adjusting * volume control; our goal is to keep the average output level * around a certain value (2500 seems to be pleasing.) We do this * by maintaining a decaying average of the recent output levels * (where "recent" is some fraction of a second.) All output levels * are multiplied by the inverse of the decaying average; this has * the volume-leveling effect we desire, and isn't too CPU-intensive. * * This is done by modifying the digital data, rather than adjusting * the system volume control, because (at least on some systems) * tweaking the system volume can generate little pops and clicks. * * There's probably a more elegant way to achieve this effect, but * what the heck, I never took a DSP class and am making this up as * I go along, with a little help from some friends. * * This is all done with fixed-point math, oriented around powers * of two, which with luck will keep the CPU usage to a minimum. * More could probably be done, for example using lookup tables to * replace multiplies and divides; whether the memory hit (128K * for each table) is worthwhile is unclear. */ if (loudness) { /* We aren't really going backwards, but i > 0 is fast */ for (i = buflen / 2; i > 0; i--) { /* * Adjust this sample to the current level. */ aval = (*buf16 = (((long)*buf16) * volume) >> 15); buf16++; /* * Don't adjust the decaying average for each sample; * that just spends CPU time for very little benefit. */ if (i & 127) continue; /* * We want to use absolute values to compute the * decaying average; otherwise it'd sit around 0. */ if (aval < 0) aval = -aval; /* * Adjust more quickly when we start hitting peaks, * or we'll get clipping when there's a sudden loud * section after lots of quiet. */ if (aval & ~8191) aval <<= 3; /* * Adjust the decaying average. */ level = ((level << 11) - level + aval) >> 11; /* * Let *really* quiet sounds play softly, or we'll * amplify background hiss to full volume and blast * the user's speakers when real sound starts up. */ if (! (level & ~511)) level = 512; /* * And adjust the volume setting using the inverse * of the decaying average. */ volume = (2500 << 15) / level; } } if (speed == 128) return (buflen); /* * Half-speed play. Stretch things out. */ if (speed == 0) { buflen /= 2; /* Since we're moving 32 bits at a time */ for (i = buflen - 1; i > 0; i--) { buf32[i] = buf32[i / 2]; } buflen *= 4; /* 2 for doubling the buffer, 2 from above */ } /* * Slow play; can't optimize it as well as half-speed. */ if (speed && speed < 128) { int multiplier = ((speed + 128) * 128) / 256; int newlen; int tally = 0, pos; buflen /= 4; /* Get the number of 32-bit values */ /* * Buffer length doubles when speed is 0, stays the same * when speed is 128. */ newlen = (buflen * 128) / multiplier; pos = buflen - 1; for (i = newlen - 1; i > 0; i--) { buf32[i] = buf32[pos]; tally += multiplier; if (tally & 128) { pos--; tally ^= 128; } } buflen = newlen * 4; } return (buflen); } main(argc, argv) char **argv; { int cd_fd = 3; fd_set readfd, dummyfd; struct timeval timeout; char *cddabuf; long cddabuflen; struct cdda_block blockinfo; long result; int nfds; char *devname; /* * Device name should be the command-line argument. */ if (argc < 2) devname = ""; else devname = argv[1]; /* * If we're running setuid root, bump up our priority then lose * superuser access. */ nice(-14); setuid(getuid()); FD_ZERO(&dummyfd); FD_ZERO(&readfd); timerclear(&timeout); cd_fd = wmcdda_init(&cddabuf, &cddabuflen, cd_fd, devname); if (cd_fd < 0) exit(1); wmaudio_init(); blockinfo.status = WMCDDA_ACK; send_status(&blockinfo); blockinfo.status = WMCDDA_STOPPED; /* * Accept commands as they come in, and play some sound if we're * supposed to be doing that. */ while (1) { FD_SET(0, &readfd); /* * If we're playing, we don't want select to block. Otherwise, * wait a little while for the next command. */ if (playing) timeout.tv_usec = 0; else timeout.tv_usec = 500000; nfds = select(1, &readfd, &dummyfd, &dummyfd, &timeout); if (nfds < 0) /* Broken pipe; our GUI exited. */ { wmcdda_close(cd_fd); wmaudio_close(); exit(0); } if (FD_ISSET(0, &readfd)) { /* If this doesn't work, just hope for the best */ if(cd_fd == -1) cd_fd = wmcdda_open(devname); cd_fd = command(cd_fd, &blockinfo); /* * Process all commands in rapid succession, rather * than possibly waiting for a CDDA read. */ continue; } if (playing) { result = wmcdda_read(cd_fd, cddabuf, cddabuflen, &blockinfo); if (result <= 0) { /* Let the output queue drain. */ if (blockinfo.status == WMCDDA_DONE) { wmaudio_mark_last(); if (wmaudio_send_status()) { /* queue drained, stop polling*/ playing = 0; } } else { playing = 0; send_status(&blockinfo); } } else { result = wmcdda_normalize(cddabuf, result, &blockinfo); result = wmcdda_transform(cddabuf, result, &blockinfo); if (output) fwrite(cddabuf, result, 1, output); result = wmaudio_convert(cddabuf, result, &blockinfo); if (wmaudio_play(cddabuf, result, &blockinfo)) { playing = 0; wmaudio_stop(); send_status(&blockinfo); } } } else send_status(&blockinfo); } } #else /* BUILD_CDDA */ main() { exit(0); } #endif /* BUILD_CDDA */ ascd-0.13.2.orig/libworkman/cdrom.c0100644000175000017500000004356306714071413016416 0ustar hallonhallon/* * $Id: cdrom.c,v 1.10 1999/05/05 16:34:19 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * Interface between most of WorkMan and the low-level CD-ROM library * routines defined in plat_*.c and drv_*.c. The goal is to have no * platform- or drive-dependent code here. */ static char cdrom_id[] = "$Id: cdrom.c,v 1.10 1999/05/05 16:34:19 dirk Exp $"; #include #include #include #include #include #include /* #include */ #include "include/wm_config.h" #include "include/wm_struct.h" #include "include/wm_cddb.h" #include "include/wm_cdrom.h" #include "include/wm_database.h" #include "include/wm_platform.h" #include "include/wm_helpers.h" #include "include/wm_cdinfo.h" #ifdef CAN_CLOSE #include #endif #define WM_MSG_CLASS WM_MSG_CLASS_CDROM /* extern struct wm_drive generic_proto, toshiba_proto, sony_proto; */ /* toshiba33_proto; <=== Somehow, this got lost */ /* * The supported drive types are listed here. NULL means match anything. * The first match in the list is used, and substring matches are done (so * put long names before their shorter prefixes.) */ struct drivelist { char *ven; char *mod; char *rev; struct wm_drive *proto; } drives[] = { { "TOSHIBA", "XM-3501", NULL, &toshiba_proto }, { "TOSHIBA", "XM-3401", NULL, &toshiba_proto }, { "TOSHIBA", "XM-3301", NULL, &toshiba_proto }, { "SONY", "CDU-8012", NULL, &sony_proto }, { "SONY", "CDU 561", NULL, &sony_proto }, { WM_STR_GENVENDOR, WM_STR_GENMODEL, WM_STR_GENREV, &generic_proto }, { NULL, NULL, NULL, &generic_proto } }; /* * Solaris 2.2 will remove the device out from under us. Getting an ENOENT * is therefore sometimes not a problem. */ int intermittent_dev = 0; /* * Do we want to keep the CD device open after quitting by default? * int keep_open = 0; */ #if defined DEFAULT_CD_DEVICE char *cd_device = DEFAULT_CD_DEVICE; #else char *cd_device = NULL; #endif int wm_cd_cur_balance = 10; struct wm_drive drive = { -1, "", "", "", NULL, NULL }; char _wm_drive_vendor[32] = "Generic"; char _wm_drive_model[32] = "drive type"; char _wm_drive_revision[32] = ""; /* * Give information about the drive we found during wmcd_open() */ char *wm_drive_vendor( void ) { char *s = NULL; wm_strmcpy( &s, _wm_drive_vendor ); return s; } char *wm_drive_model( void ) { char *s = NULL; wm_strmcpy( &s, _wm_drive_model ); return s; } char *wm_drive_revision( void ) { char *s = NULL; wm_strmcpy( &s, _wm_drive_revision ); return s; } void wm_drive_settype( char *vendor, char *model, char *revision ) { sprintf( _wm_drive_vendor, "%s", vendor ); sprintf( _wm_drive_model, "%s", model ); sprintf( _wm_drive_revision, "%s", revision ); } /* * Figure out which prototype drive structure we should be using based * on the vendor, model, and revision of the current drive. */ struct wm_drive * find_drive_struct(char *vendor, char *model, char *rev) { struct drivelist *d; for (d = drives; d; d++) { if( ( (d->ven != NULL) && strncmp(d->ven, vendor, strlen(d->ven)) ) || ( (d->mod != NULL) && strncmp(d->mod, model, strlen(d->mod)) ) || ( (d->rev != NULL) && strncmp(d->rev, rev, strlen(d->rev)) ) ) continue; if (d->proto->vendor[0] == '\0') strcpy(d->proto->vendor, vendor); if (d->proto->model[0] == '\0') strcpy(d->proto->model, model); return (d->proto); } return (NULL); /* this means the list is badly terminated. */ } /* find_drive_struct() */ /* * read_toc() * * Read the table of contents from the CD. Return a pointer to a wm_cdinfo * struct containing the relevant information (minus artist/cdname/etc.) * This is a static struct. Returns NULL if there was an error. * * XXX allocates one trackinfo too many. */ struct wm_cdinfo * read_toc() { struct wm_playlist *l; int i, pos; if ((drive.get_trackcount)(&drive, &thiscd.ntracks) < 0) { perror("trackcount"); return (NULL); } thiscd.artist[0] = thiscd.cdname[0] = '\0'; thiscd.whichdb = thiscd.otherrc = thiscd.otherdb = thiscd.user = NULL; thiscd.length = 0; thiscd.autoplay = thiscd.playmode = thiscd.volume = 0; /* Free up any left-over playlists. */ if (thiscd.lists != NULL) { for (l = thiscd.lists; l->name != NULL; l++) { free(l->name); free(l->list); } free(thiscd.lists); thiscd.lists = NULL; } if (thiscd.trk != NULL) free(thiscd.trk); thiscd.trk = malloc((thiscd.ntracks + 1) * sizeof(struct wm_trackinfo)); if (thiscd.trk == NULL) { perror("malloc"); return (NULL); } for (i = 0; i < thiscd.ntracks; i++) { if ((drive.get_trackinfo)(&drive, i + 1, &thiscd.trk[i].data, &thiscd.trk[i].start) < 0) { perror("CD track info read"); return (NULL); } thiscd.trk[i].avoid = thiscd.trk[i].data; thiscd.trk[i].length = thiscd.trk[i].start / 75; thiscd.trk[i].songname = thiscd.trk[i].otherrc = thiscd.trk[i].otherdb = NULL; thiscd.trk[i].contd = 0; thiscd.trk[i].volume = 0; thiscd.trk[i].track = i + 1; thiscd.trk[i].section = 0; } if ((drive.get_cdlen)(&drive, &thiscd.trk[i].start) < 0) { perror("CD length read"); return (NULL); } thiscd.trk[i].length = thiscd.trk[i].start / 75; /* Now compute actual track lengths. */ pos = thiscd.trk[0].length; for (i = 0; i < thiscd.ntracks; i++) { thiscd.trk[i].length = thiscd.trk[i+1].length - pos; pos = thiscd.trk[i+1].length; if (thiscd.trk[i].data) thiscd.trk[i].length = (thiscd.trk[i + 1].start - thiscd.trk[i].start) * 2; if (thiscd.trk[i].avoid) wm_strmcpy(&thiscd.trk[i].songname, "DATA TRACK"); } thiscd.length = thiscd.trk[thiscd.ntracks].length; thiscd.cddbid = cddb_discid(drive); return (&thiscd); } /* * wm_cd_status() * * Return values: * * 0 No CD in drive. * 1 CD in drive. * 2 CD has just been inserted (TOC has been read) * * Updates cur_track, cur_pos_rel, cur_pos_abs and other variables. */ int wm_cd_status( void ) { static enum wm_cd_modes oldmode = WM_CDM_UNKNOWN; enum wm_cd_modes mode; int status, trackno = cur_track; int ret = WM_CDS_DISC_READY; /* Open the drive. This returns 1 if the device isn't ready. */ status = wmcd_open(&drive); if (status < 0) return (status); if (status > 0) return (WM_CDS_NO_DISC); /* If the user hit the stop button, don't pass PLAYING as oldmode. * Likewise, if we've just started playing, don't remember that * we were stopped before (or the state machine in get_drive_status * can get confused.) */ if( (cur_cdmode == WM_CDM_STOPPED) || (cur_cdmode == WM_CDM_PLAYING) ) oldmode = cur_cdmode; if( (drive.get_drive_status)(&drive, oldmode, &mode, &cur_frame, &trackno, &cur_index) < 0) { perror("CD get drive status"); return (-1); } oldmode = mode; if (mode == WM_CDM_EJECTED || mode == WM_CDM_UNKNOWN) { cur_cdmode = WM_CDM_EJECTED; cur_track = -1; cur_cdlen = cur_tracklen = 1; cur_pos_abs = cur_pos_rel = cur_frame = 0; if (exit_on_eject) exit(0); return (WM_CDS_NO_DISC); } /* If there wasn't a CD before and there is now, learn about it. */ if (cur_cdmode == WM_CDM_EJECTED) { cur_pos_rel = cur_pos_abs = 0; status = wmcd_reopen( &drive ); if ((cd = read_toc()) == NULL) { if (exit_on_eject) { exit(-1); } else { return (-1); } } cur_nsections = 0; cur_ntracks = cd->ntracks; cur_cdlen = cd->length; load(); cur_artist = cd->artist; cur_cdname = cd->cdname; cur_cdmode = WM_CDM_STOPPED; ret = WM_CDS_JUST_INSERTED; } switch (mode) { case WM_CDM_PLAYING: case WM_CDM_PAUSED: cur_pos_abs = cur_frame / 75; /* Only look up the current track number if necessary. */ if (cur_track < 1 || cur_frame < cd->trk[cur_track-1].start || cur_frame >= (cur_track >= cur_ntracks ? (cur_cdlen + 1) * 75 : cd->trk[cur_track].start)) { cur_track = 0; while (cur_track < cur_ntracks && cur_frame >= cd->trk[cur_track].start) cur_track++; } if (cur_track >= 1 && trackno > cd->trk[cur_track-1].track) cur_track++; /* Fall through */ case WM_CDM_UNKNOWN: if (mode == WM_CDM_UNKNOWN) { mode = WM_CDM_STOPPED; cur_lasttrack = cur_firsttrack = -1; } /* Fall through */ case WM_CDM_STOPPED: if (cur_track >= 1 && cur_track <= cur_ntracks) { cur_trackname = cd->trk[cur_track-1].songname; cur_avoid = cd->trk[cur_track-1].avoid; cur_contd = cd->trk[cur_track-1].contd; cur_pos_rel = (cur_frame - cd->trk[cur_track-1].start) / 75; if (cur_pos_rel < 0) cur_pos_rel = -cur_pos_rel; } if( (playlist != NULL) && playlist[0].start & (cur_listno > 0)) { cur_pos_abs -= cd->trk[playlist[cur_listno-1]. start - 1].start / 75; cur_pos_abs += playlist[cur_listno-1].starttime; } if (cur_pos_abs < 0) cur_pos_abs = cur_frame = 0; if (cur_track < 1) cur_tracklen = cd->length; else cur_tracklen = cd->trk[cur_track-1].length; /* Fall through */ case WM_CDM_TRACK_DONE: cur_cdmode = mode; break; case WM_CDM_FORWARD: case WM_CDM_EJECTED: break; } return (ret); } #undef CLIF_VOL #ifdef CLIF_VOL /* * cd_volume(vol, bal, max) * * Set the volume levels. "vol" and "bal" are the volume and balance knob * settings, respectively. "max" is the maximum value of the volume knob * (the balance knob is assumed to always go from 0 to 20.) */ void cd_volume(vol, bal, max) int vol, bal, max; { int left, right, scale; /* * Set "left" and "right" to volume-slider values accounting for the * balance setting. */ /* printf("Vol = %d, Bal = %d, Max = %d\n", vol, bal, max); */ vol = (vol * 100 + max - 16) / max; scale = (vol + 5) / 10; if (bal < 9) { right = vol - scale * (10 - bal); #ifdef SYMETRIC_BALANCE left = vol + scale * (10 - bal); #else left = vol; #endif } else if (bal > 11) { #ifdef SYMETRIC_BALANCE right = vol + scale * (bal - 10); #else right = vol; #endif left = vol - scale * (bal - 10); } else left = right = vol; /* * some plat_*.c is missing the limitation */ left = left < 0 ? 0 : left > 100 ? 100 : left; right = right < 0 ? 0 : right > 100 ? 100 : right; /* printf("Left = %d, Right = %d\n", left, right); */ (void) (drive.set_volume)(&drive, left, right); } /* cd_volume() */ #else /* * cd_volume(vol, bal, max) * * Set the volume levels. "vol" and "bal" are the volume and balance knob * settings, respectively. "max" is the maximum value of the volume knob * (the balance knob is assumed to always go from 0 to 20.) */ void cd_volume( int vol, int bal, int max ) { int left, right; /* * Set "left" and "right" to volume-slider values accounting for the * balance setting. * * XXX - the maximum volume setting is assumed to be in the 20-30 range. */ if (bal < 9) right = vol - (9 - bal) * 2; else right = vol; if (bal > 11) left = vol - (bal - 11) * 2; else left = vol; left = (left * 100 + max - 1) / max; right = (right * 100 + max - 1) / max; if (left > 100) left = 100; if (right > 100) right = 100; (void) (drive.set_volume)(&drive, left, right); } /* cd_volume() */ #endif /* CLIF_VOL */ /* * wm_cd_pause() * * Pause the CD, if it's in play mode. If it's already paused, go back to * play mode. */ void wm_cd_pause( void ) { static int paused_pos; if (cur_cdmode == WM_CDM_EJECTED) /* do nothing if there's no CD! */ return; switch (cur_cdmode) { case WM_CDM_PLAYING: /* playing */ cur_cdmode = WM_CDM_PAUSED; (drive.pause)(&drive); paused_pos = cur_pos_rel; break; case WM_CDM_PAUSED: /* paused */ cur_cdmode = WM_CDM_PLAYING; /* (drive.resume)(&drive); */ if ((drive.resume)(&drive)) wm_cd_play(cur_track, paused_pos, playlist[cur_listno-1].end); default: /* */ break; } } /* wm_cd_pause() */ /* * wm_cd_stop() * * Stop the CD if it's not already stopped. */ void wm_cd_stop( void ) { if (cur_cdmode == WM_CDM_EJECTED) return; if (cur_cdmode != WM_CDM_STOPPED) { cur_lasttrack = cur_firsttrack = -1; cur_cdmode = WM_CDM_STOPPED; (drive.stop)(&drive); cur_track = 1; } } /* wm_cd_stop() */ /* * wm_cd_play_chunk(start, end) * * Play the CD from one position to another (both in frames.) */ void wm_cd_play_chunk( int start, int end, int realstart ) { if (cur_cdmode == WM_CDM_EJECTED || cd == NULL) return; end--; if (start >= end) start = end-1; (drive.play)(&drive, start, end, realstart); } /* * wm_cd_play(starttrack, pos, endtrack) * * Start playing the CD or jump to a new position. "pos" is in seconds, * relative to start of track. */ void wm_cd_play( int start, int pos, int end ) { if (cur_cdmode == WM_CDM_EJECTED || cd == NULL) return; cur_firsttrack = start; start--; end--; cur_lasttrack = end; wm_cd_play_chunk(cd->trk[start].start + pos * 75, end >= cur_ntracks ? cur_cdlen * 75 : cd->trk[end].start - 1, cd->trk[start].start); /* So we don't update the display with the old frame number */ wm_cd_status(); cur_frame = cd->trk[start].start + pos * 75; cur_track = cur_firsttrack; cur_cdmode = WM_CDM_PLAYING; } /* * Set the offset into the current track and play. -1 means end of track * (i.e., go to next track.) */ void wm_cd_play_from_pos( int pos ) { if (pos == -1) if (cd) pos = cd->trk[cur_track - 1].length - 1; if (cur_cdmode == WM_CDM_PLAYING) wm_cd_play(cur_track, pos, playlist[cur_listno-1].end); } /* wm_cd_play_from_pos() */ /* * Eject the current CD, if there is one, and set the mode to 5. * * Returns 0 on success, 1 if the CD couldn't be ejected, or 2 if the * CD contains a mounted filesystem. */ int wm_cd_eject( void ) { int status; status = (drive.eject)(&drive); if (status < 0) { if (status == -3) { return (2); } else { return (1); } } if (exit_on_eject) exit(0); cur_track = -1; cur_cdlen = cur_tracklen = 1; cur_pos_abs = cur_pos_rel = cur_frame = 0; cur_cdmode = WM_CDM_EJECTED; return (0); } int wm_cd_closetray(void) { return((drive.closetray)(&drive) ? 0 : wm_cd_status()==2 ? 1 : 0); } /* wm_cd_closetray() */ /* * find_trkind(track, index, start) * * Start playing at a particular track and index, optionally using a particular * frame as a starting position. Returns a frame number near the start of the * index mark if successful, 0 if the track/index didn't exist. * * This is made significantly more tedious (though probably easier to port) * by the fact that CDROMPLAYTRKIND doesn't work as advertised. The routine * does a binary search of the track, terminating when the interval gets to * around 10 frames or when the next track is encountered, at which point * it's a fair bet the index in question doesn't exist. */ int find_trkind( int track, int index, int start ) { int top = 0, bottom, current, interval, ret = 0, i; if( cur_cdmode == WM_CDM_EJECTED || cd == NULL ) return ( 0 ); /* WARNING: was nothing */ for (i = 0; i < cur_ntracks; i++) if (cd->trk[i].track == track) break; bottom = cd->trk[i].start; for (; i < cur_ntracks; i++) if (cd->trk[i].track > track) break; top = i == cur_ntracks ? (cd->length - 1) * 75 : cd->trk[i].start; if (start > bottom && start < top) bottom = start; current = (top + bottom) / 2; interval = (top - bottom) / 4; do { wm_cd_play_chunk(current, current + 75, current); if (wm_cd_status() != 1) return (0); while (cur_frame < current) if (wm_cd_status() != 1 || cur_cdmode != WM_CDM_PLAYING) return (0); else wm_susleep(1); if (cd->trk[cur_track - 1].track > track) break; if (cur_index >= index) { ret = current; current -= interval; } else current += interval; interval /= 2; } while (interval > 2); return (ret); } /* find_trkind() */ /* * Read the initial volume from the drive, if available. Set cur_balance to * the balance level (0-20, 10=centered) and return the proper setting for * the volume knob. * * "max" is the maximum value of the volume knob. */ int wm_cd_read_initial_volume( int max ) { int left, right; if ((drive.get_volume)(&drive, &left, &right) < 0 || left == -1) return (max); left = (left * max + 99) / 100; right = (right * max + 99) / 100; if (left < right) { wm_cd_cur_balance = (right - left) / 2 + 11; if (wm_cd_cur_balance > 20) wm_cd_cur_balance = 20; return (right); } else if (left == right) { wm_cd_cur_balance = 10; return (left); } else { wm_cd_cur_balance = (right - left) / 2 + 9; if (wm_cd_cur_balance < 0) wm_cd_cur_balance = 0; return (left); } } /* wm_cd_read_initial_volume() */ /* * Prototype wm_drive structure, with generic functions. The generic functions * will be replaced with drive-specific functions as appropriate once the drive * type has been sensed. */ struct wm_drive generic_proto = { -1, /* fd */ "Generic\0", /* vendor */ "drive type\0 ", /* model */ "\0", /* revision */ NULL, /* aux */ NULL, /* daux */ gen_init, /* functions... */ gen_get_trackcount, gen_get_cdlen, gen_get_trackinfo, gen_get_drive_status, gen_get_volume, gen_set_volume, gen_pause, gen_resume, gen_stop, gen_play, gen_eject, gen_closetray }; ascd-0.13.2.orig/libworkman/cdinfo.c0100644000175000017500000004573506723166072016565 0ustar hallonhallon/* * $Id: cdinfo.c,v 1.6 1999/02/14 16:47:40 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * Get information about a CD. */ static char cdinfo_id[] = "$Id: cdinfo.c,v 1.6 1999/02/14 16:47:40 dirk Exp $"; #include #include #include #include #include #include "include/wm_config.h" #include "include/wm_struct.h" #include "include/wm_cdrom.h" #include "include/wm_cdinfo.h" #include "include/wm_database.h" #include "include/wm_helpers.h" struct wm_play *playlist = NULL; struct wm_cdinfo thiscd, *cd = &thiscd; int cur_track = -1; /* Current track number, starting at 1 */ int cur_index = 0; /* Current index mark */ int cur_lasttrack = 999; /* Last track to play in current chunk */ int cur_firsttrack = 0; /* First track of current chunk */ int cur_pos_abs; /* Current absolute position in seconds */ int cur_frame; /* Current frame number */ int cur_pos_rel; /* Current track-relative position in seconds */ int cur_tracklen; /* Length in seconds of current track */ int cur_cdlen; /* Length in seconds of entire CD */ int cur_ntracks; /* Number of tracks on CD (= tracks + sections) */ int cur_nsections; /* Number of sections currently defined */ enum wm_cd_modes cur_cdmode = WM_CDM_EJECTED; int cur_listno; /* Current index into the play list, if playing */ char * cur_artist; /* Name of current CD's artist */ char * cur_cdname; /* Album name */ char * cur_trackname; /* Take a guess */ char cur_contd; /* Continued flag */ char cur_avoid; /* Avoid flag */ int exit_on_eject = 0; int cur_stopmode = -1; extern int info_modified; /* * insert_trackinfo() * * Add a new track to the CD info structure. Pass the position of the new * entry in the track list -- 0 will make this the first track, 1 the second, * etc. The new entry will be zeroed out. */ void insert_trackinfo(num) int num; { struct wm_trackinfo *newtrk; /* Easy case: the list is empty */ if (cd->trk == NULL) { if ((cd->trk = (struct wm_trackinfo *) calloc(1, sizeof(*newtrk))) == NULL) { nomem: perror("insert_trackinfo"); exit(1); } else { return; } /* if() else */ } /* if() */ /* Stick the new entry in cd->trk[]. */ if ((newtrk = (struct wm_trackinfo *) malloc(sizeof(*newtrk) * (cur_ntracks + 1))) == NULL) goto nomem; if (num) memcpy(newtrk, cd->trk, sizeof(*newtrk) * num); memset(&newtrk[num], 0, sizeof(*newtrk)); if (num < cur_ntracks) memcpy(&newtrk[num + 1], &cd->trk[num], sizeof(*newtrk) * (cur_ntracks - num)); free(cd->trk); cd->trk = newtrk; } /* * split_trackinfo() * * Split a track in two at a particular position (absolute, in frames). All * internal data structures and variables will be adjusted to the new * numbering scheme. Pass in the track number (>=1) to split, which is also * the index into cd->trk[] of the new entry. * * If pos is within 1 second of the start of another track, the split fails. * * Returns 1 on success, 0 if the track couldn't be inserted. * * Note: updating user interface elements is up to the caller. */ int split_trackinfo( int pos ) { int i, l, num; if (pos < cd->trk[0].start) return (0); /* First find the appropriate track. */ for (num = 0; num < cur_ntracks; num++) if (cd->trk[num].start - 75 < pos && cd->trk[num].start + 75 > pos) return (0); else if (cd->trk[num].start > pos) break; if (num == 0) return (0); /* Insert the new entry into the track array. */ insert_trackinfo(num); /* Update the easy variables. */ if (cur_track > num) cur_track++; if (cur_firsttrack > num) cur_firsttrack++; if (cur_lasttrack > num) cur_lasttrack++; /* Update the user-defined playlists. */ if (cd->lists != NULL) for (l = 0; cd->lists[l].name != NULL; l++) if (cd->lists[l].list != NULL) for (i = 0; cd->lists[l].list[i]; i++) if (cd->lists[l].list[i] > num) cd->lists[l].list[i]++; /* Update the internal playlist. */ if (playlist != NULL) for (i = 0; playlist[i].start; i++) { if (playlist[i].start > num) playlist[i].start++; if (playlist[i].end > num) playlist[i].end++; } /* Now adjust the information in cd->trk[]. */ cd->trk[num].start = pos; if (num == cur_ntracks) cd->trk[num].length = cur_cdlen - pos / 75; else cd->trk[num].length = (cd->trk[num + 1].start - pos) / 75; cd->trk[num - 1].length -= cd->trk[num].length; if (cur_track == num) cur_tracklen -= cd->trk[num].length; cd->trk[num].track = cd->trk[num - 1].track; cd->trk[num].data = cd->trk[num - 1].data; cd->trk[num].contd = 1; cd->trk[num].volume = cd->trk[num - 1].volume; if (cd->trk[num - 1].section == 0) cd->trk[num - 1].section = 1; cd->trk[num].section = cd->trk[num - 1].section + 1; cur_ntracks++; cur_nsections++; for (i = num + 1; i < cur_ntracks; i++) if (cd->trk[i].track == cd->trk[num].track) cd->trk[i].section++; return (1); } /* * remove_trackinfo() * * Remove a track's internal data. This is similar to split_trackinfo() * above, but simpler. A track's initial section can't be removed. Track * numbers start at 0. * * Returns 1 on success, 0 on failure. */ int remove_trackinfo( int num ) { int i, l; if (num < 1 || num >= cur_ntracks || cd->trk[num].section < 2) return (0); cd->trk[num - 1].length += cd->trk[num].length; for (i = num; i < cur_ntracks - 1; i++) memcpy(&cd->trk[i], &cd->trk[i + 1], sizeof(cd->trk[0])); if (cur_track > num) cur_track--; if (cur_firsttrack > num) cur_firsttrack--; if (cur_lasttrack > num) cur_lasttrack--; /* Update the user-defined playlists. */ if (cd->lists != NULL) for (l = 0; cd->lists[l].name != NULL; l++) if (cd->lists[l].list != NULL) for (i = 0; cd->lists[l].list[i]; i++) if (cd->lists[l].list[i] > num) cd->lists[l].list[i]--; /* Update the internal playlist. */ if (playlist != NULL) for (i = 0; playlist[i].start; i++) { if (playlist[i].start > num) playlist[i].start--; if (playlist[i].end > num) playlist[i].end--; } cur_ntracks--; cur_nsections--; /* * Update the section numbers for this track. If this is the only * user-created section in a track, get rid of the section number * in the track's entry. */ if (num == cur_ntracks || cd->trk[num - 1].track != cd->trk[num].track) { if (cd->trk[num - 1].section == 1) cd->trk[num - 1].section = 0; } else for (i = num; i < cur_ntracks; i++) if (cd->trk[i].track == cd->trk[num - 1].track) cd->trk[i].section--; return (1); } /* * listentry() * * Return a scrolling list entry. */ char * listentry( int num ) { static char buf[600]; char *name, tracknum[20]; int digits; int sdigits; if (num >= 0 && num < cur_ntracks) { /* if (big_spaces) { digits = 2; sdigits = cur_nsections < 9 ? -1 : -2; } else { digits = cd->trk[num].track < 10 ? 3 : 2; sdigits = cur_nsections < 9 ? -1 : -3; } */ digits = 2; sdigits = cur_nsections < 9 ? -1 : -2; name = cd->trk[num].songname ? cd->trk[num].songname : ""; if (cur_nsections) { if (cd->trk[num].section > 9) { sprintf(tracknum, "%*d.%d", digits, cd->trk[num].track, cd->trk[num].section); } else { if (cd->trk[num].section) { sprintf(tracknum, "%*d.%*d", digits, cd->trk[num].track, sdigits, cd->trk[num].section); } else { sprintf(tracknum, "%*d%*s", digits, cd->trk[num].track, 2 - sdigits, " "); /* 2 - sdigits - big_spaces, " ");*/ } } } else { sprintf(tracknum, "%*d", digits, cd->trk[num].track); } if (cd->trk[num].data) { sprintf(buf, "%s) %3dMB %s", tracknum, cd->trk[num].length / 1024, name); } else { sprintf(buf, "%s) %02d:%02d %s", tracknum, cd->trk[num].length / 60, cd->trk[num].length % 60, name); } return (buf); } else { return (NULL); } } /* listentry() */ /* * trackname() * * Return a track's name. */ char * trackname( int num ) { if (num >= 0 && num < cur_ntracks) { if (cd->trk[num].songname) { return (cd->trk[num].songname); } else { return (""); } } else { return (NULL); } } /* trackname() */ /* * tracklen() * * Return a track's length in seconds. */ int tracklen( int num ) { if (cd != NULL && num >= 0 && num < cur_ntracks) return (cd->trk[num].length); else return (0); } /* * get_default_volume() * * Return the default volume (0-32, 0=none) for the CD or a track. */ int get_default_volume( int track ) { if (! track) return (cd->volume); else if (track <= cur_ntracks) return (cd->trk[track - 1].volume); else return (0); } /* * get_contd() * * Return the contd value for a track. */ int get_contd( int num ) { if (num >= 0 && num < cur_ntracks) return (cd->trk[num].contd); else return (0); } /* * get_avoid() * * Return the avoid value for a track. */ int get_avoid( int num ) { if (num >= 0 && num < cur_ntracks) return (cd->trk[num].avoid); else return (0); } /* * get_autoplay() * * Is autoplay set on this disc? */ int get_autoplay( void ) { return ( cd->autoplay ); } /* * get_playmode() * * Return the default playmode for the CD. */ int get_playmode( void ) { return ( cd->playmode ); } /* * get_runtime() * * Return the total running time for the current playlist in seconds. */ int get_runtime( void ) { int i; if (playlist == NULL || playlist[0].start == 0 || cur_firsttrack == -1) return (cd == NULL ? 0 : cd->length); for (i = 0; playlist[i].start; i++) ; return (playlist[i].starttime); } /* * default_volume() * * Set the default volume for the CD or a track. */ void default_volume( int track, int vol ) { if (track == 0) cd->volume = vol; else if (track <= cur_ntracks) cd->trk[track - 1].volume = vol; } /* * Play the next thing on the playlist, if any. */ void play_next_entry( int forward ) { if (cd == NULL) return; if (playlist != NULL && playlist[cur_listno].start) { wm_cd_play(playlist[cur_listno].start, 0, playlist[cur_listno].end); cur_listno++; } else wm_cd_stop(); } /* * Play the next track, following playlists as necessary. */ void play_next_track( int forward ) { if (cd == NULL) return; /* Is the current playlist entry done? Move on, if so. */ if (playlist == NULL || cur_track + 1 == playlist[cur_listno - 1].end) play_next_entry( forward ); else wm_cd_play(cur_track + 1, 0, playlist[cur_listno - 1].end); } /* * Play the previous track, hopping around the playlist as necessary. */ void play_prev_track( int forward ) { if (cd == NULL) return; if (playlist == NULL) return; /* If we're in the middle of this playlist entry, go back one track */ if (cur_track > playlist[cur_listno - 1].start) wm_cd_play(cur_track - 1, 0, playlist[cur_listno - 1].end); else if (cur_listno > 1) { cur_listno--; wm_cd_play(playlist[cur_listno - 1].end - 1, 0, playlist[cur_listno - 1].end); } else wm_cd_play(playlist[0].start, 0, playlist[0].end); } /* * stash_cdinfo(artist, cdname) */ void stash_cdinfo(char *artist, char *cdname, int autoplay, int playmode ) { if (cd != NULL) { if (strcmp(cd->artist, artist)) info_modified = 1; strcpy(cd->artist, artist); if (strcmp(cd->cdname, cdname)) info_modified = 1; strcpy(cd->cdname, cdname); if (!!cd->autoplay != !!autoplay) info_modified = 1; cd->autoplay = autoplay; if (!!cd->playmode != !!playmode) info_modified = 1; cd->playmode = playmode; } } /* stash_cdinfo() */ /* * wipe_cdinfo() * * Clear out all a CD's soft information (presumably in preparation for * reloading from the database.) */ void wipe_cdinfo( void ) { struct wm_playlist *l; int i; if (cd != NULL) { cd->artist[0] = cd->cdname[0] = '\0'; cd->autoplay = cd->playmode = cd->volume = 0; cd->whichdb = NULL; freeup(&cd->otherrc); freeup(&cd->otherdb); if (thiscd.lists != NULL) { for (l = thiscd.lists; l->name != NULL; l++) { free(l->name); free(l->list); } freeup( (char **)&thiscd.lists ); } for (i = 0; i < cur_ntracks; i++) { freeup(&cd->trk[i].songname); freeup(&cd->trk[i].otherrc); freeup(&cd->trk[i].otherdb); cd->trk[i].avoid = cd->trk[i].contd = 0; cd->trk[i].volume = 0; if (cd->trk[i].section > 1) remove_trackinfo(i--); } } } /* * stash_trkinfo(track, songname, contd, avoid) * * Update information about a track on the current CD. */ void stash_trkinfo( int track, char *songname, int contd, int avoid ) { if (cd != NULL) { track--; if (!!cd->trk[track].contd != !!contd) info_modified = 1; cd->trk[track].contd = track ? contd : 0; if (!!cd->trk[track].avoid != !!avoid) info_modified = 1; cd->trk[track].avoid = avoid; if ((cd->trk[track].songname == NULL && songname[0]) || (cd->trk[track].songname != NULL && strcmp(cd->trk[track].songname, songname))) { info_modified = 1; wm_strmcpy(&cd->trk[track].songname, songname); } } } /* * new_list() * * Add a playlist to a CD. */ struct wm_playlist * new_list(cd, listname) struct wm_cdinfo *cd; char *listname; { int nlists = 0; struct wm_playlist *l; if (cd->lists != NULL) { for (nlists = 0; cd->lists[nlists].name != NULL; nlists++) ; l = (struct wm_playlist *)realloc(cd->lists, (nlists + 2) * sizeof (struct wm_playlist)); } else l = (struct wm_playlist *)malloc(2 * sizeof (struct wm_playlist)); if (l == NULL) return (NULL); l[nlists + 1].name = NULL; l[nlists].name = NULL; /* so wm_strmcpy doesn't free() it */ wm_strmcpy(&l[nlists].name, listname); l[nlists].list = NULL; cd->lists = l; return (&l[nlists]); } /* * make_playlist() * * Construct a playlist for the current CD. If we're in shuffle mode, play * each non-avoided track once, keeping continued tracks in the right order. * * If playmode is 2, use playlist number (playmode-2). XXX should do * bounds checking on this, probably. * * If consecutive tracks are being played, only make one playlist entry for * them, so the CD player won't pause between tracks while we wake up. */ void make_playlist( int playmode, int starttrack ) { int i, avoiding = 1, entry = 0, count, track, *thislist; cur_listno = 0; if (playlist != NULL) free(playlist); playlist = malloc(sizeof (*playlist) * (cur_ntracks + 1)); if (playlist == NULL) { perror("playlist"); exit(1); } /* If this is a data-only CD, we can't play it. */ if ((starttrack && cd->trk[starttrack - 1].data) || (cur_ntracks == 1 && cd->trk[0].data)) { playlist[0].start = 0; playlist[0].end = 0; playlist[1].start = 0; return; } if (playmode == 1) { char *done = malloc(cur_ntracks); if (done == NULL) { perror("randomizer"); exit(1); } count = cur_ntracks; if (starttrack && cd->trk[starttrack - 1].avoid) count++; for (i = 0; i < cur_ntracks; i++) if (cd->trk[i].contd || cd->trk[i].avoid || cd->trk[i].data) { done[i] = 1; count--; } else done[i] = 0; for (i = 0; i < count; i++) { int end; /* for readability */ if (starttrack) { track = starttrack - 1; starttrack = 0; } else while (done[track = rand() % cur_ntracks]) ; playlist[i].start = track + 1; /* play all subsequent continuation tracks too */ for (end = track + 1; end < cur_ntracks + 1; end++) if (! cd->trk[end].contd || cd->trk[end].avoid || cd->trk[end].data) break; playlist[i].end = end + 1; done[track]++; } playlist[i].start = 0; free(done); } else if (playmode >= 2 && cd->lists && cd->lists[playmode - 2].name) { count = 2; /* one terminating entry, and one for start */ thislist = cd->lists[playmode - 2].list; for (i = 0; thislist[i]; i++) if (thislist[i + 1] != thislist[i] + 1) count++; if (playlist != NULL) free(playlist); playlist = malloc(sizeof (*playlist) * count); if (playlist == NULL) { perror("playlist"); exit(1); } count = 0; if (starttrack) { playlist[0].start = starttrack; for (track = 0; thislist[track]; track++) if (starttrack == thislist[track]) break; if (! thislist[track]) { playlist[0].end = starttrack + 1; playlist[1].start = thislist[0]; count = 1; track = 0; } } else { playlist[0].start = thislist[0]; track = 0; } for (i = track; thislist[i]; i++) if (thislist[i + 1] != thislist[i] + 1) { playlist[count].end = thislist[i] + 1; count++; playlist[count].start = thislist[i + 1]; } } else { for (i = starttrack ? starttrack - 1 : 0; i < cur_ntracks; i++) if (avoiding && ! (cd->trk[i].avoid || cd->trk[i].data)) { playlist[entry].start = i + 1; avoiding = 0; } else if (! avoiding && (cd->trk[i].avoid || cd->trk[i].data)) { playlist[entry].end = i + 1; avoiding = 1; entry++; } if (! avoiding) playlist[entry].end = i + 1; playlist[entry + !avoiding].start = 0; } /* * Now go through the list, whatever its source, and figure out * cumulative starting times for each entry. */ entry = count = 0; do { playlist[entry].starttime = count; if (playlist[entry].start) for (i = playlist[entry].start; i < playlist[entry].end; i++) count += cd->trk[i - 1].length; } while (playlist[entry++].start); } /* * Find a particular track's location in the current playlist. Sets the * appropriate variables (cur_listno, cur_firsttrack, cur_lasttrack). */ void pl_find_track( int track ) { int i; if (playlist == NULL) { fprintf(stderr, "Null playlist! Huh?\n"); return; } for (i = 0; playlist[i].start; i++) if (track >= playlist[i].start && track < playlist[i].end) { cur_listno = i + 1; cur_firsttrack = playlist[i].start; cur_lasttrack = playlist[i].end - 1; return; } /* * Couldn't find the track in question. Make a special entry with * just that track. */ if (! playlist[i].start) { playlist = realloc(playlist, (i + 2) * sizeof(*playlist)); if (playlist == NULL) { perror("playlist realloc"); exit(1); } playlist[i + 1].start = playlist[i + 1].end = 0; playlist[i + 1].starttime = playlist[i].starttime + cd->trk[track - 1].length; playlist[i].start = track; playlist[i].end = track + 1; cur_listno = i + 1; cur_firsttrack = track; cur_lasttrack = track; } } ascd-0.13.2.orig/libworkman/plat_aix.c0100644000175000017500000002103706670435230017105 0ustar hallonhallon/* * $Id: plat_aix.c,v 1.7 1999/03/07 08:36:40 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * plat_aix - AIX 4.x IDE and SCSI support 16 Dec 1998 * * AIX 4.x Port: Erik O'Shaughnessy * Original AIX IDE Code: Cloyce Spradling (xmcd libdi_d/aixioc.c ) * * Taken from the ascd distribution. * */ #ifdef AIXV3 static char plat_aix_id[] = "$Id: plat_aix.c,v 1.7 1999/03/07 08:36:40 dirk Exp $"; #include #include #include #include #include #include #include #include #include #include "include/wm_config.h" #include "include/wm_struct.h" #define WM_MSG_CLASS WM_MSG_CLASS_PLATFORM #define LEADOUT 0xaa extern char *cd_device; int min_volume = 128; int max_volume = 255; /* NAME: gen_init * * FUNCTION: * * RETURNS: */ int gen_init(struct wm_drive *d){ return 0; } /* NAME: gen_get_trackcount * * FUNCTION: * * RETURNS: */ int gen_get_trackcount(struct wm_drive *d,int *tracks){ struct cd_audio_cmd cmd; cmd.audio_cmds = CD_TRK_INFO_AUDIO; cmd.msf_flag = 0; if( ioctl(d->fd,DKAUDIO,&cmd) < 0){ perror("DKAUDIO"); return -1; } *tracks = cmd.indexing.track_index.last_track; return 0; } /* NAME: gen_get_cdlen * * FUNCTION: * * RETURNS: */ int gen_get_cdlen(struct wm_drive *d,int *frames){ int tmp; return gen_get_trackinfo(d,LEADOUT,&tmp,frames); } /* NAME: gen_get_trackinfo * * FUNCTION: * * RETURNS: */ int gen_get_trackinfo(struct wm_drive *d,int track,int *data,int *startframe){ struct cd_audio_cmd cmd; cmd.audio_cmds = CD_GET_TRK_MSF; cmd.msf_flag = 1; cmd.indexing.track_msf.track = track; if( ioctl(d->fd,DKAUDIO,&cmd) < 0) return -1; *startframe = cmd.indexing.track_msf.mins * 60 * 75 + cmd.indexing.track_msf.secs * 75 + cmd.indexing.track_msf.frames; *data = 0; return 0; } /* NAME: gen_get_drive_status * * FUNCTION: * * RETURNS: */ int gen_get_drive_status(struct wm_drive *d, enum wm_cd_modes oldmode, enum wm_cd_modes *mode, int *pos, int *track, int *index){ struct cd_audio_cmd cmd; *mode = WM_CDM_EJECTED; if(d->fd < 0) switch( wmcd_open(d) ){ case -1: return -1; case 1: return 0; } cmd.audio_cmds = CD_INFO_AUDIO; if( ioctl(d->fd,DKAUDIO,&cmd) < 0) return -1; switch(cmd.status){ case CD_PLAY_AUDIO: *mode = WM_CDM_PLAYING; *track = cmd.indexing.info_audio.current_track; *index = cmd.indexing.info_audio.current_index; *pos = cmd.indexing.info_audio.current_mins * 60 * 75 + cmd.indexing.info_audio.current_secs * 75 + cmd.indexing.info_audio.current_frames; break; case CD_PAUSE_AUDIO: *mode = WM_CDM_PAUSED; *track = cmd.indexing.info_audio.current_track; *index = cmd.indexing.info_audio.current_index; *pos = cmd.indexing.info_audio.current_mins * 60 * 75 + cmd.indexing.info_audio.current_secs * 75 + cmd.indexing.info_audio.current_frames; break; case CD_NO_AUDIO: /* no play audio in progress */ case CD_COMPLETED: /* play operation completed successfully */ case CD_STATUS_ERROR: /* invalid status or play stopped due to err */ case CD_NOT_VALID: /* audio status is invalid or not supported */ *mode = WM_CDM_STOPPED; break; default: *mode = WM_CDM_UNKNOWN; break; } return 0; } int scale_volume(int vol,int max){ return ((vol * (max_volume - min_volume)) / max + min_volume); } int unscale_volume(int vol,int max){ int n; n = ( vol - min_volume ) * max_volume / (max - min_volume); return (n <0)?0:n; } /* NAME: gen_get_volume * * FUNCTION: * * RETURNS: */ int gen_get_volume(struct wm_drive *d,int *left,int *right){ struct cd_audio_cmd cmd; int l,r; fprintf(stderr,"gen_get_volume\n"); cmd.audio_cmds = CD_INFO_AUDIO; if( ioctl(d->fd,DKAUDIO,&cmd) < 0) return -1; *left = unscale_volume(cmd.out_port_0_vol,100); *right = unscale_volume(cmd.out_port_1_vol,100); return 0; } /* NAME: gen_set_volume * * FUNCTION: * * RETURNS: */ int gen_set_volume(struct wm_drive *d,int left,int right){ struct cd_audio_cmd cmd; cmd.audio_cmds = CD_SET_VOLUME; cmd.volume_type = CD_VOLUME_CHNLS; cmd.out_port_0_vol = scale_volume(left,100); cmd.out_port_1_vol = scale_volume(right,100); if( ioctl(d->fd,DKAUDIO,&cmd) < 0){ perror("CD_SET_VOLUME"); return -1; } return 0; } /* NAME: gen_pause * * FUNCTION: * * RETURNS: */ int gen_pause(struct wm_drive *d){ struct cd_audio_cmd cmd; cmd.audio_cmds = CD_PAUSE_AUDIO; return ioctl(d->fd,DKAUDIO,&cmd); } /* NAME: gen_resume * * FUNCTION: * * RETURNS: */ int gen_resume(struct wm_drive *d){ struct cd_audio_cmd cmd; cmd.audio_cmds = CD_RESUME_AUDIO; return ioctl(d->fd,DKAUDIO,&cmd); } /* NAME: gen_stop * * FUNCTION: * * RETURNS: */ int gen_stop(struct wm_drive *d){ struct cd_audio_cmd cmd; cmd.audio_cmds = CD_STOP_AUDIO; return ioctl(d->fd,DKAUDIO,&cmd); } /* NAME: gen_play * * FUNCTION: * * RETURNS: */ int gen_play(struct wm_drive *d,int start,int end){ struct cd_audio_cmd cmd; cmd.audio_cmds = CD_PLAY_AUDIO; cmd.msf_flag = 1; cmd.indexing.msf.first_mins = start / (60*75); cmd.indexing.msf.first_secs = (start % (60*75)) / 75; cmd.indexing.msf.first_frames = start % 75; cmd.indexing.msf.last_mins = end / (60*75); cmd.indexing.msf.last_secs = (end % (60*75)) / 75; cmd.indexing.msf.last_frames = end % 75; if( ioctl(d->fd,DKAUDIO,&cmd) < 0){ perror("DKAUDIO:CD_PLAY_AUDIO"); return -1; } return 0; } /* NAME: gen_eject * * FUNCTION: * * RETURNS: */ int gen_eject(struct wm_drive *d){ return ioctl(d->fd,DKEJECT,NULL); } /*----------------------------------------* * Close the CD tray *----------------------------------------*/ int gen_closetray(struct wm_drive *d) { #ifdef CAN_CLOSE if(!close(d->fd)) { d->fd=-1; return(wmcd_reopen(d)); } else { return(-1); } #else /* Always succeed if the drive can't close */ return(0); #endif /* CAN_CLOSE */ } /* gen_closetray() */ /* NAME: wm_scsi * * FUNCTION: * * RETURNS: */ int wm_scsi(struct wm_drive *d, uchar_t *cdb, int cdblen,void *retbuf,int retbuflen,int getreply){ return 0; } /* NAME: wmcd_open * * FUNCTION: * * RETURNS: */ int wmcd_open(struct wm_drive *d){ char vendor[32] = WM_STR_GENVENDOR; char model[32] = WM_STR_GENMODEL; char rev[32] = WM_STR_GENREV; int fd; if( ! d ){ errno = EFAULT; return -1; } if(d->fd > -1) /* device already open? */ return 0; if( cd_device == (char *)NULL ) cd_device = DEFAULT_CD_DEVICE; if( (fd=openx(cd_device,O_RDONLY,NULL,SC_SINGLE)) < 0 ){ perror("openx"); return 1; } *d = *(find_drive_struct(vendor, model, rev)); wm_drive_settype(vendor, model, rev); d->fd = fd; d->init(d); return 0; } /* wmcd_open() */ /* * Re-Open the device if it is open. */ int wmcd_reopen( struct wm_drive *d ) { int status; do { wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "wmcd_reopen "); if (d->fd >= 0) /* Device really open? */ { wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "closes the device and "); status = close( d->fd ); /* close it! */ /* we know, that the file is closed, do we? */ d->fd = -1; } wm_susleep( 1000 ); wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "calls wmcd_open()\n"); status = wmcd_open( d ); /* open it as usual */ wm_susleep( 1000 ); } while ( status != 0 ); return status; } /* wmcd_reopen() */ #endif /* _AIX */ ascd-0.13.2.orig/libworkman/database.c0100644000175000017500000010154506723407432017055 0ustar hallonhallon/* * $Id: database.c,v 1.8 1999/05/28 03:35:54 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * Manage the CD database. All these routines assume that the "cd" global * structure contains current information (as far as the outside world knows; * obviously it won't contain track titles just after a CD is inserted.) */ static char database_id[] = "$Id: database.c,v 1.8 1999/05/28 03:35:54 dirk Exp $"; #define RCFILE "/.workmanrc" #define DBFILE "/.workmandb" #define FUZZFRAMES 75 #include #include #include #include #include #include #include #include #include #include #include #include "include/wm_config.h" #include "include/wm_helpers.h" #include "include/wm_struct.h" #include "include/wm_cdinfo.h" #include "include/wm_cddb.h" #include "include/wm_index.h" #include "include/wm_database.h" #define WM_MSG_CLASS WM_MSG_CLASS_DB #define SWALLOW_LINE(fp) { int c; while ((c = getc(fp)) != '\n' && c != EOF); } int suppress_locking = 0; /* Turn off locking of datafile (dangerous) */ char *rcfile = NULL; /* Personal rcfile */ char *dbfiles = NULL; /* Colon-separated list of databases */ char **databases = NULL; /* NULL-terminated list of databases */ char *otherrc = NULL; /* Unrecognized cruft from start of rcfile */ long rcpos, rclen; /* XXX */ int found_in_db, found_in_rc; long holepos, firstpos; int fuzz_frames = FUZZFRAMES; int wm_db_save_disabled = FALSE; int cur_playnew = -1; extern int cur_ntracks, cur_nsections; int mark_a = 0; int mark_b = 0; /* * */ int wm_db_get_playnew( void ) { return 0; } /* * split_workmandb() * * Split the WORKMANDB environment variable, if any, into a list of database * files in the global "databases". If WORKMANDB is not available, make * a single entry with $HOME/DBFILE. * * Also, fill the "rcfile" global with the personal preferences filename. * * The environment variables should have already been read and placed in the * "rcfile" and "dbfiles" globals, respectively. */ void split_workmandb( void ) { int ndbs, i; char *home, *wmdb; int no_rc = 0, no_db = 0; if (rcfile == NULL) { if ((home = getenv("HOME")) != NULL) { rcfile = malloc(strlen(home) + sizeof(RCFILE)); if (rcfile == NULL) { nomem: perror("split_workmandb()"); exit(1); } strcpy(rcfile, home); strcat(rcfile, RCFILE); } else no_rc = 1; } if ((wmdb = dbfiles) == NULL) { if ((home = getenv("HOME")) != NULL) { wmdb = malloc(strlen(home) + sizeof(DBFILE)); if (wmdb == NULL) goto nomem; databases = malloc(2 * sizeof (databases[0])); if (databases == NULL) goto nomem; strcpy(wmdb, home); strcat(wmdb, DBFILE); databases[0] = wmdb; databases[1] = NULL; } else { static char *emptydb = NULL; databases = &emptydb; no_db = 1; } } else { ndbs = 1; for (home = wmdb; *home; home++) if (*home == ':') { *home = '\0'; ndbs++; } databases = malloc((ndbs + 1) * sizeof(databases[0])); if (databases == NULL) goto nomem; for (i = 0; i < ndbs; i++) { databases[i] = wmdb; wmdb += strlen(wmdb) + 1; } databases[i] = NULL; } if (no_db || no_rc) { fprintf(stderr, "WorkMan was run without a home directory, probably by a system daemon.\n"); fprintf(stderr, "It doesn't know where to find "); if (no_rc) { fprintf(stderr, "your personal preferences file "); if (no_db) fprintf(stderr, "or the\ndatabase of CD descriptions"); } else fprintf(stderr, "the database of CD descriptions"); fprintf(stderr, ".\nYou can use the X resources \"workman.db.shared\" and \"workman.db.personal\"\nto tell WorkMan where to look.\n"); wm_db_save_disabled = TRUE; } } /* * print_cdinfo(cd, prefs) * * cd A pointer to a cdinfo struct. * prefs Flag: write personal preferences? * * Print a CD's information (in more or less readable form) to a buffer. * Returns a pointer to the buffer. * * XXX - could be more efficient about calling wm_strmcat() and strlen(). */ char * print_cdinfo(struct wm_cdinfo *cd, int prefs) { int i; char tempbuf[2000]; /* XXX - is this always big enough? */ static char *cdibuf = NULL; struct wm_playlist *l; sprintf(tempbuf, "\ntracks %d", cd->ntracks); for (i = 0; i < cur_ntracks; i++) if (cd->trk[i].section < 2) sprintf(tempbuf + strlen(tempbuf), " %d", cd->trk[i].start); sprintf(tempbuf + strlen(tempbuf), " %d\n", cd->length); wm_strmcpy(&cdibuf, tempbuf); if (cur_nsections) { sprintf(tempbuf, "sections %d", cur_nsections); /* fixed a bug here */ for (i = 0; i < cur_ntracks; i++) if (cd->trk[i].section > 1) sprintf(tempbuf + strlen(tempbuf), " %d", cd->trk[i].start); sprintf(tempbuf + strlen(tempbuf), "\n"); wm_strmcat(&cdibuf, tempbuf); } if (prefs) { if (cd->autoplay) wm_strmcat(&cdibuf, "autoplay\n"); for (l = cd->lists; l != NULL && l->name != NULL; l++) { wm_strmcat(&cdibuf, "playlist "); i = strlen(cdibuf) - 1; wm_strmcat(&cdibuf, l->name); while (cdibuf[++i]) if (cdibuf[i] == ' ' || cdibuf[i] == '\t') cdibuf[i] = '_'; if (l->list != NULL) { for (i = 0; l->list[i]; i++) ; sprintf(tempbuf, " %d", i); wm_strmcat(&cdibuf, tempbuf); for (i = 0; l->list[i]; i++) { sprintf(tempbuf, " %d", l->list[i]); wm_strmcat(&cdibuf, tempbuf); } wm_strmcat(&cdibuf, "\n"); } else wm_strmcat(&cdibuf, " 0\n"); } if (cd->volume) { /* * Have to maintain compatibility with old versions, * where volume was 0-32. */ sprintf(tempbuf, "cdvolume %d\n", (cd->volume * 32) / 100); wm_strmcat(&cdibuf, tempbuf); } if (cd->playmode) { sprintf(tempbuf, "playmode %d\n", cd->playmode); wm_strmcat(&cdibuf, tempbuf); } if (mark_a) { sprintf(tempbuf, "mark %d START\n", mark_a); wm_strmcat(&cdibuf, tempbuf); } if (mark_b) { sprintf(tempbuf, "mark %d END\n", mark_b); wm_strmcat(&cdibuf, tempbuf); } if (cd->otherrc) wm_strmcat(&cdibuf, cd->otherrc); for (i = 0; i < cur_ntracks; i++) { if (cd->trk[i].avoid) { sprintf(tempbuf, "dontplay %d\n", i + 1); wm_strmcat(&cdibuf, tempbuf); } if (cd->trk[i].volume) { sprintf(tempbuf, "volume %d %d\n", i + 1, (cd->trk[i].volume * 32) / 100); wm_strmcat(&cdibuf, tempbuf); } if (cd->trk[i].otherrc) wm_strmcat(&cdibuf, cd->trk[i].otherrc); } } else { if (cd->cdname[0]) { wm_strmcat(&cdibuf, "cdname "); wm_strmcat(&cdibuf, cd->cdname); wm_strmcat(&cdibuf, "\n"); } if (cd->artist[0]) { wm_strmcat(&cdibuf, "artist "); wm_strmcat(&cdibuf, cd->artist); wm_strmcat(&cdibuf, "\n"); } if (cd->otherdb) wm_strmcat(&cdibuf, cd->otherdb); for (i = 0; i < cur_ntracks; i++) { if (cd->trk[i].section > 1) wm_strmcat(&cdibuf, "s-"); wm_strmcat(&cdibuf, "track "); if (cd->trk[i].songname != NULL) wm_strmcat(&cdibuf, cd->trk[i].songname); wm_strmcat(&cdibuf, "\n"); if (cd->trk[i].contd) { if (cd->trk[i].section > 1) wm_strmcat(&cdibuf, "s-"); wm_strmcat(&cdibuf, "continue\n"); } if (cd->trk[i].otherdb) wm_strmcat(&cdibuf, cd->trk[i].otherdb); } } return (cdibuf); } /* print_cdinfo() */ /* * Open the rcfile for reading or writing. * * name Filename * mode "r" or "w" */ FILE * open_rcfile(char *name, char *mode) { FILE *fp; struct stat st; fp = fopen(name, mode); if (fp == NULL) { if (errno != ENOENT || mode[0] == 'w') perror(name); } else { /* Don't let people open directories or devices */ if (fstat(fileno(fp), &st) < 0) { perror(name); fclose(fp); return (NULL); } #ifdef S_ISREG if (! S_ISREG(st.st_mode)) #else if ((st.st_mode & S_IFMT) != S_IFREG) #endif { errno = EISDIR; perror(name); fclose(fp); return (NULL); } if (mode[0] == 'w') /* create -- put data in so locks work */ { fputs("# WorkMan database file\n", fp); fclose(fp); fp = fopen(name, "r+"); if (fp == NULL) if (errno != ENOENT) perror(name); } } return (fp); } /* * * allocate and clear "trackmap". * */ int *reset_tracks(void) { int i, j; int *trackmap; /* * Since we access track numbers indirectly (to handle sections * with at least a little elegance), the track mapping needs to be * set up before we read anything. Initially it must assume that * no sections will appear in this datafile. */ trackmap = malloc(sizeof(int) * cur_ntracks); if (trackmap == NULL) { perror("trackmap"); exit(1); } j = 0; for (i = 0; i < cd->ntracks; i++) { trackmap[i] = j; while (cd->trk[++j].section > 1) ; } return trackmap; } /* reset_tracks() */ /* * Load a new-format database file, searching for a match with the currently * inserted CD. Modify the in-core copy of the CD info based on what's found * in the database. * * Returns 1 if there was a match or 0 if not. * * fp FILE* of database or rcfile. * prefs 1 if we're searching .workmanrc, 0 for .workmandb, * 2 if just reading settings * scan Scan for "tracks" location and entry size only * holesize_wanted How big a hole we're looking for, if any. * * If a hole was found along the way, update the global "holepos" with its * starting offset in the file. A hole is defined as a bunch of blank lines * preceding a "tracks" line. Holepos will contain the best match. * * In addition, "firstpos" will be filled with the position of the first * "tracks" keyword, so we know how much room is available for global * settings at the rcfile's start. */ int search_db( FILE *fp, int prefs, int scan, int holesize_wanted ) { char keyword[64], listname[64], *c; int b, i, j, track = 0, listsize, ntracks, scratch, searching = 1; int *trackmap = 0, gotsections = 0; int fudge, maxfudge, sizediff, bestfudge = 0; long pos = 0, thisholepos = -1, holesize = 99991239; struct wm_playlist *l; rclen = 0; /* We may not find any holes at all! */ if (holesize_wanted) holepos = -1; if( prefs != 2 ) trackmap = reset_tracks(); if (prefs) freeup(&otherrc); firstpos = -1; while (! feof(fp)) { pos = ftell(fp); keyword[0] = '\0'; do b = getc(fp); while (b != EOF && b != '\n' && isspace(b)); if (b == EOF || feof(fp)) break; if (b != '\n') { keyword[0] = b; fscanf(fp, "%s", &keyword[1]); } if (keyword[0] == '\0') /* Blank line. */ { if (thisholepos < 0) thisholepos = pos; continue; } /* Strip off "s-" if we've seen a "sections" keyword */ if (gotsections && keyword[0] == 's' && keyword[1] == '-') for (c = &keyword[2]; (c[-2] = *c) != '\0'; c++) ; /* If this is the start of a CD entry, see if it matches. */ if (! strcmp(keyword, "tracks")) { if (prefs == 2) break; /* Is this the end of a hole? */ if (holesize_wanted && (thisholepos >= 0)) { /* Yep. Is it better than the last one? */ if (pos - thisholepos < holesize && pos - thisholepos >= holesize_wanted) { holepos = thisholepos; holesize = pos - thisholepos; } thisholepos = -1; } /* Is it the start of the CD entries? */ if (firstpos == -1) firstpos = pos; /* Is this the end of the entry we really wanted? */ if (! searching) { rclen = pos - rcpos; break; } /* If we have a near match, indicate that we should stop reading tracks, etc now */ if (searching == 2) { searching = 3; continue; } fscanf(fp, "%d", &ntracks); if (ntracks != cd->ntracks) { chomp: SWALLOW_LINE(fp); continue; } fudge = 0; maxfudge = (ntracks * fuzz_frames) >> 1; track = 0; for (i = 0; i < ntracks; i++) { fscanf(fp, "%d", &scratch); if (scratch != cd->trk[track].start) { sizediff = abs(scratch - cd->trk[track].start); if (sizediff > fuzz_frames || (sizediff && scan)) break; fudge += sizediff; } while (cd->trk[++track].section > 1) ; } if (i != ntracks) goto chomp; if (fudge > 0) /* best near match? */ { if (fudge > maxfudge) goto chomp; if (bestfudge == 0 || fudge < bestfudge) bestfudge = fudge; else goto chomp; rcpos = pos; track = 0; searching = 2; } else /* probably exact match */ { fscanf(fp, "%d", &scratch); if (scratch != -1 && scratch != cd->length) goto chomp; /* Found it! */ rcpos = pos; track = 0; searching = 0; } SWALLOW_LINE(fp); /* Get rid of newline */ } /* Global mode stuff goes here */ else if (! strcmp(keyword, "cddbprotocol")) { getc(fp); i = getc(fp); /* only first letter is used */ cddb.protocol = i == 'c' ? 1 : i == 'h' ? 2 : 3 ; do i = getc(fp); while (i != '\n' && i != EOF); } else if (! strcmp(keyword, "cddbserver")) { getc(fp); /* lose the space */ if (cddb.cddb_server[0]) do i = getc(fp); while (i != '\n' && i != EOF); else { fgets(cddb.cddb_server, sizeof(cddb.cddb_server), fp); if ((i = strlen(cddb.cddb_server))) cddb.cddb_server[i - 1] = '\0'; } } else if (! strcmp(keyword, "cddbmailadress")) { getc(fp); /* lose the space */ if (cddb.mail_adress[0]) do i = getc(fp); while (i != '\n' && i != EOF); else { fgets(cddb.mail_adress, sizeof(cddb.mail_adress), fp); if ((i = strlen(cddb.mail_adress))) cddb.mail_adress[i - 1] = '\0'; } } else if (! strcmp(keyword, "cddbpathtocgi")) { getc(fp); /* lose the space */ if (cddb.path_to_cgi[0]) do i = getc(fp); while (i != '\n' && i != EOF); else { fgets(cddb.path_to_cgi, sizeof(cddb.path_to_cgi), fp); if ((i = strlen(cddb.path_to_cgi))) cddb.path_to_cgi[i - 1] = '\0'; } } else if (! strcmp(keyword, "cddbproxy")) { getc(fp); /* lose the space */ if (cddb.proxy_server[0]) do i = getc(fp); while (i != '\n' && i != EOF); else { fgets(cddb.proxy_server, sizeof(cddb.proxy_server), fp); if ((i = strlen(cddb.proxy_server))) cddb.proxy_server[i - 1] = '\0'; } } else if (! strcmp(keyword, "whendone")) { getc(fp); i = getc(fp); /* only first letter is used */ if (cur_stopmode == -1) /* user's setting preferred */ cur_stopmode = i == 's' ? 0 : i == 'r' ? 1 : 2; do i = getc(fp); while (i != '\n' && i != EOF); } else if (! strcmp(keyword, "playnew")) { if (cur_playnew == -1) cur_playnew = 1; SWALLOW_LINE(fp); } /* If we're searching, skip to the next "tracks" line. */ else if (((searching & 1)|| scan) && !(prefs && firstpos == -1)) SWALLOW_LINE(fp) else if (! strcmp(keyword, "sections")) { gotsections = 1; fscanf(fp, "%d", &ntracks); free(trackmap); trackmap = (int *) malloc(sizeof(int) * (cur_ntracks + ntracks)); if (trackmap == NULL) { perror("section mapping"); exit(1); } /* * If sections are already defined, use these as a * reference, mapping this CD entry's section numbers * to the ones in core. * * Otherwise, split the CD up according to the sections * listed here. */ if (cur_nsections) { track = 0; i = 0; while (ntracks) { ntracks--; fscanf(fp, "%d", &scratch); while (scratch > cd->trk[track].start) { if (cd->trk[track].section < 2) trackmap[i++] = track; ++track; if (track == cur_ntracks) break; } /* rc has later sections than db... */ if (track == cur_ntracks) break; /* Matches can be approximate */ if (scratch+75 > cd->trk[track].start && scratch-75 < cd->trk[track].start) trackmap[i++] = track++; else trackmap[i++] = -1; if (track == cur_ntracks) break; } /* This only happens if track == cur_ntracks */ while (ntracks--) trackmap[i++] = -1; while (track < cur_ntracks) { if (cd->trk[track].section < 2) trackmap[i++] = track; track++; } track = 0; SWALLOW_LINE(fp); } else { while (ntracks--) { fscanf(fp, "%d", &scratch); split_trackinfo(scratch); } for (i = 0; i < cur_ntracks; i++) { trackmap[i] = i; /* split_trackinfo() sets this */ cd->trk[i].contd = 0; } SWALLOW_LINE(fp); } } else if (! strcmp(keyword, "track")) { char buf[502]; getc(fp); /* lose the space */ /* don't overwrite existing track names. */ /* However, overwrite them if there was a "bad" fuzzy match before */ if ((trackmap[track] == -1 || track > (cd->ntracks + cur_nsections)) && (searching == 2)) SWALLOW_LINE(fp) else if (cd->trk[trackmap[track]].songname && cd->trk[trackmap[track]].songname[0]) do i = getc(fp); while (i != '\n' && i != EOF); else { fgets(buf, sizeof(buf), fp); if( (i = strlen(buf)) ) buf[i - 1] = '\0'; wm_strmcpy(&cd->trk[trackmap[track]].songname, buf); } track++; } else if (! strcmp(keyword, "playmode")) fscanf(fp, "%d", &cd->playmode); else if (! strcmp(keyword, "autoplay")) cd->autoplay = 1; else if (! strcmp(keyword, "cdname")) { /* because of fuzzy matching that may change the disk contents, we reset everything when we find the name, in hopes that we will recover most, if not all, of the information from the file. */ /* * nasty bug was here. Was it? BUGBUGBUG * * wipe_cdinfo(); */ trackmap = reset_tracks(); getc(fp); /* lose the space */ /* don't overwrite existing cd name. */ if (cd->cdname[0] && (searching == 2)) do i = getc(fp); while (i != '\n' && i != EOF); else { if (searching > 1) { strcpy(cd->cdname, "Probably://"); fgets(cd->cdname + strlen(cd->cdname), sizeof(cd->cdname), fp); } else { fgets(cd->cdname, sizeof(cd->cdname), fp); } if ( (i = strlen(cd->cdname)) ) cd->cdname[i - 1] = '\0'; } } else if (! strcmp(keyword, "artist")) { getc(fp); /* lose the space */ /* don't overwrite existing artist names. */ if (cd->artist[0]) do i = getc(fp); while (i != '\n' && i != EOF); else { fgets(cd->artist, sizeof(cd->artist), fp); if( (i = strlen(cd->artist)) ) cd->artist[i - 1] = '\0'; } } else if (! strcmp(keyword, "cdvolume")) { fscanf(fp, "%d", &cd->volume); cd->volume = (cd->volume * 100) / 32; } else if (! strcmp(keyword, "dontplay")) { fscanf(fp, "%d", &i); if (trackmap[i - 1] != -1) cd->trk[trackmap[i - 1]].avoid = 1; } else if (! strcmp(keyword, "continue")) { if (trackmap[track - 1] != -1) cd->trk[trackmap[track - 1]].contd = 1; } else if (! strcmp(keyword, "volume")) { fscanf(fp, "%d", &i); if (trackmap[i - 1] == -1) SWALLOW_LINE(fp) else { i = trackmap[i - 1]; fscanf(fp, "%d", &cd->trk[i].volume); cd->trk[i].volume = (cd->trk[i].volume*100)/32; if (cd->trk[i].volume > 32) cd->trk[i].volume = 0; } } else if (! strcmp(keyword, "playlist")) { getc(fp); fscanf(fp, "%s", listname); /* XXX take this out at some point */ if (! strcmp(listname, "Default")) strcpy(listname, "List A"); for (i = 0; listname[i]; i++) if (listname[i] == '_') listname[i] = ' '; l = new_list(cd, listname); if (l == NULL) { plnomem: perror("playlist read"); exit(1); } fscanf(fp, "%d", &listsize); l->list = malloc(sizeof(int) * (listsize + 1)); if (l->list == NULL) goto plnomem; /* Leave out tracks that weren't in .workmandb. */ j = 0; for (i = 0; i < listsize; i++) { fscanf(fp, "%d", &scratch); scratch = trackmap[scratch - 1]; if (scratch != -1) l->list[j++] = scratch + 1; } l->list[j] = 0; } else if (! strcmp(keyword, "mark")) { int mark_val = -1, mark_namelen; char mark_name[32]; fscanf(fp, "%d", &mark_val); if (mark_val == -1) goto chomp; if (getc(fp) != ' ') continue; fgets(mark_name, sizeof(mark_name), fp); if( ( mark_namelen = strlen(mark_name)) ) mark_name[mark_namelen - 1] = '\0'; if (! strcmp(mark_name, "START")) set_abtimer(0, mark_val); else if (! strcmp(mark_name, "END")) set_abtimer(1, mark_val); } /* Unrecognized keyword. Put it in the right place. */ else { char **buf, input[BUFSIZ]; if (track && trackmap[track - 1] == -1) { SWALLOW_LINE(fp); continue; } i = track ? trackmap[track - 1] : 0; buf = prefs ? i ? &cd->trk[i].otherrc : &cd->otherrc : i ? &cd->trk[i].otherdb : &cd->otherdb; if (firstpos == -1) { if (prefs) { buf = &otherrc; } else { goto chomp; } /* if() else */ } /* if() */ wm_strmcat(buf, keyword); do { input[sizeof(input) - 1] = 'x'; fgets(input, sizeof(input), fp); wm_strmcat(buf, input); } while (input[sizeof(input) - 1] != 'x'); } } if (rclen == 0 && !searching) rclen = pos - rcpos; if (searching > 1) /* A near match has been found. Good enough. */ searching = 0; cddb_struct2cur(); return (! searching); } /* search_db() */ /* * Delay some amount of time without using interval timers. */ void spinwheels(int secs) { struct timeval tv; tv.tv_usec = 0; tv.tv_sec = secs; select(0, NULL, NULL, NULL, &tv); } /* spinwheels() */ /* * lockit(fd, type) * * fd file descriptor * type lock type * * Lock a file. Time out after a little while if we can't get a lock; * this usually means the locking system is broken. * * Unfortunately, if there are lots of people contending for a lock, * this can result in the file not getting locked when it probably should. */ int lockit(int fd, int type) { struct flock fl; int result, timer = 0; if (suppress_locking) return (0); fl.l_type = type; fl.l_whence = 0; fl.l_start = 0; fl.l_len = 0; while ((result = fcntl(fd, F_SETLK, &fl)) < 0) { if (errno != EACCES || errno != EAGAIN) break; if (timer++ == 30) { errno = ETIMEDOUT; break; } spinwheels(1); } return (result); } /* lockit */ /* * Search all the database files and our personal preference file for * more information about the current CD. */ void load( void ) { FILE *fp; char **dbfile; int locked = 0; int dbfound = 0, *trklist, i; unsigned long dbpos; /* This is some kind of profiling code. I don't change it to wm_lib_message() for now... */ #ifdef DEBUG long t1, t2; if( getenv( "WORKMAN_DEBUG" ) != NULL ) { time(&t1); printf("%s (%d): search start = %ld\n", __FILE__, __LINE__, t1); fflush(stdout); } #endif dbfile = databases; found_in_db = 0; /* Turn the cd->trk array into a simple array of ints. */ trklist = (int *)malloc(sizeof(int) * cd->ntracks); for (i = 0; i < cd->ntracks; i++) trklist[i] = cd->trk[i].start; do { if (*dbfile && idx_find_entry(*dbfile, cd->ntracks, trklist, cd->length * 75, 0, &dbpos) == 0) dbfound = 1; fp = *dbfile ? open_rcfile(*dbfile, "r") : NULL; if (fp != NULL) { if (lockit(fileno(fp), F_RDLCK)) perror("Couldn't get read (db) lock"); else locked = 1; if (dbfound) fseek(fp, dbpos, 0); if (search_db(fp, 0, 0, 0)) { found_in_db = 1; cd->whichdb = *dbfile; } if (locked && lockit(fileno(fp), F_UNLCK)) perror("Couldn't relinquish (db) lock"); fclose(fp); } } while (*++dbfile != NULL && cd->whichdb == NULL); #ifdef DEBUG if( getenv( "WORKMAN_DEBUG" ) != NULL ) { time(&t2); printf("%s (%d): db search end = %ld, elapsed = %ld\n", __FILE__, __LINE__, t2, t2 - t1); fflush(stdout); } #endif fp = rcfile ? open_rcfile(rcfile, "r") : NULL; if (fp != NULL) { locked = 0; if (lockit(fileno(fp), F_RDLCK)) perror("Couldn't get read (rc) lock"); else locked = 1; rcpos = 0; found_in_rc = search_db(fp, 1, 0, 0); if (! found_in_rc) cd->autoplay = wm_db_get_playnew(); if (locked && lockit(fileno(fp), F_UNLCK)) perror("Couldn't relinquish (rc) lock"); fclose(fp); } free(trklist); if (cur_playnew == -1) cur_playnew = 0; #ifdef DEBUG if( getenv( "WORKMAN_DEBUG" ) != NULL ) { time(&t2); printf("%s (%d): search end = %ld, elapsed = %ld\n", __FILE__, __LINE__, t2, t2 - t1); fflush(stdout); } #endif } /* load() */ /* * Load program settings from the rcfile. */ void load_settings( void ) { FILE *fp; int locked; fp = rcfile ? open_rcfile(rcfile, "r") : NULL; if (fp != NULL) { locked = 0; if (lockit(fileno(fp), F_RDLCK)) perror("Couldn't get read (rc) lock"); else locked = 1; rcpos = 0; found_in_rc = search_db(fp, 2, 0, 0); if (! found_in_rc) cd->autoplay = wm_db_get_playnew(); if (locked && lockit(fileno(fp), F_UNLCK)) perror("Couldn't relinquish (rc) lock"); fclose(fp); } } /* load_settings() */ /* * save_globals() * * Save the global preferences, scooting CD entries to the end if needed. * The assumption here is that the rcfile is locked, and that firstpos has * been set by a previous scan. */ void save_globals(FILE *fp) { char *globes = NULL, *cdentry = NULL, temp[100]; long curpos; int globesize, hit_cdent = 0, c = 0; if (otherrc) wm_strmcpy(&globes, otherrc); if (cddb.protocol) { sprintf(temp, "cddbprotocol "); switch(cddb.protocol) { case 1: /* cddbp */ sprintf(temp + strlen(temp), "cddbp\n"); break; case 2: /* http */ sprintf(temp + strlen(temp), "http\n"); break; case 3: /* proxy */ sprintf(temp + strlen(temp), "proxy\n"); break; default: break; } wm_strmcat(&globes, temp); if(cddb.mail_adress[0]) { sprintf(temp,"cddbmailadress %s\n", cddb.mail_adress); wm_strmcat(&globes, temp); } if(cddb.cddb_server[0]) { sprintf(temp,"cddbserver %s\n", cddb.cddb_server); wm_strmcat(&globes, temp); } if(cddb.path_to_cgi[0]) { sprintf(temp,"cddbpathtocgi %s\n", cddb.mail_adress); wm_strmcat(&globes, temp); } if(cddb.proxy_server[0]) { sprintf(temp,"cddbproxy %s\n", cddb.mail_adress); wm_strmcat(&globes, temp); } } if (cur_stopmode == 1 || cur_stopmode == 2) { sprintf(temp, "whendone %s\n", cur_stopmode == 1 ? "repeat" : "eject"); wm_strmcat(&globes, temp); } if (cur_playnew == 1) wm_strmcat(&globes, "playnew\n"); curpos = firstpos; if (curpos < 0) curpos = 0; fseek(fp, curpos, SEEK_SET); if (firstpos < (globesize = globes != NULL ? strlen(globes) : 0)) { while (1) { temp[sizeof(temp)-1] = 'x'; if (fgets(temp, sizeof(temp), fp) == NULL) { fseek(fp, 0, SEEK_SET); if (globes != NULL) { fwrite(globes, globesize, 1, fp); free(globes); } if (cdentry != NULL) { fwrite(cdentry, strlen(cdentry), 1, fp); free(cdentry); } return; } if (! strncmp(temp, "tracks ", 7)) { hit_cdent = 1; if (curpos >= globesize) break; } if (! hit_cdent) { curpos += strlen(temp); if (temp[sizeof(temp)-1] == '\0') while ((c = getc(fp)) != '\n' && c != EOF) curpos++; if (c == '\n') curpos++; continue; } wm_strmcat(&cdentry, temp); curpos += strlen(temp); while (temp[sizeof(temp)-1] == '\0') { temp[sizeof(temp)-1] = 'x'; if (fgets(temp, sizeof(temp), fp) == NULL) break; wm_strmcat(&cdentry, temp); curpos += strlen(temp); } } if (cdentry != NULL) { fseek(fp, 0, SEEK_END); fwrite(cdentry, strlen(cdentry), 1, fp); free(cdentry); } } if (globes != NULL) { fseek(fp, 0, SEEK_SET); fwrite(globes, globesize, 1, fp); free(globes); } while (globesize++ < curpos) putc('\n', fp); } /* save_globals() */ /* * save_entry() * * Save the CD information to one database. * * filename Database to save to. * pref 0 for hard data, 1 for preferences. * * If an entry for this CD exists already, overwrite it with the new entry * if the new entry is the same size or smaller, or with newlines if the new * entry is larger (in which case the new entry is appended to the file.) * * Also, if the preference information is being updated, save it to the * file while we've got it locked. Scoot stuff from the beginning of * the file to the end as needed to facilitate this. * * XXX Preference-saving should probably be done elsewhere, like in an * Apply button on the Goodies popup, and in any case needs to go to a * different file (.Xdefaults?) * * Returns 0 on success. */ int save_entry(char *filename, int pref) { FILE *fp; char *buf; int len, i, locked = 0; if( filename == NULL ) return (-1); fp = open_rcfile(filename, "r+"); if (fp == NULL) { if (errno == ENOENT) /* doesn't exist already */ fp = open_rcfile(filename, "w"); if (fp == NULL) return (-1); } if (lockit(fileno(fp), F_WRLCK)) perror("Warning: Couldn't get write lock"); else locked = 1; buf = print_cdinfo(cd, pref); len = strlen(buf); /* doesn't return if there's an error */ rcpos = -1; search_db(fp, pref, 1, len); if (rcpos != -1) /* XXX */ { /* * Jump to the entry's position in the database file, if * it was found. */ fseek(fp, rcpos, SEEK_SET); if (rclen >= len && holepos == -1) { /* * If the new entry will fit in the space occupied by * the old one, overwrite the old one and make a hole * of the appropriate size at its end. * * No need to update the index file in this case, as * the entry's position hasn't changed. */ fputs(buf, fp); for (i = len; i < rclen; i++) fputc('\n', fp); } else { /* * Overwrite the old entry with a hole and delete * its pointer in the index file. */ for (i = 0; i < rclen; i++) fputc('\n', fp); idx_delete_entry(filename, cd->trk[cd->ntracks-1].start, 0, rcpos); rcpos = -1; } } /* * Old entry wasn't found, or its new version wouldn't fit where * the old one was. */ if (rcpos == -1) { /* * Write the new entry in a hole, if there is one, * or at the end of the file. */ if (holepos >= 0) { fseek(fp, holepos, SEEK_SET); if (holepos < firstpos) firstpos = holepos; } else { fseek(fp, 0, SEEK_END); holepos = ftell(fp); } fputs(buf, fp); /* * Write a new index entry for this CD. */ idx_write_entry(filename, cd->trk[cd->ntracks - 1].start, holepos); } if (pref) save_globals(fp); fflush(fp); if (locked && lockit(fileno(fp), F_UNLCK)) perror("Warning: Couldn't relinquish write lock"); fclose(fp); return (0); } /* save_entry() */ /* * save() * * Save CD information to the appropriate datafile (the first file in the * list, unless the entry came from another database file) and to the * personal prefs file. */ int save( void ) { if( wm_db_save_disabled == FALSE ) { if (save_entry(rcfile, 1)) return (0); if (cd->whichdb == NULL || access(cd->whichdb, W_OK)) cd->whichdb = databases[0]; if (save_entry(cd->whichdb, 0)) return (0); return( WM_DB_SAVE_ERROR ); } else { return( WM_DB_SAVE_DISABLED ); } } /* save() */ ascd-0.13.2.orig/libworkman/drv_sony.c0100644000175000017500000001103406661516162017147 0ustar hallonhallon/* * $Id: drv_sony.c,v 1.3 1999/02/14 09:50:42 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * Vendor-specific drive control routines for Sony CDU-8012 series. */ static char drv_sony_id[] = "$Id: drv_sony.c,v 1.3 1999/02/14 09:50:42 dirk Exp $"; #include #include #include "include/wm_config.h" #include "include/wm_struct.h" #include "include/wm_scsi.h" #define PAGE_AUDIO 0x0e /* local prototypes */ static int sony_init( struct wm_drive *d ); static int sony_set_volume(struct wm_drive *d, int left, int right ); static int sony_get_volume( struct wm_drive *d, int *left, int *right ); extern int min_volume, max_volume; struct wm_drive sony_proto = { -1, /* fd */ "Sony", /* vendor */ "CDU-8012", /* model */ "", /* revision */ NULL, /* aux */ NULL, /* daux */ sony_init, /* functions... */ gen_get_trackcount, gen_get_cdlen, gen_get_trackinfo, gen_get_drive_status, sony_get_volume, sony_set_volume, gen_pause, gen_resume, gen_stop, gen_play, gen_eject, gen_closetray }; /* * Initialize the driver. */ static int sony_init( struct wm_drive *d ) { /* Sun use Sony drives as well */ #if defined(SYSV) && defined(CODEC) codec_init(); #endif min_volume = 128; max_volume = 255; return( 0 ); } /* sony_init() */ /* * On the Sony CDU-8012 drive, the amount of sound coming out the jack * increases much faster toward the top end of the volume scale than it * does at the bottom. To make up for this, we make the volume scale look * sort of logarithmic (actually an upside-down inverse square curve) so * that the volume value passed to the drive changes less and less as you * approach the maximum slider setting. Additionally, only the top half * of the volume scale is valid; the bottom half is all silent. The actual * formula looks like * * max^2 - (max - vol)^2 max * v = --------------------- + --- * max * 2 2 * * Where "max" is the maximum value of the volume scale, usually 100. */ static int scale_volume(vol, max) int vol, max; { vol = (max*max - (max - vol) * (max - vol)) / max; return ((vol + max) / 2); } /* * Given a value between min_volume and max_volume, return the standard-scale * volume value needed to achieve that hardware value. * * Rather than perform floating-point calculations to reverse the above * formula, we simply do a binary search of scale_volume()'s return values. */ static int unscale_volume(cd_vol, max) int cd_vol, max; { int vol = 0, top = max, bot = 0, scaled = 0; cd_vol = (cd_vol * 100 + (max_volume - 1)) / max_volume; while (bot <= top) { vol = (top + bot) / 2; scaled = scale_volume(vol, max); if (cd_vol <= scaled) top = vol - 1; else bot = vol + 1; } /* Might have looked down too far for repeated scaled values */ if (cd_vol < scaled) vol++; if (vol < 0) vol = 0; else if (vol > max) vol = max; return (vol); } /* * Get the volume. Sun's CD-ROM driver doesn't support this operation, even * though their drive does. Dumb. */ static int sony_get_volume( struct wm_drive *d, int *left, int *right ) { unsigned char mode[16]; /* Get the current audio parameters first. */ if (wm_scsi_mode_sense(d, PAGE_AUDIO, mode)) return (-1); *left = unscale_volume(mode[9], 100); *right = unscale_volume(mode[11], 100); return (0); } /* * Set the volume using the wacky scale outlined above. The Sony drive * responds to the standard set-volume command. */ static int sony_set_volume(struct wm_drive *d, int left, int right ) { left = scale_volume(left, 100); right = scale_volume(right, 100); return (gen_set_volume(d, left, right)); } ascd-0.13.2.orig/libworkman/drv_toshiba.c0100644000175000017500000000716406661516162017621 0ustar hallonhallon/* * $Id: drv_toshiba.c,v 1.3 1999/02/14 09:50:42 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * Vendor-specific drive control routines for Toshiba XM-3401 series. */ static char drv_toshiba_id[] = "$Id: drv_toshiba.c,v 1.3 1999/02/14 09:50:42 dirk Exp $"; #include #include #include "include/wm_config.h" #include "include/wm_struct.h" #include "include/wm_scsi.h" #define SCMD_TOSH_EJECT 0xc4 /* local prototypes */ static int tosh_init( struct wm_drive *d ); static int tosh_eject( struct wm_drive *d ); static int tosh_set_volume( struct wm_drive *d, int left, int right ); static int tosh_get_volume( struct wm_drive *d, int *left, int *right ); struct wm_drive toshiba_proto = { -1, /* fd */ "Toshiba", /* vendor */ "", /* model */ "", /* revision */ NULL, /* aux */ NULL, /* daux */ tosh_init, /* functions... */ gen_get_trackcount, gen_get_cdlen, gen_get_trackinfo, gen_get_drive_status, tosh_get_volume, tosh_set_volume, gen_pause, gen_resume, gen_stop, gen_play, tosh_eject, gen_closetray }; /* * Initialize the driver. */ static int tosh_init( struct wm_drive *d ) { extern int min_volume; /* Sun use Toshiba drives as well */ #if defined(SYSV) && defined(CODEC) codec_init(); #endif min_volume = 0; return ( 0 ); } /* * Send the Toshiba code to eject the CD. */ static int tosh_eject( struct wm_drive *d ) { return (sendscsi(d, NULL, 0, 0, SCMD_TOSH_EJECT, 1, 0,0,0,0,0,0,0,0,0,0)); } /* * Set the volume. The low end of the scale is more sensitive than the high * end, so make up for that by transforming the volume parameters to a square * curve. */ static int tosh_set_volume( struct wm_drive *d, int left, int right ) { left = (left * left * left) / 10000; right = (right * right * right) / 10000; return (gen_set_volume(d, left, right)); } /* * Undo the transformation above using a binary search (so no floating-point * math is required.) */ static int unscale_volume(cd_vol, max) int cd_vol, max; { int vol = 0, top = max, bot = 0, scaled = 0; /*cd_vol = (cd_vol * 100 + (max_volume - 1)) / max_volume;*/ while (bot <= top) { vol = (top + bot) / 2; scaled = (vol * vol) / max; if (cd_vol <= scaled) top = vol - 1; else bot = vol + 1; } /* Might have looked down too far for repeated scaled values */ if (cd_vol < scaled) vol++; if (vol < 0) vol = 0; else if (vol > max) vol = max; return (vol); } /* * Get the volume. */ static int tosh_get_volume( struct wm_drive *d, int *left, int *right ) { int status; status = gen_get_volume(d, left, right); if (status < 0) return (status); *left = unscale_volume(*left, 100); *right = unscale_volume(*right, 100); return (0); } ascd-0.13.2.orig/libworkman/index.c0100644000175000017500000002017106661516162016415 0ustar hallonhallon/* * $Id: index.c,v 1.2 1999/02/14 09:50:42 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * Maintain an external index file for a WorkMan CD database. * Uses the Berkeley libdb library, available from ftp.cs.berkeley.edu. */ static char index_id[] = "$Id: index.c,v 1.2 1999/02/14 09:50:42 dirk Exp $"; #ifdef LIBDB #include #include #include #include #include #include /* for htonl() */ #include "include/wm_config.h" #include "include/wm_index.h" extern int suppress_locking; /* * idx_find_entry() * * Find an entry in the index file. * * Input: * file Name of database file (text version). * ntracks Number of tracks on the CD we're looking for. * tracks Array of track start times. * len CD length in frames. * fuzz Fuzz factor (tolerance value). * pos Pointer to return value. * * Output: * 1 No matching record found. * 0 Record found; *pos contains offset into text file. * -1 Index file out of date or inaccessible, or another error. */ int idx_find_entry( char *file, int ntracks, int *tracks, int len, int fuzz, unsigned long *pos ) { unsigned long dbpos; char *indexname = NULL, keyval[8]; int c; FILE *text; DB *index; DBT key, data; BTREEINFO bti; /* * First, see if the text file is accessible. Lock it if so. */ text = fopen(file, "r"); if (text == NULL) return (-1); if ((c = getc(text)) == EOF) { fclose(text); return (-1); } if (! suppress_locking) if (lockit(fileno(text), F_RDLCK)) { fclose(text); return (-1); } /* * Open the index file. */ indexname = malloc(strlen(file) + sizeof(".ind")); if (indexname == NULL) { fclose(text); return (-1); } strcpy(indexname, file); strcat(indexname, ".ind"); bti.flags = 0; bti.cachesize = 0; bti.minkeypage = bti.maxkeypage = 0; bti.psize = bti.lorder = 0; bti.compare = NULL; bti.prefix = NULL; index = dbopen(indexname, O_RDONLY, 0666, DB_BTREE, &bti); free(indexname); if (index == NULL) { fclose(text); return (-1); } /* * Search for the first matching entry. */ sprintf(keyval, "%07d", tracks[ntracks - 1] - fuzz); key.data = keyval; key.size = 7; if (c = (index->seq)(index, &key, &data, R_CURSOR)) { (index->close)(index); fclose(text); return (c); } /* * Now loop through all the possible matches, collecting them into * memory. */ do { char tracksline[750], *s; int i, val; /* Hit the end of the valid entries? */ sscanf(key.data, "%d", &val); if (val > tracks[ntracks - 1] + fuzz) break; dbpos = ntohl(*((unsigned long *) data.data)); if (fseek(text, dbpos, 0)) break; fgets(tracksline, sizeof(tracksline), text); if (strncmp(tracksline, "tracks ", 7)) break; (void) strtok(tracksline, " \t"); /* Got a valid tracks line. See if it matches the CD. */ s = strtok(NULL, " \t"); if (s == NULL) break; if (atoi(s) != ntracks) continue; for (i = 0; i < ntracks; i++) { s = strtok(NULL, " \t"); if (s == NULL) break; val = atoi(s); if (val + fuzz < tracks[i] || val - fuzz > tracks[i]) break; } if (i != ntracks) continue; s = strtok(NULL, " \t"); if (s == NULL) continue; val = atoi(s); if (val + fuzz / 75 < len / 75 || val + fuzz / 75 > len / 75) continue; /* XXX - add to sorted list! */ *pos = dbpos; (index->close)(index); fclose(text); return (0); } while ((c = (index->seq)(index, &key, &data, R_NEXT)) == 0); if (c == 0) { /* An error. */ (index->close)(index); fclose(text); return (-1); } (index->close)(index); fclose(text); return (1); } /* * idx_delete_entry() * * Delete an entry from the index file. * * Input: * file Name of database file (text version). * track Last track's start time (database key). * fuzz Fuzz factor (tolerance value). * pos Position of CD in database file. * * Output: * 1 No matching record found. * 0 Record deleted. * -1 Index file out of date or inaccessible, or another error. * * Note: it is the caller's responsibility to do locking, as it's assumed * that this operation will accompany a modification of the main database * file and will need to be atomic with that modification. */ int idx_delete_entry(char *file, int track, int fuzz, unsigned long pos ) { unsigned long dbpos; char *indexname = NULL, keyval[8]; int c, status; DB *index; DBT key, data; BTREEINFO bti; /* * Open the index file. */ indexname = malloc(strlen(file) + sizeof(".ind")); if (indexname == NULL) return (-1); strcpy(indexname, file); strcat(indexname, ".ind"); bti.flags = 0; bti.cachesize = 0; bti.minkeypage = bti.maxkeypage = 0; bti.psize = bti.lorder = 0; bti.compare = NULL; bti.prefix = NULL; index = dbopen(indexname, O_RDWR, 0666, DB_BTREE, &bti); free(indexname); if (index == NULL) return (-1); /* * Search for the first matching entry. */ sprintf(keyval, "%07d", track - fuzz); key.data = keyval; key.size = 7; if (c = (index->seq)(index, &key, &data, R_CURSOR)) { /* * Nothing matched! */ (index->close)(index); return (c); } /* * Look for the entry the user wants to delete. */ do { int val; /* Hit the end of the valid entries? */ sscanf(key.data, "%d", &val); if (val > track + fuzz) break; /* Is this the entry we want? */ if (pos == ntohl(*((unsigned long *) data.data))) { /* * Yep! Delete it. */ status = (index->del)(index, &key, R_CURSOR); (index->close)(index); return (status); } } while ((c = (index->seq)(index, &key, &data, R_NEXT)) == 0); if (c == 0) { /* An error. */ (index->close)(index); return (-1); } (index->close)(index); return (1); } /* * idx_write_entry() * * Write out an index file entry. * * Input: * file Name of database file (text version). * track Start time of last track (database key). * pos Position of entry in text file. * * Output: * 0 Record written. * -1 Index file inaccessible, or another error. * * Note: it is the caller's responsibility to do locking, as it's assumed * that this operation will accompany a modification of the main database * file and will need to be atomic with that modification. */ int idx_write_entry( char *file, int track, unsigned long pos ) { char *indexname, keyval[8]; int status; DB *index; DBT key, data; BTREEINFO bti; /* * Open the index file. */ indexname = malloc(strlen(file) + sizeof(".ind")); if (indexname == NULL) return (-1); strcpy(indexname, file); strcat(indexname, ".ind"); bti.flags = R_DUP; bti.cachesize = 0; bti.minkeypage = 0; bti.maxkeypage = 0; bti.psize = 0; bti.lorder = 4321; /* network byte order */ bti.compare = NULL; bti.prefix = NULL; index = dbopen(indexname, O_RDWR, 0666, DB_BTREE, &bti); free(indexname); if (index == NULL) return (-1); /* * Create a new key and value. */ pos = htonl(pos); data.data = &pos; data.size = sizeof(pos); key.data = keyval; key.size = 7; sprintf(keyval, "%07d", track); status = (index->put)(index, &key, &data, 0); (index->close)(index); return (status); } #else /* LIBDB */ int idx_find_entry() { return (1); /* no record found; text file will be searched. */ } int idx_delete_entry() { return (0); } int idx_write_entry() { return (0); } #endif /* LIBDB */ ascd-0.13.2.orig/libworkman/plat_hpux.c0100644000175000017500000002147406733127560017321 0ustar hallonhallon/* * $Id: plat_hpux.c,v 1.8 1999/06/17 06:48:03 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * HP/UX-specific drive control routines. */ #if defined(hpux) || defined(__hpux) static char plat_hpux_id[] = "$Id: plat_hpux.c,v 1.8 1999/06/17 06:48:03 dirk Exp $"; #include #include #include #include #include #include #include #include #include "include/wm_config.h" /* * this is for glibc 2.x which the ust structure in * ustat.h not stat.h */ #ifdef __GLIBC__ #include #endif #include #include #include "include/wm_struct.h" #include "include/wm_helpers.h" #define WM_MSG_CLASS WM_MSG_CLASS_PLATFORM void *malloc(); char *strchr(); int min_volume = 0; int max_volume = 255; extern char *cd_device; /*--------------------------------------------------------* * Initialize the drive. A no-op for the generic driver. *--------------------------------------------------------*/ int gen_init( struct wm_drive *d ) { return (0); } /*-------------------------------------* * Get the number of tracks on the CD. *-------------------------------------*/ int gen_get_trackcount(struct wm_drive *d, int *tracks ) { return (wm_scsi2_get_trackcount(d, tracks)); } /*---------------------------------------------------------* * Get the start time and mode (data or audio) of a track. *---------------------------------------------------------*/ int gen_get_trackinfo( struct wm_drive *d, int *track, int *data, int *startframe) { return (wm_scsi2_get_trackinfo(d, track, data, startframe)); } /*-------------------------------------* * Get the number of frames on the CD. *-------------------------------------*/ int gen_get_cdlen(struct wm_drive *d, int *frames) { int tmp; return (wm_scsi2_get_cdlen(d, frames)); } /*--------------------------------------------------------------------------* * Get the current status of the drive: the current play mode, the absolute * position from start of disc (in frames), and the current track and index * numbers if the CD is playing or paused. *--------------------------------------------------------------------------*/ int gen_get_drive_status( struct wm_drive *d, enum wm_cd_modes oldmode, enum wm_cd_modes *mode, int *pos, int *track, int *index ) struct wm_drive *d; enum wm_cd_modes oldmode, *mode; int *pos, *track, *index; { return (wm_scsi2_get_drive_status(d, oldmode, mode, pos, track, index)); } /*---------------------------------------------------------------------* * Set the volume level for the left and right channels. Their values * range from 0 to 100. *---------------------------------------------------------------------*/ int gen_set_volume( struct wm_drive *d, int left, int right ) { return (wm_scsi2_set_volume(d, left, right)); } /*---------------------------------------------------------------------* * Read the initial volume from the drive, if available. Each channel * ranges from 0 to 100, with -1 indicating data not available. *---------------------------------------------------------------------*/ int gen_get_volume( struct wm_drive *d, int *left, int *right ) { return (wm_scsi2_get_volume(d, left, right)); } /*---------------* * Pause the CD. *---------------*/ int gen_pause( struct wm_drive *d ) { return (wm_scsi2_pause(d)); } /*-------------------------------------------------* * Resume playing the CD (assuming it was paused.) *-------------------------------------------------*/ int gen_resume( struct wm_drive *d ) { return (wm_scsi2_resume(d)); } /*--------------* * Stop the CD. *--------------*/ int gen_stop( struct wm_drive *d ) { return (wm_scsi2_stop(d)); } /*------------------------------------------------------------* * Play the CD from one position to another (both in frames.) *------------------------------------------------------------*/ int gen_play( struct wm_drive *d, int start, int end ) { return (wm_scsi2_play(d, start, end)); } /*----------------------------------------* * Eject the current CD, if there is one. *----------------------------------------*/ int gen_eject( struct wm_drive *d ) { struct stat stbuf; struct ustat ust; if (fstat(d->fd, &stbuf) != 0) return (-2); /* Is this a mounted filesystem? */ if (ustat(stbuf.st_rdev, &ust) == 0) return (-3); return (wm_scsi2_eject(d)); } /*----------------------------------------* * Close the CD tray *----------------------------------------*/ int gen_closetray(struct wm_drive *d) { #ifdef CAN_CLOSE return (wm_scsi2_closetray(d)); #else /* Always succeed if the drive can't close */ return(0); #endif /* CAN_CLOSE */ } /* gen_closetray() */ /*----------------------------------* * Send a SCSI command out the bus. *----------------------------------*/ int wm_scsi( struct wm_drive *d, unsigned char *cdb, int cdblen, void *retbuf, int retbuflen, int getreply ) { #ifdef SIOC_IO struct sctl_io cmd; memset(&cmd, 0, sizeof(cmd)); cmd.cdb_length = cdblen; cmd.data = retbuf; cmd.data_length = retbuflen; cmd.max_msecs = 1000; cmd.flags = getreply ? SCTL_READ : 0; memcpy(cmd.cdb, cdb, cdblen); return (ioctl(d->fd, SIOC_IO, &cmd)); #else /* this code, for pre-9.0, is BROKEN! ugh. */ char reply_buf[12]; struct scsi_cmd_parms cmd; memset(&cmd, 0, sizeof(cmd)); cmd.clock_ticks = 500; cmd.cmd_mode = 1; cmd.cmd_type = cdblen; memcpy(cmd.command, cdb, cdblen); if (ioctl(d->fd, SIOC_SET_CMD, &cmd) < 0) return (-1); if (! retbuf || ! retbuflen) (void) read(d->fd, reply_buf, sizeof(reply_buf)); else if (getreply) { if (read(d->fd, retbuf, retbuflen) < 0) return (-1); } else if (write(d->fd, retbuf, retbuflen) < 0) return (-1); return (0); #endif } /*-------------------------------------------------------------* * Open the CD and figure out which kind of drive is attached. *-------------------------------------------------------------*/ int wmcd_open( struct wm_drive *d ) { int fd, flag = 1; static int warned = 0; /* unsigned ? */ char vendor[32], model[32], rev[32]; if (d->fd >= 0) /* Device already open? */ return (0); if (cd_device == NULL) cd_device = DEFAULT_CD_DEVICE; d->fd = open(cd_device, O_RDWR); if (d->fd < 0) { if (errno == EACCES) { if (! warned) { fprintf(stderr, "As root, please run\n\nchmod 666 %s\n\n%s\n", cd_device, "to give yourself permission to access the CD-ROM device."); warned++; } } else if (errno != EINTR) { perror(cd_device); exit(1); } /* No CD in drive. */ return (1); } /* Prepare the device to receive raw SCSI commands. */ if (ioctl(d->fd, SIOC_CMD_MODE, &flag) < 0) { fprintf(stderr, "%s: SIOC_CMD_MODE: true: %s\n", cd_device, strerror(errno)); /*exit(1);*/ } if (warned) { warned = 0; fprintf(stderr, "Thank you.\n"); } /* Now fill in the relevant parts of the wm_drive structure. */ fd = d->fd; /* Default drive is the HP one, which might not respond to INQUIRY */ strcpy(&vendor, "TOSHIBA"); strcpy(&model, "XM-3301"); rev[0] = '\0'; wm_scsi_get_drive_type(d, vendor, model, rev); *d = *(find_drive_struct(vendor, model, rev)); wm_drive_settype(vendor, model, rev); d->fd = fd; (d->init)(d); return (0); } /* wmcd_open() */ /* * Re-Open the device if it is open. */ int wmcd_reopen( struct wm_drive *d ) { int status; do { wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "wmcd_reopen "); if (d->fd >= 0) /* Device really open? */ { wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "closes the device and "); status = close( d->fd ); /* close it! */ /* we know, that the file is closed, do we? */ d->fd = -1; } wm_susleep( 1000 ); wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "calls wmcd_open()\n"); status = wmcd_open( d ); /* open it as usual */ wm_susleep( 1000 ); } while ( status != 0 ); return status; } /* wmcd_reopen() */ #endif ascd-0.13.2.orig/libworkman/plat_bsd386.c0100644000175000017500000003143306670435230017336 0ustar hallonhallon/* * $Id: plat_bsd386.c,v 1.5 1999/03/07 08:36:40 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * BSD/386-specific drive control routines. */ #ifdef __bsdi__ static char plat_bsd386_id[] = "$Id: plat_bsd386.c,v 1.5 1999/03/07 08:36:40 dirk Exp $"; #include #include #include #include #include #include #include #include "include/wm_config.h" #define WM_MSG_CLASS WM_MSG_CLASS_PLATFORM /* * The following is included from the Linux module. However, I didn't * see a check here if the CD to be ejected is mounted... */ #if defined(BSD_MOUNTTEST) #include #else /* * this is for glibc 2.x which defines ust structure in * ustat.h not stat.h. */ #ifdef __GLIBC__ #include #endif #endif #include #include #include #ifdef SOUNDBLASTER # include #endif #include "include/wm_struct.h" /* * Since we can't sense the drive type with libcdrom anyway, and since the * library doesn't provide "pause" or "resume" functions, use the daux field * to point to the frame number at which we paused. */ struct pause_info { int frame; int endframe; }; #define PAUSE_FRAME (((struct pause_info *) d->daux)->frame) #define END_FRAME (((struct pause_info *) d->daux)->endframe) #define CUR_CD ((struct cdinfo *) d->aux) void *malloc(); extern char *cd_device; #ifdef SOUNDBLASTER int min_volume = 0; int max_volume = 15; int min_volume_drive = 10; /* Toshiba drive does low values. */ int max_volume_drive = 255; #else /* not SOUNDBLASTER, libcdrom only */ int min_volume = 10; int max_volume = 255; #endif /*--------------------------------------------------------* * Initialize the drive. A no-op for the generic driver. *--------------------------------------------------------*/ int gen_init(struct wm_drive *d) { return (0); } /*-------------------------------------* * Get the number of tracks on the CD. *-------------------------------------*/ int gen_get_trackcount(struct wm_drive *d, int *tracks) { *tracks = CUR_CD->ntracks; return (0); } /*---------------------------------------------------------* * Get the start time and mode (data or audio) of a track. *---------------------------------------------------------*/ int gen_get_trackinfo(struct wm_drive *d, int track, int *data, int *startframe) { *data = (CUR_CD->tracks[track - 1].control & 4) ? 1 : 0; *startframe = CUR_CD->tracks[track - 1].start_frame; return (0); } /*-------------------------------------* * Get the number of frames on the CD. *-------------------------------------*/ int gen_get_cdlen(struct wm_drive *d, int *frames) { *frames = CUR_CD->total_frames; return (0); } /*--------------------------------------------------------------------------* * Get the current status of the drive: the current play mode, the absolute * position from start of disc (in frames), and the current track and index * numbers if the CD is playing or paused. *--------------------------------------------------------------------------*/ int gen_get_drive_status(struct wm_drive *d, enum wm_cd_modes oldmode, enum wm_cd_modes *mode, int *pos, int *track, int *index) { struct cdstatus status; extern enum wm_cd_modes cur_cdmode; /* If we can't get status, the CD is ejected, so default to that. */ *mode = WM_CDM_EJECTED; /* Is the device open? */ if (d->aux == NULL) { switch (wmcd_open(d)) { case -1: /* error */ return (-1); case 1: /* retry */ return (0); } } if (cdstatus (CUR_CD, &status) < 0) { *mode = WM_CDM_TRACK_DONE; /* waiting for next track. */ return (0); } #define DOPOS \ *pos = status.abs_frame; \ *track = status.track_num; \ *index = status.index_num switch (status.state) { case cdstate_playing: *mode = WM_CDM_PLAYING; DOPOS; break; case cdstate_stopped: /* the MITSUMI drive doesn't have a "paused" state, so it always comes here and not to the paused section. The PAUSE_FRAME stuff below (in gen_pause()) fakes out the paused state. */ if (oldmode == WM_CDM_PLAYING) { *mode = WM_CDM_TRACK_DONE; break; } else if (cur_cdmode != WM_CDM_PAUSED) { *mode = WM_CDM_STOPPED; DOPOS; break; } /* fall through if paused */ case cdstate_paused: /* the SCSI2 code in the cdrom library only pauses with cdstop(); it never truly stops a disc (until an in-progress play reaches the end). So it always comes here. */ if (cur_cdmode == WM_CDM_STOPPED) { *mode = WM_CDM_STOPPED; DOPOS; break; } if (oldmode == WM_CDM_PLAYING || oldmode == WM_CDM_PAUSED) { *mode = WM_CDM_PAUSED; DOPOS; } else { *mode = WM_CDM_STOPPED; DOPOS; } break; default: *mode = WM_CDM_STOPPED; } return (0); } /*------------------------------------------------------------------------* * Return a volume value suitable for passing to the CD-ROM drive. "vol" * is a volume slider setting; "max" is the slider's maximum value. *------------------------------------------------------------------------*/ static int scale_volume(int vol, int max) { /* on Toshiba XM-3401B drive, and on soundblaster, this works fine. */ return ((vol * (max_volume - min_volume)) / max + min_volume); } /*---------------------------------------------------------------------* * Set the volume level for the left and right channels. Their values * range from 0 to 100. *---------------------------------------------------------------------*/ int gen_set_volume(struct wm_drive *d, int left, int right) { left = scale_volume(left, 100); right = scale_volume(right, 100); #ifdef SOUNDBLASTER /* Send a Mixer IOCTL */ if (d->fd >= 0) { struct sb_mixer_levels levels; if (ioctl(d->fd, MIXER_IOCTL_READ_LEVELS, &levels) == 0) { levels.cd.l = left < 0 ? 0 : left; levels.cd.r = right < 0 ? 0 : right; (void) ioctl(d->fd, MIXER_IOCTL_SET_LEVELS, &levels); } else perror("SoundBlaster mixer read failed"); } else #endif /* NOTE: the cdvolume2() call is an addition to the cdrom library. Pick it up from the archives on bsdi.com */ cdvolume2 (CUR_CD, left < 0 ? 0 : left > 255 ? 255 : left, right < 0 ? 0 : right > 255 ? 255 : right); return (0); } /*--------------------------------------------------------------------* * Pause the CD. This is a bit of a trick since there's no cdpause() * function in the library. We fake it by saving the frame number * and stopping. *--------------------------------------------------------------------*/ int gen_pause(struct wm_drive *d) { struct cdstatus status; if (cdstatus(d->aux, &status) < 0) return (-1); if (status.state != cdstate_playing) PAUSE_FRAME = CUR_CD->tracks[0].start_frame; else PAUSE_FRAME = status.abs_frame; if (cdstop(d->aux) < 0) return (-1); return (0); } /*-------------------------------------------------* * Resume playing the CD (assuming it was paused.) *-------------------------------------------------*/ int gen_resume(struct wm_drive *d) { int status; status = (d->play)(d, PAUSE_FRAME, END_FRAME); PAUSE_FRAME = 0; return (status); } /*--------------* * Stop the CD. *--------------*/ int gen_stop(struct wm_drive *d) { return cdstop(d->aux); } /*------------------------------------------------------------* * Play the CD from one position to another (both in frames.) *------------------------------------------------------------*/ int gen_play(struct wm_drive *d, int start, int end) { END_FRAME = end; if (cdplay(d->aux, start, end) < 0) return (-1); else return (0); } /*----------------------------------------* * Eject the current CD, if there is one. *----------------------------------------*/ int gen_eject(struct wm_drive *d) { cdeject(d->aux); cdclose(d->aux); d->aux = NULL; free(d->daux); d->daux = NULL; return (0); } /*----------------------------------------* * Close the CD tray *----------------------------------------*/ int gen_closetray(struct wm_drive *d) { #ifdef CAN_CLOSE if(!close(d->fd)) { d->fd=-1; return(wmcd_open(d)); } else { return(-1); } #else /* Always succeed if the drive can't close */ return(0); #endif /* CAN_CLOSE */ } /* gen_closetray() */ /*---------------------------------------------------------------------------* * unscale_volume(cd_vol, max) * * Given a value between min_volume and max_volume, return the volume slider * value needed to achieve that value. * * Rather than perform floating-point calculations to reverse the above * formula, we simply do a binary search of scale_volume()'s return values. *--------------------------------------------------------------------------*/ static int unscale_volume(int cd_vol, int max) { int vol = 0, top = max, bot = 0, scaled; while (bot <= top) { vol = (top + bot) / 2; scaled = scale_volume(vol, max); if (cd_vol == scaled) break; if (cd_vol < scaled) top = vol - 1; else bot = vol + 1; } if (vol < 0) vol = 0; else if (vol > max) vol = max; return (vol); } /*---------------------------------------------------------------------* * Read the initial volume from the drive, if available. Each channel * ranges from 0 to 100, with -1 indicating data not available. *---------------------------------------------------------------------*/ int gen_get_volume(struct wm_drive *d, int *left, int *right) { /* Most systems can't seem to do this... */ *left = *right = -1; #ifdef SOUNDBLASTER /* Send a Mixer IOCTL */ if (d->fd >= 0) { struct sb_mixer_levels levels; if (ioctl(d->fd, MIXER_IOCTL_READ_LEVELS, &levels) == 0) { *left = unscale_volume(levels.cd.l, 100); *right = unscale_volume(levels.cd.r, 100); } else perror("SoundBlaster mixer read failed"); } #endif return (0); } /*---------------------------------------------* * Send an arbitrary SCSI command to a device. *---------------------------------------------*/ int wm_scsi(struct wm_drive *d, unsigned char *cdb, int cdblen, void *retbuf, int retbuflen, int getreply) { /* Don't know how to do SCSI passthrough... */ return (-1); } #ifdef SOUNDBLASTER int sb_fd = -3; /* patchable from external programs */ #endif /*-----------------------------------------------------------------------* * Open the CD device. We can't determine the drive type under BSD/386. *-----------------------------------------------------------------------*/ int wmcd_open(struct wm_drvie *d) { void *aux = NULL, *daux = NULL; int fd = -1; if (d->aux) /* Device already open? */ return (0); if ((aux = cdopen(cd_device)) == NULL) { fprintf(stderr, "No cdrom found by libcdrom\n"); exit(1); } if ((daux = malloc(sizeof(struct pause_info))) == NULL) return (-1); #ifdef SOUNDBLASTER if (sb_fd != -3 && sb_fd < 0) fd = open ("/dev/sb_mixer", O_RDWR, 0); if (fd < 0) { if (sb_fd != -3) fprintf (stderr,"SoundBlaster mixer not found/disabled; will use direct CD volume control\n"); max_volume = max_volume_drive; min_volume = min_volume_drive; } #endif /* Now fill in the relevant parts of the wm_drive structure. */ *d = *(find_drive_struct("", "", "")); d->aux = aux; d->daux = daux; d->fd = fd; PAUSE_FRAME = 0; END_FRAME = 0; (d->init)(d); return (0); } /* wmcd_open() */ /* * Re-Open the device if it is open. */ int wmcd_reopen( struct wm_drive *d ) { int status; do { wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "wmcd_reopen "); if (d->fd >= 0) /* Device really open? */ { wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "closes the device and "); status = close( d->fd ); /* close it! */ /* we know, that the file is closed, do we? */ d->fd = -1; } wm_susleep( 1000 ); wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "calls wmcd_open()\n"); status = wmcd_open( d ); /* open it as usual */ wm_susleep( 1000 ); } while ( status != 0 ); return status; } /* wmcd_reopen() */ #endif /* __bsdi__ */ ascd-0.13.2.orig/libworkman/plat_freebsd.c0100644000175000017500000003316306670435230017741 0ustar hallonhallon/* * $Id: plat_freebsd.c,v 1.8 1999/03/07 08:36:40 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * plat_freebsd.c * * FreeBSD-specific drive control routines. * * Todd Pfaff, 3/20/94 * */ #if defined(__FreeBSD__) || defined(__NetBSD__) static char freebsd_id[] = "$Id: plat_freebsd.c,v 1.8 1999/03/07 08:36:40 dirk Exp $"; #include #include #include #include #include #include #include #include #include #include "include/wm_config.h" #include #include #include #include #if defined(__NetBSD__) # define MSF_MINUTES 1 # define MSF_SECONDS 2 # define MSF_FRAMES 3 # include "/sys/scsi/scsi_all.h" # include "/sys/scsi/scsi_cd.h" #else # define LEFT_PORT 0 # define RIGHT_PORT 1 # if __FreeBSD_version < 300000 # include # endif #endif #include "include/wm_struct.h" #include "include/wm_platform.h" #include "include/wm_cdrom.h" #include "include/wm_scsi.h" #include "include/wm_helpers.h" #define WM_MSG_CLASS WM_MSG_CLASS_PLATFORM void *malloc(); int min_volume = 10; int max_volume = 255; extern char *cd_device; /*--------------------------------------------------------* * Initialize the drive. A no-op for the generic driver. *--------------------------------------------------------*/ int gen_init(struct wm_drive *d) { return (0); } /*-------------------------------------* * Get the number of tracks on the CD. *-------------------------------------*/ int gen_get_trackcount(struct wm_drive *d, int *tracks) { struct ioc_toc_header hdr; if (ioctl(d->fd, CDIOREADTOCHEADER, &hdr) == -1) return (-1); *tracks = hdr.ending_track - hdr.starting_track + 1; return (0); } /*-----------------------------------------------------------------------* * Get the start time and mode (data or audio) of a track. * * XXX - this should get cached, but that means keeping track of ejects. *-----------------------------------------------------------------------*/ int gen_get_trackinfo(struct wm_drive *d, int track, int *data, int *startframe) { struct ioc_read_toc_entry toc; struct cd_toc_entry toc_buffer; bzero((char *)&toc_buffer, sizeof(toc_buffer)); toc.address_format = CD_MSF_FORMAT; toc.starting_track = track; toc.data_len = sizeof(toc_buffer); toc.data = &toc_buffer; if (ioctl(d->fd, CDIOREADTOCENTRYS, &toc)) return (-1); *data = ((toc_buffer.control & 0x4) != 0); #ifdef __NetBSD__ *startframe = toc_buffer.addr[MSF_MINUTES]*60*75 + toc_buffer.addr[MSF_SECONDS] * 75 + toc_buffer.addr[MSF_FRAMES]; #else *startframe = toc_buffer.addr.msf.minute*60*75 + toc_buffer.addr.msf.second * 75 + toc_buffer.addr.msf.frame; #endif return (0); } /*-------------------------------------* * Get the number of frames on the CD. *-------------------------------------*/ int gen_get_cdlen(struct wm_drive *d, int *frames) { int tmp; struct ioc_toc_header hdr; int status; #define LEADOUT 0xaa /* see scsi.c. what a hack! */ return gen_get_trackinfo(d, LEADOUT, &tmp, frames); } /*--------------------------------------------------------------------------* * Get the current status of the drive: the current play mode, the absolute * position from start of disc (in frames), and the current track and index * numbers if the CD is playing or paused. *--------------------------------------------------------------------------*/ int gen_get_drive_status(struct wm_drive *d, enum wm_cd_modes oldmode, enum wm_cd_modes *mode, int *pos, int *track, int *index) { struct ioc_read_subchannel sc; struct cd_sub_channel_info scd; /* If we can't get status, the CD is ejected, so default to that. */ *mode = WM_CDM_EJECTED; sc.address_format = CD_MSF_FORMAT; sc.data_format = CD_CURRENT_POSITION; sc.track = 0; sc.data_len = sizeof(scd); sc.data = (struct cd_sub_channel_info *)&scd; /* Is the device open? */ if (d->fd < 0) { switch (wmcd_open(d)) { case -1: /* error */ return (-1); case 1: /* retry */ return (0); } } if (ioctl(d->fd, CDIOCREADSUBCHANNEL, &sc)) { /* * #ifdef __NetBSD__ * * Denis Bourez told me, that closing the * device is mandatory for FreeBSD, too. */ /* we need to release the device so the kernel will notice reloaded media */ (void) close(d->fd); d->fd = -1; /* * #endif */ return (0); /* ejected */ } switch (scd.header.audio_status) { case CD_AS_PLAY_IN_PROGRESS: *mode = WM_CDM_PLAYING; dopos: #ifdef __NetBSD__ *pos = scd.what.position.absaddr[MSF_MINUTES] * 60 * 75 + scd.what.position.absaddr[MSF_SECONDS] * 75 + scd.what.position.absaddr[MSF_FRAMES]; #else *pos = scd.what.position.absaddr.msf.minute * 60 * 75 + scd.what.position.absaddr.msf.second * 75 + scd.what.position.absaddr.msf.frame; #endif *track = scd.what.position.track_number; *index = scd.what.position.index_number; break; case CD_AS_PLAY_PAUSED: if (oldmode == WM_CDM_PLAYING || oldmode == WM_CDM_PAUSED) { *mode = WM_CDM_PAUSED; goto dopos; } else *mode = WM_CDM_STOPPED; break; case CD_AS_PLAY_COMPLETED: *mode = WM_CDM_TRACK_DONE; /* waiting for next track. */ break; case CD_AS_NO_STATUS: case 0: *mode = WM_CDM_STOPPED; break; } return (0); } /*---------------------------------------------------------------------------* * scale_volume(vol, max) * * Return a volume value suitable for passing to the CD-ROM drive. "vol" * is a volume slider setting; "max" is the slider's maximum value. * * On Sun and DEC CD-ROM drives, the amount of sound coming out the jack * increases much faster toward the top end of the volume scale than it * does at the bottom. To make up for this, we make the volume scale look * sort of logarithmic (actually an upside-down inverse square curve) so * that the volume value passed to the drive changes less and less as you * approach the maximum slider setting. The actual formula looks like * * (max^2 - (max - vol)^2) * (max_volume - min_volume) * v = --------------------------------------------------- + min_volume * max^2 * * If your system's volume settings aren't broken in this way, something * like the following should work: * * return ((vol * (max_volume - min_volume)) / max + min_volume); *---------------------------------------------------------------------------*/ static int scale_volume(int vol, int max) { return ((vol * (max_volume - min_volume)) / max + min_volume); } /*---------------------------------------------------------------------* * Set the volume level for the left and right channels. Their values * range from 0 to 100. *---------------------------------------------------------------------*/ int gen_set_volume(struct wm_drive *d, int left, int right) { struct ioc_vol vol; if (left < 0) /* don't laugh, I saw this happen once! */ left = 0; if (right < 0) right = 0; left = scale_volume(left, 100); right = scale_volume(right, 100); bzero((char *)&vol, sizeof(vol)); vol.vol[LEFT_PORT] = left; vol.vol[RIGHT_PORT] = right; if (ioctl(d->fd, CDIOCSETVOL, &vol)) return (-1); return (0); } /*---------------* * Pause the CD. *---------------*/ int gen_pause( struct wm_drive *d ) { return (ioctl(d->fd, CDIOCPAUSE)); } /*-------------------------------------------------* * Resume playing the CD (assuming it was paused.) *-------------------------------------------------*/ int gen_resume( struct wm_drive *d ) { return (ioctl(d->fd, CDIOCRESUME)); } /*--------------* * Stop the CD. *--------------*/ int gen_stop( struct wm_drive *d) { return (ioctl(d->fd, CDIOCSTOP)); } /*------------------------------------------------------------* * Play the CD from one position to another (both in frames.) *------------------------------------------------------------*/ int gen_play(struct wm_drive *d, int start, int end ) { struct ioc_play_msf msf; msf.start_m = start / (60*75); msf.start_s = (start % (60*75)) / 75; msf.start_f = start % 75; msf.end_m = end / (60*75); msf.end_s = (end % (60*75)) / 75; msf.end_f = end % 75; if (ioctl(d->fd, CDIOCSTART)) return (-1); if (ioctl(d->fd, CDIOCPLAYMSF, &msf)) return (-2); return (0); } /*----------------------------------------* * Eject the current CD, if there is one. *----------------------------------------*/ int gen_eject( struct wm_drive *d ) { /* On some systems, we can check to see if the CD is mounted. */ struct stat stbuf; struct statfs buf; int rval; if (fstat(d->fd, &stbuf) != 0) return (-2); /* Is this a mounted filesystem? */ if (fstatfs(stbuf.st_rdev, &buf) == 0) return (-3); rval = ioctl(d->fd, CDIOCALLOW); if (rval == 0) rval = ioctl(d->fd, CDIOCEJECT); if (rval == 0) rval = ioctl(d->fd, CDIOCPREVENT); (void) close(d->fd); return rval; } /*----------------------------------------* * Close the CD tray *----------------------------------------*/ int gen_closetray(struct wm_drive *d) { #ifdef CAN_CLOSE if(!close(d->fd)) { d->fd=-1; return(wmcd_reopen(d)); } else { return(-1); } #else /* Always succeed if the drive can't close */ return(0); #endif /* CAN_CLOSE */ } /* gen_closetray() */ /*---------------------------------------------------------------------------* * unscale_volume(cd_vol, max) * * Given a value between min_volume and max_volume, return the volume slider * value needed to achieve that value. * * Rather than perform floating-point calculations to reverse the above * formula, we simply do a binary search of scale_volume()'s return values. *--------------------------------------------------------------------------*/ static int unscale_volume( int cd_vol, int max ) { int vol = 0, top = max, bot = 0, scaled; while (bot <= top) { vol = (top + bot) / 2; scaled = scale_volume(vol, max); if (cd_vol == scaled) break; if (cd_vol < scaled) top = vol - 1; else bot = vol + 1; } if (vol < 0) vol = 0; else if (vol > max) vol = max; return (vol); } /*---------------------------------------------------------------------* * Read the initial volume from the drive, if available. Each channel * ranges from 0 to 100, with -1 indicating data not available. *---------------------------------------------------------------------*/ int gen_get_volume( struct wm_drive *d, int *left, int *right ) { struct ioc_vol vol; if (d->fd >= 0) { bzero((char *)&vol, sizeof(vol)); if (ioctl(d->fd, CDIOCGETVOL, &vol)) *left = *right = -1; else { *left = unscale_volume(vol.vol[LEFT_PORT], 100); *right = unscale_volume(vol.vol[RIGHT_PORT], 100); } } else *left = *right = -1; return (0); } /*---------------------------------------------* * Send an arbitrary SCSI command to a device. * *---------------------------------------------*/ int wm_scsi(d, cdb, cdblen, retbuf, retbuflen, getreply) struct wm_drive *d; unsigned char *cdb; int cdblen; void *retbuf; int retbuflen; int getreply; { return (-1); } /*-------------------------------------------------------------------* * Open the CD device and figure out what kind of drive is attached. *-------------------------------------------------------------------*/ int wmcd_open( struct wm_drive *d ) { int fd; static int warned = 0; char vendor[32] = WM_STR_GENVENDOR; char model[32] = WM_STR_GENMODEL; char rev[32] = WM_STR_GENREV; if (d->fd >= 0) /* Device already open? */ return (0); if (cd_device == NULL) cd_device = DEFAULT_CD_DEVICE; d->fd = open(cd_device, 0); if (d->fd < 0) { if (errno == EACCES) { if (!warned) { fprintf(stderr, "As root, please run\n\nchmod 666 %s\n\n%s\n", cd_device, "to give yourself permission to access the CD-ROM device."); warned++; } } /* No CD in drive. */ return (1); } if (warned) { warned = 0; fprintf(stderr, "Thank you.\n"); } /* Now fill in the relevant parts of the wm_drive structure. */ fd = d->fd; *d = *(find_drive_struct(vendor, model, rev)); wm_drive_settype(vendor, model, rev); (d->init)(d); d->fd = fd; return (0); } /* wmcd_open() */ /* * Re-Open the device if it is open. */ int wmcd_reopen( struct wm_drive *d ) { int status; do { wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "wmcd_reopen "); if (d->fd >= 0) /* Device really open? */ { wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "closes the device and "); status = close( d->fd ); /* close it! */ /* we know, that the file is closed, do we? */ d->fd = -1; } wm_susleep( 1000 ); wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "calls wmcd_open()\n"); status = wmcd_open( d ); /* open it as usual */ wm_susleep( 1000 ); } while ( status != 0 ); return status; } /* wmcd_reopen() */ #endif ascd-0.13.2.orig/libworkman/plat_irix.c0100644000175000017500000002605106670435230017300 0ustar hallonhallon/* * $Id: plat_irix.c,v 1.6 1999/03/07 08:36:40 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * IRIX specific. * * Taken from the kscd distribution * * Paul Kendall * paul@orion.co.nz, or * paul@kcbbs.gen.nz */ #ifdef sgi static char plat_irix_id[] = "$Id: plat_irix.c,v 1.6 1999/03/07 08:36:40 dirk Exp $"; #include "include/wm_config.h" /* * Yes, it was designed for WorkMan 1.4b3 * Because I did start over from 1.3a, I disable it here. * There is no guarantee of getting working code by defining * CDDA yourself. * */ #undef CDDA /*#define CDDA*/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "include/wm_struct.h" #define WM_MSG_CLASS WM_MSG_CLASS_PLATFORM void *malloc(); char *strchr(); int min_volume = 0; int max_volume = 255; extern char *cd_device; #ifdef CDDA static int playing = STOPPED; static CDPLAYER *icd; static CDPARSER *icdp; static CDFRAME cdbuf[12]; static ALport audioport; static ALconfig aconfig; static struct itimerval audiotimer = { {0,0}, {0,25000} }; static int cdtrack=0; static int cdframe=0; static int cdstopframe=0; cbprognum(void *arg, CDDATATYPES type, CDPROGNUM* prognum) { cdtrack = prognum->value; } cbabstime(void *arg, CDDATATYPES type, struct cdtimecode* atime) { cdframe = CDtctoframe(atime); if( cdframe == cdstopframe ) playing = STOPPED; } cbplayaudio(void *arg, CDDATATYPES type, short* audio) { if(playing != PLAYING) return; ALwritesamps(audioport, audio, CDDA_NUMSAMPLES); } static void alarmsignal() { int n, i; if(playing != PLAYING) return; if( ALgetfilled(audioport) < CDDA_NUMSAMPLES*8 ) { /* Only get more samples and play them if we're getting low * this ensures that the CD stays close to the sound */ n = CDreadda(icd, cdbuf, 12); if( n == 0 ) return; for( i=0 ; i<12 ; i++ ) CDparseframe(icdp, &cdbuf[i]); } signal(SIGALRM, alarmsignal); setitimer(ITIMER_REAL, &audiotimer, NULL); } #endif /*--------------------------------------------------------* * Initialize the drive. A no-op for the generic driver. *--------------------------------------------------------*/ int gen_init( struct wm_drive *d ) { #ifdef CDDA long Param[4]; /* Set the audio rate to 44100Hz 16bit 2s-comp stereo */ aconfig = ALnewconfig(); ALsetwidth(aconfig, AL_SAMPLE_16); ALsetsampfmt(aconfig, AL_SAMPFMT_TWOSCOMP); ALsetchannels(aconfig, 2); Param[0] = AL_OUTPUT_RATE; Param[1] = AL_RATE_44100; Param[2] = AL_CHANNEL_MODE; Param[3] = AL_STEREO; ALsetparams(AL_DEFAULT_DEVICE, Param, 4); audioport = ALopenport("KDE KSCD Audio", "w", aconfig); /* setup cdparser */ icdp = CDcreateparser(); CDaddcallback(icdp, cd_audio, (CDCALLBACKFUNC)cbplayaudio, 0); CDaddcallback(icdp, cd_pnum, (CDCALLBACKFUNC)cbprognum, 0); CDaddcallback(icdp, cd_atime, (CDCALLBACKFUNC)cbabstime, 0); /* Lets handle those floating point exceptions expeditiously. */ sigfpe_[_UNDERFL].repls = _ZERO; handle_sigfpes(_ON, _EN_UNDERFL, NULL, _ABORT_ON_ERROR, NULL); #endif return 0; } /*-------------------------------------* * Get the number of tracks on the CD. *-------------------------------------*/ int gen_get_trackcount( struct wm_drive *d, int *tracks ) { CDSTATUS s; if( CDgetstatus(d->daux, &s)==0 ) return -1; *tracks = s.last; return 0; } /*---------------------------------------------------------* * Get the start time and mode (data or audio) of a track. *---------------------------------------------------------*/ int gen_get_trackinfo( struct wm_drive *d, int track, int *data, int *startframe) { CDTRACKINFO i; int ret = CDgettrackinfo(d->daux, track, &i); if( ret == 0 ) return -1; *data = 0; *startframe = CDmsftoframe(i.start_min,i.start_sec,i.start_frame); return 0; } /*-------------------------------------* * Get the number of frames on the CD. *-------------------------------------*/ int gen_get_cdlen( struct wm_drive *d, int *frames ) { CDSTATUS s; if( CDgetstatus(d->daux, &s)==0 ) return -1; *frames = CDmsftoframe(s.total_min,s.total_sec,s.total_frame); return 0; } /*--------------------------------------------------------------------------* * Get the current status of the drive: the current play mode, the absolute * position from start of disc (in frames), and the current track and index * numbers if the CD is playing or paused. *--------------------------------------------------------------------------*/ int gen_get_drive_status( struct wm_drive *d, enum wm_cd_modes oldmode, enum wm_cd_modes *mode, int *pos, int *track, int *index ) { #ifdef CDDA *mode = playing; *track = cdtrack; *pos = cdframe; *index = 0; #else CDSTATUS s; if( CDgetstatus(d->daux, &s)==0 ) return -1; *pos = CDmsftoframe(s.min,s.sec,s.frame); *track = s.track; *index = 0; switch( s.state ) { case CD_READY: *mode = WM_CDM_STOPPED; break; case CD_STILL: case CD_PAUSED: *mode = WM_CDM_PAUSED; break; case CD_PLAYING: *mode = WM_CDM_PLAYING; break; default: *mode = WM_CDM_UNKNOWN; } #endif return 0; } /*---------------------------------------------------------------------* * Set the volume level for the left and right channels. Their values * range from 0 to 100. *---------------------------------------------------------------------*/ int gen_set_volume( struct wm_drive *d, int left, int right ) { long Param[4]; Param[0] = AL_LEFT_SPEAKER_GAIN; Param[1] = left*255/100; Param[2] = AL_RIGHT_SPEAKER_GAIN; Param[3] = right*255/100; ALsetparams(AL_DEFAULT_DEVICE, Param, 4); return 0; } /*---------------------------------------------------------------------* * Read the initial volume from the drive, if available. Each channel * ranges from 0 to 100, with -1 indicating data not available. *---------------------------------------------------------------------*/ int gen_get_volume( struct wm_drive *d, int *left, int *right ) { long Param[4]; Param[0] = AL_LEFT_SPEAKER_GAIN; Param[1] = 0; Param[2] = AL_RIGHT_SPEAKER_GAIN; Param[3] = 0; ALgetparams(AL_DEFAULT_DEVICE, Param, 4); *left = Param[1] * 100 / 255; *right = Param[3] * 100 / 255; return 0; } /*---------------* * Pause the CD. *---------------*/ int gen_pause( struct wm_drive *d ) { #ifdef CDDA playing = WM_CDM_PAUSED; #else CDSTATUS s; if( CDgetstatus(d->daux, &s)==0 ) return -1; if(s.state == CD_PLAYING) CDtogglepause(d->daux); #endif return 0; } /*-------------------------------------------------* * Resume playing the CD (assuming it was paused.) *-------------------------------------------------*/ int gen_resume( struct wm_drive *d ) { #ifdef CDDA playing = WM_CDM_PLAYING; signal(SIGALRM, alarmsignal); setitimer(ITIMER_REAL, &audiotimer, NULL); #else CDSTATUS s; if( CDgetstatus(d->daux, &s)==0 ) return -1; if(s.state == CD_PAUSED) CDtogglepause(d->daux); #endif return 0; } /*--------------* * Stop the CD. *--------------*/ int gen_stop( struct wm_drive *d ) { #ifdef CDDA playing = WM_CDM_STOPPED; #else CDstop(d->daux); #endif return 0; } /*------------------------------------------------------------* * Play the CD from one position to another (both in frames.) *------------------------------------------------------------*/ int gen_play( struct wm_drive *d, int start, int end ) { #ifdef CDDA int m, s, f; CDframetomsf(start, &m, &s, &f); CDseek(icd, m, s, f); cdstopframe = end; playing = PLAYING; signal(SIGALRM, alarmsignal); setitimer(ITIMER_REAL, &audiotimer, NULL); #else int m, s, f; CDframetomsf(start, &m, &s, &f); CDplayabs(d->daux, m, s, f, 1); #endif return 0; } /*----------------------------------------* * Eject the current CD, if there is one. *----------------------------------------*/ int gen_eject( struct wm_drive *d ) { #ifdef CDDA playing = WM_CDM_STOPPED; #endif CDeject(d->daux); return 0; } /*----------------------------------------* * Close the CD tray * * Please edit and send changes to * milliByte@Deathsdoor.com *----------------------------------------*/ int gen_closetray(struct wm_drive *d) { #ifdef CAN_CLOSE if(!close(d->fd)) { d->fd=-1; return(wmcd_reopen(d)); } else { return(-1); } #else /* Always succeed if the drive can't close */ return(0); #endif /* CAN_CLOSE */ } /* gen_closetray() */ /*-------------------------------------------------------------* * Open the CD and figure out which kind of drive is attached. *-------------------------------------------------------------*/ int wmcd_open( struct wm_drive *d ) { int fd; CDSTATUS s; if (d->fd < 0) /* Device already open? */ { if (cd_device == NULL) cd_device = DEFAULT_CD_DEVICE; d->fd = 1; /* Now fill in the relevant parts of the wm_drive structure. */ fd = d->fd; *d = *(find_drive_struct("", "", "")); d->fd = fd; (d->init)(d); d->daux = CDopen(cd_device,"r"); if (d->daux == 0) { perror(cd_device); exit(1); } #ifdef CDDA icd = d->daux; #endif } CDgetstatus(d->daux, &s); if( s.state==CD_NODISC || s.state==CD_ERROR ) return 1; return (0); } /* wmcd_open() */ /* * Re-Open the device if it is open. */ int wmcd_reopen( struct wm_drive *d ) { int status; do { wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "wmcd_reopen "); if (d->fd >= 0) /* Device really open? */ { wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "closes the device and "); status = close( d->fd ); /* close it! */ /* we know, that the file is closed, do we? */ d->fd = -1; } wm_susleep( 1000 ); wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "calls wmcd_open()\n"); status = wmcd_open( d ); /* open it as usual */ wm_susleep( 1000 ); } while ( status != 0 ); return status; } /* wmcd_reopen() */ /*----------------------------------* * Send a SCSI command out the bus. *----------------------------------*/ int wm_scsi(d, xcdb, cdblen, retbuf, retbuflen, getreply) struct wm_drive *d; unsigned char *xcdb; int cdblen; int getreply; char *retbuf; int retbuflen; { return -1; } #endif ascd-0.13.2.orig/libworkman/plat_linux.c0100644000175000017500000004716306732115043017467 0ustar hallonhallon/* * $Id: plat_linux.c,v 1.8 1999/06/17 06:48:03 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * Linux-specific drive control routines. Very similar to the Sun module. */ #ifdef linux /* Id for ident command */ static char plat_linux_id[] = "$Id: plat_linux.c,v 1.8 1999/06/17 06:48:03 dirk Exp $"; #include #include #include #include #include #include #include #include #include #include #include #include #include "include/wm_config.h" #if defined(BSD_MOUNTTEST) #include #else /* * this is for glibc 2.x which defines ust structure in * ustat.h not stat.h */ #ifdef __GLIBC__ #include #endif #endif #include #include #include #include "include/wm_cdda.h" #include "include/wm_struct.h" #include "include/wm_platform.h" #include "include/wm_cdrom.h" #include "include/wm_scsi.h" #include "include/wm_helpers.h" #ifdef OSS_SUPPORT #include #define CD_CHANNEL SOUND_MIXER_CD #endif #define max(a,b) ((a) > (b) ? (a) : (b)) #define WM_MSG_CLASS WM_MSG_CLASS_PLATFORM #ifdef LINUX_SCSI_PASSTHROUGH /* this is from */ # define SCSI_IOCTL_SEND_COMMAND 1 #endif int min_volume = 0; int max_volume = 255; #ifdef OSS_SUPPORT int mixer; char mixer_dev_name[20] = "/dev/mixer"; #endif extern char *cd_device, *cddaslave_path; int cdda_slave = -1; /* * Wait for an acknowledgement from the CDDA slave. */ static int get_ack(int fd) { #if defined(BUILD_CDDA) && defined(WMCDDA_DONE) /* { */ struct cdda_block blk; do if (read(fd, &blk, sizeof(blk)) <= 0) return (0); while (blk.status != WMCDDA_ACK); #endif /* } */ return (1); } /* get_ack() */ /*--------------------------------------------------------* * Initialize the drive. A no-op for the generic driver. *--------------------------------------------------------*/ int gen_init( struct wm_drive *d ) { #ifdef OSS_SUPPORT /* * Open and use the mixer device to set volume */ if( ( mixer = open( mixer_dev_name, O_RDWR, 0 ) ) == -1 ) { perror( mixer_dev_name ); exit( -1 ); } #endif return (0); } /* gen_init() */ /* * Try to initialize the CDDA slave. Returns 0 on error. */ int cdda_init( struct wm_drive *d ) { #if defined(BUILD_CDDA) && defined(WMCDDA_DONE) /* { */ int slavefds[2]; if (cdda_slave > -1) return (1); fprintf( stderr, "slave okay\n" ); if (socketpair(AF_UNIX, SOCK_STREAM, 0, slavefds)) { perror("socketpair"); return (0); } fprintf( stderr, "going to fork\n" ); switch (fork()) { case 0: close(slavefds[0]); dup2(slavefds[1], 1); dup2(slavefds[1], 0); close(slavefds[1]); close(d->fd); /* Try the default path first. */ execl(cddaslave_path, cddaslave_path, cd_device, NULL); /* Search $PATH if that didn't work. */ execlp("cddaslave", "cddaslave", cd_device, NULL); perror(cddaslave_path); exit(1); case -1: close(slavefds[0]); close(slavefds[1]); perror("fork"); return (0); } close(slavefds[1]); cdda_slave = slavefds[0]; if (!get_ack(cdda_slave)) { fprintf( stderr, "get_ack failed\n" ); cdda_slave = -1; /* codec_start(); */ return (0); } return (1); #else /* BUILD_CDDA } { */ /* * If we're not building CDDA support, don't even bother trying. */ return (0); #endif } /* cdda_init() */ /* * Turn off the CDDA slave. */ void cdda_kill( struct wm_drive *d ) { if (cdda_slave > -1) { write(cdda_slave, "Q", 1); get_ack(cdda_slave); wait(NULL); cdda_slave = -1; /* codec_start(); */ } } /* cdda_kill() */ /*-------------------------------------* * Get the number of tracks on the CD. *-------------------------------------*/ int gen_get_trackcount(struct wm_drive *d, int *tracks) { struct cdrom_tochdr hdr; if (ioctl(d->fd, CDROMREADTOCHDR, &hdr)) return (-1); *tracks = hdr.cdth_trk1; return (0); } /*---------------------------------------------------------* * Get the start time and mode (data or audio) of a track. *---------------------------------------------------------*/ int gen_get_trackinfo(struct wm_drive *d, int track, int *data, int *startframe) { struct cdrom_tocentry entry; entry.cdte_track = track; entry.cdte_format = CDROM_MSF; if (ioctl(d->fd, CDROMREADTOCENTRY, &entry)) return (-1); *startframe = entry.cdte_addr.msf.minute * 60 * 75 + entry.cdte_addr.msf.second * 75 + entry.cdte_addr.msf.frame; *data = entry.cdte_ctrl & CDROM_DATA_TRACK ? 1 : 0; return (0); } /*-------------------------------------* * Get the number of frames on the CD. *-------------------------------------*/ int gen_get_cdlen(struct wm_drive *d, int *frames) { int tmp; return (gen_get_trackinfo(d, CDROM_LEADOUT, &tmp, frames)); } /* Alarm signal handler. static void do_nothing(int x) { x++; } */ /*--------------------------------------------------------------------------* * Get the current status of the drive: the current play mode, the absolute * position from start of disc (in frames), and the current track and index * numbers if the CD is playing or paused. *--------------------------------------------------------------------------*/ int gen_get_drive_status( struct wm_drive *d, enum wm_cd_modes oldmode, enum wm_cd_modes *mode, int *pos, int *track, int *index ) { struct cdrom_subchnl sc; #ifdef SBPCD_HACK static int prevpos = 0; #endif /* If we can't get status, the CD is ejected, so default to that. */ *mode = WM_CDM_EJECTED; /* Is the device open? */ if (d->fd < 0) { switch (wmcd_open(d)) { case -1: /* error */ return (-1); case 1: /* retry */ return (0); } } sc.cdsc_format = CDROM_MSF; if (ioctl(d->fd, CDROMSUBCHNL, &sc)) return (0); switch (sc.cdsc_audiostatus) { case CDROM_AUDIO_PLAY: *mode = WM_CDM_PLAYING; *track = sc.cdsc_trk; *index = sc.cdsc_ind; *pos = sc.cdsc_absaddr.msf.minute * 60 * 75 + sc.cdsc_absaddr.msf.second * 75 + sc.cdsc_absaddr.msf.frame; #ifdef SBPCD_HACK if( *pos < prevpos ) { if( (prevpos - *pos) < 75 ) { *mode = WM_CDM_TRACK_DONE; } } prevpos = *pos; #endif break; case CDROM_AUDIO_PAUSED: case CDROM_AUDIO_NO_STATUS: case CDROM_AUDIO_INVALID: /**/ if (oldmode == WM_CDM_PLAYING || oldmode == WM_CDM_PAUSED) { *mode = WM_CDM_PAUSED; *track = sc.cdsc_trk; *index = sc.cdsc_ind; *pos = sc.cdsc_absaddr.msf.minute * 60 * 75 + sc.cdsc_absaddr.msf.second * 75 + sc.cdsc_absaddr.msf.frame; } else *mode = WM_CDM_STOPPED; break; case CDROM_AUDIO_COMPLETED: *mode = WM_CDM_TRACK_DONE; /* waiting for next track. */ break; default: *mode = WM_CDM_UNKNOWN; break; } return (0); } /*------------------------------------------------------------------------* * scale_volume(vol, max) * * Return a volume value suitable for passing to the CD-ROM drive. "vol" * is a volume slider setting; "max" is the slider's maximum value. * This is not used if sound card support is enabled. * *------------------------------------------------------------------------*/ #ifndef OSS_SUPPORT static int scale_volume( int vol, int max ) { #ifdef CURVED_VOLUME return ((max * max - (max - vol) * (max - vol)) * (max_volume - min_volume) / (max * max) + min_volume); #else return ((vol * (max_volume - min_volume)) / max + min_volume); #endif } /* scale_volume() */ #endif /*---------------------------------------------------------------------* * Set the volume level for the left and right channels. Their values * range from 0 to 100. *---------------------------------------------------------------------*/ int gen_set_volume( struct wm_drive *d, int left, int right ) { #ifndef OSS_SUPPORT struct cdrom_volctrl v; #endif int vol; #ifdef OSS_SUPPORT left = left < 0 ? 0 : left > 100 ? 100 : left; right = right < 0 ? : right > 100 ? 100 : right; vol = ( 0x007f & left ) | ( 0x7f00 & ( right << 8 ) ); if( ioctl( mixer, MIXER_WRITE( CD_CHANNEL ), &vol ) == -1 ) { perror( "MIXER_WRITE" ); return ( -1 ); } return ( 0 ); #else /* Adjust the volume to make up for the CD-ROM drive's weirdness. */ left = scale_volume(left, 100); right = scale_volume(right, 100); v.channel0 = v.channel2 = left < 0 ? 0 : left > 255 ? 255 : left; v.channel1 = v.channel3 = right < 0 ? 0 : right > 255 ? 255 : right; return (ioctl(d->fd, CDROMVOLCTRL, &v)); # endif } /*---------------* * Pause the CD. *---------------*/ int gen_pause(d) struct wm_drive *d; { return (ioctl(d->fd, CDROMPAUSE)); } /*-------------------------------------------------* * Resume playing the CD (assuming it was paused.) *-------------------------------------------------*/ int gen_resume(struct wm_drive *d) { return (ioctl(d->fd, CDROMRESUME)); } /*--------------* * Stop the CD. *--------------*/ int gen_stop(struct wm_drive *d) { return (ioctl(d->fd, CDROMSTOP)); } /*------------------------------------------------------------* * Play the CD from one position to another (both in frames.) *------------------------------------------------------------*/ int gen_play(struct wm_drive *d, int start, int end) { struct cdrom_msf msf; msf.cdmsf_min0 = start / (60*75); msf.cdmsf_sec0 = (start % (60*75)) / 75; msf.cdmsf_frame0 = start % 75; msf.cdmsf_min1 = end / (60*75); msf.cdmsf_sec1 = (end % (60*75)) / 75; msf.cdmsf_frame1 = end % 75; #ifndef FAST_IDE if (ioctl(d->fd, CDROMSTART)) return (-1); #endif if (ioctl(d->fd, CDROMPLAYMSF, &msf)) return (-2); return (0); } /*----------------------------------------* * Eject the current CD, if there is one. *----------------------------------------*/ int gen_eject(struct wm_drive *d) { struct stat stbuf; #if !defined(BSD_MOUNTTEST) struct ustat ust; #else struct mntent *mnt; FILE *fp; #endif if (fstat(d->fd, &stbuf) != 0) return (-2); /* Is this a mounted filesystem? */ #if !defined(BSD_MOUNTTEST) if (ustat(stbuf.st_rdev, &ust) == 0) return (-3); #else /* * This is the same test as in the WorkBone interface. * I should eliminate it there, because there is no need * for it in the UI */ /* check if drive is mounted (from Mark Buckaway's cdplayer code) */ /* Changed it again (look at XPLAYCD from ???? */ /* It's better to check the device name rather than one device is */ /* mounted as iso9660. That prevents "no playing" if you have more*/ /* than one CD-ROM, and one of them is mounted, but it's not the */ /* audio CD -dirk */ if ((fp = setmntent (MOUNTED, "r")) == NULL) { fprintf (stderr, "Could not open %s: %s\n", MOUNTED, strerror (errno)); return(-3); } while ((mnt = getmntent (fp)) != NULL) { if (strcmp (mnt->mnt_fsname, cd_device) == 0) { fputs ("CDROM already mounted (according to mtab). Operation aborted.\n", stderr); endmntent (fp); return(-3); } } endmntent (fp); #endif /* BSD_MOUNTTEST */ if (ioctl(d->fd, CDROMEJECT)) return (-1); /*------------------ * Things in "foobar_one" are left over from 1.4b3 * I put them here for further observation. In 1.4b3, however, * that workaround didn't help at least for /dev/sbpcd * (The tray closed just after ejecting because re-opening the * device causes the tray to close) *------------------*/ #ifdef foobar_one extern int intermittent_dev /* * Some drives (drivers?) won't recognize a new CD if we leave the * device open. */ if (intermittent_dev) { close(d->fd); d->fd = -1; } #endif return (0); } /* gen_eject() */ /*----------------------------------------* * Close the CD tray *----------------------------------------*/ int gen_closetray(struct wm_drive *d) { #ifdef CAN_CLOSE #ifdef CDROMCLOSETRAY wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "CDROMCLOSETRAY closing tray...\n"); if (ioctl(d->fd, CDROMCLOSETRAY)) return (-1); #else wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "wmcd_reopen() closing tray...\n"); if(!close(d->fd)) { d->fd=-1; return(wmcd_reopen(d)); } else { return(-1); } #endif /* CDROMCLOSETRAY */ #else /* CAN_CLOSE */ /* Always succeed if the drive can't close. */ return(0); #endif /* CAN_CLOSE */ } /* gen_closetray() */ /*--------------------------------* * Keep the CD open all the time. * disabled, analogous to 1.4b3 *--------------------------------* void keep_cd_open( void ) { int fd; struct flock fl; extern end; for (fd = 0; fd < 256; fd++) close(fd); if (fork()) exit(0); if ((fd = open("/tmp/cd.lock", O_RDWR | O_CREAT, 0666)) < 0) exit(0); fl.l_type = F_WRLCK; fl.l_whence = 0; fl.l_start = 0; fl.l_len = 0; if (fcntl(fd, F_SETLK, &fl) < 0) exit(0); if (open(cd_device, 0) >= 0) { brk(&end); pause(); } exit(0); } */ /*---------------------------------------------------------------------* * Read the initial volume from the drive, if available. Each channel * ranges from 0 to 100, with -1 indicating data not available. *---------------------------------------------------------------------*/ int gen_get_volume( struct wm_drive *d, int *left, int *right ) { #if defined(BUILD_CDDA) && defined(WMCDDA_DONE) /* { */ struct cdda_block blk; if (cdda_slave > -1) { write(cdda_slave, "G", 1); get_ack(cdda_slave); read(cdda_slave, &blk, sizeof(blk)); *left = *right = (blk.volume * 100 + 254) / 255; if (blk.balance < 110) *right = (((blk.volume * blk.balance + 127) / 128) * 100 + 254) / 255; else if (blk.balance > 146) *left = (((blk.volume * (255 - blk.balance) + 127) / 128) * 100 + 254) / 255; return (0); } #else /* } */ #ifdef OSS_SUPPORT int vol; if( ioctl( mixer, MIXER_READ( CD_CHANNEL ), &vol ) == -1 ) { perror( "MIXER_READ" ); *left = *right = -1; } *right = 0x007f & ( vol >> 8 ); *left = 0x007f & vol; #else /* Suns, HPs, Linux, NEWS can't read the volume; oh well */ *left = *right = -1; #endif #endif return (0); } #ifdef BUILD_CDDA /* { */ /* * Tell the CDDA slave to set the play direction. */ void gen_set_direction( int newdir ) { unsigned char buf[2]; if (cdda_slave > -1) { buf[0] = 'd'; buf[1] = newdir; write(cdda_slave, buf, 2); get_ack(cdda_slave); } } /* * Tell the CDDA slave to set the play speed. */ void gen_set_speed( int speed ) { unsigned char buf[2]; if (cdda_slave > -1) { buf[0] = 's'; buf[1] = speed; write(cdda_slave, buf, 2); get_ack(cdda_slave); } } /* * Tell the CDDA slave to set the loudness level. */ void gen_set_loudness( int loud ) { unsigned char buf[2]; if (cdda_slave > -1) { buf[0] = 'L'; buf[1] = loud; write(cdda_slave, buf, 2); get_ack(cdda_slave); } } /* * Tell the CDDA slave to start (or stop) saving to a file. */ void gen_save( char *filename ) { int len; if (filename == NULL || filename[0] == '\0') len = 0; else len = strlen(filename); write(cdda_slave, "F", 1); write(cdda_slave, &len, sizeof(len)); if (len) write(cdda_slave, filename, len); get_ack(cdda_slave); } #endif /* BUILD_CDDA } */ /*---------------------------------------------* * Send an arbitrary SCSI command to a device. *---------------------------------------------*/ int wm_scsi( struct wm_drive *d, unsigned char *cdb, int cdblen, void *retbuf, int retbuflen, int getreply ) { #ifdef LINUX_SCSI_PASSTHROUGH char *cmd; int cmdsize; cmdsize = 2 * sizeof(int); if (retbuf) { if (getreply) cmdsize += max(cdblen, retbuflen); else cmdsize += (cdblen + retbuflen); } else cmdsize += cdblen; cmd = malloc(cmdsize); if (cmd == NULL) return (-1); ((int*)cmd)[0] = cdblen + ((retbuf && !getreply) ? retbuflen : 0); ((int*)cmd)[1] = ((retbuf && getreply) ? retbuflen : 0); memcpy(cmd + 2*sizeof(int), cdb, cdblen); if (retbuf && !getreply) memcpy(cmd + 2*sizeof(int) + cdblen, retbuf, retbuflen); if (ioctl(d->fd, SCSI_IOCTL_SEND_COMMAND, cmd)) { wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "%s: ioctl() failure\n", __FILE__); wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "command buffer is:\n"); wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "%02x %02x %02x %02x %02x %02x\n", cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5]); free(cmd); return (-1); } if (retbuf && getreply) memcpy(retbuf, cmd + 2*sizeof(int), retbuflen); free(cmd); return 0; #else /* Linux SCSI passthrough*/ return (-1); #endif } /*---------------------------------------------------------------------------* * Open the CD device and figure out what kind of drive is attached. *---------------------------------------------------------------------------*/ int wmcd_open( struct wm_drive *d ) { int fd; static int warned = 0; int retval = 0; char vendor[32], model[32], rev[32]; if (cd_device == NULL) cd_device = DEFAULT_CD_DEVICE; if (d->fd >= 0) /* Device already open? */ { wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "wmcd_open(): [device is open (fd=%d)]\n", d->fd); return (0); } d->fd = open(cd_device, O_RDONLY | O_NONBLOCK); if (d->fd < 0) { if (errno == EACCES) { if (!warned) { fprintf(stderr, "As root, please run\n\nchmod 666 %s\n\n%s\n", cd_device, "to give yourself permission to access the CD-ROM device."); warned++; } } /* Hack proposed by Carey Evans, introduced by Debian maintainer : * treat EIO like ENXIO since some Linux drives do never return ENXIO */ else if ((errno != ENXIO) && (errno != EIO) && (errno != ENOMEDIUM)) { perror(cd_device); exit(1); } /* No CD in drive. */ retval = 1; } if (warned) { warned = 0; fprintf(stderr, "Thank you.\n"); } /* Now fill in the relevant parts of the wm_drive structure. */ fd = d->fd; #ifdef LINUX_SCSI_PASSTHROUGH /* Can we figure out the drive type? */ wm_scsi_get_drive_type(d, vendor, model, rev); #endif *d = *(find_drive_struct(vendor, model, rev)); wm_drive_settype(vendor, model, rev); d->fd = fd; (d->init)(d); return retval; } /* wmcd_open() */ /* * Re-Open the device if it is open. */ int wmcd_reopen( struct wm_drive *d ) { int status; do { wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "wmcd_reopen "); if (d->fd >= 0) /* Device really open? */ { wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "closes the device and "); status = close( d->fd ); /* close it! */ /* we know, that the file is closed, do we? */ d->fd = -1; } wm_susleep( 1000 ); wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "calls wmcd_open()\n"); status = wmcd_open( d ); /* open it as usual */ wm_susleep( 1000 ); } while ( status != 0 ); return status; } /* wmcd_reopen() */ #endif /* linux */ ascd-0.13.2.orig/libworkman/plat_news.c0100644000175000017500000002155006670435230017300 0ustar hallonhallon/* * $Id: plat_news.c,v 1.7 1999/03/07 08:36:40 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * Sony NEWS-specific drive control routines. */ #if defined( __sony_news) || defined(sony_news) static char plat_news_id[] = "$Id: plat_news.c,v 1.7 1999/03/07 08:36:40 dirk Exp $"; #include #include #include #include #include #include #include #include #include #include "include/wm_config.h" #include "include/wm_struct.h" #define WM_MSG_CLASS WM_MSG_CLASS_PLATFORM void *malloc(); char *strchr(); extern char *cd_device; extern int intermittent_dev; int min_volume = 128; int max_volume = 255; /* * Initialize the drive. A no-op for the generic driver. */ int gen_init(d) struct wm_drive *d; { return (0); } /* * Get the number of tracks on the CD. */ int gen_get_trackcount(d, tracks) struct wm_drive *d; int *tracks; { struct CD_Capacity cc; if (CD_GetCapacity(d->fd, &cc)) return (-1); *tracks = cc.etrack - 1; return (0); } /* * Get the start time and mode (data or audio) of a track. */ int gen_get_trackinfo(d, track, data, startframe) struct wm_drive *d; int track, *data, *startframe; { struct CD_TOCinfo hdr; struct CD_TOCdata ent; hdr.strack = track; hdr.ntrack = 1; hdr.data = &ent; if (CD_ReadTOC(d->fd, &hdr)) return (-1); *data = (ent.control & 4) ? 1 : 0; *startframe = ent.baddr; return (0); } /* * Get the number of frames on the CD. */ int gen_get_cdlen(d, frames) struct wm_drive *d; int *frames; { int tmp; if ((d->get_trackcount)(d, &tmp)) return (-1); return (gen_get_trackinfo(d, tmp + 1, &tmp, frames)); } /* * Get the current status of the drive: the current play mode, the absolute * position from start of disc (in frames), and the current track and index * numbers if the CD is playing or paused. */ int gen_get_drive_status(d, oldmode, mode, pos, track, index) struct wm_drive *d; enum wm_cd_modes oldmode, *mode; int *pos, *track, *index; { struct CD_Status sc; /* If we can't get status, the CD is ejected, so default to that. */ *mode = WM_CDM_EJECTED; /* Is the device open? */ if (d->fd < 0) { switch (wmcd_open(d)) { case -1: /* error */ return (-1); case 1: /* retry */ return (0); } } /* Disc is ejected. Close the device. */ if (CD_GetStatus(d->fd, &sc)) { WMclose(d->fd); d->fd = -1; return (0); } switch (sc.status) { case CDSTAT_PLAY: *mode = PLAYING; *track = sc.tno; *index = sc.index; *pos = sc.baddr; break; case CDSTAT_PAUSE: if (oldmode == WM_CDM_PLAYING || oldmode == WM_CDM_PAUSED) { *mode = WM_CDM_PAUSED; *track = sc.tno; *index = sc.index; *pos = sc.baddr; } else *mode = WM_CDM_STOPPED; break; case CDSTAT_STOP: if (oldmode == WM_CDM_PLAYING) { *mode = WM_CDM_TRACK_DONE; /* waiting for next track. */ break; } /* fall through */ default: *mode = WM_CDM_STOPPED; break; } return (0); } /* * Set the volume level for the left and right channels. Their values * range from 0 to 100. */ int gen_set_volume(d, left, right) struct wm_drive *d; int left, right; { /* NEWS can't adjust volume! */ return (0); } /* * Pause the CD. */ int gen_pause(d) struct wm_drive *d; { CD_Pause(d->fd); return (0); } /* * Resume playing the CD (assuming it was paused.) */ int gen_resume(d) struct wm_drive *d; { CD_Restart(d->fd); return (0); } /* * Stop the CD. */ int gen_stop(d) struct wm_drive *d; { CD_Stop(d->fd); return (0); } /* * Play the CD from one position to another (both in frames.) */ int gen_play(d, start, end) struct wm_drive *d; int start, end; { struct CD_PlayAddr msf; msf.addrmode = CD_MSF; msf.addr.msf.startmsf.min = start / (60*75); msf.addr.msf.startmsf.sec = (start % (60*75)) / 75; msf.addr.msf.startmsf.frame = start % 75; msf.addr.msf.endmsf.min = end / (60*75); msf.addr.msf.endmsf.sec = (end % (60*75)) / 75; msf.addr.msf.endmsf.frame = end % 75; if (CD_Play(d->fd, &msf)) { printf("wm_cd_play_chunk(%d,%d)\n",start,end); printf("msf = %d:%d:%d %d:%d:%d\n", msf.addr.msf.startmsf.min, msf.addr.msf.startmsf.sec, msf.addr.msf.startmsf.frame, msf.addr.msf.endmsf.min, msf.addr.msf.endmsf.sec, msf.addr.msf.endmsf.frame); perror("CD_Play"); return (-1); } return (0); } /* * Eject the current CD, if there is one. */ int gen_eject(d) struct wm_drive *d; { struct stat stbuf; struct ustat ust; if (fstat(d->fd, &stbuf) != 0) return (-2); /* Is this a mounted filesystem? */ if (ustat(stbuf.st_rdev, &ust) == 0) return (-3); if (CD_AutoEject(d->fd)) return (-1); /* Close the device if it needs to vanish. */ if (intermittent_dev) { WMclose(d->fd); d->fd = -1; } return (0); } /*----------------------------------------* * Close the CD tray * * Please edit and send changes to * milliByte@DeathsDoor.com *----------------------------------------*/ int gen_closetray(struct wm_drive *d) { #ifdef CAN_CLOSE if(!close(d->fd)) { d->fd=-1; return(wmcd_reopen(d)); } else { return(-1); } #else /* Always succeed if the drive can't close */ return(0); #endif /* CAN_CLOSE */ } /* gen_closetray() */ /* * Close the CD device. */ int WMclose(fd) int fd; { int ret; ret = CD_Close(fd); wm_susleep(3000000); return (ret); } /* * Read the initial volume from the drive, if available. Each channel * ranges from 0 to 100, with -1 indicating data not available. */ int gen_get_volume(d, left, right) struct wm_drive *d; int *left, *right; { /* Suns, HPs, Linux, NEWS can't read the volume; oh well */ *left = *right = -1; return (0); } /* * Pass SCSI commands to the device. */ int wm_scsi(d, cdb, cdblen, buf, buflen, getreply) struct wm_drive *d; unsigned char *cdb, *buf; int cdblen, buflen, getreply; { /* NEWS can't do SCSI passthrough... or can it? */ return (-1); } /* * Open the CD device and figure out what kind of drive is attached. */ int wmcd_open(d) struct wm_drive *d; { int fd; static int warned = 0; char vendor[32] = WM_STR_GENVENDOR; char model[32] = WM_STR_GENMODEL; char rev[32] = WM_STR_GENREV; if (d->fd >= 0) /* Device already open? */ return (0); intermittent_dev = 1; if (cd_device == NULL) cd_device = DEFAULT_CD_DEVICE; if ((d->fd = CD_Open(cd_device, 0)) < 0) { /* Solaris 2.2 volume manager moves links around */ if (errno == ENOENT && intermittent_dev) return (0); if (errno == EACCES) { if (!warned) { char realname[MAXPATHLEN]; if (realpath(cd_device, realname) == NULL) { perror("realpath"); return (0); } fprintf(stderr, "As root, please run\n\nchmod 666 %s\n\n%s\n", realname, "to give yourself permission to access the CD-ROM device."); warned++; } } else if (errno != EIO) /* defined at top */ { perror(cd_device); exit(1); } /* No CD in drive. */ return (1); } if (warned) { warned = 0; fprintf(stderr, "Thank you.\n"); } /* Now fill in the relevant parts of the wm_drive structure. */ fd = d->fd; /* Figure out the drive type, if possible */ wm_scsi_get_drive_type(d, vendor, model, rev); *d = *(find_drive_struct(vendor, model, rev)); wm_drive_settype(vendor, model, rev); d->fd = fd; (d->init)(d); return (0); } /* wmcd_open() */ /* * Re-Open the device if it is open. */ int wmcd_reopen( struct wm_drive *d ) { int status; do { wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "wmcd_reopen "); if (d->fd >= 0) /* Device really open? */ { wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "closes the device and "); status = close( d->fd ); /* close it! */ /* we know, that the file is closed, do we? */ d->fd = -1; } wm_susleep( 1000 ); wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "calls wmcd_open()\n"); status = wmcd_open( d ); /* open it as usual */ wm_susleep( 1000 ); } while ( status != 0 ); return status; } /* wmcd_reopen() */ #endif ascd-0.13.2.orig/libworkman/plat_linux_audio.c0100644000175000017500000002642706670435230020654 0ustar hallonhallon/* * $Id: plat_linux_audio.c,v 1.3 1999/03/07 08:36:40 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * Linux digital audio functions. */ #include "include/wm_config.h" #if defined(linux) && defined(BUILD_CDDA) /* { */ static char plat_linux_audio_id[] = "$Id: plat_linux_audio.c,v 1.3 1999/03/07 08:36:40 dirk Exp $"; #include "include/wm_cdda.h" /* types.h included by wm_cdda.h */ #include #include #include #include #include #include #include #include #include #define WM_MSG_CLASS WM_MSG_CLASS_PLATFORM /* * Since there's a lag time between writing audio to the audio device and * hearing it, we need to make sure the status indicators correlate to what's * playing out the speaker. Luckily, Solaris gives us some audio * synchronization facilities that make this pretty easy. * * We maintain a circular queue of status information. When we write some * sound to the audio device, we put its status info into the queue. We write * a marker into the audio stream; when the audio device driver encounters the * marker, it increments a field in a status structure. When we see that * field go up, we grab the next status structure from the queue and send it * to the parent process. * * The minimum size of the queue depends on the latency of the audio stream. */ #define QSIZE 500 struct cdda_block queue[QSIZE]; int qtail; int qstart; /* * We only send WMCDDA_PLAYED status messages upstream when the CD is supposed * to be playing; this is used to keep track. */ extern int playing; static int aufd, aucfd; static int raw_audio = 1; /* Can /dev/audio take 44.1KHz stereo? */ /* * For fast linear-to-ulaw mapping, we use a lookup table that's generated * at startup. */ unsigned char *ulawmap, linear_to_ulaw(); char *getenv(); /* * Dummy signal handler so writes to /dev/audio will interrupt. */ static void dummy( void ) { signal(SIGALRM, dummy); } /* * Initialize the audio device. */ void wmaudio_init( void ) { audio_info_t info; char *audiodev, *acdev; int linval; audiodev = getenv("AUDIODEV"); if (audiodev == NULL) audiodev = "/dev/audio"; acdev = malloc(strlen(audiodev) + 4); if (acdev == NULL) { perror("Can't allocate audio control filename"); exit(1); } strcpy(acdev, audiodev); strcat(acdev, "ctl"); aucfd = open(acdev, O_WRONLY, 0); if (aucfd < 0) { perror(acdev); exit(1); } free(acdev); aufd = open(audiodev, O_WRONLY, 0); if (aufd < 0) { perror(audiodev); exit(1); } signal(SIGALRM, dummy); /* * Try to set the device to CD-style audio; we can process it * with the least CPU overhead. */ AUDIO_INITINFO(&info); info.play.sample_rate = 44100; info.play.channels = 2; info.play.precision = 16; info.play.encoding = AUDIO_ENCODING_LINEAR; info.play.pause = 0; info.record.pause = 0; info.monitor_gain = 0; if (ioctl(aufd, AUDIO_SETINFO, &info) < 0) if (errno == EINVAL) { /* * Oh well, so much for that idea. */ AUDIO_INITINFO(&info); info.play.sample_rate = 8000; info.play.channels = 1; info.play.precision = 8; info.play.encoding = AUDIO_ENCODING_ULAW; info.play.pause = 0; info.record.pause = 0; info.monitor_gain = 0; if (ioctl(aufd, AUDIO_SETINFO, &info) < 0) { perror("Can't set up audio device"); exit(1); } /* * Initialize the linear-to-ulaw mapping table. */ if (ulawmap == NULL) ulawmap = malloc(65536); if (ulawmap == NULL) { perror("malloc"); exit(1); } for (linval = 0; linval < 65536; linval++) ulawmap[linval] = linear_to_ulaw(linval-32768); ulawmap += 32768; raw_audio = 0; } else { perror(audiodev); exit(1); } } /* * Get ready to play some sound. */ void wmaudio_ready( void ) { audio_info_t info; /* * Start at the correct queue position. */ if (ioctl(aucfd, AUDIO_GETINFO, &info) < 0) perror("AUDIO_GETINFO"); qtail = info.play.eof % QSIZE; qstart = qtail; queue[qtail].status = WMCDDA_OK; } /* * Stop the audio immediately. */ void wmaudio_stop( void ) { if (ioctl(aufd, I_FLUSH, FLUSHRW) < 0) perror("flush"); } /* * Close the audio device. */ void wmaudio_close( void ) { wmaudio_stop(); close(aufd); close(aucfd); } /* * Set the volume level. */ void wmaudio_volume(int level) { audio_info_t info; AUDIO_INITINFO(&info); if (ioctl(aucfd, AUDIO_GETINFO, &info) < 0) perror("AUDIO_GETINFO"); info.play.gain = level; if (ioctl(aucfd, AUDIO_SETINFO, &info) < 0) perror("AUDIO_SETINFO"); } /* * Set the balance level. */ void wmaudio_balance(int level) { audio_info_t info; AUDIO_INITINFO(&info); if (ioctl(aucfd, AUDIO_GETINFO, &info) < 0) perror("AUDIO_GETINFO"); level *= AUDIO_RIGHT_BALANCE; info.play.balance = level / 255; if (ioctl(aucfd, AUDIO_SETINFO, &info) < 0) perror("AUDIO_SETINFO"); } /* * Mark the most recent audio block on the queue as the last one. */ void wmaudio_mark_last( void ) { queue[qtail].status = WMCDDA_DONE; } /* * Figure out the most recent status information and send it upstream. */ int wmaudio_send_status( void ) { audio_info_t info; int qhead; /* * Now send the most current status information to our parent. */ if (ioctl(aucfd, AUDIO_GETINFO, &info) < 0) perror("AUDIO_GETINFO"); qhead = info.play.eof % QSIZE; if (qhead != qstart && playing) { int balance; if (queue[qhead].status != WMCDDA_DONE) queue[qhead].status = WMCDDA_PLAYED; queue[qhead].volume = info.play.gain; queue[qhead].balance = (info.play.balance * 255) / AUDIO_RIGHT_BALANCE; send_status(queue + qhead); qstart = -1; } return (queue[qhead].status == WMCDDA_DONE); } /* * Play some audio and pass a status message upstream, if applicable. * Returns 0 on success. */ int wmaudio_play(unsigned char *rawbuf, long buflen, struct cdda_block *blk) { int i; short *buf16; int alarmcount = 0; struct itimerval it; alarm(1); while (write(aufd, rawbuf, buflen) <= 0) if (errno == EINTR) { if (! raw_audio && alarmcount++ < 5) { /* * 8KHz /dev/audio blocks for several seconds * waiting for its queue to drop below a low * water mark. */ wmaudio_send_status(); timerclear(&it.it_interval); timerclear(&it.it_value); it.it_value.tv_usec = 500000; setitimer(ITIMER_REAL, &it, NULL); continue; } /* close(aufd); close(aucfd); wmaudio_init(); */ wmaudio_stop( void ); alarm(2); continue; } else { blk->status = WMCDDA_ERROR; return (-1); } alarm(0); /* * Mark this spot in the audio stream. * * Marks don't always succeed (if the audio buffer is empty * this call will block forever) so do it asynchronously. */ fcntl(aufd, F_SETFL, O_NONBLOCK); if (write(aufd, rawbuf, 0) < 0) { if (errno != EAGAIN) perror("audio mark"); } else qtail = (qtail + 1) % QSIZE; fcntl(aufd, F_SETFL, 0); queue[qtail] = *blk; if (wmaudio_send_status() < 0) return (-1); else return (0); } /* * Get the current audio state. */ void wmaudio_state(struct cdda_block *blk) { audio_info_t info; int balance; if (ioctl(aucfd, AUDIO_GETINFO, &info) < 0) perror("AUDIO_GETINFO"); blk->volume = info.play.gain; blk->balance = (info.play.balance * 255) / AUDIO_RIGHT_BALANCE; } /* ** This routine converts from linear to ulaw. ** ** Craig Reese: IDA/Supercomputing Research Center ** Joe Campbell: Department of Defense ** 29 September 1989 ** ** References: ** 1) CCITT Recommendation G.711 (very difficult to follow) ** 2) "A New Digital Technique for Implementation of Any ** Continuous PCM Companding Law," Villeret, Michel, ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1, ** 1973, pg. 11.12-11.17 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards ** for Analog-to_Digital Conversion Techniques," ** 17 February 1987 ** ** Input: Signed 16 bit linear sample ** Output: 8 bit ulaw sample */ #define ZEROTRAP /* turn on the trap as per the MIL-STD */ #define BIAS 0x84 /* define the add-in bias for 16 bit samples */ #define CLIP 32635 unsigned char linear_to_ulaw( sample ) int sample; { static int exp_lut[256] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3, 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7}; int sign, exponent, mantissa; unsigned char ulawbyte; /* Get the sample into sign-magnitude. */ sign = (sample >> 8) & 0x80; /* set aside the sign */ if ( sign != 0 ) sample = -sample; /* get magnitude */ if ( sample > CLIP ) sample = CLIP; /* clip the magnitude */ /* Convert from 16 bit linear to ulaw. */ sample = sample + BIAS; exponent = exp_lut[( sample >> 7 ) & 0xFF]; mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F; ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa ); #ifdef ZEROTRAP if ( ulawbyte == 0 ) ulawbyte = 0x02; /* optional CCITT trap */ #endif return ulawbyte; } /* * Downsample a block of CDDA data, if necessary, for playing out an old-style * audio device. */ long wmaudio_convert(unsigned char *rawbuf, long buflen, struct cdda_block *blk) { short *buf16 = (short *)rawbuf; int i, j, samples; int mono_value; unsigned char *rbend = rawbuf + buflen; /* Don't do anything if the audio device can take the raw values. */ if (raw_audio) return (buflen); for (i = 0; buf16 < (short *)(rbend); i++) { /* Downsampling to 8KHz is a little irregular. */ samples = (i & 1) ? ((i % 20) ? 10 : 12) : 12; /* And unfortunately, we don't always end on a nice boundary. */ if (buf16 + samples > (short *)(rbend)) samples = ((short *)rbend) - buf16; /* * No need to average all the values; taking the first one * is sufficient and less CPU-intensive. But we do need to * do both channels. */ mono_value = (buf16[0] + buf16[1]) / 2; buf16 += samples; rawbuf[i] = ulawmap[mono_value]; } return (i); } #endif /* ... && BUILD_CDDA */ ascd-0.13.2.orig/libworkman/plat_linux_cdda.c0100644000175000017500000002047306670435230020441 0ustar hallonhallon/* * $Id: plat_linux_cdda.c,v 1.3 1999/03/07 08:36:40 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * Linux CDDA functions. Derived from the SUN module. */ #include "include/wm_config.h" #if defined(linux) && defined(BUILD_CDDA) /* { */ static char plat_linux_cdda_id[] = "$Id: plat_linux_cdda.c,v 1.3 1999/03/07 08:36:40 dirk Exp $"; #include "include/wm_cdda.h" /* types.h and cdio.h are included by wmcdda.h */ #include #include #include #include #include #define WM_MSG_CLASS WM_MSG_CLASS_PLATFORM #define CDDABLKSIZE 2368 #define SAMPLES_PER_BLK 588 /* Address of next block to read. */ int current_position = 0; /* Address of first and last blocks to read. */ int starting_position = 0; int ending_position = 0; /* Playback direction. */ int direction = 1; /* Number of blocks to read at once; initialize to the maximum. */ int numblocks = 30; /* * This is the fastest way to convert from BCD to 8-bit. */ unsigned char unbcd[256] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0,0,0,0,0,0, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0,0,0,0,0,0, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 0,0,0,0,0,0, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 0,0,0,0,0,0, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 0,0,0,0,0,0, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 0,0,0,0,0,0, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 0,0,0,0,0,0, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 0,0,0,0,0,0, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 0,0,0,0,0,0, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; /* * Initialize the CDDA data buffer and open the appropriate device. * * NOTE: We allocate twice as much space as we need to actually read a block; * this lets us do audio manipulations without bothering to malloc a second * buffer. * * Also, test to see if we can actually *do* CDDA on this drive; if not, we * need to exit right away so the UI doesn't show the user any CDDA controls. */ int wmcdda_init(char **bufadr, long *buflenadr, int init_fd, char *devname) { struct cdrom_cdda cdda; *bufadr = malloc(numblocks * CDDABLKSIZE * 2); if (*bufadr == NULL) return (-1); *buflenadr = numblocks * CDDABLKSIZE; /*init_fd = open(devname, 0); if (init_fd == -1) init_fd = open("/dev/rdsk/c0t6d0s2", 0); */ init_fd = wmcdda_open(devname); if (init_fd > -1) { cdda.cdda_addr = 200; cdda.cdda_length = 1; cdda.cdda_data = *bufadr; cdda.cdda_subcode = CDROM_DA_SUBQ; if (ioctl(init_fd, CDROMCDDA, &cdda) < 0) { close(init_fd); init_fd = -1; } } return (init_fd); } /* * Try to open the CD device */ int wmcdda_open(char *devname) { int fd; fd = open(devname, 0); if (fd == -1) fd = open("/dev/rdsk/c0t6d0s2", 0); return(fd); } /* * Close the CD-ROM device in preparation for exiting. */ void wmcdda_close(int fd) { close(fd); } /* * Set up for playing the CD. Actually this doesn't play a thing, just sets a * couple variables so we'll know what to do when we're called. */ void wmcdda_setup(int start, int end, int realstart) { current_position = start - 150; ending_position = end - 150; starting_position = realstart - 150; /* * Special case: don't start at the "end" of a track if we're * playing backwards! */ if (direction == -1 && start == realstart) current_position = ending_position - numblocks; } /* * Read some blocks from the CD. Stop if we hit the end of the current region. * * Returns number of bytes read, -1 on error, 0 if stopped for a benign reason. */ long wmcdda_read(int fd, unsigned char *rawbuf, long buflen, struct cdda_block *block) { struct cdrom_cdda cdda; int blk; unsigned char *q; extern int speed; if ((direction > 0 && current_position >= ending_position) || (direction < 0 && current_position < starting_position)) { block->status = WMCDDA_DONE; return (0); } cdda.cdda_addr = current_position; if (ending_position && current_position + numblocks > ending_position) cdda.cdda_length = ending_position - current_position; else cdda.cdda_length = numblocks; cdda.cdda_data = rawbuf; cdda.cdda_subcode = CDROM_DA_SUBQ; if (ioctl(fd, CDROMCDDA, &cdda) < 0) { if (errno == ENXIO) /* CD ejected! */ { block->status = WMCDDA_EJECTED; return (-1); } if (current_position + numblocks > ending_position) { /* * Hit the end of the CD, probably. */ block->status = WMCDDA_DONE; return (0); } /* Sometimes it fails once, dunno why */ if (ioctl(fd, CDROMCDDA, &cdda) < 0) { if (ioctl(fd, CDROMCDDA, &cdda) < 0) { if (ioctl(fd, CDROMCDDA, &cdda) < 0) { perror("CDROMCDDA"); block->status = WMCDDA_ERROR; return (-1); } } } } if (speed > 148) { /* * We want speed=148 to advance by cdda_length, but * speed=256 to advance cdda_length * 4. */ current_position = current_position + (cdda.cdda_length * direction * (speed - 112)) / 36; } else current_position = current_position + cdda.cdda_length * direction; for (blk = 0; blk < numblocks; blk++) { /* * New valid Q-subchannel information? Update the block * status. */ q = &rawbuf[blk * CDDABLKSIZE + SAMPLES_PER_BLK * 4]; if (*q == 1) { block->status = WMCDDA_OK; block->track = unbcd[q[1]]; block->index = unbcd[q[2]]; block->minute = unbcd[q[7]]; block->second = unbcd[q[8]]; block->frame = unbcd[q[9]]; } } return (cdda.cdda_length * CDDABLKSIZE); } /* * Normalize a bunch of CDDA data. Basically this means ripping out the * Q subchannel data and doing byte-swapping, since the CD audio is in * littleendian format. * * Scanning is handled here too. * * XXX - do byte swapping on Intel boxes? */ long wmcdda_normalize(unsigned char *rawbuf, long buflen, struct cdda_block *block) { int i, nextq; int blocks = buflen / CDDABLKSIZE; unsigned char *dest = rawbuf; unsigned char tmp; long *buf32 = (long *)rawbuf, tmp32; /* * this was #ifndef LITTLEENDIAN * in wmcdda it was called LITTLE_ENDIAN. Was this a flaw? */ #if WM_BIG_ENDIAN if (blocks--) for (i = 0; i < SAMPLES_PER_BLK * 2; i++) { /* Only need to use temp buffer on first block. */ tmp = *rawbuf++; *dest++ = *rawbuf++; *dest++ = tmp; } #endif while (blocks--) { /* Skip over Q data. */ rawbuf += 16; for (i = 0; i < SAMPLES_PER_BLK * 2; i++) { #if WM_LITTLE_ENDIAN *dest++ = *rawbuf++; *dest++ = *rawbuf++; #else *dest++ = rawbuf[1]; *dest++ = rawbuf[0]; rawbuf += 2; #endif } } buflen -= ((buflen / CDDABLKSIZE) * 16); /* * Reverse the data here if we're playing backwards. * XXX - ideally this should be done above. */ if (direction < 0) { buflen /= 4; /* we can move 32 bits at a time. */ for (i = 0; i < buflen / 2; i++) { tmp32 = buf32[i]; buf32[i] = buf32[buflen - i - 1]; buf32[buflen - i - 1] = tmp32; } buflen *= 4; } return (buflen); } /* * Set the playback direction. */ void wmcdda_direction(int newdir) { if (newdir == 0) { numblocks = 20; direction = 1; } else { numblocks = 30; direction = -1; } } /* * Do system-specific stuff to get ready to play at a particular speed. */ void wmcdda_speed(int speed) { if (speed > 128) numblocks = 12; else numblocks = direction > 0 ? 20 : 30; } #endif /* } */ ascd-0.13.2.orig/libworkman/plat_openbsd.c0100644000175000017500000002645706670435230017771 0ustar hallonhallon/* * $Id: plat_openbsd.c,v 1.7 1999/03/07 08:36:40 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * OpenBSD-specific drive control routines. (Based on plat_freebsd.c) * * Michael Shalayeff, 7/24/96 * Todd Pfaff, 3/20/94 * */ #if defined(__OpenBSD__) static char plat_openbsd[] = "$Id: plat_openbsd.c,v 1.7 1999/03/07 08:36:40 dirk Exp $"; #include #include #include #include #include #include #include #include #include "include/wm_config.h" /* this is for glibc 2.x which defines the ust structure in ustat.h not stat.h */ #ifdef __GLIBC__ #include #endif #include #include #include #include #include #include #include #include "include/wm_struct.h" #define WM_MSG_CLASS WM_MSG_CLASS_PLATFORM void *malloc(); int min_volume = 10; int max_volume = 255; extern char *cd_device; /* * Initialize the drive. A no-op for the generic driver. */ int gen_init(struct wm_drive *d) { return (0); } /* * Get the number of tracks on the CD. */ int gen_get_trackcount(struct wm_drive *d, int tracks) { struct ioc_toc_header hdr; if (ioctl(d->fd, CDIOREADTOCHEADER, &hdr) == -1) return (-1); *tracks = hdr.ending_track - hdr.starting_track + 1; return (0); } /* * Get the start time and mode (data or audio) of a track. * * XXX - this should get cached, but that means keeping track of ejects. */ int gen_get_trackinfo(struct wm_drive *d, int track, int *data, int *startframe) { struct ioc_read_toc_entry toc; struct cd_toc_entry toc_buffer; bzero((char *)&toc_buffer, sizeof(toc_buffer)); toc.address_format = CD_MSF_FORMAT; toc.starting_track = track; toc.data_len = sizeof(toc_buffer); toc.data = &toc_buffer; if (ioctl(d->fd, CDIOREADTOCENTRYS, &toc)) return (-1); *data = ((toc_buffer.control & 0x4) != 0); *startframe = toc_buffer.addr.msf.minute*60*75 + toc_buffer.addr.msf.second * 75 + toc_buffer.addr.msf.frame; return (0); } /* * Get the number of frames on the CD. */ int gen_get_cdlen(struct wm_drive *d, int *frames) { int tmp; struct ioc_toc_header hdr; int status; #define LEADOUT 0xaa /* see scsi.c. what a hack! */ return gen_get_trackinfo(d, LEADOUT, &tmp, frames); } /* * Get the current status of the drive: the current play mode, the absolute * position from start of disc (in frames), and the current track and index * numbers if the CD is playing or paused. */ int gen_get_drive_status(struct wm_drive *d, enum wm_cd_modes oldmode, enum wm_cd_modes *mode, int *pos, int *track, int *index) { struct ioc_read_subchannel sc; struct cd_sub_channel_info scd; /* If we can't get status, the CD is ejected, so default to that. */ *mode = WM_CDM_EJECTED; sc.address_format = CD_MSF_FORMAT; sc.data_format = CD_CURRENT_POSITION; sc.track = 0; sc.data_len = sizeof(scd); sc.data = (struct cd_sub_channel_info *)&scd; /* Is the device open? */ if (d->fd < 0) { switch (wmcd_open(d)) { case -1: /* error */ return (-1); case 1: /* retry */ return (0); } } if (ioctl(d->fd, CDIOCREADSUBCHANNEL, &sc)) { /* we need to release the device so the kernel will notice reloaded media */ (void) close(d->fd); d->fd = -1; return (0); /* ejected */ } switch (scd.header.audio_status) { case CD_AS_PLAY_IN_PROGRESS: *mode = WM_CDM_PLAYING; dopos: *pos = scd.what.position.absaddr.msf.minute * 60 * 75 + scd.what.position.absaddr.msf.second * 75 + scd.what.position.absaddr.msf.frame; *track = scd.what.position.track_number; *index = scd.what.position.index_number; break; case CD_AS_PLAY_PAUSED: if (oldmode == WM_CDM_PLAYING || oldmode == WM_CDM_PAUSED) { *mode = WM_CDM_PAUSED; goto dopos; } else *mode = WM_CDM_STOPPED; break; case CD_AS_PLAY_COMPLETED: *mode = WM_CDM_TRACK_DONE; /* waiting for next track. */ break; case CD_AS_NO_STATUS: case 0: *mode = WM_CDM_STOPPED; break; } return (0); } /* * scale_volume(vol, max) * * Return a volume value suitable for passing to the CD-ROM drive. "vol" * is a volume slider setting; "max" is the slider's maximum value. * * On Sun and DEC CD-ROM drives, the amount of sound coming out the jack * increases much faster toward the top end of the volume scale than it * does at the bottom. To make up for this, we make the volume scale look * sort of logarithmic (actually an upside-down inverse square curve) so * that the volume value passed to the drive changes less and less as you * approach the maximum slider setting. The actual formula looks like * * (max^2 - (max - vol)^2) * (max_volume - min_volume) * v = --------------------------------------------------- + min_volume * max^2 * * If your system's volume settings aren't broken in this way, something * like the following should work: * * return ((vol * (max_volume - min_volume)) / max + min_volume); */ static int scale_volume(int vol, int max) { return ((vol * (max_volume - min_volume)) / max + min_volume); } /* * Set the volume level for the left and right channels. Their values * range from 0 to 100. */ int gen_set_volume(struct wm_drive *d, int left, int right) { struct ioc_vol vol; if (left < 0) /* don't laugh, I saw this happen once! */ left = 0; if (right < 0) right = 0; left = scale_volume(left, 100); right = scale_volume(right, 100); bzero((char *)&vol, sizeof(vol)); vol.vol[LEFT_PORT] = left; vol.vol[RIGHT_PORT] = right; if (ioctl(d->fd, CDIOCSETVOL, &vol)) return (-1); return (0); } /* * Pause the CD. */ int gen_pause(struct wm_drive *d) { return (ioctl(d->fd, CDIOCPAUSE)); } /* * Resume playing the CD (assuming it was paused.) */ int gen_resume(struct wm_drive *d) { return (ioctl(d->fd, CDIOCRESUME)); } /* * Stop the CD. */ int gen_stop(struct wm_drive *d) { return (ioctl(d->fd, CDIOCSTOP)); } /* * Play the CD from one position to another (both in frames.) */ int gen_play(struct wm_drive *d, int start, int end) { struct ioc_play_msf msf; msf.start_m = start / (60*75); msf.start_s = (start % (60*75)) / 75; msf.start_f = start % 75; msf.end_m = end / (60*75); msf.end_s = (end % (60*75)) / 75; msf.end_f = end % 75; if (ioctl(d->fd, CDIOCSTART)) return (-1); if (ioctl(d->fd, CDIOCPLAYMSF, &msf)) return (-2); return (0); } /* * Eject the current CD, if there is one. */ int gen_eject(struct wm_drive *d) { /* On some systems, we can check to see if the CD is mounted. */ struct stat stbuf; struct statfs buf; int rval; if (fstat(d->fd, &stbuf) != 0) return (-2); /* Is this a mounted filesystem? */ if (fstatfs(stbuf.st_rdev, &buf) == 0) return (-3); rval = ioctl(d->fd, CDIOCALLOW); if (rval == 0) rval = ioctl(d->fd, CDIOCEJECT); if (rval == 0) rval = ioctl(d->fd, CDIOCPREVENT); if (rval == 0) rval = close(d->fd); if (rval == 0) d->fd = -1; return rval; } /* gen_eject() */ /*----------------------------------------* * Close the CD tray * * Please edit and send changes to * milliByte@DeathsDoor.com *----------------------------------------*/ int gen_closetray(struct wm_drive *d) { #ifdef CAN_CLOSE if(!close(d->fd)) { d->fd=-1; return(wmcd_reopen(d)); } else { return(-1); } #else /* Always succeed if the drive can't close */ return(0); #endif /* CAN_CLOSE */ } /* gen_closetray() */ /* * unscale_volume(cd_vol, max) * * Given a value between min_volume and max_volume, return the volume slider * value needed to achieve that value. * * Rather than perform floating-point calculations to reverse the above * formula, we simply do a binary search of scale_volume()'s return values. */ static int unscale_volume(int cd_vol, int max) { int vol = 0, top = max, bot = 0, scaled; while (bot <= top) { vol = (top + bot) / 2; scaled = scale_volume(vol, max); if (cd_vol == scaled) break; if (cd_vol < scaled) top = vol - 1; else bot = vol + 1; } if (vol < 0) vol = 0; else if (vol > max) vol = max; return (vol); } /* * Read the initial volume from the drive, if available. Each channel * ranges from 0 to 100, with -1 indicating data not available. */ int gen_get_volume(struct wm_drive *d, int *left, int *right) { struct ioc_vol vol; if (d->fd >= 0) { bzero((char *)&vol, sizeof(vol)); if (ioctl(d->fd, CDIOCGETVOL, &vol)) *left = *right = -1; else { *left = unscale_volume(vol.vol[LEFT_PORT], 100); *right = unscale_volume(vol.vol[RIGHT_PORT], 100); } } else *left = *right = -1; return (0); } /* * Send an arbitrary SCSI command to a device. * */ int wm_scsi(struct wm_drive *d, unsigned char *cdb, int cdblen, void *retbuf, int retbuflen, int getreply) { return (-1); } /* * Open the CD device and figure out what kind of drive is attached. */ int wmcd_open(struct wm_drive *d) { int fd; static int warned = 0; char vendor[32] = WM_STR_GENVENDOR; char model[32] = WM_STR_GENMODEL; char rev[32] = WM_STR_GENREV; if (d->fd >= 0) /* Device already open? */ return (0); if (cd_device == NULL) cd_device = DEFAULT_CD_DEVICE; d->fd = open(cd_device, 0); if (d->fd < 0) { if (errno == EACCES) { if (!warned) { fprintf(stderr, "As root, please run\n\nchmod 666 %s\n\n%s\n", cd_device, "to give yourself permission to access the CD-ROM device."); warned++; } } /* No CD in drive. */ return (1); } if (warned) { warned = 0; fprintf(stderr, "Thank you.\n"); } /* Now fill in the relevant parts of the wm_drive structure. */ fd = d->fd; *d = *(find_drive_struct(vendor, model, rev)); wm_drive_settype(vendor, model, rev); (d->init)(d); d->fd = fd; return (0); } /* wmcd_open() */ /* * Re-Open the device if it is open. */ int wmcd_reopen( struct wm_drive *d ) { int status; do { wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "wmcd_reopen "); if (d->fd >= 0) /* Device really open? */ { wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "closes the device and "); status = close( d->fd ); /* close it! */ /* we know, that the file is closed, do we? */ d->fd = -1; } wm_susleep( 1000 ); wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "calls wmcd_open()\n"); status = wmcd_open( d ); /* open it as usual */ wm_susleep( 1000 ); } while ( status != 0 ); return status; } /* wmcd_reopen() */ #endif ascd-0.13.2.orig/libworkman/plat_osf1.c0100644000175000017500000003543606670435230017204 0ustar hallonhallon/* * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * OSF drive control routines. */ #if defined(__osf__) static char plat_osf_id[] = "$Id: plat_osf1.c,v 1.6 1999/03/07 08:36:40 dirk Exp $"; #include #include #include #include #include #include #include #include #include /* #include #include */ #include #include #include "include/wm_config.h" #include "include/wm_struct.h" #define WM_MSG_CLASS WM_MSG_CLASS_PLATFORM /* * This structure will be filled with the TOC header and all entries. * Ultrix doesn't seem to allow getting single TOC entries. * - Chris Ross (cross@eng.umd.edu) */ struct cd_toc_header_and_entries { struct cd_toc_header cdth; struct cd_toc_entry cdte[CDROM_MAX_TRACK+1]; }; void *malloc(); char *strchr(); int min_volume = 128; int max_volume = 255; extern char *cd_device; /* * find_cdrom * * Determine the name of the CD-ROM device. * * Read through the boot records (via a call to uerf) and find the SCSI * address of the CD-ROM. */ void find_cdrom() { char *data, *fgetline(); FILE *uerf; int fds[2]; int pid; extern char *getenv(); pipe(fds); cd_device = getenv("CDROM"); if (cd_device != NULL) return; if ((pid = fork()) == 0) { close(fds[0]); dup2(fds[1], 1); execl("/etc/uerf", "uerf", "-R", "-r", "300", NULL); execl("/usr/sbin/uerf", "uerf", "-R", "-r", "300", NULL); _exit(1); } else if (pid < 0) { perror("fork"); exit(1); } close(fds[1]); uerf = fdopen(fds[0], "r"); while (data = fgetline(uerf)) if (strstr(data, "RRD42")) { char *device; cd_device = (char *)malloc(sizeof("/dev/rrz##c")); strcpy(cd_device, "/dev/r"); device = strstr(data, "rz"); device[(int)(strchr(device, ' ') - device)] = '\0'; strcat(cd_device, device); strcat(cd_device, "c"); break; } fclose(uerf); if (cd_device == NULL) { fprintf(stderr, "No cdrom (RRD42) is installed on this system\n"); exit(1); } kill(pid, 15); (void)wait((int *)NULL); } /* * Initialize the drive. A no-op for the generic driver. */ int gen_init(d) struct wm_drive *d; { return (0); } /* * Get the number of tracks on the CD. */ int gen_get_trackcount(d, tracks) struct wm_drive *d; int *tracks; { struct cd_toc_header hdr; if (ioctl(d->fd, CDROM_TOC_HEADER, &hdr)) return (-1); *tracks = hdr.th_ending_track; return (0); } /* * Get the start time and mode (data or audio) of a track. * * XXX - this should get cached, but that means keeping track of ejects. */ int gen_get_trackinfo(d, track, data, startframe) struct wm_drive *d; int track, *data, *startframe; { struct cd_toc toc; struct cd_toc_header hdr; struct cd_toc_header_and_entries toc_buffer; if (ioctl(d->fd, CDROM_TOC_HEADER, &hdr)) return (-1); bzero((char *)&toc_buffer, sizeof(toc_buffer)); toc.toc_address_format = CDROM_MSF_FORMAT; toc.toc_starting_track = 0; toc.toc_alloc_length = (u_short)(((hdr.th_data_len1 << 8) + hdr.th_data_len0) & 0xfff) + 2; toc.toc_buffer = (caddr_t)&toc_buffer; if (ioctl(d->fd, CDROM_TOC_ENTRYS, &toc)) return (-1); if (track == 0) track = hdr.th_ending_track + 1; *data = (toc_buffer.cdte[track-1].te_control & CDROM_DATA_TRACK) ? 1:0; *startframe = toc_buffer.cdte[track - 1].te_absaddr.msf.m_units*60*75 + toc_buffer.cdte[track - 1].te_absaddr.msf.s_units * 75 + toc_buffer.cdte[track - 1].te_absaddr.msf.f_units; return (0); } /* * Get the number of frames on the CD. */ int gen_get_cdlen(d, frames) struct wm_drive *d; int *frames; { int tmp; return (gen_get_trackinfo(d, 0, &tmp, frames)); } /* * Get the current status of the drive: the current play mode, the absolute * position from start of disc (in frames), and the current track and index * numbers if the CD is playing or paused. */ int gen_get_drive_status(d, oldmode, mode, pos, track, index) struct wm_drive *d; enum wm_cd_modes oldmode, *mode; int *pos, *track, *index; { struct cd_sub_channel sc; struct cd_subc_channel_data scd; /* If we can't get status, the CD is ejected, so default to that. */ *mode = WM_CDM_EJECTED; sc.sch_address_format = CDROM_MSF_FORMAT; sc.sch_data_format = CDROM_CURRENT_POSITION; sc.sch_track_number = 0; sc.sch_alloc_length = sizeof(scd); sc.sch_buffer = (caddr_t)&scd; /* Is the device open? */ if (d->fd < 0) { switch (wmcd_open(d)) { case -1: /* error */ return (-1); case 1: /* retry */ return (0); } } if (ioctl(d->fd, CDROM_READ_SUBCHANNEL, &sc)) return (0); /* ejected */ switch (scd.scd_header.sh_audio_status) { case AS_PLAY_IN_PROGRESS: *mode = WM_CDM_PLAYING; dopos: *pos = scd.scd_position_data.scp_absaddr.msf.m_units * 60 * 75 + scd.scd_position_data.scp_absaddr.msf.s_units * 75 + scd.scd_position_data.scp_absaddr.msf.f_units; *track = scd.scd_position_data.scp_track_number; *index = scd.scd_position_data.scp_index_number; break; case AS_PLAY_PAUSED: if (oldmode == WM_CDM_PLAYING || oldmode == WM_CDM_PAUSED) { *mode = WM_CDM_PAUSED; goto dopos; } else *mode = WM_CDM_STOPPED; break; case AS_PLAY_COMPLETED: *mode = WM_CDM_TRACK_DONE; /* waiting for next track. */ break; case AS_NO_STATUS: *mode = WM_CDM_STOPPED; break; default: abort(); } return (0); } /* * scale_volume(vol, max) * * Return a volume value suitable for passing to the CD-ROM drive. "vol" * is a volume slider setting; "max" is the slider's maximum value. * * On Sun and DEC CD-ROM drives, the amount of sound coming out the jack * increases much faster toward the top end of the volume scale than it * does at the bottom. To make up for this, we make the volume scale look * sort of logarithmic (actually an upside-down inverse square curve) so * that the volume value passed to the drive changes less and less as you * approach the maximum slider setting. The actual formula looks like * * (max^2 - (max - vol)^2) * (max_volume - min_volume) * v = --------------------------------------------------- + min_volume * max^2 * * If your system's volume settings aren't broken in this way, something * like the following should work: * * return ((vol * (max_volume - min_volume)) / max + min_volume); */ scale_volume(vol, max) int vol, max; { return ((max * max - (max - vol) * (max - vol)) * (max_volume - min_volume) / (max * max) + min_volume); } /* * Set the volume level for the left and right channels. Their values * range from 0 to 100. */ int gen_set_volume(d, left, right) struct wm_drive *d; int left, right; { struct cd_playback pb; struct cd_playback_status ps; struct cd_playback_control pc; left = scale_volume(left, 100); right = scale_volume(right, 100); bzero((char *)&pb, sizeof(pb)); bzero((char *)&ps, sizeof(ps)); bzero((char *)&pc, sizeof(pc)); pb.pb_alloc_length = sizeof(ps); pb.pb_buffer = (caddr_t)&ps; if (ioctl(d->fd, CDROM_PLAYBACK_STATUS, &pb)) return (-1); pc.pc_chan0_select = ps.ps_chan0_select; pc.pc_chan0_volume = (left < CDROM_MIN_VOLUME) ? CDROM_MIN_VOLUME : (left > CDROM_MAX_VOLUME) ? CDROM_MAX_VOLUME : left; pc.pc_chan1_select = ps.ps_chan1_select; pc.pc_chan1_volume = (right < CDROM_MIN_VOLUME) ? CDROM_MIN_VOLUME : (right > CDROM_MAX_VOLUME) ? CDROM_MAX_VOLUME : right; pb.pb_alloc_length = sizeof(pc); pb.pb_buffer = (caddr_t)&pc; if (ioctl(d->fd, CDROM_PLAYBACK_CONTROL, &pb)) return (-1); return (0); } /* * Pause the CD. */ int gen_pause(d) struct wm_drive *d; { return (ioctl(d->fd, CDROM_PAUSE_PLAY, 0)); } /* * Resume playing the CD (assuming it was paused.) */ int gen_resume(d) struct wm_drive *d; { return (ioctl(d->fd, CDROM_RESUME_PLAY, 0)); } /* * Stop the CD. */ int gen_stop(d) struct wm_drive *d; { return (ioctl(d->fd, SCSI_STOP_UNIT, 0)); } /* * Play the CD from one position to another (both in frames.) */ int gen_play(d, start, end) struct wm_drive *d; int start, end; { struct cd_play_audio_msf msf; msf.msf_starting_M_unit = start / (60*75); msf.msf_starting_S_unit = (start % (60*75)) / 75; msf.msf_starting_F_unit = start % 75; msf.msf_ending_M_unit = end / (60*75); msf.msf_ending_S_unit = (end % (60*75)) / 75; msf.msf_ending_F_unit = end % 75; if (ioctl(d->fd, SCSI_START_UNIT)) return (-1); if (ioctl(d->fd, CDROM_PLAY_AUDIO_MSF, &msf)) return (-2); return (0); } /* * Eject the current CD, if there is one. */ int gen_eject(struct wm_drive *d) { /* On some systems, we can check to see if the CD is mounted. */ struct stat stbuf; struct ustat ust; if (fstat(d->fd, &stbuf) != 0) return (-2); /* Is this a mounted filesystem? */ if (ustat(stbuf.st_rdev, &ust) == 0) return (-3); return (ioctl(d->fd, CDROM_EJECT_CADDY, 0)); } /* gen_eject() */ /*----------------------------------------* * Close the CD tray * * Please edit and send changes to * milliByte@DeathsDoor.com *----------------------------------------*/ int gen_closetray(struct wm_drive *d) { #ifdef CAN_CLOSE if(!close(d->fd)) { d->fd=-1; return(wmcd_reopen(d)); } else { return(-1); } #else /* Always succeed if the drive can't close */ return(0); #endif /* CAN_CLOSE */ } /* gen_closetray() */ /* * unscale_volume(cd_vol, max) * * Given a value between min_volume and max_volume, return the volume slider * value needed to achieve that value. * * Rather than perform floating-point calculations to reverse the above * formula, we simply do a binary search of scale_volume()'s return values. */ static int unscale_volume(cd_vol, max) int cd_vol, max; { int vol = 0, top = max, bot = 0, scaled; while (bot <= top) { vol = (top + bot) / 2; scaled = scale_volume(vol, max); if (cd_vol == scaled) break; if (cd_vol < scaled) top = vol - 1; else bot = vol + 1; } if (vol < 0) vol = 0; else if (vol > max) vol = max; return (vol); } /* * Read the initial volume from the drive, if available. Each channel * ranges from 0 to 100, with -1 indicating data not available. */ int gen_get_volume(d, left, right) struct wm_drive *d; int *left, *right; { struct cd_playback pb; struct cd_playback_status ps; bzero((char *)&pb, sizeof(pb)); bzero((char *)&ps, sizeof(ps)); pb.pb_alloc_length = sizeof(ps); pb.pb_buffer = (caddr_t)&ps; if (d->fd >= 0) { if (ioctl(d->fd, CDROM_PLAYBACK_STATUS, &pb)) *left = *right = -1; else { *left = unscale_volume(ps.ps_chan0_volume, 100); *right = unscale_volume(ps.ps_chan1_volume, 100); } } else *left = *right = -1; return (0); } /* * Send an arbitrary SCSI command to a device. */ int wm_scsi(d, cdb, cdblen, retbuf, retbuflen, getreply) struct wm_drive *d; unsigned char *cdb; int cdblen; void *retbuf; int retbuflen; int getreply; { /* ULTRIX doesn't have a SCSI passthrough interface, does it? */ return (-1); } /* * fgetline() * * Simulate fgets, but joining continued lines in the output of uerf. */ #define BUF_SIZE 85 /* Max length of a (real) line */ char * fgetline(fp) FILE *fp; { static char *retval = NULL; static char holdbuf[BUF_SIZE + 1]; char tmp[BUF_SIZE + 1]; char *stmp; if (!retval) { retval = malloc(BUF_SIZE * 3); /* 3 lines can be joined */ if (!retval) return(NULL); else *retval = '\0'; } if (*holdbuf) { strcpy(retval, holdbuf); retval[strlen(retval)-1] = '\0'; memset(holdbuf, 0, BUF_SIZE+1); } while (fgets(tmp, BUF_SIZE, fp)) { stmp = tmp + strspn(tmp, " \t"); if (*stmp == '_') { /* Continuation line */ retval[strlen(retval)-1] = '\0'; /* Trim off C/R */ strcat(retval, stmp+1); } else { if (*retval) { strcpy(holdbuf, tmp); holdbuf[strlen(holdbuf)-1] = -1; return retval; } else { /* First line read, keep reading */ strcat(retval, stmp); retval[strlen(retval)-1] = '\0'; } } } return NULL; } /* * Open the CD device and figure out what kind of drive is attached. */ int wmcd_open(d) struct wm_drive *d; { int fd; static int warned = 0; if (d->fd >= 0) /* Device already open? */ return (0); if (cd_device == NULL) find_cdrom(); d->fd = open(cd_device, O_RDWR); if (d->fd < 0) { if (errno == EACCES) { if (!warned) { fprintf(stderr, "As root, please run\n\nchmod 666 %s\n\n%s\n", cd_device, "to give yourself permission to access the CD-ROM device."); warned++; } } else if (errno != EINTR) { perror(cd_device); exit(1); } /* No CD in drive. */ return (1); } if (warned) { warned = 0; fprintf(stderr, "Thank you.\n"); } /* Now fill in the relevant parts of the wm_drive structure. */ fd = d->fd; *d = *(find_drive_struct("", "", "")); d->fd = fd; (d->init)(d); return (0); } /* wmcd_open() */ /* * Re-Open the device if it is open. */ int wmcd_reopen( struct wm_drive *d ) { int status; do { wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "wmcd_reopen "); if (d->fd >= 0) /* Device really open? */ { wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "closes the device and "); status = close( d->fd ); /* close it! */ /* we know, that the file is closed, do we? */ d->fd = -1; } wm_susleep( 1000 ); wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "calls wmcd_open()\n"); status = wmcd_open( d ); /* open it as usual */ wm_susleep( 1000 ); } while ( status != 0 ); return status; } /* wmcd_reopen() */ #endif ascd-0.13.2.orig/libworkman/plat_sun.c0100644000175000017500000006070106723407432017134 0ustar hallonhallon/* * $Id: plat_sun.c,v 1.9 1999/05/28 03:35:54 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * Sun-specific drive control routines. */ #ifdef sun static char plat_sun_id[] = "$Id: plat_sun.c,v 1.9 1999/05/28 03:35:54 dirk Exp $"; #include #include #include #include #include #include #include #include #include #include "include/wm_config.h" #include "include/wm_helpers.h" #include "include/wm_cdrom.h" #include #include #include #ifdef solbourne # include # include # include # include #else /* A real Sun */ # ifdef SYSV # include # include # include # include # include # include "include/wm_cdda.h" # else # include # include # include # include # include # endif #endif #include "include/wm_struct.h" #define WM_MSG_CLASS WM_MSG_CLASS_PLATFORM int min_volume = 0; int max_volume = 255; extern char *cd_device, *cddaslave_path; extern int intermittent_dev; int cdda_slave = -1; int current_end; #if defined(SYSV) && defined(SIGTHAW) #ifdef __GNUC__ void sigthawinit(void) __attribute__ ((constructor)); #else #pragma init(sigthawinit) #endif /* GNUC */ static int last_left, last_right; static struct wm_drive *thecd; static void thawme(int sig) { change_mode(NULL, WM_CDM_STOPPED, NULL); codec_init(); if( thecd ) gen_set_volume(thecd, last_left, last_right); } /* thawme */ void sigthawinit( void ) { struct sigaction sa; sa.sa_handler = thawme; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sigaction(SIGTHAW, &sa, NULL); } #endif /* SYSV && SIGTHAW */ /* * find_cdrom * * Determine the name of the CD-ROM device. * * Use the first of /vol/dev/aliases/cdrom0, /dev/rdsk/c0t6d0s2, and /dev/rsr0 * that exists. (Check for /vol/dev/aliases, not cdrom0, since it won't be * there if there's no CD in the drive.) This is done so a single SunOS 4.x * binary can be used on any 4.x or higher Sun system. */ void find_cdrom( void ) { if (access("/vol/dev/aliases", X_OK) == 0) { /* Volume manager. Device might not be there. */ intermittent_dev = 1; /* If vold is running us, it'll tell us the device name. */ cd_device = getenv("VOLUME_DEVICE"); if (cd_device == NULL) cd_device = "/vol/dev/aliases/cdrom0"; } else if (access("/dev/rdsk/c0t6d0s2", F_OK) == 0) { /* Solaris 2.x w/o volume manager. */ cd_device = "/dev/rdsk/c0t6d0s2"; } else if (access("/dev/rcd0", F_OK) == 0) { cd_device = "/dev/rcd0"; } else if (access("/dev/rsr0", F_OK) == 0) cd_device = "/dev/rsr0"; else { fprintf(stderr, "Couldn't find a CD device!\n"); exit(1); } } /* * Wait for an acknowledgement from the CDDA slave. */ static int get_ack(int fd) { #if defined(BUILD_CDDA) && defined(WMCDDA_DONE) /* { */ struct cdda_block blk; do if (read(fd, &blk, sizeof(blk)) <= 0) return (0); while (blk.status != WMCDDA_ACK); #endif /* } */ return (1); } /* * Initialize the drive. A no-op for the generic driver. */ int gen_init( struct wm_drive *d ) { codec_init(); return (0); } /* * Try to initialize the CDDA slave. Returns 0 on error. */ int cdda_init( struct wm_drive *d ) { #if defined(BUILD_CDDA) && defined(WMCDDA_DONE) /* { */ int slavefds[2]; if (cdda_slave > -1) return (1); if (socketpair(AF_UNIX, SOCK_STREAM, 0, slavefds)) { perror("socketpair"); return (0); } switch (fork()) { case 0: close(slavefds[0]); dup2(slavefds[1], 1); dup2(slavefds[1], 0); close(slavefds[1]); close(d->fd); /* Try the default path first. */ execl(cddaslave_path, cddaslave_path, cd_device, NULL); /* Search $PATH if that didn't work. */ execlp("cddaslave", "cddaslave", cd_device, NULL); perror(cddaslave_path); exit(1); case -1: close(slavefds[0]); close(slavefds[1]); perror("fork"); return (0); } close(slavefds[1]); cdda_slave = slavefds[0]; if (!get_ack(cdda_slave)) { cdda_slave = -1; codec_start(); return (0); } return (1); #else /* BUILD_CDDA } { */ /* * If we're not building CDDA support, don't even bother trying. */ return (0); #endif } /* * Turn off the CDDA slave. */ void cdda_kill( struct wm_drive *d ) { if (cdda_slave > -1) { write(cdda_slave, "Q", 1); get_ack(cdda_slave); wait(NULL); cdda_slave = -1; codec_start(); } } /* * Get the number of tracks on the CD. */ int gen_get_trackcount( struct wm_drive *d, int *tracks ) { struct cdrom_tochdr hdr; if (ioctl(d->fd, CDROMREADTOCHDR, &hdr)) return (-1); *tracks = hdr.cdth_trk1; return (0); } /* * Get the start time and mode (data or audio) of a track. */ int gen_get_trackinfo( struct wm_drive *d, int track, int *data, int *startframe) { struct cdrom_tocentry entry; entry.cdte_track = track; entry.cdte_format = CDROM_MSF; if (ioctl(d->fd, CDROMREADTOCENTRY, &entry)) return (-1); *startframe = entry.cdte_addr.msf.minute * 60 * 75 + entry.cdte_addr.msf.second * 75 + entry.cdte_addr.msf.frame; *data = entry.cdte_ctrl & CDROM_DATA_TRACK ? 1 : 0; return (0); } /* * Get the number of frames on the CD. */ int gen_get_cdlen(struct wm_drive *d, int *frames ) { int tmp; return (gen_get_trackinfo(d, CDROM_LEADOUT, &tmp, frames)); } /* Alarm signal handler. */ static void do_nothing( int x ) { x++; } /* * Get the current status of the drive: the current play mode, the absolute * position from start of disc (in frames), and the current track and index * numbers if the CD is playing or paused. */ int gen_get_drive_status( struct wm_drive *d, enum wm_cd_modes oldmode, enum wm_cd_modes *mode, int *pos, int *track, int *index ) { struct cdrom_subchnl sc; struct itimerval old_timer, new_timer; struct sigaction old_sig, new_sig; /* If we can't get status, the CD is ejected, so default to that. */ *mode = WM_CDM_EJECTED; /* Is the device open? */ if (d->fd < 0) { switch (wmcd_open(d)) { case -1: /* error */ return (-1); case 1: /* retry */ return (0); } } #if defined(BUILD_CDDA) && defined(WMCDDA_DONE) /* { */ if ((oldmode == WM_CDM_PAUSED || oldmode == WM_CDM_PLAYING || oldmode == WM_CDM_STOPPED) && cdda_slave > -1) { struct cdda_block blk; struct pollfd fds; int gotone = 0; fds.fd = cdda_slave; fds.events = POLLRDNORM; *mode = oldmode; while (poll(&fds, 1, 0) > 0) { read(cdda_slave, &blk, sizeof(blk)); gotone = 1; } /* We only want to use the latest status report. */ if (gotone) { if (blk.status == WMCDDA_PLAYED) { *track = blk.track; *index = blk.index; *pos = blk.minute * 60 * 75 + blk.second * 75 + blk.frame; *mode = WM_CDM_PLAYING; } else if (blk.status == WMCDDA_DONE) *mode = WM_CDM_TRACK_DONE; else if (blk.status == WMCDDA_STOPPED) { if (oldmode == WM_CDM_PLAYING || oldmode == WM_CDM_PAUSED) *mode = WM_CDM_PAUSED; else *mode = WM_CDM_STOPPED; } else if (blk.status == WMCDDA_ERROR) { /* * An error near the end of the CD probably * just means we hit the end. */ *mode = WM_CDM_TRACK_DONE; } else if (blk.status == WMCDDA_EJECTED) { *mode = WM_CDM_EJECTED; } } return (0); } #endif /* } */ /* * Solaris 2.2 hangs on this ioctl if someone else ejects the CD. * So we schedule a signal to break out of the hang if the call * takes an unreasonable amount of time. The signal handler and * timer are restored immediately to avoid interfering with XView. */ if (intermittent_dev) { /* * First clear out the timer so XView's signal doesn't happen * while we're diddling with the signal handler. */ timerclear(&new_timer.it_interval); timerclear(&new_timer.it_value); setitimer(ITIMER_REAL, &new_timer, &old_timer); /* * Now install the no-op signal handler. */ new_sig.sa_handler = do_nothing; memset(&new_sig.sa_mask, 0, sizeof(new_sig.sa_mask)); new_sig.sa_flags = 0; if (sigaction(SIGALRM, &new_sig, &old_sig)) perror("sigaction"); /* * And finally, set the timer. */ new_timer.it_value.tv_sec = 2; setitimer(ITIMER_REAL, &new_timer, NULL); } sc.cdsc_format = CDROM_MSF; if (ioctl(d->fd, CDROMSUBCHNL, &sc)) { if (intermittent_dev) { sigaction(SIGALRM, &old_sig, NULL); setitimer(ITIMER_REAL, &old_timer, NULL); /* If the device can disappear, let it do so. */ close(d->fd); d->fd = -1; } return (0); } if (intermittent_dev) { sigaction(SIGALRM, &old_sig, NULL); setitimer(ITIMER_REAL, &old_timer, NULL); } switch (sc.cdsc_audiostatus) { case CDROM_AUDIO_PLAY: *mode = WM_CDM_PLAYING; *track = sc.cdsc_trk; *index = sc.cdsc_ind; *pos = sc.cdsc_absaddr.msf.minute * 60 * 75 + sc.cdsc_absaddr.msf.second * 75 + sc.cdsc_absaddr.msf.frame; break; case CDROM_AUDIO_PAUSED: case CDROM_AUDIO_INVALID: case CDROM_AUDIO_NO_STATUS: if (oldmode == WM_CDM_PLAYING || oldmode == WM_CDM_PAUSED) { *mode = WM_CDM_PAUSED; *track = sc.cdsc_trk; *index = sc.cdsc_ind; *pos = sc.cdsc_absaddr.msf.minute * 60 * 75 + sc.cdsc_absaddr.msf.second * 75 + sc.cdsc_absaddr.msf.frame; } else *mode = WM_CDM_STOPPED; break; /* CD ejected manually during play. */ case CDROM_AUDIO_ERROR: break; case CDROM_AUDIO_COMPLETED: *mode = WM_CDM_TRACK_DONE; /* waiting for next track. */ break; default: *mode = WM_CDM_UNKNOWN; break; } return (0); } /* * Set the volume level for the left and right channels. Their values * range from 0 to 100. */ int gen_set_volume( struct wm_drive *d, int left, int right ) { struct cdrom_volctrl v; #if defined(SIGTHAW) && defined(SYSV) last_left = left; last_right = right; thecd = d; #endif if (cdda_slave > -1) { int bal, vol; unsigned char cmd[2]; bal = (right - left) + 100; bal *= 255; bal /= 200; if (right > left) vol = right; else vol = left; vol *= 255; vol /= 100; cmd[0] = 'B'; cmd[1] = bal; write(cdda_slave, cmd, 2); cmd[0] = 'V'; cmd[1] = vol; write(cdda_slave, cmd, 2); /* * Don't wait for the ack, or the user won't be able to drag * the volume slider smoothly. */ return (0); } left = (left * (max_volume - min_volume)) / 100 + min_volume; right = (right * (max_volume - min_volume)) / 100 + min_volume; v.channel0 = left < 0 ? 0 : left > 255 ? 255 : left; v.channel1 = right < 0 ? 0 : right > 255 ? 255 : right; return (ioctl(d->fd, CDROMVOLCTRL, &v)); } /* * Pause the CD. */ int gen_pause( struct wm_drive *d ) { if (cdda_slave > -1) { int dummy, mode = WM_CDM_PLAYING; write(cdda_slave, "S", 1); get_ack(cdda_slave); /* while (mode != WM_CDM_PAUSED) gen_get_drive_status(d, WM_CDM_PAUSED, &mode, &dummy, &dummy, &dummy); */ return (0); } codec_stop(); return (ioctl(d->fd, CDROMPAUSE)); } /* * Resume playing the CD (assuming it was paused.) */ int gen_resume( struct wm_drive *d ) { if (cdda_slave > -1) return (1); codec_start(); return (ioctl(d->fd, CDROMRESUME)); } /* * Stop the CD. */ int gen_stop( struct wm_drive *d ) { if (cdda_slave > -1) { write(cdda_slave, "S", 1); get_ack(cdda_slave); /* * The WMCDDA_STOPPED status message will be caught by * gen_get_drive_status. */ return (0); } codec_stop(); return (ioctl(d->fd, CDROMSTOP)); } /* * Play the CD from one position to another. * * d Drive structure. * start Frame to start playing at. * end End of this chunk. * realstart Beginning of this chunk (<= start) */ int gen_play( struct wm_drive *d, int start, int end, int realstart) { struct cdrom_msf msf; unsigned char cmdbuf[10]; current_end = end; if (cdda_slave > -1) { cmdbuf[0] = 'P'; cmdbuf[1] = start / (60 * 75); cmdbuf[2] = (start % (60*75)) / 75; cmdbuf[3] = start % 75; cmdbuf[4] = end / (60*75); cmdbuf[5] = (end % (60*75)) / 75; cmdbuf[6] = end % 75; cmdbuf[7] = realstart / (60 * 75); cmdbuf[8] = (realstart % (60*75)) / 75; cmdbuf[9] = realstart % 75; /* Write the play command and make sure the slave has it. */ write(cdda_slave, cmdbuf, 10); get_ack(cdda_slave); return (0); } msf.cdmsf_min0 = start / (60*75); msf.cdmsf_sec0 = (start % (60*75)) / 75; msf.cdmsf_frame0 = start % 75; msf.cdmsf_min1 = end / (60*75); msf.cdmsf_sec1 = (end % (60*75)) / 75; msf.cdmsf_frame1 = end % 75; codec_start(); if (ioctl(d->fd, CDROMSTART)) return (-1); if (ioctl(d->fd, CDROMPLAYMSF, &msf)) return (-2); return (0); } /* * Eject the current CD, if there is one. */ int gen_eject( struct wm_drive *d ) { struct stat stbuf; struct ustat ust; if (fstat(d->fd, &stbuf) != 0) return (-2); /* Is this a mounted filesystem? */ if (ustat(stbuf.st_rdev, &ust) == 0) return (-3); if (cdda_slave > -1) { write(cdda_slave, "S", 1); get_ack(cdda_slave); } if (ioctl(d->fd, CDROMEJECT)) return (-1); /* Close the device if it needs to vanish. */ if (intermittent_dev) { close(d->fd); d->fd = -1; /* Also remember to tell the cddaslave since volume manager switches links around on us */ if (cdda_slave > -1) { write(cdda_slave, "E", 1); get_ack(cdda_slave); } } return (0); } /* gen_eject() */ /*----------------------------------------* * Close the CD tray * * Please edit and send changes to * milliByte@DeathsDoor.com *----------------------------------------*/ int gen_closetray(struct wm_drive *d) { #ifdef CAN_CLOSE if(!close(d->fd)) { d->fd=-1; return(wmcd_reopen(d)); } else { return(-1); } #else /* Always succeed if the drive can't close */ return(0); #endif /* CAN_CLOSE */ } /* gen_closetray() */ /* * Read the initial volume from the drive, if available. Each channel * ranges from 0 to 100, with -1 indicating data not available. */ int gen_get_volume( struct wm_drive *d, int *left, int *right ) { #if defined(BUILD_CDDA) && defined(WMCDDA_DONE) /* { */ struct cdda_block blk; if (cdda_slave > -1) { write(cdda_slave, "G", 1); get_ack(cdda_slave); read(cdda_slave, &blk, sizeof(blk)); *left = *right = (blk.volume * 100 + 254) / 255; if (blk.balance < 110) *right = (((blk.volume * blk.balance + 127) / 128) * 100 + 254) / 255; else if (blk.balance > 146) *left = (((blk.volume * (255 - blk.balance) + 127) / 128) * 100 + 254) / 255; return (0); } #endif /* } */ *left = *right = -1; return (wm_scsi2_get_volume(d, left, right)); } #ifdef BUILD_CDDA /* { */ /* * Tell the CDDA slave to set the play direction. */ void gen_set_direction( int newdir ) { unsigned char buf[2]; if (cdda_slave > -1) { buf[0] = 'd'; buf[1] = newdir; write(cdda_slave, buf, 2); get_ack(cdda_slave); } } /* * Tell the CDDA slave to set the play speed. */ void gen_set_speed( int speed ) { unsigned char buf[2]; if (cdda_slave > -1) { buf[0] = 's'; buf[1] = speed; write(cdda_slave, buf, 2); get_ack(cdda_slave); } } /* * Tell the CDDA slave to set the loudness level. */ void gen_set_loudness( int loud ) { unsigned char buf[2]; if (cdda_slave > -1) { buf[0] = 'L'; buf[1] = loud; write(cdda_slave, buf, 2); get_ack(cdda_slave); } } /* * Tell the CDDA slave to start (or stop) saving to a file. */ void gen_save( char *filename ) { int len; if (filename == NULL || filename[0] == '\0') len = 0; else len = strlen(filename); write(cdda_slave, "F", 1); write(cdda_slave, &len, sizeof(len)); if (len) write(cdda_slave, filename, len); get_ack(cdda_slave); } #endif /* BUILD_CDDA } */ #ifndef solbourne /* * Send an arbitrary SCSI command out the bus and optionally wait for * a reply if "retbuf" isn't NULL. */ int wm_scsi( struct wm_drive *d, unsigned char *cdb, int cdblen, void *retbuf, int retbuflen, int getreply ) { char x; struct uscsi_cmd cmd; memset(&cmd, 0, sizeof(cmd)); cmd.uscsi_cdb = (void *) cdb; cmd.uscsi_cdblen = cdblen; cmd.uscsi_bufaddr = retbuf ? retbuf : (void *)&x; cmd.uscsi_buflen = retbuf ? retbuflen : 0; cmd.uscsi_flags = USCSI_ISOLATE | USCSI_SILENT; if (getreply) cmd.uscsi_flags |= USCSI_READ; if (ioctl(d->fd, USCSICMD, &cmd)) return (-1); if (cmd.uscsi_status) return (-1); return (0); } #else int wm_scsi() { return (-1); } #endif /* * Open the CD device and figure out what kind of drive is attached. */ int wmcd_open( struct wm_drive *d ) { int fd; static int warned = 0; char vendor[32] = WM_STR_GENVENDOR; char model[32] = WM_STR_GENMODEL; char rev[32] = WM_STR_GENREV; if (cd_device == NULL) find_cdrom(); if (d->fd >= 0) /* Device already open? */ return (0); d->fd = open(cd_device, 0); if (d->fd < 0) { /* Solaris 2.2 volume manager moves links around */ if (errno == ENOENT && intermittent_dev) return (1); if (errno == EACCES) { if (!warned) { char realname[MAXPATHLEN]; if (realpath(cd_device, realname) == NULL) { perror("realpath"); return (-1); } fprintf(stderr, "As root, please run\n\nchmod 666 %s\n\n%s\n", realname, "to give yourself permission to access the CD-ROM device."); warned++; } } else if (errno != ENXIO) { perror(cd_device); exit(1); } /* No CD in drive. */ return (1); } if (warned) { warned = 0; fprintf(stderr, "Thank you.\n"); } /* Now fill in the relevant parts of the wm_drive structure. */ fd = d->fd; /* * See if we can do digital audio. */ if (cdda_init(d)) enable_cdda_controls(1); /* Can we figure out the drive type? */ if (wm_scsi_get_drive_type(d, vendor, model, rev)) { if (errno == EPERM) { /* * Solaris 2.4 seems to refuse to do USCSICMD ioctls * when not running as root. SunOS 4.x allows it * as an unprivileged user, though. */ fprintf(stderr, "Warning: WorkMan can't adapt itself to your drive unless it runs as root.\n"); } else { fprintf(stderr, "Warning: WorkMan couldn't determine drive type\n"); } *d = *(find_drive_struct("Generic", "drive type", "")); } else { *d = *(find_drive_struct(vendor, model, rev)); } wm_drive_settype(vendor, model, rev); d->fd = fd; (d->init)(d); return (0); } /* wmcd_open() */ /* * Re-Open the device if it is open. */ int wmcd_reopen( struct wm_drive *d ) { int status; do { wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "wmcd_reopen "); if (d->fd >= 0) /* Device really open? */ { wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "closes the device and "); status = close( d->fd ); /* close it! */ /* we know, that the file is closed, do we? */ d->fd = -1; } wm_susleep( 1000 ); wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "calls wmcd_open()\n"); status = wmcd_open( d ); /* open it as usual */ wm_susleep( 1000 ); } while ( status != 0 ); return status; } /* wmcd_reopen() */ /* * The following code activates the internal CD audio passthrough on * SPARCstation 5 systems (and possibly others.) * * Thanks to , Roger Oscarsson * and Steve McKinty <> * * Most CD drives have a headphone socket on the front, but it * is often more convenient to route the audio though the * built-in audio device. That way the user can leave their * headphones plugged-in to the base system, for use with * other audio stuff like ShowMeTV */ #ifdef CODEC /* { */ #ifdef SYSV /* { */ # include # include # include #else /* } { */ # include # define AUDIO_DEV_SS5STYLE 5 typedef int audio_device_t; #endif /* } */ #endif /* } */ /* * Don't do anything with /dev/audio if we can't set it to high quality. * Also, don't do anything real if it's not Solaris. */ #if !defined(AUDIO_ENCODING_LINEAR) || !defined(CODEC) || !defined(SYSV) /* { */ codec_init() { return 0; } codec_start() { return 0; } codec_stop() { return 0; } #else #ifndef AUDIO_INTERNAL_CD_IN #define AUDIO_INTERNAL_CD_IN 0x4 #endif static char* devname = 0; static char* ctlname = 0; static int ctl_fd = -1; static int port = AUDIO_LINE_IN; int internal_audio = 1; codec_init( void ) { register int i; char* ctlname; audio_info_t foo; audio_device_t aud_dev; if (internal_audio == 0) { ctl_fd = -1; return(0); } if (!(devname = getenv("AUDIODEV"))) devname = "/dev/audio"; ctlname = strcat(strcpy(malloc(strlen(devname) + 4), devname), "ctl"); if ((ctl_fd = open(ctlname, O_WRONLY, 0)) < 0) { perror(ctlname); return -1; } if (ioctl(ctl_fd, AUDIO_GETDEV, &aud_dev) < 0) { close(ctl_fd); ctl_fd = -1; return -1; } /* * Instead of filtering the "OLD_SUN_AUDIO", try to find the new ones. * Not sure if this is all correct. */ #ifdef SYSV if (strcmp(aud_dev.name, "SUNW,CS4231") && strcmp(aud_dev.name, "SUNW,sb16") && strcmp(aud_dev.name, "SUNW,sbpro")) #else if (aud_dev != AUDIO_DEV_SS5STYLE) #endif { close(ctl_fd); ctl_fd = -1; return 0; /* but it's okay */ } /* * Does the chosen device have an internal CD port? * If so, use it. If not then try and use the * Line In port. */ if (ioctl(ctl_fd, AUDIO_GETINFO, &foo) < 0) { perror("AUDIO_GETINFO"); close(ctl_fd); ctl_fd = -1; return(-1); } if (foo.record.avail_ports & AUDIO_INTERNAL_CD_IN) port = AUDIO_INTERNAL_CD_IN; else port = AUDIO_LINE_IN; /* * now set it up to use it. See audio(7I) */ AUDIO_INITINFO(&foo); foo.record.port = port; foo.record.balance = foo.play.balance = AUDIO_MID_BALANCE; #ifdef BUILD_CDDA if (cdda_slave > -1) foo.monitor_gain = 0; else #endif foo.monitor_gain = AUDIO_MAX_GAIN; /* * These next ones are tricky. The voulme will depend on the CD drive * volume (set by the knob on the drive and/or by workman's volume * control), the audio device record gain and the audio device * play gain. For simplicity we set the latter two to something * reasonable, but we don't force them to be reset if the user * wants to change them. */ foo.record.gain = (AUDIO_MAX_GAIN * 80) / 100; foo.play.gain = (AUDIO_MAX_GAIN * 40) / 100; ioctl(ctl_fd, AUDIO_SETINFO, &foo); return 0; } static kick_codec( void ) { audio_info_t foo; int dev_fd; int retval = 0; /* * Open the audio device, not the control device. This * will fail if someone else has taken it. */ if ((dev_fd = open(devname, O_WRONLY|O_NDELAY, 0)) < 0) { perror(devname); return -1; } AUDIO_INITINFO(&foo); foo.record.port = port; foo.monitor_gain = AUDIO_MAX_GAIN; /* These can only be set on the real device */ foo.play.sample_rate = 44100; foo.play.channels = 2; foo.play.precision = 16; foo.play.encoding = AUDIO_ENCODING_LINEAR; if ((retval = ioctl(dev_fd, AUDIO_SETINFO, &foo)) < 0) perror(devname); close(dev_fd); return retval; } codec_start( void ) { audio_info_t foo; if (ctl_fd < 0) return 0; if (ioctl(ctl_fd, AUDIO_GETINFO, &foo) < 0) return -1; if (foo.play.channels != 2) return kick_codec(); if (foo.play.encoding != AUDIO_ENCODING_LINEAR) return kick_codec(); if (foo.play.precision != 16) return kick_codec(); if (foo.play.sample_rate != 44100) return kick_codec(); if (foo.record.channels != 2) return kick_codec(); if (foo.record.encoding != AUDIO_ENCODING_LINEAR) return kick_codec(); if (foo.record.precision != 16) return kick_codec(); if (foo.record.sample_rate != 44100) return kick_codec(); if (foo.monitor_gain != AUDIO_MAX_GAIN) return kick_codec(); if (foo.record.port != port) return kick_codec(); return 0; } codec_stop( void ) { return 0; } #endif /* CODEC } */ #endif /* sun } */ ascd-0.13.2.orig/libworkman/plat_svr4.c0100644000175000017500000002166606670435231017233 0ustar hallonhallon/* * $Id: plat_svr4.c,v 1.7 1999/03/07 08:36:41 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * SVR4 specific. Much of this is similar to plat_hpux.c. */ #if defined(SVR4) && !defined(sun) && !defined(__sun__) && !defined(__sony_news) static char plat_svr4_id[] = "$Id: plat_svr4.c,v 1.7 1999/03/07 08:36:41 dirk Exp $"; #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "include/wm_config.h" #include "include/wm_struct.h" #define WM_MSG_CLASS WM_MSG_CLASS_PLATFORM void *malloc(); char *strchr(); int min_volume = 0; int max_volume = 255; extern char *cd_device; /* * Initialize the drive. A no-op for the generic driver. */ int gen_init(d) struct wm_drive *d; { return (0); } /* * Get the number of tracks on the CD. */ int gen_get_trackcount(d, tracks) struct wm_drive *d; int *tracks; { return (wm_scsi2_get_trackcount(d, tracks)); } /* * Get the start time and mode (data or audio) of a track. */ int gen_get_trackinfo(d, track, data, startframe) struct wm_drive *d; int track, *data, *startframe; { return (wm_scsi2_get_trackinfo(d, track, data, startframe)); } /* * Get the number of frames on the CD. */ int gen_get_cdlen(d, frames) struct wm_drive *d; int *frames; { int tmp; return (wm_scsi2_get_cdlen(d, frames)); } /* * Get the current status of the drive: the current play mode, the absolute * position from start of disc (in frames), and the current track and index * numbers if the CD is playing or paused. */ int gen_get_drive_status(d, oldmode, mode, pos, track, index) struct wm_drive *d; enum wm_cd_modes oldmode, *mode; int *pos, *track, *index; { return (wm_scsi2_get_drive_status(d, oldmode, mode, pos, track, index)); } /* * Set the volume level for the left and right channels. Their values * range from 0 to 100. */ int gen_set_volume(d, left, right) struct wm_drive *d; int left, right; { return (wm_scsi2_set_volume(d, left, right)); } /* * Read the initial volume from the drive, if available. Each channel * ranges from 0 to 100, with -1 indicating data not available. */ int gen_get_volume(d, left, right) struct wm_drive *d; int *left, *right; { return (wm_scsi2_get_volume(d, left, right)); } /* * Pause the CD. */ int gen_pause(d) struct wm_drive *d; { return (wm_scsi2_pause(d)); } /* * Resume playing the CD (assuming it was paused.) */ int gen_resume(d) struct wm_drive *d; { return (wm_scsi2_resume(d)); } /* * Stop the CD. */ int gen_stop(d) struct wm_drive *d; { return (wm_scsi2_stop(d)); } /* * Play the CD from one position to another (both in frames.) */ int gen_play(d, start, end) struct wm_drive *d; int start, end; { return (wm_scsi2_play(d, start, end)); } /* * Eject the current CD, if there is one. */ int gen_eject(struct wm_drive *d) { return (wm_scsi2_eject(d)); } /* gen_eject() */ /* * Close the tray. * please review scsi.c / wm_scsi2_closetray() * and send changes to milliByte@DeathsDoor.com */ int gen_closetray( struct wm_drive *d ) { return(wm_scsi2_closetray(d)); } /* gen_closetray() */ static int create_cdrom_node(char *dev_name) { char pass_through[100]; int file_des; dev_t pass_thru_device; int err; int ccode; strcpy(pass_through, dev_name); strcat(pass_through, "p" ); if (setreuid(-1,0) < 0) { perror("setregid/setreuid/access"); exit(1); } ccode = access(pass_through, F_OK); if (ccode < 0) { if ((file_des = open(dev_name, O_RDONLY)) < 0) { perror("open cdrom devices failed"); return -1; } if (ioctl(file_des, B_GETDEV, &pass_thru_device) < 0) { perror("Call to get pass-through device number failed"); return -1; } (void)close(file_des); if (mknod(pass_through, (S_IFCHR | S_IREAD | S_IWRITE), pass_thru_device) < 0) { perror("Unable to make pass-through node"); return -1; } if (chown(pass_through, 0 , 0) < 0) { perror("chown"); return -1; } if (chmod(pass_through, 0660 ) < 0) { perror("chmod"); return -1; } } file_des = open( pass_through, O_RDWR); err = errno; if ( (setreuid(-1,getuid()) < 0) || (setregid(-1,getgid()) < 0) ) { perror("setreuid/setregid"); exit(1); } errno = err; return file_des; } /* * Open the CD and figure out which kind of drive is attached. */ int wmcd_open(d) struct wm_drive *d; { int fd, flag = 1; static int warned = 0; char vendor[32] = WM_STR_GENVENDOR; char model[32] = WM_STR_GENMODEL; char rev[32] = WM_STR_GENREV; if (d->fd >= 0) /* Device already open? */ return (0); if (cd_device == NULL) cd_device = DEFAULT_CD_DEVICE; d->fd = create_cdrom_node(cd_device); /* this will do open */ if (d->fd < 0) { if (errno == EACCES) { if (! warned) { fprintf(stderr,"Cannot access %s\n",cd_device); warned++; } } else if (errno != EINTR) { perror(cd_device); exit(1); } /* No CD in drive. (Is this true also for svr4 ? XXX ) */ return (1); } if (warned) { warned = 0; fprintf(stderr, "Thank you.\n"); } /* Now fill in the relevant parts of the wm_drive structure. */ fd = d->fd; if (wm_scsi_get_drive_type(d, vendor, model, rev) < 0) { perror("Cannot inquiry drive for it's type"); exit(1); } *d = *(find_drive_struct(vendor, model, rev)); wm_drive_settype(vendor, model, rev); d->fd = fd; return (0); } /* wmcd_open() */ /* * Re-Open the device if it is open. */ int wmcd_reopen( struct wm_drive *d ) { int status; do { wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "wmcd_reopen "); if (d->fd >= 0) /* Device really open? */ { wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "closes the device and "); status = close( d->fd ); /* close it! */ /* we know, that the file is closed, do we? */ d->fd = -1; } wm_susleep( 1000 ); wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "calls wmcd_open()\n"); status = wmcd_open( d ); /* open it as usual */ wm_susleep( 1000 ); } while ( status != 0 ); return status; } /* wmcd_reopen() */ /* * Send a SCSI command out the bus. */ int wm_scsi(d, xcdb, cdblen, retbuf, retbuflen, getreply) struct wm_drive *d; unsigned char *xcdb; int cdblen; int getreply; char *retbuf; int retbuflen; { int ccode; int file_des = d->fd; int i,j; unsigned char sense_buffer[ SENSE_SZ ]; int errno_save; /* getreply == 1 is read, == 0 is write */ struct sb sb; struct scs scs; sb.sb_type = ISCB_TYPE; sb.SCB.sc_comp_code = SDI_PROGRES; sb.SCB.sc_int = NULL; sb.SCB.sc_wd = 0; sb.SCB.sc_dev.sa_major = 0; sb.SCB.sc_dev.sa_minor = 0; sb.SCB.sc_dev.sa_lun = 0; sb.SCB.sc_dev.sa_exlun = 0; sb.SCB.sc_status = 0; sb.SCB.sc_link = (struct sb *) NULL; sb.SCB.sc_resid = 0; sb.SCB.sc_cmdpt = (void *)xcdb; sb.SCB.sc_cmdsz = cdblen; sb.SCB.sc_datapt = retbuf ; sb.SCB.sc_datasz = retbuflen ; if (getreply == 1) sb.SCB.sc_mode = SCB_READ; else sb.SCB.sc_mode = SCB_WRITE; sb.SCB.sc_time = 500; ccode = ioctl(file_des, SDI_SEND, &sb); if ( (sb.SCB.sc_comp_code != 0xd000000e ) || ( sb.SCB.sc_status != 02) ) return ccode; errno_save = errno; sb.SCB.sc_comp_code = SDI_PROGRES; sb.SCB.sc_int = NULL; sb.SCB.sc_wd = 0; sb.SCB.sc_dev.sa_major = 0; sb.SCB.sc_dev.sa_minor = 0; sb.SCB.sc_dev.sa_lun = 0; sb.SCB.sc_dev.sa_exlun = 0; sb.SCB.sc_status = 0; sb.SCB.sc_link = (struct sb *) NULL; sb.SCB.sc_resid = 0; scs.ss_op = SS_REQSEN; scs.ss_lun = 0; scs.ss_addr1 = 0; scs.ss_addr = 0; scs.ss_len = SENSE_SZ; scs.ss_cont = 0; sb.SCB.sc_cmdpt = SCS_AD(&scs); sb.SCB.sc_cmdsz = SCS_SZ; sb.SCB.sc_datapt = sense_buffer; sb.SCB.sc_datasz = 18; sb.SCB.sc_mode = SCB_READ; sb.SCB.sc_time = 5000; if (ioctl(file_des, SDI_SEND, &sb) < 0) { fprintf(stderr,"Cannot read sense.\n"); exit(-1); } errno=errno_save; return -1; } #endif ascd-0.13.2.orig/libworkman/plat_sun_audio.c0100644000175000017500000002644006670435231020316 0ustar hallonhallon/* * $Id: plat_sun_audio.c,v 1.3 1999/03/07 08:36:41 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * Sun (really Solaris) digital audio functions. */ #include "include/wm_config.h" #if defined(sun) && defined(SYSV) && defined(BUILD_CDDA) static char plat_sun_audio_id[] = "$Id: plat_sun_audio.c,v 1.3 1999/03/07 08:36:41 dirk Exp $"; #include "include/wm_cdda.h" /* types.h included by wmcdda.h */ #include #include #include #include #include #include #include #include #include #define WM_MSG_CLASS WM_MSG_CLASS_PLATFORM /* * Since there's a lag time between writing audio to the audio device and * hearing it, we need to make sure the status indicators correlate to what's * playing out the speaker. Luckily, Solaris gives us some audio * synchronization facilities that make this pretty easy. * * We maintain a circular queue of status information. When we write some * sound to the audio device, we put its status info into the queue. We write * a marker into the audio stream; when the audio device driver encounters the * marker, it increments a field in a status structure. When we see that * field go up, we grab the next status structure from the queue and send it * to the parent process. * * The minimum size of the queue depends on the latency of the audio stream. */ #define QSIZE 500 struct cdda_block queue[QSIZE]; int qtail; int qstart; /* * We only send WMCDDA_PLAYED status messages upstream when the CD is supposed * to be playing; this is used to keep track. */ extern int playing; static int aufd, aucfd; static int raw_audio = 1; /* Can /dev/audio take 44.1KHz stereo? */ /* * For fast linear-to-ulaw mapping, we use a lookup table that's generated * at startup. */ unsigned char *ulawmap, linear_to_ulaw(); char *getenv(); /* * Dummy signal handler so writes to /dev/audio will interrupt. */ static void dummy( void ) { signal(SIGALRM, dummy); } /* * Initialize the audio device. */ void wmaudio_init( void ) { audio_info_t info; char *audiodev, *acdev; int linval; audiodev = getenv("AUDIODEV"); if (audiodev == NULL) audiodev = "/dev/audio"; acdev = malloc(strlen(audiodev) + 4); if (acdev == NULL) { perror("Can't allocate audio control filename"); exit(1); } strcpy(acdev, audiodev); strcat(acdev, "ctl"); aucfd = open(acdev, O_WRONLY, 0); if (aucfd < 0) { perror(acdev); exit(1); } free(acdev); aufd = open(audiodev, O_WRONLY, 0); if (aufd < 0) { perror(audiodev); exit(1); } signal(SIGALRM, dummy); /* * Try to set the device to CD-style audio; we can process it * with the least CPU overhead. */ AUDIO_INITINFO(&info); info.play.sample_rate = 44100; info.play.channels = 2; info.play.precision = 16; info.play.encoding = AUDIO_ENCODING_LINEAR; info.play.pause = 0; info.record.pause = 0; info.monitor_gain = 0; if (ioctl(aufd, AUDIO_SETINFO, &info) < 0) if (errno == EINVAL) { /* * Oh well, so much for that idea. */ AUDIO_INITINFO(&info); info.play.sample_rate = 8000; info.play.channels = 1; info.play.precision = 8; info.play.encoding = AUDIO_ENCODING_ULAW; info.play.pause = 0; info.record.pause = 0; info.monitor_gain = 0; if (ioctl(aufd, AUDIO_SETINFO, &info) < 0) { perror("Can't set up audio device"); exit(1); } /* * Initialize the linear-to-ulaw mapping table. */ if (ulawmap == NULL) ulawmap = malloc(65536); if (ulawmap == NULL) { perror("malloc"); exit(1); } for (linval = 0; linval < 65536; linval++) ulawmap[linval] = linear_to_ulaw(linval-32768); ulawmap += 32768; raw_audio = 0; } else { perror(audiodev); exit(1); } } /* * Get ready to play some sound. */ void wmaudio_ready( void ) { audio_info_t info; /* * Start at the correct queue position. */ if (ioctl(aucfd, AUDIO_GETINFO, &info) < 0) perror("AUDIO_GETINFO"); qtail = info.play.eof % QSIZE; qstart = qtail; queue[qtail].status = WMCDDA_OK; } /* * Stop the audio immediately. */ void wmaudio_stop( void ) { if (ioctl(aufd, I_FLUSH, FLUSHRW) < 0) perror("flush"); } /* * Close the audio device. */ void wmaudio_close( void ) { wmaudio_stop(); close(aufd); close(aucfd); } /* * Set the volume level. */ void wmaudio_volume(int level) { audio_info_t info; AUDIO_INITINFO(&info); if (ioctl(aucfd, AUDIO_GETINFO, &info) < 0) perror("AUDIO_GETINFO"); info.play.gain = level; if (ioctl(aucfd, AUDIO_SETINFO, &info) < 0) perror("AUDIO_SETINFO"); } /* * Set the balance level. */ void wmaudio_balance(int level) { audio_info_t info; AUDIO_INITINFO(&info); if (ioctl(aucfd, AUDIO_GETINFO, &info) < 0) perror("AUDIO_GETINFO"); level *= AUDIO_RIGHT_BALANCE; info.play.balance = level / 255; if (ioctl(aucfd, AUDIO_SETINFO, &info) < 0) perror("AUDIO_SETINFO"); } /* * Mark the most recent audio block on the queue as the last one. */ void wmaudio_mark_last( void ) { queue[qtail].status = WMCDDA_DONE; } /* * Figure out the most recent status information and send it upstream. */ int wmaudio_send_status( void ) { audio_info_t info; int qhead; /* * Now send the most current status information to our parent. */ if (ioctl(aucfd, AUDIO_GETINFO, &info) < 0) perror("AUDIO_GETINFO"); qhead = info.play.eof % QSIZE; if (qhead != qstart && playing) { int balance; if (queue[qhead].status != WMCDDA_DONE) queue[qhead].status = WMCDDA_PLAYED; queue[qhead].volume = info.play.gain; queue[qhead].balance = (info.play.balance * 255) / AUDIO_RIGHT_BALANCE; send_status(queue + qhead); qstart = -1; } return (queue[qhead].status == WMCDDA_DONE); } /* * Play some audio and pass a status message upstream, if applicable. * Returns 0 on success. */ int wmaudio_play(unsigned char *rawbuf, long buflen, struct cdda_block *blk) { int i; short *buf16; int alarmcount = 0; struct itimerval it; alarm(1); while (write(aufd, rawbuf, buflen) <= 0) if (errno == EINTR) { if (! raw_audio && alarmcount++ < 5) { /* * 8KHz /dev/audio blocks for several seconds * waiting for its queue to drop below a low * water mark. */ wmaudio_send_status(); timerclear(&it.it_interval); timerclear(&it.it_value); it.it_value.tv_usec = 500000; setitimer(ITIMER_REAL, &it, NULL); continue; } /* close(aufd); close(aucfd); wmaudio_init(); */ wmaudio_stop(); alarm(2); continue; } else { blk->status = WMCDDA_ERROR; return (-1); } alarm(0); /* * Mark this spot in the audio stream. * * Marks don't always succeed (if the audio buffer is empty * this call will block forever) so do it asynchronously. */ fcntl(aufd, F_SETFL, O_NONBLOCK); if (write(aufd, rawbuf, 0) < 0) { if (errno != EAGAIN) perror("audio mark"); } else qtail = (qtail + 1) % QSIZE; fcntl(aufd, F_SETFL, 0); queue[qtail] = *blk; if (wmaudio_send_status() < 0) return (-1); else return (0); } /* * Get the current audio state. */ void wmaudio_state(struct cdda_block *blk) { audio_info_t info; int balance; if (ioctl(aucfd, AUDIO_GETINFO, &info) < 0) perror("AUDIO_GETINFO"); blk->volume = info.play.gain; blk->balance = (info.play.balance * 255) / AUDIO_RIGHT_BALANCE; } /* ** This routine converts from linear to ulaw. ** ** Craig Reese: IDA/Supercomputing Research Center ** Joe Campbell: Department of Defense ** 29 September 1989 ** ** References: ** 1) CCITT Recommendation G.711 (very difficult to follow) ** 2) "A New Digital Technique for Implementation of Any ** Continuous PCM Companding Law," Villeret, Michel, ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1, ** 1973, pg. 11.12-11.17 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards ** for Analog-to_Digital Conversion Techniques," ** 17 February 1987 ** ** Input: Signed 16 bit linear sample ** Output: 8 bit ulaw sample */ #define ZEROTRAP /* turn on the trap as per the MIL-STD */ #define BIAS 0x84 /* define the add-in bias for 16 bit samples */ #define CLIP 32635 unsigned char linear_to_ulaw( sample ) int sample; { static int exp_lut[256] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3, 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7}; int sign, exponent, mantissa; unsigned char ulawbyte; /* Get the sample into sign-magnitude. */ sign = (sample >> 8) & 0x80; /* set aside the sign */ if ( sign != 0 ) sample = -sample; /* get magnitude */ if ( sample > CLIP ) sample = CLIP; /* clip the magnitude */ /* Convert from 16 bit linear to ulaw. */ sample = sample + BIAS; exponent = exp_lut[( sample >> 7 ) & 0xFF]; mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F; ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa ); #ifdef ZEROTRAP if ( ulawbyte == 0 ) ulawbyte = 0x02; /* optional CCITT trap */ #endif return ulawbyte; } /* * Downsample a block of CDDA data, if necessary, for playing out an old-style * audio device. */ long wmaudio_convert(unsigned char *rawbuf, long buflen, struct cdda_block *blk) { short *buf16 = (short *)rawbuf; int i, j, samples; int mono_value; unsigned char *rbend = rawbuf + buflen; /* Don't do anything if the audio device can take the raw values. */ if (raw_audio) return (buflen); for (i = 0; buf16 < (short *)(rbend); i++) { /* Downsampling to 8KHz is a little irregular. */ samples = (i & 1) ? ((i % 20) ? 10 : 12) : 12; /* And unfortunately, we don't always end on a nice boundary. */ if (buf16 + samples > (short *)(rbend)) samples = ((short *)rbend) - buf16; /* * No need to average all the values; taking the first one * is sufficient and less CPU-intensive. But we do need to * do both channels. */ mono_value = (buf16[0] + buf16[1]) / 2; buf16 += samples; rawbuf[i] = ulawmap[mono_value]; } return (i); } #endif /* ... && BUILD_CDDA */ ascd-0.13.2.orig/libworkman/plat_sun_cdda.c0100644000175000017500000002055506670435231020111 0ustar hallonhallon/* * $Id: plat_sun_cdda.c,v 1.3 1999/03/07 08:36:41 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * Sun (really Solaris) CDDA functions. */ #include "include/wm_config.h" #if defined(sun) && defined(SYSV) && defined(BUILD_CDDA) /* { */ static char plat_sun_cdda_id[] = "$Id: plat_sun_cdda.c,v 1.3 1999/03/07 08:36:41 dirk Exp $"; #include "include/wm_cdda.h" /* types.h and cdio.h are included by wmcdda.h */ #include #include #include #include #include #define WM_MSG_CLASS WM_MSG_CLASS_PLATFORM #define CDDABLKSIZE 2368 #define SAMPLES_PER_BLK 588 /* Address of next block to read. */ int current_position = 0; /* Address of first and last blocks to read. */ int starting_position = 0; int ending_position = 0; /* Playback direction. */ int direction = 1; /* Number of blocks to read at once; initialize to the maximum. */ /* (was 30. Set to 15 for INTeL. Maybe config option? */ int numblocks = 15; /* * This is the fastest way to convert from BCD to 8-bit. */ unsigned char unbcd[256] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0,0,0,0,0,0, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0,0,0,0,0,0, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 0,0,0,0,0,0, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 0,0,0,0,0,0, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 0,0,0,0,0,0, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 0,0,0,0,0,0, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 0,0,0,0,0,0, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 0,0,0,0,0,0, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 0,0,0,0,0,0, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; /* * Initialize the CDDA data buffer and open the appropriate device. * * NOTE: We allocate twice as much space as we need to actually read a block; * this lets us do audio manipulations without bothering to malloc a second * buffer. * * Also, test to see if we can actually *do* CDDA on this drive; if not, we * need to exit right away so the UI doesn't show the user any CDDA controls. */ int wmcdda_init(char **bufadr, long *buflenadr, int init_fd, char *devname) { struct cdrom_cdda cdda; *bufadr = malloc(numblocks * CDDABLKSIZE * 2); if (*bufadr == NULL) return (-1); *buflenadr = numblocks * CDDABLKSIZE; /*init_fd = open(devname, 0); if (init_fd == -1) init_fd = open("/dev/rdsk/c0t6d0s2", 0); */ init_fd = wmcdda_open(devname); if (init_fd > -1) { cdda.cdda_addr = 200; cdda.cdda_length = 1; cdda.cdda_data = *bufadr; cdda.cdda_subcode = CDROM_DA_SUBQ; if (ioctl(init_fd, CDROMCDDA, &cdda) < 0) { close(init_fd); init_fd = -1; } } return (init_fd); } /* * Try to open the CD device */ int wmcdda_open(char *devname) { int fd; fd = open(devname, 0); if (fd == -1) fd = open("/dev/rdsk/c0t6d0s2", 0); return(fd); } /* * Close the CD-ROM device in preparation for exiting. */ void wmcdda_close(int fd) { close(fd); } /* * Set up for playing the CD. Actually this doesn't play a thing, just sets a * couple variables so we'll know what to do when we're called. */ void wmcdda_setup(int start, int end, int realstart) { current_position = start - 150; ending_position = end - 150; starting_position = realstart - 150; /* * Special case: don't start at the "end" of a track if we're * playing backwards! */ if (direction == -1 && start == realstart) current_position = ending_position - numblocks; } /* * Read some blocks from the CD. Stop if we hit the end of the current region. * * Returns number of bytes read, -1 on error, 0 if stopped for a benign reason. */ long wmcdda_read(int fd, unsigned char *rawbuf, long buflen, struct cdda_block *block) { struct cdrom_cdda cdda; int blk; unsigned char *q; extern int speed; if ((direction > 0 && current_position >= ending_position) || (direction < 0 && current_position < starting_position)) { block->status = WMCDDA_DONE; return (0); } cdda.cdda_addr = current_position; if (ending_position && current_position + numblocks > ending_position) cdda.cdda_length = ending_position - current_position; else cdda.cdda_length = numblocks; cdda.cdda_data = rawbuf; cdda.cdda_subcode = CDROM_DA_SUBQ; if (ioctl(fd, CDROMCDDA, &cdda) < 0) { if (errno == ENXIO) /* CD ejected! */ { block->status = WMCDDA_EJECTED; return (-1); } if (current_position + numblocks > ending_position) { /* * Hit the end of the CD, probably. */ block->status = WMCDDA_DONE; return (0); } /* Sometimes it fails once, dunno why */ if (ioctl(fd, CDROMCDDA, &cdda) < 0) { if (ioctl(fd, CDROMCDDA, &cdda) < 0) { if (ioctl(fd, CDROMCDDA, &cdda) < 0) { perror("CDROMCDDA"); block->status = WMCDDA_ERROR; return (-1); } } } } if (speed > 148) { /* * We want speed=148 to advance by cdda_length, but * speed=256 to advance cdda_length * 4. */ current_position = current_position + (cdda.cdda_length * direction * (speed - 112)) / 36; } else current_position = current_position + cdda.cdda_length * direction; for (blk = 0; blk < numblocks; blk++) { /* * New valid Q-subchannel information? Update the block * status. */ q = &rawbuf[blk * CDDABLKSIZE + SAMPLES_PER_BLK * 4]; if (*q == 1) { block->status = WMCDDA_OK; block->track = unbcd[q[1]]; block->index = unbcd[q[2]]; block->minute = unbcd[q[7]]; block->second = unbcd[q[8]]; block->frame = unbcd[q[9]]; } } return (cdda.cdda_length * CDDABLKSIZE); } /* * Normalize a bunch of CDDA data. Basically this means ripping out the * Q subchannel data and doing byte-swapping, since the CD audio is in * littleendian format. * * Scanning is handled here too. * * XXX - do byte swapping on Intel boxes? */ long wmcdda_normalize(unsigned char *rawbuf, long buflen, struct cdda_block *block) { int i, nextq; int blocks = buflen / CDDABLKSIZE; unsigned char *dest = rawbuf; unsigned char tmp; long *buf32 = (long *)rawbuf, tmp32; /* * this was #ifndef LITTLEENDIAN * in wmcdda it was called LITTLE_ENDIAN. Was this a flaw? */ #if WM_BIG_ENDIAN if (blocks--) for (i = 0; i < SAMPLES_PER_BLK * 2; i++) { /* Only need to use temp buffer on first block. */ tmp = *rawbuf++; *dest++ = *rawbuf++; *dest++ = tmp; } #endif while (blocks--) { /* Skip over Q data. */ rawbuf += 16; for (i = 0; i < SAMPLES_PER_BLK * 2; i++) { #if WM_LITTLE_ENDIAN *dest++ = *rawbuf++; *dest++ = *rawbuf++; #else *dest++ = rawbuf[1]; *dest++ = rawbuf[0]; rawbuf += 2; #endif } } buflen -= ((buflen / CDDABLKSIZE) * 16); /* * Reverse the data here if we're playing backwards. * XXX - ideally this should be done above. */ if (direction < 0) { buflen /= 4; /* we can move 32 bits at a time. */ for (i = 0; i < buflen / 2; i++) { tmp32 = buf32[i]; buf32[i] = buf32[buflen - i - 1]; buf32[buflen - i - 1] = tmp32; } buflen *= 4; } return (buflen); } /* * Set the playback direction. */ void wmcdda_direction(int newdir) { if (newdir == 0) { numblocks = 20; direction = 1; } else { numblocks = 30; direction = -1; } } /* * Do system-specific stuff to get ready to play at a particular speed. */ void wmcdda_speed(int speed) { if (speed > 128) numblocks = 12; else numblocks = direction > 0 ? 20 : 30; } #endif /* } */ ascd-0.13.2.orig/libworkman/plat_ultrix.c0100644000175000017500000003546006670435231017661 0ustar hallonhallon/* * $Id: plat_ultrix.c,v 1.6 1999/03/07 08:36:41 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * ULTRIX 4.2 drive control routines. */ #if defined(ultrix) || defined(__ultrix) static char plat_ultrix_id[] = "$Id: plat_ultrix.c,v 1.6 1999/03/07 08:36:41 dirk Exp $"; #include #include #include #include #include #include #include #include #include #include #include #include "include/wm_config.h" #include "include/wm_struct.h" #define WM_MSG_CLASS WM_MSG_CLASS_PLATFORM /* * This structure will be filled with the TOC header and all entries. * Ultrix doesn't seem to allow getting single TOC entries. * - Chris Ross (cross@eng.umd.edu) */ struct cd_toc_header_and_entries { struct cd_toc_header cdth; struct cd_toc_entry cdte[CDROM_MAX_TRACK+1]; }; void *malloc(); char *strchr(); int min_volume = 128; int max_volume = 255; extern char *cd_device; /* * find_cdrom * * Determine the name of the CD-ROM device. * * Read through the boot records (via a call to uerf) and find the SCSI * address of the CD-ROM. If the "CDROM" environment variable is set, * use that instead. */ void find_cdrom() { char *data, *fgetline(); FILE *uerf; int fds[2]; int pid; if ((cd_device = getenv("CDROM")) != NULL) return; pipe(fds); if ((pid = fork()) == 0) { close(fds[0]); dup2(fds[1], 1); execl("/etc/uerf", "uerf", "-R", "-r", "300", NULL); execl("/usr/sbin/uerf", "uerf", "-R", "-r", "300", NULL); _exit(1); } else if (pid < 0) { perror("fork"); exit(1); } close(fds[1]); uerf = fdopen(fds[0], "r"); while (data = fgetline(uerf)) if (strstr(data, "RRD42")) { char *device; cd_device = (char *)malloc(sizeof("/dev/rrz##c")); strcpy(cd_device, "/dev/r"); device = strstr(data, "rz"); device[(int)(strchr(device, ' ') - device)] = '\0'; strcat(cd_device, device); strcat(cd_device, "c"); break; } fclose(uerf); if (cd_device == NULL) { fprintf(stderr, "No cdrom (RRD42) is installed on this system\n"); exit(1); } kill(pid, 15); (void)wait((int *)NULL); } /* * Initialize the drive. A no-op for the generic driver. */ int gen_init(d) struct wm_drive *d; { return (0); } /* * Get the number of tracks on the CD. */ int gen_get_trackcount(d, tracks) struct wm_drive *d; int *tracks; { struct cd_toc_header hdr; if (ioctl(d->fd, CDROM_TOC_HEADER, &hdr)) return (-1); *tracks = hdr.th_ending_track; return (0); } /* * Get the start time and mode (data or audio) of a track. * * XXX - this should get cached, but that means keeping track of ejects. */ int gen_get_trackinfo(d, track, data, startframe) struct wm_drive *d; int track, *data, *startframe; { struct cd_toc toc; struct cd_toc_header hdr; struct cd_toc_header_and_entries toc_buffer; if (ioctl(d->fd, CDROM_TOC_HEADER, &hdr)) return (-1); bzero((char *)&toc_buffer, sizeof(toc_buffer)); toc.toc_address_format = CDROM_MSF_FORMAT; toc.toc_starting_track = 0; toc.toc_alloc_length = (u_short)(((hdr.th_data_len1 << 8) + hdr.th_data_len0) & 0xfff) + 2; toc.toc_buffer = (caddr_t)&toc_buffer; if (ioctl(d->fd, CDROM_TOC_ENTRYS, &toc)) return (-1); if (track == 0) track = hdr.th_ending_track + 1; *data = (toc_buffer.cdte[track-1].te_control & CDROM_DATA_TRACK) ? 1:0; *startframe = toc_buffer.cdte[track - 1].te_absaddr.msf.m_units*60*75 + toc_buffer.cdte[track - 1].te_absaddr.msf.s_units * 75 + toc_buffer.cdte[track - 1].te_absaddr.msf.f_units; return (0); } /* * Get the number of frames on the CD. */ int gen_get_cdlen(d, frames) struct wm_drive *d; int *frames; { int tmp; return (gen_get_trackinfo(d, 0, &tmp, frames)); } /* * Get the current status of the drive: the current play mode, the absolute * position from start of disc (in frames), and the current track and index * numbers if the CD is playing or paused. */ int gen_get_drive_status(d, oldmode, mode, pos, track, index) struct wm_drive *d; enum wm_cd_modes oldmode, *mode; int *pos, *track, *index; { struct cd_sub_channel sc; struct cd_subc_channel_data scd; /* If we can't get status, the CD is ejected, so default to that. */ *mode = WM_CDM_EJECTED; sc.sch_address_format = CDROM_MSF_FORMAT; sc.sch_data_format = CDROM_CURRENT_POSITION; sc.sch_track_number = 0; sc.sch_alloc_length = sizeof(scd); sc.sch_buffer = (caddr_t)&scd; /* Is the device open? */ if (d->fd < 0) { switch (wmcd_open(d)) { case -1: /* error */ return (-1); case 1: /* retry */ return (0); } } if (ioctl(d->fd, CDROM_READ_SUBCHANNEL, &sc)) return (0); /* ejected */ switch (scd.scd_header.sh_audio_status) { case AS_PLAY_IN_PROGRESS: *mode = WM_CDM_PLAYING; dopos: *pos = scd.scd_position_data.scp_absaddr.msf.m_units * 60 * 75 + scd.scd_position_data.scp_absaddr.msf.s_units * 75 + scd.scd_position_data.scp_absaddr.msf.f_units; *track = scd.scd_position_data.scp_track_number; *index = scd.scd_position_data.scp_index_number; break; case AS_PLAY_PAUSED: if (oldmode == WM_CDM_PLAYING || oldmode == WM_CDM_PAUSED) { *mode = WM_CDM_PAUSED; goto dopos; } else *mode = WM_CDM_STOPPED; break; case AS_PLAY_COMPLETED: *mode = WM_CDM_TRACK_DONE; /* waiting for next track. */ break; case AS_NO_STATUS: *mode = WM_CDM_STOPPED; break; } return (0); } /* * scale_volume(vol, max) * * Return a volume value suitable for passing to the CD-ROM drive. "vol" * is a volume slider setting; "max" is the slider's maximum value. * * On Sun and DEC CD-ROM drives, the amount of sound coming out the jack * increases much faster toward the top end of the volume scale than it * does at the bottom. To make up for this, we make the volume scale look * sort of logarithmic (actually an upside-down inverse square curve) so * that the volume value passed to the drive changes less and less as you * approach the maximum slider setting. The actual formula looks like * * (max^2 - (max - vol)^2) * (max_volume - min_volume) * v = --------------------------------------------------- + min_volume * max^2 * * If your system's volume settings aren't broken in this way, something * like the following should work: * * return ((vol * (max_volume - min_volume)) / max + min_volume); */ scale_volume(vol, max) int vol, max; { return ((max * max - (max - vol) * (max - vol)) * (max_volume - min_volume) / (max * max) + min_volume); } /* * Set the volume level for the left and right channels. Their values * range from 0 to 100. */ int gen_set_volume(d, left, right) struct wm_drive *d; int left, right; { struct cd_playback pb; struct cd_playback_status ps; struct cd_playback_control pc; left = scale_volume(left, 100); right = scale_volume(right, 100); bzero((char *)&pb, sizeof(pb)); bzero((char *)&ps, sizeof(ps)); bzero((char *)&pc, sizeof(pc)); pb.pb_alloc_length = sizeof(ps); pb.pb_buffer = (caddr_t)&ps; if (ioctl(d->fd, CDROM_PLAYBACK_STATUS, &pb)) return (-1); pc.pc_chan0_select = ps.ps_chan0_select; pc.pc_chan0_volume = (left < CDROM_MIN_VOLUME) ? CDROM_MIN_VOLUME : (left > CDROM_MAX_VOLUME) ? CDROM_MAX_VOLUME : left; pc.pc_chan1_select = ps.ps_chan1_select; pc.pc_chan1_volume = (right < CDROM_MIN_VOLUME) ? CDROM_MIN_VOLUME : (right > CDROM_MAX_VOLUME) ? CDROM_MAX_VOLUME : right; pb.pb_alloc_length = sizeof(pc); pb.pb_buffer = (caddr_t)&pc; if (ioctl(d->fd, CDROM_PLAYBACK_CONTROL, &pb)) return (-1); return (0); } /* * Pause the CD. */ int gen_pause(d) struct wm_drive *d; { return (ioctl(d->fd, CDROM_PAUSE_PLAY)); } /* * Resume playing the CD (assuming it was paused.) */ int gen_resume(d) struct wm_drive *d; { return (ioctl(d->fd, CDROM_RESUME_PLAY)); } /* * Stop the CD. */ int gen_stop(d) struct wm_drive *d; { return (ioctl(d->fd, SCSI_STOP_UNIT)); } /* * Play the CD from one position to another (both in frames.) */ int gen_play(d, start, end) struct wm_drive *d; int start, end; { struct cd_play_audio_msf msf; msf.msf_starting_M_unit = start / (60*75); msf.msf_starting_S_unit = (start % (60*75)) / 75; msf.msf_starting_F_unit = start % 75; msf.msf_ending_M_unit = end / (60*75); msf.msf_ending_S_unit = (end % (60*75)) / 75; msf.msf_ending_F_unit = end % 75; if (ioctl(d->fd, SCSI_START_UNIT)) return (-1); if (ioctl(d->fd, CDROM_PLAY_MSF, &msf)) return (-2); return (0); } /* * Eject the current CD, if there is one. */ int gen_eject(struct wm_drive *d) { /* On some systems, we can check to see if the CD is mounted. */ struct stat stbuf; struct ustat ust; if (fstat(d->fd, &stbuf) != 0) return (-2); /* Is this a mounted filesystem? */ if (ustat(stbuf.st_rdev, &ust) == 0) return (-3); return (ioctl(d->fd, CDROM_EJECT_CADDY)); } /* gen_eject() */ /*----------------------------------------* * Close the CD tray * * Please edit and send changes to * milliByte@DeathsDoor.com *----------------------------------------*/ int gen_closetray(struct wm_drive *d) { #ifdef CAN_CLOSE if(!close(d->fd)) { d->fd=-1; return(wmcd_reopen(d)); } else { return(-1); } #else /* Always succeed if the drive can't close */ return(0); #endif /* CAN_CLOSE */ } /* gen_closetray() */ /* * unscale_volume(cd_vol, max) * * Given a value between min_volume and max_volume, return the volume slider * value needed to achieve that value. * * Rather than perform floating-point calculations to reverse the above * formula, we simply do a binary search of scale_volume()'s return values. */ static int unscale_volume(cd_vol, max) int cd_vol, max; { int vol = 0, top = max, bot = 0, scaled; while (bot <= top) { vol = (top + bot) / 2; scaled = scale_volume(vol, max); if (cd_vol == scaled) break; if (cd_vol < scaled) top = vol - 1; else bot = vol + 1; } if (vol < 0) vol = 0; else if (vol > max) vol = max; return (vol); } /* * Read the initial volume from the drive, if available. Each channel * ranges from 0 to 100, with -1 indicating data not available. */ int gen_get_volume(d, left, right) struct wm_drive *d; int *left, *right; { struct cd_playback pb; struct cd_playback_status ps; bzero((char *)&pb, sizeof(pb)); bzero((char *)&ps, sizeof(ps)); pb.pb_alloc_length = sizeof(ps); pb.pb_buffer = (caddr_t)&ps; if (d->fd >= 0) { if (ioctl(d->fd, CDROM_PLAYBACK_STATUS, &pb)) *left = *right = -1; else { *left = unscale_volume(ps.ps_chan0_volume, 100); *right = unscale_volume(ps.ps_chan1_volume, 100); } } else *left = *right = -1; return (0); } /* * Send an arbitrary SCSI command to a device. */ int wm_scsi(d, cdb, cdblen, retbuf, retbuflen, getreply) struct wm_drive *d; unsigned char *cdb; int cdblen; void *retbuf; int retbuflen; int getreply; { /* ULTRIX doesn't have a SCSI passthrough interface, does it? */ return (-1); } /* * fgetline() * * Simulate fgets, but joining continued lines in the output of uerf. */ #define BUF_SIZE 85 /* Max length of a (real) line */ char * fgetline(fp) FILE *fp; { static char *retval = NULL; static char holdbuf[BUF_SIZE + 1]; char tmp[BUF_SIZE + 1]; char *stmp; if (!retval) { retval = malloc(BUF_SIZE * 3); /* 3 lines can be joined */ if (!retval) return(NULL); else *retval = '\0'; } if (*holdbuf) { strcpy(retval, holdbuf); retval[strlen(retval)-1] = '\0'; memset(holdbuf, 0, BUF_SIZE+1); } while (fgets(tmp, BUF_SIZE, fp)) { stmp = tmp + strspn(tmp, " \t"); if (*stmp == '_') { /* Continuation line */ retval[strlen(retval)-1] = '\0'; /* Trim off C/R */ strcat(retval, stmp+1); } else { if (*retval) { strcpy(holdbuf, tmp); holdbuf[strlen(holdbuf)-1] = -1; return retval; } else { /* First line read, keep reading */ strcat(retval, stmp); retval[strlen(retval)-1] = '\0'; } } } return NULL; } /* * Open the CD device and figure out what kind of drive is attached. */ int wmcd_open(d) struct wm_drive *d; { int fd; static int warned = 0; if (d->fd >= 0) /* Device already open? */ return (0); if (cd_device == NULL) find_cdrom(); d->fd = open(cd_device, 0); if (d->fd < 0) { if (errno == EACCES) { if (!warned) { fprintf(stderr, "As root, please run\n\nchmod 666 %s\n\n%s\n", cd_device, "to give yourself permission to access the CD-ROM device."); warned++; } } else if (errno != EINTR) { perror(cd_device); exit(1); } /* No CD in drive. */ return (1); } if (warned) { warned = 0; fprintf(stderr, "Thank you.\n"); } /* Now fill in the relevant parts of the wm_drive structure. */ fd = d->fd; *d = *(find_drive_struct("", "", "")); d->fd = fd; (d->init)(d); return (0); } /* wmcd_open() */ /* * Re-Open the device if it is open. */ int wmcd_reopen( struct wm_drive *d ) { int status; do { wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "wmcd_reopen "); if (d->fd >= 0) /* Device really open? */ { wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "closes the device and "); status = close( d->fd ); /* close it! */ /* we know, that the file is closed, do we? */ d->fd = -1; } wm_susleep( 1000 ); wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "calls wmcd_open()\n"); status = wmcd_open( d ); /* open it as usual */ wm_susleep( 1000 ); } while ( status != 0 ); return status; } /* wmcd_reopen() */ #endif ascd-0.13.2.orig/libworkman/wm_helpers.c0100644000175000017500000001145006670435231017450 0ustar hallonhallon/* * $Id: wm_helpers.c,v 1.7 1999/03/07 08:36:41 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * Some helpful functions... * */ static char wm_helpers_id[] = "$Id: wm_helpers.c,v 1.7 1999/03/07 08:36:41 dirk Exp $"; #include #include #include #include #include #include #include "include/workman_defs.h" #include "include/wm_config.h" #include "include/wm_helpers.h" #include "include/wm_struct.h" int wm_lib_verbosity = WM_MSG_LEVEL_NONE; /* * Some seleced functions of version reporting follow... */ int wm_libver_major( void ){return WM_LIBVER_MAJOR;} int wm_libver_minor( void ){return WM_LIBVER_MINOR;} int wm_libver_pl( void ){return WM_LIBVER_PL;} char *wm_libver_name( void ) { char *s = NULL; wm_strmcat(&s, WM_LIBVER_NAME); return s; } /* wm_libver_name() */ char *wm_libver_number( void ) { char *s = NULL; s = malloc(10); /* this is not used very often, so don't care about speed...*/ sprintf(s, "%d.%d.%d", wm_libver_major(), wm_libver_minor(), wm_libver_pl()); return s; } /* wm_libver_number() */ char *wm_libver_date( void ) { char *s = NULL; wm_strmcat(&s, __DATE__); return s; } /* wm_libver_date() */ char *wm_libver_string( void ) { char *s = NULL; wm_strmcat( &s, wm_libver_name() ); wm_strmcat( &s, " " ); wm_strmcat( &s, wm_libver_number() ); return s; } /* wm_libver_string() */ /* * * Now for some memory management... * */ /* Free some memory and set a pointer to null. */ void freeup( char **x ) { if (*x != NULL) { free(*x); *x = NULL; } } /* freeup() */ /* Copy into a malloced string. */ void wm_strmcpy( char **t, char *s ) { if (*t != NULL) free(*t); *t = malloc(strlen(s) + 1); if (*t == NULL) { perror("wm_strmcpy"); exit(1); } (void) strcpy(*t, s); } /* wm_strmcpy() */ /* Add to a malloced string. */ void wm_strmcat( char **t, char *s) { int len = strlen(s) + 1; if (*s == '\0') return; if (*t != NULL) { len += strlen(*t); *t = realloc(*t, len); if (*t == NULL) { perror("strmcat"); exit(1); } strcat(*t, s); } else wm_strmcpy(t, s); } /* wm_strmcat() */ /* Duplicate a string. Some systems have this in libc, but not all. */ char * wm_strdup( char *s ) { char *new; new = malloc(strlen(s) + 1); if (new) strcpy(new, s); return (new); } /* wm_strdup() */ /* * set and get verbosity level. */ void wm_lib_set_verbosity( int level ) { if( WM_MSG_LEVEL_NONE <= level <= WM_MSG_LEVEL_DEBUG ) { wm_lib_verbosity = level; } } /* wm_lib_set_verbosity */ int wm_lib_get_verbosity( void ) { return wm_lib_verbosity; } /* * wm_lib_message(). * * any message that falls into allowed classes and has at least * verbosity level wm_lib_verbosity & 0xf will be printed. * * Usage: * * wm_lib_message( WM_MSG_LEVEL | WM_MSG_CLASS, "format", contents); * * To simplify the usage, you may simply use WM_MSG_CLASS. It should be * defined in each module to reflect the correct message class. * */ void wm_lib_message( unsigned int level, char *fmt, ... ) { va_list ap; /* verbosity level */ unsigned int vlevel = wm_lib_verbosity & 0xf; /* allowed classes */ unsigned int vclass = (level & WM_MSG_CLASS_ALL) & (wm_lib_verbosity & WM_MSG_CLASS_ALL); /* * just give me the level */ level &= 0xf; if(level <= WM_MSG_LEVEL_NONE) { fprintf(stderr, "LibWorkMan warning: A LibWorkMan programmer specified an invalid message level.\n"); } /* * print it only if level and class are allowed. */ if( (level <= vlevel) && (vclass != 0) ) { va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); } } /* wm_lib_message() */ /* * Simulate usleep() using select(). */ int wm_susleep( int usec ) { struct timeval tv; timerclear(&tv); tv.tv_sec = usec / 1000000; tv.tv_usec = usec % 1000000; return (select(0, NULL, NULL, NULL, &tv)); } /* wm_susleep() */ ascd-0.13.2.orig/libworkman/cddb.c0100644000175000017500000002705106723164026016203 0ustar hallonhallon/* * $Id: cddb.c,v 1.2 1999/02/14 09:50:42 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * establish connection to cddb server and get data * socket stuff gotten from gnu port of the finger command * * provided by Sven Oliver Moll * */ static char cddb_id[] = "$Id: cddb.c,v 1.2 1999/02/14 09:50:42 dirk Exp $"; #include #include #include #include #include #include #include #include #include #include #include #include #include "include/wm_config.h" #include "include/wm_struct.h" #include "include/wm_cdinfo.h" #include "include/wm_helpers.h" /* * This is for identifying WorkMan at CDDB servers */ #define PROGRAM WORKMAN_NAME #define VERSION WORKMAN_VERSION struct wm_cddb cddb; int cur_cddb_protocol; char *cur_cddb_server; char *cur_cddb_mail_adress; char *cur_cddb_path_to_cgi; char *cur_cddb_proxy_server; int Socket; FILE *Connection; /* * */ void cddb_cur2struct(void) { cddb.protocol = cur_cddb_protocol; strcpy(cddb.cddb_server, cur_cddb_server); strcpy(cddb.mail_adress, cur_cddb_mail_adress); strcpy(cddb.path_to_cgi, cur_cddb_path_to_cgi); strcpy(cddb.proxy_server, cur_cddb_proxy_server); } /* cddb_cur2struct() */ /* * */ void cddb_struct2cur(void) { cur_cddb_protocol = cddb.protocol; cur_cddb_server = (cddb.cddb_server); cur_cddb_mail_adress = (cddb.mail_adress); cur_cddb_path_to_cgi = (cddb.path_to_cgi); cur_cddb_proxy_server = (cddb.proxy_server); } /* cddb_struct2cur() */ /* * Subroutine from cddb_discid */ int cddb_sum(int n) { char buf[12], *p; int ret = 0; /* For backward compatibility this algorithm must not change */ sprintf(buf, "%lu", (unsigned long)n); for (p = buf; *p != '\0'; p++) ret += (*p - '0'); return (ret); } /* cddb_sum() */ /* * Calculate the discid of a CD according to cddb */ unsigned long cddb_discid(void) { int i, t, n = 0; /* For backward compatibility this algorithm must not change */ for (i = 0; i < thiscd.ntracks; i++) { n += cddb_sum(thiscd.trk[i].start / 75); /* * Just for demonstration (See below) * * t += (thiscd.trk[i+1].start / 75) - * (thiscd.trk[i ].start / 75); */ } /* * Mathematics can be fun. Example: How to reduce a full loop to * a simple statement. The discid algorhythm is so half-hearted * developed that it doesn't even use the full 32bit range. * But it seems to be always this way: The bad standards will be * accepted, the good ones turned down. */ t = (thiscd.trk[thiscd.ntracks].start-thiscd.trk[0].start)/75; return ((n % 0xff) << 24 | t << 8 | thiscd.ntracks); } /* cddb_discid() */ /* * Split a string into two components according to the first occurance of * the delimiter. */ char * string_split(char *line, char delim) { char *p1; for (p1=line;*p1;p1++) { if(*p1 == delim) { *p1 = 0; return ++p1; } } return (NULL); } /* string_split() */ /* * Generate the hello string according to the cddb protocol * delimiter is either ' ' (cddbp) or '+' (http) */ void string_makehello(char *line,char delim) { char mail[84],*host; strcpy(mail,cddb.mail_adress); host=string_split(mail,'@'); sprintf(line,"%shello%c%s%c%s%c%s%c%s", delim == ' ' ? "cddb " : "&", delim == ' ' ? ' ' : '=', mail,delim, host,delim, PROGRAM,delim, VERSION); } /* string_makehello() */ /* * Open the TCP connection to the cddb/proxy server */ int connect_open(void) { char *host; struct hostent *hp; struct sockaddr_in soc_in; int port; if(cddb.protocol == 3) /* http proxy */ host = strdup(cddb.proxy_server); else host = strdup(cddb.cddb_server); /* * t=string_split(host,':'); */ port=atoi(string_split(host,':')); if(!port) port=8880; printf("%s:%d\n",host,port); hp =gethostbyname(host); if (hp == NULL) { static struct hostent def; static struct in_addr defaddr; static char *alist[1]; static char namebuf[128]; int inet_addr(); defaddr.s_addr = inet_addr(host); if (defaddr.s_addr == -1) { printf("unknown host: %s\n", host); return (-1); } strcpy(namebuf, host); def.h_name = namebuf; def.h_addr_list = alist, def.h_addr = (char *)&defaddr; def.h_length = sizeof (struct in_addr); def.h_addrtype = AF_INET; def.h_aliases = 0; hp = &def; } soc_in.sin_family = hp->h_addrtype; bcopy(hp->h_addr, (char *)&soc_in.sin_addr, hp->h_length); soc_in.sin_port = htons(port); Socket = socket(hp->h_addrtype, SOCK_STREAM, 0); if (Socket < 0) { perror("socket"); return (-1); } fflush(stdout); if (connect(Socket, (struct sockaddr *)&soc_in, sizeof (soc_in)) < 0) { perror("connect"); close(Socket); return (-1); } Connection = fdopen(Socket, "r"); return (0); } /* connect_open() */ /* * Close the connection */ void connect_close(void) { (void)fclose(Connection); close(Socket); } /* connect_close() */ /* * Get a line from the connection with CR and LF stripped */ void connect_getline(char *line) { char c; while ((c = getc(Connection)) != '\n') { *line = c; if ((c != '\r') && (c != (char)0xff)) line++; } *line=0; } /* connect_getline() */ /* * Read the CD data from the server and place them into the cd struct */ void connect_read_entry(void) { char type; int trknr; char *t,*t2,tempbuf[2000]; while(strcmp(tempbuf,".")) { connect_getline(tempbuf); t=string_split(tempbuf,'='); if(t != NULL) { type=tempbuf[0]; if(strncmp("TITLE",tempbuf+1,5)) continue; if('D' == type) { /* * Annahme: "Interpret / Titel" ist falsch. * Daher: NULL-String erwarten. */ t2=string_split(t,'/'); if(t2 == NULL) t2 = t; if(*t2 == ' ') t2++; strcpy(cd->cdname,t2); for(t2=t;*t2;t2++) { if((*t2 == ' ') && (*(t2+1) == 0)) *t2=0; } strcpy(cd->artist,t); } if('T' == type) { trknr=atoi(tempbuf+6); /* * printf("Track %d:%s\n",trknr,t); */ wm_strmcpy(&cd->trk[trknr].songname,t); } /* * fprintf(stderr, "%s %s\n",tempbuf,t); */ } } } /* connect_read_entry() */ /* * Send a command to the server using cddbp */ void cddbp_send(char *line) { write(Socket, line, strlen(line)); write(Socket, "\n", 1); } /* cddbp_send() */ /* * Send the "read from cddb" command to the server using cddbp */ void cddbp_read(char *category, unsigned int id) { char tempbuf[84]; sprintf(tempbuf, "cddb read %s %08x", category, id); cddbp_send(tempbuf); } /* cddbp_read() */ /* * Send a command to the server using http */ void http_send(char* line) { char tempbuf[2000]; write(Socket, "GET ", 4); printf("GET "); if(cddb.protocol == 3) { write(Socket, "http://", 7); write(Socket, cddb.cddb_server, strlen(cddb.cddb_server)); printf("http://%s",cddb.cddb_server); } write(Socket, cddb.path_to_cgi, strlen(cddb.path_to_cgi)); write(Socket, "?cmd=" ,5); write(Socket, line, strlen(line)); printf("%s?cmd=%s",cddb.path_to_cgi,line); string_makehello(tempbuf,'+'); write(Socket, tempbuf, strlen(tempbuf)); printf("%s",tempbuf); write(Socket, "&proto=1 HTTP/1.0\n\n", 19); printf("&proto=1 HTTP/1.0\n"); do connect_getline(tempbuf); while(strcmp(tempbuf,"")); } /* http_send() */ /* * Send the "read from cddb" command to the server using http */ void http_read(char *category, unsigned int id) { char tempbuf[84]; sprintf(tempbuf, "cddb+read+%s+%08x", category, id); http_send(tempbuf); } /* http_read() */ /* * The main routine called from the ui */ void cddb_request(void) { int i; char tempbuf[2000]; extern int cur_ntracks; int status; char category[20]; unsigned int id; strcpy(cddb.cddb_server,"localhost:888"); strcpy(cddb.mail_adress,"svolli@bigfoot.com"); /* * cddb.protocol = 1; */ wipe_cdinfo(); switch(cddb.protocol) { case 1: /* cddbp */ printf("USING CDDBP\n"); printf("open\n"); connect_open(); connect_getline(tempbuf); printf("[%s]\n",tempbuf); /* * if(atoi(tempbuf) == 201) return; */ /* * strcpy(tempbuf,"cddb hello svolli bigfoot.com Eierkratzer eins"); */ string_makehello(tempbuf,' '); fprintf(stderr, "%s\n", tempbuf); cddbp_send(tempbuf); connect_getline(tempbuf); printf("[%s]\n",tempbuf); printf("query\n"); sprintf(tempbuf, "cddb query %08x %d",thiscd.cddbid,thiscd.ntracks); for (i = 0; i < cur_ntracks; i++) if (thiscd.trk[i].section < 2) sprintf(tempbuf + strlen(tempbuf), " %d", thiscd.trk[i].start); sprintf(tempbuf + strlen(tempbuf), " %d\n", thiscd.length); printf(">%s<\n",tempbuf); cddbp_send(tempbuf); connect_getline(tempbuf); printf("[%s]\n",tempbuf); status=atoi(tempbuf); /* * fprintf(stderr, "status:%d\n",status); * fprintf(stderr,"category:%s\n",category); * fprintf(stderr,"id:%s\n",id); */ if(status == 200) /* Exact match */ { sscanf(tempbuf,"%d %s %08x",&status,category,&id); cddbp_read(category,id); connect_read_entry(); } if(status == 211) /* Unexact match, multiple possible * Hack: always use first. */ { connect_getline(tempbuf); sscanf(tempbuf,"%s %08x",category,&id); while(strcmp(tempbuf,".")) connect_getline(tempbuf); cddbp_read(category,id); connect_read_entry(); } cddbp_send("quit"); connect_close(); printf("close\n"); break; case 2: /* http */ case 3: /* http proxy */ printf("USING HTTP%s\n", (cddb.protocol == 3) ? " WITH PROXY" : ""); printf("query\n"); sprintf(tempbuf, "cddb+query+%08x+%d",thiscd.cddbid,thiscd.ntracks); for (i = 0; i < cur_ntracks; i++) if (thiscd.trk[i].section < 2) sprintf(tempbuf + strlen(tempbuf), "+%d", thiscd.trk[i].start); sprintf(tempbuf + strlen(tempbuf), "+%d", thiscd.length); printf(">%s<\n",tempbuf); connect_open(); http_send(tempbuf); connect_getline(tempbuf); printf("[%s]\n",tempbuf); status=atoi(tempbuf); /* * fprintf(stderr, "status:%d\n",status); * fprintf(stderr, "category:%s\n",category); * fprintf(stderr, "id:%s\n",id); */ if(status == 200) /* Exact match */ { connect_close(); connect_open(); sscanf(tempbuf,"%d %s %08x",&status,category,&id); http_read(category,id); connect_read_entry(); } if(status == 211) /* Unexact match, multiple possible * Hack: always use first. */ { connect_getline(tempbuf); sscanf(tempbuf,"%s %08x",category,&id); while(strcmp(tempbuf,".")) connect_getline(tempbuf); connect_close(); connect_open(); http_read(category,id); connect_read_entry(); } /* moved close above break */ connect_close(); break; default: /* off */ break; } } /* cddb_request() */ ascd-0.13.2.orig/libworkman/include/0040744000175000017500000000000006723407436016567 5ustar hallonhallonascd-0.13.2.orig/libworkman/include/wm_cdda.h0100600000175000017500000000660406661516166020335 0ustar hallonhallon#ifndef WM_CDDA_H #define WM_CDDA_H /* * $Id: wm_cdda.h,v 1.2 1999/02/14 09:50:46 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /* * Information about a particular block of CDDA data. */ struct cdda_block { unsigned char status; /* see below */ unsigned char track; unsigned char index; unsigned char minute; unsigned char second; unsigned char frame; /* Average volume levels, for level meters */ unsigned char lev_chan0; unsigned char lev_chan1; /* Current volume setting (0-255) */ unsigned char volume; /* Current balance setting (0-255, 128 = balanced) */ unsigned char balance; }; /* * cdda_block status codes. */ #define WMCDDA_ERROR 0 /* Couldn't read CDDA from disc */ #define WMCDDA_OK 1 /* Read this block successfully (raw data) */ #define WMCDDA_PLAYED 2 /* Just played the block in question */ #define WMCDDA_STOPPED 3 /* Block data invalid; we've just stopped */ #define WMCDDA_ACK 4 /* Acknowledgement of command from parent */ #define WMCDDA_DONE 5 /* Chunk of data is done playing */ #define WMCDDA_EJECTED 6 /* Disc ejected or offline */ /* * Enable or disable CDDA building depending on platform capabilities, and * determine endianness based on architecture. (Gross!) * * For header-comfort, the macros LITTLE_ENDIAN and BIG_ENDIAN had to be * renamed. At least Linux does have bytesex.h and endian.h for easy * byte-order examination. */ #ifdef sun # ifdef SYSV # include # include # ifndef CDROMCDDA # undef BUILD_CDDA # endif # ifdef i386 # define WM_LITTLE_ENDIAN 1 # define WM_BIG_ENDIAN 0 # else # define WM_BIG_ENDIAN 1 # define WM_LITTLE_ENDIAN 0 # endif # else # undef BUILD_CDDA # endif #endif /* Linux only allows definition of endianness, because there's no * standard interface for CDROM CDDA functions that aren't available * if there is no support. */ #ifdef linux # include # include /* * XXX could this be a problem? The results are only 0 and 1 because * of the ! operator. How about other linux compilers than gcc ? */ # define WM_LITTLE_ENDIAN !(__BYTE_ORDER - __LITTLE_ENDIAN) # define WM_BIG_ENDIAN !(__BYTE_ORDER - __BIG_ENDIAN) #endif /* * The following code shouldn't take effect now. * In 1998, the WorkMan platforms don't support __PDP_ENDIAN * architectures. * */ #if !WM_LITTLE_ENDIAN # if !WM_BIG_ENDIAN # error yet unsupported architecture foo bar this is to stop the compiler. # endif #endif #endif /* WM_CDDA_H */ ascd-0.13.2.orig/libworkman/include/wm_config.h0100600000175000017500000003165006714071416020677 0ustar hallonhallon#ifndef WM_CONFIG_H #define WM_CONFIG_H /* * $Id: wm_config.h,v 1.5 1999/05/05 16:34:22 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ********************************************************************** * * This file consists of several parts. First, there's a generic, * platform independent part. Set needed options there. * The following parts are platform dependent. You may search for the * names listed below and then set your OS specific options there. * Don't be surprised, if there are no options for your OS. They aren't * needed in any case. * * The default values should produce a functional WorkMan on every * platform. * ********************* * Current platforms: ********************* * BSD386 * FreeBSD * HP-UX * Irix (SGI) * Linux * News (Sony NewsOS) * OpenBSD * OSF1 * Sun (SunOS/Solaris, Sparc or x86) * SVR4 * Ultrix * AIX * * The above order corresponds with the order of the platform specific * options below. */ /****************************************************************** * generic options ****************************************************************** ** ** *** **** ** **** ** * ** ** ** * ** * * * *** **** * * *** * ** ** *** * * * * * * ** * * *** **** ** *** ** ** ** * * ** * * ** * * * *** **** **** *** * ** ** *** * * * * *** ** * * * * ** **** * * ** ** **** ** * * *** ** ******************************************************************/ /* * This option is obvious. But please do not forget the original * WorkMan version string if you need support. */ #define WORKMAN_NAME "LibWorkMan" #define WORKMAN_VERSION "1.4.0" /* * If your CD-ROM drive closes its tray if the device is opened, then * the next define can make WorkMans "Eject" button an "open/close" * button. If it disturbs you, just comment it out. * * ### this is preliminary. It may have no effect for you ### */ #define CAN_CLOSE 1 /* * Define the following if you want the balance slider to * decrease one channel's volume while increasing the other's */ /* #define SYMETRIC_BALANCE 1 */ /* * Define this if you want CDDA support. Supported systems are: * * - Solaris (2.4 or newer) * --> Linux is on the way. Don't define it now. It would lead to errors only. */ /*#define BUILD_CDDA 1*/ /* * * This is for experimental cddb support. * This activates the UI component. */ #define CDDB_IN_UI 1 /****************************************************************** * BSD386 ****************************************************************** *** **** *** ******* ** **** **** ************ *** ** ** ****** * ***** ****** ** ** ** *************** *** ****** **** ** *** ***** ***** *** ************ *** ** ****** ** * *** ******** ** ** ** ** *********** *** **** *** *** ****** **** **** ************ ******************************************************************/ #ifdef __bsdi__ /* * This lets you use the SoundBlaster Mixer on BSD/386 */ #define SOUNDBLASTER 1 #endif /* __bsdi__ (BSD/386) */ /****************************************************************** * FreeBSD ****************************************************************** *** ** *** ** ** **** *** *********** *** ****** ** ** ****** ****** ** ** ****** * ********** *** **** *** **** **** ****** **** ** ********* *** ****** ** ** ****** ****** ** ****** ** * ********** *** ****** ** ** ** ** **** *** *********** ******************************************************************/ #if defined(__FreeBSD__) || defined(__NetBSD__) #define DEFAULT_CD_DEVICE "/dev/rmatcd0c" #endif /* freebsd */ /****************************************************************** * HP-UX ****************************************************************** *** ** ** ********* ** ** ** *************************** *** ** ** ** ******** ** *** **************************** *** ** *** ** ** **** ***************************** *** ** ** ************ ** *** **************************** *** ** ** ************* *** ** *************************** ******************************************************************/ #if defined(hpux) || defined (__hpux) #define DEFAULT_CD_DEVICE "/dev/rscsi" #endif /* hpux */ /****************************************************************** * Irix ****************************************************************** *** ** *** ** ** ********************************* ***** **** ** **** ***** ********************************** ***** **** ***** ****** *********************************** ***** **** ** **** ***** ********************************** *** ** ** ** ** ** ********************************* ******************************************************************/ #if defined(sgi) #define DEFAULT_CD_DEVICE "/dev/scsi/sc0d6l0" #endif /* sgi IRIX */ /****************************************************************** * Linux ****************************************************************** *** ****** ** *** ** ** ** ** *********************** *** ******** **** ** ** ** *** ************************ *** ******** **** * * ** ** **** ************************* *** ******** **** ** ** ** *** ************************ *** ** ** *** *** *** ** *********************** ******************************************************************/ #ifdef linux /* * Uncomment the following line to have WorkMan send SCSI commands * directly to the CD-ROM drive. If you have a SCSI drive you * probably want this, but it will cause WorkMan to not work on IDE * drives. */ #define LINUX_SCSI_PASSTHROUGH 1 /* * Which device should be opened by WorkMan at default? */ #define DEFAULT_CD_DEVICE "/dev/sbpcd" /* * Uncomment the following if you use the sbpcd or mcdx device driver. * It shouldn't hurt if you use it on other devices. It'll be nice to * hear from non-sbpcd (or mcdx) users if this is right. */ /*#define SBPCD_HACK 1*/ /* * Linux Soundcard support */ #define OSS_SUPPORT 1 /* * This has nothing to do with the above. */ /* #define CURVED_VOLUME */ /* * Uncomment the following if you want to try out a better responding * WorkMan, especially with IDE drives. This may work with non-IDE * drives as well. But it may be possible, that it doesn't work at all. * If your drive/driver combination cannot handle the faster access, * the driver will usually hang and you have to reboot your machine. */ /* #define FAST_IDE 1 */ /* * There are two alternative ways of checking a device containing a * mounted filesystem. Define BSD_MOUNTTEST for the test using * getmntent(). Undefine it for using the SVR4 ustat(). * I built in the choice, because it's not clear which method should * be used in Linux. The ustat manpage tells us since 1995, that * fstat() should be used, but I'm too dumb to do so. */ #define BSD_MOUNTTEST #endif /* linux */ /****************************************************************** * Sony NewsOS ****************************************************************** *** *** ** ** ***** *** ***************************** *** ** ** ****** ***** ** ******************************** *** * * ** **** ** ** **** ****************************** *** ** ** ****** * * ****** **************************** *** *** ** ** * *** ***************************** ******************************************************************/ #if defined(__sony_news) || defined(sony_news) #define DEFAULT_CD_DEVICE "/dev/rsd/b0i6u0p2\0" #endif /****************************************************************** * OpenBSD ****************************************************************** **** *** *** ** *** ** **** *** ********* *** ** ** ** ** ****** ** ** ** ** ****** * ******** *** ** ** *** **** * * ** ****** **** ** ******* *** ** ** ****** ****** ** ** ** ****** ** * ******** **** *** ****** ** *** ** **** *** ********* ******************************************************************/ #ifdef __OpenBSD__ #define DEFAULT_CD_DEVICE "/dev/rcdrom" #endif /****************************************************************** * OSF1 ****************************************************************** **** **** *** *** *** ******************************* *** ** ** ****** ****** ** ******************************* *** ** **** **** *** ***** ******************************* *** ** ****** ** **** ****** ******************************* **** **** *** *** ***** ***************************** ******************************************************************/ #if defined(__osf__) #define DEFAULT_CD_DEVICE "/dev/rcdrom/cd0" #endif /****************************************************************** * SunOS/Solaris ****************************************************************** **** *** ** ** *** *************************************** *** ****** ** ** ** *************************************** ***** **** ** ** * * *************************************** ******* ** ** ** ** *************************************** **** **** *** *** *************************************** ******************************************************************/ #if defined(sun) || defined(__sun__) /* * Define the following for Solaris 2.x * If you don't want WorkMan to try to activate the SPARCstation 5 * internal audio input so you get sound from the workstation, comment * out the CODEC define. */ #define SYSV 1 #define CODEC 1 /* * set the following to "SUNW,CS4231" for Sun and to "SUNW,sb16" * for PC (with SoundBlaster 16) running Solaris x86 * (only important if you define CODEC above) */ /*#define SUN_AUD_DEV "SUNW,CS4231"*/ #define SUN_AUD_DEV "SUNW,sbpro" #endif /****************************************************************** * SVR4 ****************************************************************** **** *** **** ** *** * ******************************** *** ****** **** ** ** ** * ******************************** ***** ***** ** *** *** ******************************* ******* *** ** *** ** ***** ******************************** **** ***** **** ** ***** ******************************** ******************************************************************/ #if defined(SVR4) && !defined(sun) && !defined(__sun__) #define DEFAULT_CD_DEVICE "/dev/rcdrom/cd0" #endif /****************************************************************** * Ultrix ****************************************************************** *** ** ** ***** ** *** ** ** ****************** *** ** ** ******* **** ** **** ***** ******************* *** ** ** ******* **** ***** ****** ******************** *** ** ** ******* **** ** **** ***** ******************* **** *** *** **** ** ** ** ** ****************** ******************************************************************/ #if defined(ultrix) || defined(__ultrix) #endif /****************************************************************** * IBM AIX ****************************************************************** **** *** ** ** ***************************************** *** ** **** ***** ****************************************** *** **** ****** ******************************************* *** ** **** ***** ****************************************** *** ** ** ** ** ***************************************** ******************************************************************/ #if defined(AIXV3) #define DEFAULT_CD_DEVICE "/dev/cd0" #endif /* IBM AIX */ /******************************************************************/ #endif /* WM_CONFIG_H */ ascd-0.13.2.orig/libworkman/include/wm_cdinfo.h0100644000175000017500000000547506723407436020717 0ustar hallonhallon#ifndef WM_CDINFO_H #define WM_CDINFO_H /* * $Id: wm_cdinfo.h,v 1.5 1999/05/28 03:35:58 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Prototypes from cdinfo.c * * This is just one more step to a more modular and understandable code. */ extern char *cur_trackname; /* Take a guess */ extern int cur_index; /* Current index mark */ extern int cur_frame; /* Current frame number */ extern struct wm_play *playlist; /* = NULL */ extern struct wm_cdinfo thiscd; extern struct wm_cdinfo *cd; extern int cur_track; /* Current track number, starting at 1 */ extern char *cur_artist; /* Name of current CD's artist */ extern char cur_avoid; /* Avoid flag */ extern char cur_contd; /* Continued flag */ extern char *cur_cdname; /* Album name */ extern int cur_nsections; /* Number of sections currently defined */ extern int exit_on_eject; extern int cur_track; extern int cur_pos_abs; extern int cur_pos_rel; extern int cur_tracklen; extern int cur_cdlen; extern enum wm_cd_modes cur_cdmode; extern int cur_ntracks; extern int cur_lasttrack; extern int cur_firsttrack; extern int cur_listno; extern int cur_stopmode; void wipe_cdinfo( void ); void play_next_entry( int forward ); void make_playlist( int playmode, int starttrack ); int get_autoplay( void ); int get_playmode( void ); void pl_find_track( int track ); void play_prev_track( int forward ); void play_next_track( int forward ); int tracklen( int num ); int get_default_volume( int track ); int split_trackinfo( int pos ); int remove_trackinfo( int num ); void freeup( char **x ); int get_runtime( void ); char *trackname( int num ); void stash_cdinfo( char *artist, char *cdname, int autoplay, int playmode ); void stash_trkinfo( int track, char *songname, int contd, int avoid ); int get_avoid( int num ); int get_contd( int num ); void default_volume( int track, int vol ); char *listentry( int num ); #endif /* WM_CDINFO_H */ ascd-0.13.2.orig/libworkman/include/wm_cdrom.h0100600000175000017500000000404206714066523020534 0ustar hallonhallon#ifndef WM_CDROM_H #define WM_CDROM_H /* * $Id: wm_cdrom.h,v 1.6 1999/05/05 16:09:55 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Prototypes from cdrom.c * * This is just one more step to a more modular and understandable code. */ #define WM_CDS_NO_DISC 0 #define WM_CDS_DISC_READY 1 #define WM_CDS_JUST_INSERTED 2 #define WM_STR_GENVENDOR "Generic" #define WM_STR_GENMODEL "drive" #define WM_STR_GENREV "type" extern int wm_cd_cur_balance; char * wm_drive_vendor( void ); char * wm_drive_model( void ); char * wm_drive_revision( void ); void wm_drive_settype( char *vendor, char *model, char *revision ); int wm_cd_status( void ); void wm_cd_play( int start, int pos, int end ); void wm_cd_play_chunk( int start, int end, int realstart ); void wm_cd_play_from_pos( int pos ); void wm_cd_pause( void ); void wm_cd_stop( void ); int wm_cd_eject( void ); int wm_cd_closetray( void ); int wm_cd_read_initial_volume( int max ); /* * Following are the missing to rename. */ int find_trkind( int track, int index, int start ); void cd_volume( int vol, int bal, int max ); #endif /* WM_CDROM_H */ ascd-0.13.2.orig/libworkman/include/wm_helpers.h0100600000175000017500000000656106670435234021102 0ustar hallonhallon#ifndef WM_HELPERS_H #define WM_HELPERS_H /* * $Id: wm_helpers.h,v 1.6 1999/03/07 08:36:44 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Here to be found: Prototypes. Including variable names to be easier * to read. * This is just one more step to a more modular and understandable code. * */ /* * LibWorkMan message levels. I'm not sure how to call them all and which * use they should fulfill. This is not very urgent now, because there * aren't many messages in LibWorkMan now. */ #define WM_MSG_LEVEL_NONE 0 #define WM_MSG_LEVEL_ERROR 1 #define WM_MSG_LEVEL_TWO 2 #define WM_MSG_LEVEL_THREE 3 #define WM_MSG_LEVEL_FOUR 4 #define WM_MSG_LEVEL_INFO 5 #define WM_MSG_LEVEL_SIX 6 #define WM_MSG_LEVEL_SEVEN 7 #define WM_MSG_LEVEL_EIGHT 8 #define WM_MSG_LEVEL_DEBUG 9 /* * Message classes. This is somehow a definition of * the message's source. */ #define WM_MSG_CLASS_PLATFORM 0x010 #define WM_MSG_CLASS_SCSI 0x020 #define WM_MSG_CLASS_CDROM 0x040 #define WM_MSG_CLASS_DB 0x080 #define WM_MSG_CLASS_MISC 0x100 #define WM_MSG_CLASS_ALL 0xff0 extern int wm_lib_verbosity; /* * I did not know any better place... */ #ifdef DEBUG #define CHECKPOINT(t) fprintf(stderr, "%s (%d): %s\n", __FILE__, __LINE__, t ); #else #define CHECKPOINT(t) #endif #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif #ifdef linux #include /* Linux doesn't have a SIGEMT */ #if !defined( SIGEMT ) # define SIGEMT SIGUNUSED #endif #endif /* linux */ void freeup( char **x ); void wm_strmcat( char **t, char *s); void wm_strmcpy( char **t, char *s ); char * wm_strdup( char *s ); /* Somebody's version query unsatisfied? */ int wm_libver_major( void ); /* return major internal version number */ int wm_libver_minor( void ); /* return minor internal version number */ int wm_libver_pl( void ); /* return internal patchlevel number */ char * wm_libver_name( void ); /* return internal name (LibWorkMan) */ char * wm_libver_number( void ); /* returns string: ".." */ char * wm_libver_string( void ); /* returns string: " " */ char * wm_libver_date( void ); /* returns string: date of compilation */ void wm_lib_set_verbosity( int level ); /* set verbosity level */ int wm_lib_get_verbosity( void ); /* get verbosity level */ void wm_lib_message( unsigned int level, char *format, ... ); /* put out a message on stderr */ int wm_susleep( int usec ); #endif /* WM_HELPERS_H */ ascd-0.13.2.orig/libworkman/include/wm_database.h0100600000175000017500000000272506661516167021207 0ustar hallonhallon#ifndef WM_DATABASE_H #define WM_DATABASE_H /* * $Id: wm_database.h,v 1.3 1999/02/14 09:50:47 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Prototypes for WorkMan database * * This is just one more step to a more modular and understandable code. */ #define WM_DB_SAVE_ERROR 1 #define WM_DB_SAVE_DISABLED 2 int wm_db_get_playnew( void ); void split_workmandb( void ); int save( void ); void load( void ); void load_settings( void ); extern int wm_db_save_disabled; extern int cur_playnew; #endif /* WM_DATABASE_H */ ascd-0.13.2.orig/libworkman/include/wm_struct.h0100644000175000017500000001336406723407436020775 0ustar hallonhallon#ifndef WM_STRUCT_H #define WM_STRUCT_H /* * $Id: wm_struct.h,v 1.7 1999/05/28 03:35:58 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /* * Structure for a single track. This is pretty much self-explanatory -- * one of these exists for each track on the current CD. */ struct wm_trackinfo { char *songname; /* Name of song, dynamically allocated */ char *otherdb; /* Unrecognized info for this track */ char *otherrc; int length; /* Length of track in seconds or Kbytes */ int start; /* Starting position (f+s*75+m*60*75) */ int volume; /* Per-track volume (1-32, 0 to disable) */ int track; /* Physical track number */ int section; /* Section number (0 if track not split) */ int contd; /* Flag: continuation of previous track */ int avoid; /* Flag: don't play this track. */ int data; /* Flag: data track */ }; /* * Structure for internal playlist management. The internal playlist is * simply the list of track ranges that are being played currently. This * is built whenever the CD starts playing; it's used in normal and shuffle * modes as well as playlist mode. * * The "starttime" element represents how much time has elapsed by the time * we get to this entry. For instance, if the list begins with a 5-minute * track and a 3-minute track, the third entry would have a starttime of 8 * minutes. This is used so that the elapsed play time can be displayed * even in shuffle or playlist modes. * * The last member of the list has a start track of 0, and its starttime is * the total playing time of the playlist (which will usually be overestimated, * since we don't play leadouts in some cases.) */ struct wm_play { int start; /* Start track, or 0 if end of list */ int end; /* last track plus 1 */ int starttime; /* Number of seconds elapsed previously */ }; /* * Structure for playlists (as seen by the user.) This is simply a name * followed by a zero-terminated list of track numbers to play. The list * is terminated by a NULL name. */ struct wm_playlist { char *name; /* Name of this playlist */ int *list; /* List of tracks */ }; struct wm_cdinfo { char artist[84]; /* Artist's name */ char cdname[84]; /* Disc's name */ int ntracks; /* Number of tracks on the disc */ int length; /* Total running time in seconds */ int autoplay; /* Start playing CD immediately */ int playmode; /* How to play the CD */ int volume; /* Default volume (1-32, 0 for none) */ struct wm_trackinfo *trk; /* struct wm_trackinfo[ntracks] */ struct wm_playlist *lists; /* User-specified playlists */ char *whichdb; /* Which database is this entry from? */ char *otherdb; /* Unrecognized lines from this entry */ char *otherrc; char *user; /* Name of originating user */ unsigned int cddbid; /* CDDB-ID of the current disc */ struct cdinfo *next; /* For browsers, etc. */ }; /* The global variable "cd" points to the struct for the CD that's playing. */ extern struct wm_cdinfo *cd; struct wm_playlist *new_list(); enum wm_cd_modes { WM_CDM_UNKNOWN = -1, WM_CDM_BACK = 0, WM_CDM_TRACK_DONE = 0, WM_CDM_PLAYING = 1, WM_CDM_FORWARD = 2, WM_CDM_PAUSED = 3, WM_CDM_STOPPED = 4, WM_CDM_EJECTED = 5 }; /* * Drive descriptor structure. Used for access to low-level routines. */ struct wm_drive { int fd; /* File descriptor, if used by platform */ char vendor[32]; /* Vendor name */ char model[32]; /* Drive model */ char revision[32]; /* Revision of the drive */ void *aux; /* Pointer to optional platform-specific info */ void *daux; /* Pointer to optional drive-specific info */ int (*init)(); int (*get_trackcount)(); int (*get_cdlen)(); int (*get_trackinfo)(); int (*get_drive_status)(); int (*get_volume)(); int (*set_volume)(); int (*pause)(); int (*resume)(); int (*stop)(); int (*play)(); int (*eject)(); int (*closetray)(); }; /* * Structure for information of the usage of cddb. */ struct wm_cddb { int protocol; /* 0-off, 1-cddbp, 2-http, 3-htproxy */ char cddb_server[84]; /* host.domain.name:port */ char mail_adress[84]; /* user@domain.name */ char path_to_cgi[84]; /* (/)path/to/cddb.cgi */ char proxy_server[84]; /* host.domain.name:port */ }; extern struct wm_cddb cddb; /* * Each platform has to define generic functions, so may as well declare * them all here to save space. * These functions should never be seen outside libworkman. So I don't care * about the wm_ naming convention here. */ int gen_init(), gen_get_trackcount(), gen_get_cdlen(), gen_get_trackinfo(), gen_get_drive_status(), gen_get_volume(), gen_set_volume(), gen_pause(), gen_resume(), gen_stop(), gen_play(), gen_eject(), gen_closetray(); struct wm_drive *find_drive_struct(); #endif /* WM_STRUCT_H */ ascd-0.13.2.orig/libworkman/include/wm_index.h0100600000175000017500000000270306661516167020546 0ustar hallonhallon#ifndef WM_INDEX_H #define WM_INDEX_H /* * $Id: wm_index.h,v 1.2 1999/02/14 09:50:47 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Prototypes for wm_index.c * * This is just one more step to a more modular and understandable code. */ int idx_find_entry( char *file, int ntracks, int *tracks, int len, int fuzz, unsigned long *pos ); int idx_delete_entry(char *file, int track, int fuzz, unsigned long pos ); int idx_write_entry( char *file, int track, unsigned long pos ); #endif /* WM_INDEX_H */ ascd-0.13.2.orig/libworkman/include/wm_platform.h0100600000175000017500000000323106661516167021260 0ustar hallonhallon#ifndef WM_PLATFORM_H #define WM_PLATFORM_H /* * $Id: wm_platform.h,v 1.3 1999/02/14 09:50:47 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * The platform interface * * This is just one more step to a more modular and understandable code. */ #include "wm_struct.h" int wmcd_open( struct wm_drive *d ); int wmcd_reopen( struct wm_drive *d ); /* * void keep_cd_open( void ); */ int wm_scsi( struct wm_drive *d, unsigned char *cdb, int cdblen, void *retbuf, int retbuflen, int getreply ); /**************************************** * * The drive prototypes. * */ extern struct wm_drive generic_proto; extern struct wm_drive sony_proto; extern struct wm_drive toshiba_proto; #endif /* WM_PLATFORM_H */ ascd-0.13.2.orig/libworkman/include/wm_scsi.h0100600000175000017500000000340506661516167020400 0ustar hallonhallon#ifndef WM_SCSI_H #define WM_SCSI_H /* * $Id: wm_scsi.h,v 1.3 1999/02/14 09:50:47 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * SCSI prototypes (scsi.c) * * This is just one more step to a more modular and understandable code. */ #include "wm_struct.h" #define WM_ERR_SCSI_INQUIRY_FAILED -1 int wm_scsi_mode_sense( struct wm_drive *d, unsigned char page, unsigned char *buf ); int sendscsi( struct wm_drive *d, void *buf, unsigned int len, int dir, unsigned char a0, unsigned char a1, unsigned char a2, unsigned char a3, unsigned char a4, unsigned char a5, unsigned char a6, unsigned char a7, unsigned char a8, unsigned char a9, unsigned char a10, unsigned char a11 ); int wm_scsi_get_drive_type( struct wm_drive *d, char *vendor, char *model, char *rev ); #endif /* WM_SCSI_H */ ascd-0.13.2.orig/libworkman/include/workman.h0100600000175000017500000000277206714071416020410 0ustar hallonhallon#ifndef WORKMAN_H #define WORKMAN_H /* * $Id: workman.h,v 1.5 1999/05/05 16:34:22 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * all-in-one libworkman include file. * */ /* * wm_config should always be included first */ #include "wm_config.h" #include "workman_defs.h" #ifdef BUILD_CDDA #include "wm_cdda.h" #endif #include "wm_cddb.h" #include "wm_cdinfo.h" #include "wm_cdrom.h" #include "wm_database.h" #include "wm_helpers.h" #include "wm_index.h" #include "wm_platform.h" #include "wm_scsi.h" #include "wm_struct.h" #endif /* WORKMAN_H */ ascd-0.13.2.orig/libworkman/include/wm_cddb.h0100600000175000017500000000264706702051640020324 0ustar hallonhallon#ifndef WM_CDDB_H #define WM_CDDB_H /* * $Id: wm_cddb.h,v 1.2 1999/02/14 09:50:46 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ extern struct wm_cddb cddb; extern int cur_cddb_protocol; extern char *cur_cddb_server, *cur_cddb_mail_adress, *cur_cddb_path_to_cgi, *cur_cddb_proxy_server; unsigned int cddb_discid(); void cddb_struct2cur(); void cddb_cur2struct(); void cddb_select(); void connect_cddb(); void update_cddbserver(); void cddb_request(); #endif /* WM_CDDB_H */ ascd-0.13.2.orig/libworkman/include/workman_defs.h0100600000175000017500000000176506661516167021422 0ustar hallonhallon#ifndef WORKMAN_DEFS_H #define WORKMAN_DEFS_H /* * $Id: workman_defs.h,v 1.4 1999/02/14 09:50:47 dirk Exp $ * * This file is part of WorkMan, the civilized CD player program * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * #defined CONSTANTS * * Too bad this file seems to be so empty... * */ #include "wm_version.h" #endif /* WORKMAN_DEFS_H */ ascd-0.13.2.orig/libworkman/include/wm_version.h0100644000175000017500000000237006723407436021131 0ustar hallonhallon#ifndef WM_VERSION_H #define WM_VERSION_H /* * $Id: wm_version.h,v 1.2 1999/05/28 03:35:58 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Version information * */ #define WM_LIBVER_MAJOR 1 #define WM_LIBVER_MINOR 4 #define WM_LIBVER_PL 2 #define WM_LIBVER_NAME "LibWorkMan" #endif /* WM_VERSION_H */ ascd-0.13.2.orig/libworkman/plat_template.c0100644000175000017500000001053606665013105020136 0ustar hallonhallon/* * $Id$ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * */ #if [TEMPLATESYSTEM] static char plat_template_id[] = "$Id$" #include "include/wm_config.h" #include "include/wm_struct.h" #define WM_MSG_CLASS WM_MSG_CLASS_PLATFORM /* * gen_init(); * */ int gen_init(struct wm_drive *d) { return (0); } /* * gen_get_trackcount() * */ int gen_get_trackcount(struct wm_drive *d,int *tracks) { return (0); } /* * gen_get_cdlen() * */ int gen_get_cdlen(struct wm_drive *d,int *frames) { return (0); } /* * gen_get_trackinfo() * */ int gen_get_trackinfo(struct wm_drive *d,int track,int *data,int *startframe) { return (0); } /* * gen_get_drive_status() * */ int gen_get_drive_status(struct wm_drive *d, enum wm_cd_modes oldmode, enum wm_cd_modes *mode, int *pos, int *track, int *index) { return (0); } int scale_volume(int vol,int max) { return ((vol * (max_volume - min_volume)) / max + min_volume); } int unscale_volume(int vol,int max) { int n; n = ( vol - min_volume ) * max_volume / (max - min_volume); return (n <0)?0:n; } /* * gen_get_volume() * */ int gen_get_volume(struct wm_drive *d,int *left,int *right) { return (0); } /* * gen_set_volume() * */ int gen_set_volume(struct wm_drive *d,int left,int right) { return (0); } /* * gen_pause() * */ int gen_pause(struct wm_drive *d) { return ioctl( 0 ); } /* * gen_resume * */ int gen_resume(struct wm_drive *d) { return (0); } /* * gen_stop() * */ int gen_stop(struct wm_drive *d){ return (0); } /* * gen_play() * */ int gen_play(struct wm_drive *d,int start,int end) { return (0); } /* * gen_eject() * */ int gen_eject(struct wm_drive *d) { return (0); } /*----------------------------------------* * Close the CD tray *----------------------------------------*/ int gen_closetray(struct wm_drive *d) { #ifdef CAN_CLOSE if(!close(d->fd)) { d->fd=-1; return(wmcd_reopen(d)); } else { return(-1); } #else /* Always succeed if the drive can't close */ return(0); #endif /* CAN_CLOSE */ } /* gen_closetray() */ /* * wm_scsi() * */ int wm_scsi(struct wm_drive *d, uchar_t *cdb, int cdblen,void *retbuf,int retbuflen,int getreply) { return (0); } /* * wmcd_open() * */ int wmcd_open(struct wm_drive *d) { char vendor[32] = WM_STR_GENVENDOR; char model[32] = WM_STR_GENMODEL; char rev[32] = WM_STR_GENREV; int fd; if( ! d ){ errno = EFAULT; return -1; } if(d->fd > -1) /* device already open? */ return 0; if( cd_device == (char *)NULL ) cd_device = DEFAULT_CD_DEVICE; /* open() goes here */ *d = *(find_drive_struct(vendor, model, rev)); wm_drive_settype(vendor, model, rev); d->fd = fd; d->init(d); return (0); } /* wmcd_open() */ /* * Re-Open the device if it is open. */ int wmcd_reopen( struct wm_drive *d ) { int status; do { wm_lib_message(WM_MSG_LEVEL_DEBUG, "wmcd_reopen "); if (d->fd >= 0) /* Device really open? */ { wm_lib_message(WM_MSG_LEVEL_DEBUG, "closes the device and "); status = close( d->fd ); /* close it! */ /* we know, that the file is closed, do we? */ d->fd = -1; } wm_susleep( 1000 ); wm_lib_message(WM_MSG_LEVEL_DEBUG, "calls wmcd_open()\n"); status = wmcd_open( d ); /* open it as usual */ wm_susleep( 1000 ); } while ( status != 0 ); return status; } /* wmcd_reopen() */ #endif /* TEMPLATESYSTEM */ ascd-0.13.2.orig/ascd/0040754000175000017500000000000006764326157013717 5ustar hallonhallonascd-0.13.2.orig/ascd/themes/0040755000175000017500000000000006764325707015205 5ustar hallonhallonascd-0.13.2.orig/ascd/themes/themes.tar0100644000175000017500000026400006720035545017167 0ustar hallonhallonThemes/default/ 40755 1750 1750 0 6720035545 12347 5ustar denisdenisThemes/default/quick/ 40755 1750 1750 0 6720035545 13463 5ustar denisdenisThemes/default/quick/quick1.gif100644 1750 1750 34262 6720032577 15475 0ustar denisdenisGIF89a6ç*žŒ†‚|žÂźž˘¤Š24ââäÖŚŹFFDچ”ćÂIJ˛´ŢN|Ž’ŒjdÖŇIJ˘¤ŚŞ¤Ţj|ÖĆĚJ$Ҳ´ffdĆĘĚňňô64†ŠŒvvtśşÄššœâÚÜö<6ΔĆÂĂöâäVVTƜö6TŞŚ¤Öv„ęśÄŽŠˆćZtŚŞŹ**,Âžź–’”ÖÚÜnnl^˘tÂĆŔŚ˘œú˘´~~{ţŇÜ664BöÂĚÎşźžşź˘žœę*Tňęě^^\ ††‚²´~z|šžŁ^VLŽŽ‹vrs~‚„žÂĚęęěţRTŇŇÔöj„ÎĘÄúúüzzlňz”ŽŞŹîŞźúžŹö.L˘ŚŹNNLşś´’–œŽŞ ŠŽęŢäîŹĆĆÄúâäňFdň^t––”nrlö’¤>><ň&L††ŒŽŽ”nŽdÚÖŘ ÂÂĞ˘ŹîćäNJDú‚”ňĘÔ˛ś´’’”Ţśźzv|şžÁZZZúžÇ224ŢÚÜŚŚŁňÚÜ:6<ţĘÔھ̂*,N˛„ž>D&ޜţ´FžŒćvŒÚšŹöVtśŞŹîrŒú˛ź&rl><î>\Ţ~Œú~”îNl6Ňźâr„ö"DúŠœŢŞ´žŚŹţňôöŞźöNlîÂĚörŒÖ˛ź2.$ţĆÔÖžÄúvŒâ–¤ęĆÔžž˝^ZZŇŞ´JJKÎśźjjdâŢäňćěžśź‚†„ţćěöJlöb|öŢäúÎÜććä֊”ĘÎĚööôŚŽŹ..,öŚ´ňîěîîěÖÖÔţţüö–¤ň*LúŽźŢĆÔÎÎĚŽŽŹŽŽ¤îZtö>\ţÖÜŢŢÜöRlŽŚ´––œÂĆĚzz|ĆĆĚŚŚŹ˘˘¤jf\ŠŠ‰şşźžš”ZVLŽŚŹĆžżrnt:6.î*LІ‚žž’ŽŒ‚‚ƒö^|š–ŒrrtŢžÄ  ćâ䜲´ŞŞ¤ĘĘĚŞŞŹÚÚÜöęěÂÂĚÖŇÔţúüîŢäţâäú’¤’Ž”śś´úrŒćŢäúŚ´ú–¤ö*L†‚„žÂϒ”vv|!ţMade with GIMP,6ţ H° Áƒ*\ȰĄĂ‡#JœHą˘Ĺ‹3jÜČąŁÇ CŠI˛¤É“(SŞ\ɲĽË—0cƜIłŚÍ›8sęÜÉł§ĎŸ@ƒ J´¨ŃŁH“*]Ę´ŠÓ§PŁJJľŞŐŤXłjÝĘľŤ×Ż`ÊKśŹŮłhÓŞ]Ëś­ŰˇpăʝKˇŽÝťxóęÝˡď×€ŰRiHáÂ~+Fḛ̈c ÎރĆBTË˜E!€śŔ$f̋C‹öjëóçÁ mY0ů˛eQ˘Ö‘ü {´íŰUľX6-*˛B[,\łŢyäkи“+_Š ČńÝ~ß ű¸sÓĹEň^νťĐu—˝ţ —kh^Đdwc$­ńNż~Nhî-{{ -áőëţ d‹yAd'``&dK`}śŸ}FSpĂ]ĆBş¸wYj,ŔwĐíńĆ4ää …Ž!` kśč˘I+ş×Á–žA+f&ʍ­SŮ­Áf pśv݃/&Š$G4ţ˜i@¤ A°ŕ j-Pd…œpáU8ߒd–)‘-E D›(Ą9œ(,X0F‰ˇćîeb´9ČŚ™€š­E ~ŸůVPs:jh™ DĄ{Đŕ"-ş0ęáE˛ÝT *ę¨Ŕ0Š™ĽŔ\`ZtáژţU&ăgş|čŠ@MîvaA}’ęk™Ľšˇ Aťđ‰%A ňf$llX@P“Žőǐx™ŃŠf~żf›$×I+P ­y[ĐŒRť%f]űY— ­“ŚAŰi+o„?^G§Ş™íŠĐ”)K›ž@ţšĐ”™ZĐťó&ܝŸÍčđžö2„i Đ档š´5ŞŒ)pNP´Óޏ…<˛b&“\Ä|ž+ŠÁi1ÝgĹ˝ÚÁŽÁÜ i=`M@q›Ď@ íŃAÓgä›kd‹ľáKł@ęşľAÉbĆęÁ˜!šŘRĚ2äâËKř’Kb`‹MśŮhŤWŰc—ý'čô˛śţm„: +fŮ­¨¨@’G#Ľ Üą†>ľcÍĎĹŹ#ů:ÖDsě^ŽC>9ĺ–ă•yĹŹ˘‚0 T~šbŚZ†ŔŒ…9„*Ť´1 c$”uâÉžf¤ŔřXܤ— Žąp<™ý‹Čí„ýĹĹXC‡5đeö—ňČŚ,ßüóŃÓe<ňMœPÉ>Č`½hÁ~Ć㸯˘–áu#.€ĺćĺ'n՘‘({s˘xnkWČř—™řbë8 ČŠÁŽě­ă cĂ/ö†—Žgř@%$`BP‚„‹ř\@ ›)"8ÁĐüď:[;ě„ă›Y§:T˛ŒžțęPç2ţĹ) k~č1ŕ Ä/–Ń&Ă´G5ŘąŒź,aśX%„Q‚dˆÁPüÂ:¤HEš\1‹KD.n1Š8”aSŹâbfv-(„˙Hލ$&œîvCD×@%żń,'(đA7¨Đ[ˆlm0ĹĎž`Ši ÁÝłËlá ¤‚˛`Ć,H É6PҒ˜ŒË&}á‹F6qŚXĹ h0 s 2“}‘ÚnNç4GÉfŚâăĹU ˆibfX`Gé„’Ĺ"~фW.cÖ0…$; ލĚ.HÖp'Ü#eŔŚ6­ÁMoĆ%œl<ŹšOüÁ´ţŘB7żŮö´Ä<4„ěŘB ĐbÍfxY„VëˆĚ>ł ;ƒ :Ť :¤ŕ„QÕË0ĺ´É:AëŔĺ\ŕ‰[Ô!–FB‘MS”ô¤)… KmŃ4Q¤!˜G.šŕ œŞÔLŇŞ"˛ čB~ Á`"ú“\PĄ Uȃ5 ŔÄäasGj`Œ%ÜĹlHëx‘FäAö°XĹJVłž­i5WŰą‡'Ěá /]ËŞ°´@AšČƒ Öđ…,.ă6Ă4¤Ń€ŁwBZs‘‹VT ÷ěCř YĘZłoB.ʆ4vľţ†1Č1ŮĘ^ś°h‰‡;đ™‰x؃ŤżX;:` cLÒGˆ†Ńč˘ÚÍbŕ}+Ö` âšĘMíjW‹ß2Q¸E(îqѐÜĺâ–,šřŢ0І64á ł†=ŘÁŇÖŔG ^1đ…üâ <Ȃ|ék_üÂeżímB$­Áƒ9x ÷Íďyż˘YÇ6ĄMhÂĺĘiđAĐCSŰR&6á ž|Đá‡xÄg‚/,Œ‹ A–†‡_YƏŽcmjTŤš/밉#@¨6UĆ@-œQ˜+ĹH ë śÓˆ-9hƒĐetAfAQ‚YĐĽ Qň4u@rBÖľÉl€Â$j3›#żLI#OŁĚŇЁ— Ux ô6…˝ń­o~딳-mGŔŢá‚ű…[ťÁ|r$q/ł¸r×{ ˛˘fÁY{´Œ-ţöřń‹~†U—i’Ĺ3™ĄČ7 ykŢí‘NŽ6‹íаŻŤvT m@s\:Ée[řTç˛=nĎt¸,Ąlg{,Ňyîs  ˝.nęĎłáœÎl˝ëĽŞŇ`œmç|) Ć°ŒŒą7ÉŚ9Ř67Ř>†MŰ"X˛qŒŃˆ˘?xźPŽÓg9ˆ˝ƒŰĂБČęhsŇÁQf/@Š%ú&s˝óiPž–Ç|Œ‰ő/wţóĄç ŁąúËL|CŔ° |œĂŽŃ(†Á´=Ľ÷á*?âzđ‡W#ÖÞFQB>AlˆgĽ„č- 5%Ű2WV“'kţpę[żŘzZŁ˙ĺh˜Âűz˙^Ň>ŚaŹ3î~gŻ;8]ćt+ňĆ@Ř˙TžË†ý¸˛i ` şlňˇ35ĐđgŤá,í3ü7€l§š•V3Ćy Î@yŕbve2śZhz¸|ЁŕđnQE‡ȁČÁŇx4&—AŔPƒ×0 °3 š#–1B$-ë`GSň'Z ݖw'<˜mýĄ{ĘwxA %DDmÂc\NWÔd ŕ0ŐŕNxVhó]_`†hx‚kČOná†cX†g˜†u؇CRˆCÎ!–Ń>ňţ|{•AL¸îá Q˛u&ç$ą7|+W@[§|Ľ)ÇzÖá|*ŃIhăS˘V]G@ĺ@żf˘hɇpŠŠ¸Š­čŻHОH‹ŞČŠt,ăŒ¸0#¸RiańmOcŒŠ2#ÇrÎ8“1#Z0ë0Źç0Ĺ1#t˘Œ3˘?Ůh(Ą(ěPäÁ/Öh‡'!c3FŠď`ŠŐĐÎPc`ćUîhtɏł8őxůŘűňHöˆŠÂJwˇ ďe ÎP  p{áY‘Y‘p‘ěˆ‹3ś‘qؑ‰‘ŠĄ{hăH˘śc ţ5€ŠQ0 *˜Y-‹0)“4i“Ě•“/“3Ů5y“=†^ fĆ@аY Đ#=IŮKٔO•Ţ3•Ué”╢w”`!2ďĽcU ĺ@VË0ž“s_@–5`–hŠ–p!–_Ŕey–Ɛ–`™š` Ĺđ%EՐT$—g嗀I‚I˜zy˜`˜ƒY˜{šžŕZ€a ë° W§•ů—™™›)ů™š9™ŚIܕ †iŠšš§ůš°›™ľYŽ)›śš”›şš›źŮ›žů›ŔœÂ9œÄYœĆyœĹИc ˜Ę‰œÎůœĐŇŠ›t°œÍ9Ř™Úţ)ŐɜŰůŕš ÁœäYžćyžč™žęšžěٞîůžđŸđiÔ)ŸöyŸř™ŸúIžË™›űůŸ ˙ٟ$ z Z;   Ú ú Ą:ĄZĄzĄj ˇšĄÚĄúĄ ˘":˘$Z˘&z˘(š˘*ş˘,Ú˘.ú˘0Ł2:Ł4ZŁ6zŁ8šŁ:şŁ<ÚŁ>úŁ@¤B!Iaś<ý!€¤_ ŃpPĽ*†¤!đÚd ďŕ¤Zú ýđ ZŞĽJZ¤ Ë#ŚpĽhÚýf`JpEfC:§qWP \0˜ip\§}Ú§ţţŕţ P¨\ŕ‡ş§xÚ§ŔGŔ§ЇziŠŠxzŠ\ Ő°¨ŽZŠŞ ° tzŞÁß`Ř0xp x0˛:Ť˛z łj´:°ZŤ˛Š ¸:ŤŻŤłşŤłÚŞ#ĐŞž:Ź˝úŤÁšŤ´ ŁPĺŐFźóŐ:× m÷4ƒ€ai*ÁB0 8pŽćzŽęŠ~€z ÜŕŽëŞŽńjŽńęŽé:ŻčúŽčŠŻÜŻçzŻđĘŻęJ°çj`ç–m§ ŕzŔń° Š Ńfą5ĄąL5 `ą„hKĐ  Z")˛Q„¨/ŕţ!‡g,Ŕ[

”ł:ťł<Űł<[#>´Őń¨5Ŕ3G˛Ѳ a Nks>"1ŃÚ;¸gl?¨c";W3ŃFŃŽŃV Qś ’ľ!jŇ;CŇľ A %r[gűľ ňGŹbĹ!0_߆+đaLß4­nŤö0ŽzŔŽű¸Ž‹ ëPš•ë›š”‹š™ š’Ë—ş”kšŔš;ş–kşAş˘`­@Ŕd„ŮJ_[l„ťˇ8¸KŮľX{,c;m4w%;ľ€Ť˛1@Ë Ëűź Č&íţQŔചĄ˝ť2@@0"„8• Ƥ˝lRźŔp+ŔažŤ#žąGžlb H{+ÁË ݋ťâ#Úą{(ÎçźRřřžŇň'çëwzTż‘ň'*˘u󵢀&ƒľl, łűé#Ŕ0Â$<¨PÂ0 *ŹÂPÂ.œÂ-ěÂ%|Â/źÂ,\Ă6ĂŔ;üw!Ůƀ{닍2ýa˝*›˝í Éť:YČq1žĹ‘źá;rŽaLD,Flž,TěGLŹź42ł&!ł 2{wQ8˜ƒ ZÇ*tǑ8Áo+…’Á ‚ Uţ*ăąü2ʞ}üÇĚdqmk0ƒzÜwwŽźž6mťėŇÇ^lq$Óž‹Ňwŕ,Đ ({(ý‘Ćľ+;óĂ"ą ź 2ěÂŕś|ˡœ´ě0 :<ËťŒË¸ŹËľ,ĚšźĂŹ ŻKá+'†řŃP+š,…E2Ŕ(ĚVLŹťt@ŽŠě!ƒÍLl ĆçĚĆڜĘkźÍ1QťSPĺ! ";uŤG†RĎRkźuĚu­cżgŒ+ĄÓŃĎĆ`0’ži7Ď^r´ƒČu˛'32˛‘˝Z@_+Ď_ťĎ•-űąáĆřĚĎąˇülL­ƒţąn|ĐÇ€ťÉŞĄżĆ ş`ŃděşÂ" Ě# Ă5üːÂ7ĚÓ?]Ô>ÂžÜðąE;ëđÍâ[Ď%• Ńý,Đ#˝|tLĹÚë€ô%S ŃƄ…Á&TLĹU,óľČë!şŠ,˝Ök×&]ǁ[\Ĺe‡ ,@,ú§G 8&u!{ĆŘŔ0ŘŹ§"z ž’ŒĆłˇv PĹ˙°Ć“lžt ŃűüśAŹ×ě˘G›!ÍŕAť$ ˙ĆxĚГm%*ą°ÂDÔIÔ:\ĚźźŰťŹËźmÔŔÝÓI ŐĄĚI&„(ąG.!kՍţ]ň\ČWŘ z-iÜÜQ˛#ŃQÚNœ˝ÝiMŘ2QÁĆŤÇäí!k Úd(sÍ*Ě]Ňvl„cŮV}ß“Λ,qlˇĘ[Çţm„`ě%ńM,Ď}WŔą+š1˜,@Ő˛ÎÜŔĄlƒ$3ŕLĐë{+ä‹%{ÇŕS;Ö # ËD}Ô$,ă>-ăĂ}ă3žÔ6ŽŰ-ě° ŽźÓŞČĽ˘"áu,0HŽŕÝýŢYí ŃߗrŢRhäÚ+á >tŤßMžQ,Ń݇‚´üKŢj ŠiĚ·ćY}ŔÍQĺŃqÎŰŰ!źÂßÚžU+ďű'ŕQ3ţŇRçÁqŐ+’´m+¸ía)}Ý;qRŕ´¸˛+FžŐVmŘď;&N#žĐ jr†"0‡ç!ć1#ü[vI{ÓÁ..žmËÂÍăEíŰşźă#\Ë­nÜ@íÓŤ~Ë˝ÜăѲĚß'3"çŔđ˛"äÁî#eMĺŁíˆÁŽGŰŐ9ˆ´AěťG•n؉ž|e.DśđѰ "•ÉÉHĺî%%˛é8%R\D¨áTć+@ …ťň.;ľR rl’=€*“ăÎzŃ@śĘŚ…ľË­ö^ďďŹ'ťŐ:äYËwţž|Ç2€%ŇTA-`ł˛,Ô+ŹĂ;^ţăŔ-ë<]ň'oĂ#żĂ¨ŕLm€Á.śŔ#]R+zôî˛*ĂđF¸RźĆpđĐD6ď4|GŃ0˝ÓóŚN{ŮÜLŚňë­Žň-œÂ ë“đőľžő0ö\OšžëČěʍŞn?ýŔذÓ)_ÜŽ.ň,o÷gă2ěÓČýă˙öxáósqősŸŰgŸöa_öÁ]Ô|öšŒ /ĎöžŽ„Ď—ĎžŤő\Ö0Ž0^÷ˇn÷śžŰň6ţň­ŰÔ\ą_(NÎ͎>l jnťpa 6K÷ŔœëĂ<Ë(ßűĆ|Ěł.Ě­.š”Ż°w{śż‹Ţ˛ţ;źć›mwkž  źE˙ô/!mwÝ.äÁý^Âś[Ąžě{!Č+ĆĚ{äák(blĆ`ě.ë\<đ Řú1Îň@ýřŚ÷zßň%Ě!J 4Ŕ D˜PáB† ><¸€€™Č™AQ-,f AÖ ’ҢD ,@.@-ˆĹˆ#KB#)ę$0›,vR<5ѠȖś€AËHâRŚÇ@;ČÂhϓĆ,Z=Ř˜( XeK—M͞E›ś!L`ë¸3csé¤#׃ě,:“{‘/2AŠVńbĆL[¤ŔĆŔdʕ)gp9s˕1sţîú˛ć͖1—ŽĚ&Ľ(h­żNk ˆQ`ślI­-ʨ֚uÜćěj`¸‹ĂőŠĐßŕĚÇč <†ď^ƒXót•7mŘŻmie Ř t¸răf5¤ ě‚߁7zźű|ú;B3ÖтďĂuÇĘĽŤ:ýŰ .‹XŔ*ˆúd°ĄŞaŃ&¤°B / T‚eƒvŃ@„Î3]P:(@Ä,Ż:𰈎°RhŔHÄ*Ŕôzc‘(˘ćЉŔĎ"ŒGQĊF ÜqG‰`”qH)CŒ…ŢpŰ/$˙tąHÇ TĽuä2‰š)ĎděÁ$ðM7ßĚP5Ö\Cţł; ˛ŃŁşxËrEó„ cĐĽŽ;G¤ G+ĐĎó€řǘAw2'3ëth9[ÂôIóc’7QTF1Eu!:Hk¤}óďźěđҋ&ęxȍRĺ"TTc6"6Řa%6YQ~Ůd‘uVY˘•–Zb9 – ^۔6Űpë%ÚrőR.ż şÍ[• PŹÄě"ąÄŁC)ُ s[…š70ę’dnÓ&—D1]ƒĐŃwŰu‚H,ąTL ŤŰDúĘ Ş ’ O“ćř 26€Ś>Ţ ä Č Łœ’I6šĺĄ!cä–O&e•gvg—SŢŕŸ}ţ†ĆçrĘéX-gžbő薀CŠ˘˛ľH6  2& ˘<ô H4°‹‹Ł8°–(’K’Â*ú ht:čbY 0Gm˛ęŤyKMץďśh3`'¸Ö ü b„´Ep!óćueĐiĽÉ'o§t–ig0§|ň4źóĘ/sŃ3ßütÉ-7]ôÇ?Ëc—ťśę"ź­‚jŰɖź]ÁJÜ Ây?hĹg/Ţ ĺ_`ř˘ X|F›‡ë‚ąŞÓ:˘ƒd?vńÇ'ż|óĎG?}ő×gż}÷߇?~ůç§ż~űďÇ?ý÷çż˙˙`8@ЀD`ţ¸@6Ё„`%8A VЂÄ`5¸AvЃaE8B–Đ„' ALц|Á…!€Ą ]h\Ŕ†7ź€ żC%ÜÁ?žBô€BҐ„d!‰=,’č@%9IňB8V&5ŠÉ|ˆ’Ÿ%íH=°Xڤ@(`JV˘˛Ż|ĺ*YÉ!;Đ)”ˇÄĽӑ„5M&X“ ţš`2LfjXłť\6ә\/%$,ä ƒ`Ć0+cÍ@tӛÝĚ64§g*Ěvô[C|÷ť†¤łœ _ƒtÁK6Ť˜ÉŹL0ľI™@dSXńĐEaĽĄÄ“!ëŘUB’5“ĽŒAz PCϒĽ˘-T)qhB jQ´Pt!^ššĂâч\tJÄB[Z>ňšË  1é\¤őR‡ä+D €E/ŠiÍAŕ“Ÿ>f2‡EN reWGŠ^C”„›˘k§˛ŢNHŠ]€J!ëÔhbŽÄąŚÖ抉ęPwŞŞóŤ9ëVÁj&ß%QHžďvbSš†(Lś@@B‰ÇţNˆÔŐ!XMHYֈđľŤ):ŃA“ú˝Ĺâ DÖĐ@„|ÉOć¨Đç?—šÁŮĚf. š EV‚‰lJ% éęD@ĐŚM¤jŠç`"“9 ]‰ŇJoCS4ĽÖśGÉ]V[P͖ĄŞ%hhs Ú˛híR9›QtŤZš°„$2H[TË ŕDź=KžÎ# Œt„, AŔNÖ1Źcť­ŽEFÇf &- ÜJb#b-äHÝEŔwď›Rë’ O¸a"+™ üł—Íl>ý9ÎÖô(PYQŽxŁX 8UąęAŹv5“fi;bՊ-)“ćKźr™ęk¸ŇćđćI1Ҋgľ˛h­-*žcqí9aňÔ¤Ú˘%˘HôD ç0ĘŁÖfś]žŇ†Čb0*~:čţł;łś%ľ hŹH’’md˛“V35!ő>‰Ÿ`ŠkT)w¸–€á„´„Č\ý7ž˜ťJ­98¨ž%†#Äášţž‚ …ď‰oßżËZžxcćú|wv詎 ĽUg(ŮŢÍţ,‹Ú݌(Ä,Đ´"ť–Ŕ˜ŰG:ЅŢ"ŚŽvĎôéG5°1Muł˛ëśL?‡9T"Đقůb‘p=äčçRH¨Ç\|ĺ<Ĺ R’ŽrEf<ď§8ŕ=“Ú-ĆvťÇώ3Ošź+éă•ęĽăý{áÂ3oĎ*ă-]͗Á€°śŒä'MN ™ƒ‹pţgŤ)GW˘qîXż•QwMôßŒœ§wçÜ:­zťłádÂŰÂăaX—Ďöťä@#jVKßGô•°ƒ$Až2V%Š8#eqoŒD^|7aM]ąWĘň|Ż@EúÁŽ>ÜŻßŢŻ”„G݇ę@côđąU$çĹ9[]”ĆŞ‘đĺHcŽN鎮Âť‰ƒť‰˙ ćp Š`Z­„Ȱ0Żaó†“č?˙r=čş6ě@ [k¤i4ŢsˇŢăCË !1<­a§uPœ{á+ď,cHœÝ‘ÁQž…Ŕ칝Ŕa&SK§ 94‰'ĺŮÁęx9祹 ĺ!B­ńţ#¤>SKcŕ0ÝąBfňŤÁњ.ôBú ž„°ňÁ"řĐ`¸€+!ŹŽń7źÁ',fĘ­ÁĂďyBYŹü žb‚A„pš nú&o 'ß{§J´Äůą$#@Á“dâ=Oź:ŽóşK$ĹR,KšşÉ‚Dp˛ŒUlDĘ DS”ĹYdm@ˇÉP7TČ˝714O˘Ĺ_Ć^ąEÉú8ąŒX ĆdTĆ!ِ °hŃ,ia–i€Ž[ĆkÄĆú€Ů€‘ů‡Q™r`™™ů2ř‡ ů‡ĄÉĆudGĆ@Ö™ÖyGŐAÉќvÄÇ|ÔÇ}äÇ~ôÇţȀȁ$Ȃ4ȃDȄTȅdȆtȇ„Čˆ”ȉ¤ČIĄjĄŠ!˘!ş! w0…‘|2Égč‡g0I“„ĄxĄ6€ɚÉ~čbɍœĄňČ’ĄŹÉ’\I”TɕŒ†–”ÉŠdJL1"$R˘-z"(’"*˛˘Ŕ"-:$â".8‚&‚˘°Ä˘#Hƒ°ÔąD˘łä˘jŕJŻ,K(jK-˛Ę+Ę")ÚJ(:ËŻ˰ô˛ËŚĚ)9Ł4Z#<ĘŁ;˘#;2Ě9l¨#8b#7‚#Ă|#5jĚĆ|LÄÄĚ7ŠĚÜĚČŁĹŹĚĚ,Lɔ#ÓÔŁţŔTÍ1Á0ĆׄÍ6I–ÉˆŘ„ETÉŮEwJ˜âąĂŐü ,$Ű4Î㤠M:Nl@‡)`‡š ¨˝‹žKBLI’˜R˜§ŞÎôĄ8ˆü#×DÎň„Ík™MŰÄMPt`‡čŹ01€1˝łR8§zŤŮŞB‹ô§,çšÁŹÂšŹéźÂ-ÖŘ b‚Ú;š1`gŕ7î\mš:ëź ś1ʂœňÄecDŚăŃ×ÔEó'\܃vh†fX›‚䂋á ý"­łÉ/’žó,Ť °Ą>㲡š îLV1ç3g¸ł„@ňŕţŔŤ:Ť~C+˙äO°şÁ0á6TąŠ#ąŰ S´şN ,DďdŹý4+ľţDS<šÁ7ĐÁÚĎ2= œcŇSdb Qă,Q=NÉiŃU(+¸ĄˆÎ5ƒ˝Ę37ă2ůH‘3K23ĄS2ň8M•ŰX)÷ŞQŠňŽ’ˆB‘/ íMýňžđł?ň ˇ‹Č Ő Öë ­ Ż ,§Ť ęâˆň˘@¤é’ť9‰ů ҐˆŽƒŔ°čŐŰ-Ě pŐĂ@V!•‘Ŕ Łh-$mŠh@Ľ r˝c:NtÔă\ŃˆéD­Wł´ó´ŕٍó7q ­Œţ:śŒˆhťOŔ XŮTp­´‹Wű7}ŠiĐI,–2ÁB+P1€Mٝ‚‚ ťöđ,.-š/ő mÔš ٍp˛“ŘŘŤRĂ9)ˆçä“5‹ąPÇKŮVsC‹őšxi™•&˛Ĺ˜§qýÓĘ0W IZ?]×Amw…×äውƒŒ‘8#ń0ÔŰŞZÁs;šă‹ŮŘĂ3¸éě š‰˜őK˛é ż°óÔÖY…¨l5@ǒ@‚ ݐŤş˜´…4^ą?§ÚÝj¸„’ŮNš×ŇS@+Z2téapQ6 ĺţ˜ÉKbŠ"3)ž ‹ź…Hbĺő"~x ^= źĆ#[(Â9k6Y čĐ1îŔUłP0ŁQ &×:.];F] Žŕ ƐĺŰ­SŃB(ŹÂŰ!dżá›A6†@|:äŽ4Tˆ9„Ş´Cë9ˆÂ N^1€ŐęŠ ¸ Ť‰y=T6 ŘóŤášQŮȲˆą9šą)ŒđŠ]1_ŽÉž–8*Fĺ>Ž5„xe’-NFĺߪżӑ•ş?¸Ąáe“pfd抙bŢeVy>üJ™ăîÓr˝ăpFZ؝`>†MÉůălTů_,–ÂńÍlžuždŢŤţ`&ę᷄ f Ď´‘f˘ -čĺągšŇgtaőäçQˆtІžáŽ€Vh{ö‹žă‹hč\(„ž8\ Sxŕo6Ś ™ăÓľŕŇEénFéÉhisn“dád ľş8ýÁłÓůč Ŕ†Ýă]Ý;ţćÉ ×ĄvÝ<†ic”išvjظ=<6iqç Ů㥞vxÚ ß$"°V LŽ k ÝqŹ>jŤŽŞÖę6Aç–’Ž­WźşťnźîŸ,‘PV3X ˛nÖc:NjŁNě<^lĹ~k7Ađ`TądłPˆhŞłÚ˙ěŸĘnŠË~ˆţĚNŒÍĐö‘Ó‡Ŕ1=,Ľ ÂţéĂNëĄ.j@j ś`¤žmÇ~l ięúP㼚čÖőšH/°RŐ5 ˇŔ퐊ě - 9›`›÷ůmîNć0>‹™ÂäĆ ć^˛FéŻčžîœŘióšVh°Đ˛đÔýpf °ĽY ˛$ňÜíýf×v˜ěúpVůŮč€ ĎbZź‚(ĂČšZFŕp\ŕP2÷ pś8 mXGpSđÂ>]˜WâŃK˛>e‹4`ßH,-`Ťĺ@—7† ŰăďˇMtžiú3x”Š˜VÄř6Š4ŤŰI őľKţ,#^Ÿ7`ˇ? ďŠAňĆąˆš˜Ś˛€%7qóÉÜÁýŘŐ™\ mˆ,wsc”œ÷d˜đÉߗł‘œ†ŕŤí}ł1ć¨eÇŇ.‰:× ;'š˙Đóŕóäńs1!â^•Ű_ƒ0t ˇ ű,+Ą ěĆÚŔ^ĺł fÜĹ7Gu ‰sř\~a/ž—Ü 8'Ók2rĄť[mÂs;ľUWoXV‚2›ZŸT\š´]ŃußńGsŸ2ŽTš€‰œo˙H^7T 5w Šə]Ęůvp7q'÷É wo÷rGwuo‡soww‡÷t_wsţ—÷yŸwt@‡-`őúŘ7Ŕ;f›čM͘ąŘ˜%Ů@÷ęäŔ•Ÿ~_—ŻŃ€/2‚gž+‹q…—n†7íó^˜†y˜ş8?ô‚žS˜ Bg’KöA>L§LŚgáé<ŃĹšBŔIoôiyăyyô–2yäᛯœwŸ‹.Ţ˝‘h(ÜÂ{Ë{ꪡúŤÇúŹ×ú­çúŽ÷úŻű°űą'ű˛7űłGű´Wűľgűśwűˇ‡ű¸—űš§űşˇűťÇűź×ű˝çűž÷űżüŔüÁ'ü§Ĺ=@ü=Ŕ÷ÄW|t`üĹO|ČG|ɟ|Ǐ|ËŻüÇÇüĆß|ţĘ÷üÎÇ|ĂżzvwŇŻ÷w7}ÓŻ÷ҧwu}Ť_ϜLĆôĚS ýÚżý<˛}ٗŁÜWLßÍS(ňI–‡‹ÁŽP;}Pś§úÁúԏ Řç}<@Í<˘~Ţ_ŁęˇŁëŸ~í#î÷LęWŕń‘O'}~φÓăeˆ(}.űěO2˝Rî8í…̤_Ę΀u : ~<(„˙ˆB^$dˆ„ 14$čáĂ'ŞQ#ę˘(T¨0r̸ą#HŒCzźˆÝ`*W˛léň%̘2YaéĚc€-@M`aa ˜-@,YäₖëXcąNeŇĽ5ł2EţŞÁÎŞDEEe16ęĚ´jײmëö-ܸrĺÖ\) Ř:´R\m Ę­GWć]ů—°ŕ—yűŞ\ ×%_–݌<÷ňL:x6ę,ŕŔƒ&l袠‰->-ÉąőH’­aol-ŠöERbîłîʚƂłŞrLP`c C@+0 ş^BٜyóçHłCG`L%‚źÉX0ހďôę׳oŸ8° DPšRaW%¤ďPEeAT˜Ee*áWÔNYq—Đ @VV`5–_T ˜UvîÍľÁ!zöh˘Dši¨A¤ZEŮv[GłščI ˝(J;ţí<áĄowąt—NŔ gX@X_tßšd”W*!ů¤@˜RZ\•••nÇÚÝ É9ĂÜai*čLKf…€ĐI‰^sJ†g“€ň„Vfzšˆ"zZh&˘ŘŠ­V#ĽĹViHOíąc‡śß:„¤J@üc ޔ闒,ÄSO]ečŞ4ĄŠęQeŽ,Đé)°Á ›žĄfUœ>ľjZC`’B5;^ŠĘ:ْ­!ĺ”â%ă!9ŹK#l†Çˆ%:şi§­¨Z ]*ŇG˜ş6ΎäŚe' Q:žţ3ăÝůë€Ë–úŤrA!€ps‰ŸBQ1Šţjź1Ç*Ë,™BJH(šÓFw*ŞWYŔN´<íˇ’1#ă ŤvÝş€Ćxˇ€.ßeLkÇćrśhAë–ÖފđĆŤFž4bžőv¤[§Ó´A(9ęËEÔTZąŠßc´ŢvWh×(X,ă”Vym ÄVŰ}ˇ—`öÝa”!y˜ĹlîwÔą-;גßëŠzْÔ`G y-Ţf´ryŽ­,óç{Ž›çœ/Ł›/”N:ꥏN:珃n:뜿îşęłŰňşnˇˇłGżxŤt벜\e@ŐëÓ)Ş„-KźTƒ%ţó˛¨ňi ŽX9VąďŮkßŰÇĽ"•(DąĐĄ÷ż'ç5QŃřľKásˆ—Rt‡Lކn 9ˇpű˝}oPăż[Čż°€´[ôƒžuđémUĂËôł•ŹƒpoSĚ,Ó%1°%ŐĂĘ۰ °„&ü!ƒ(Ä!ąˆF<"“¨Ä%2ą‰N|"Ł(Ĺ)RąŠVź"ł¨Ĺ-rą‹^ü"Ă(Ć1’ąŒf<#Ó¨Ć5˛ąn|#ă(Ç9ŇąŽvź#ó¨Ç=ňą~ü# )ČArŒŚřB $ţ2‘ďÁ3HXČIRr€ęŕäq>Ź`W Ŕ:Š‹$T˛”6| [*˜U>QE¸Fpa˜C@€˜˛—( I|\B ™d+-Ĺ|â čŕ´Ŕ ƒ)|Ń-ĐÁHă}™Dřœ •ÔŕŢ&ҔŞUyIb:嘘€Sœ,§ď: qŔ˘ ŕ€)8@KXŔB08cRňƒt˛d˜cx 6gŚůÔ§p Ňśŕ‰o@:“XňĐĹB˘ĐW¢Ą˘d¨~äĂ6 Ň ücžXVş—ÖQÉdr̄ÚLbâřV‚N9cţMmRɛ˘ETh0ĚcBmNžśł'đř‰˘JO ľ=.X Ť\X@ř Ž9TŁŤQ2ăTZÂ$3 ó/ŻzŠ7yúÂî‘)YĐŔ`á÷Źôf˜C“ľ‚YPmqËmŢ×_›=„hđđ0 _̍5cĆĘgŹďł…r!] —טIÔ/&3Ő­TĆ2Ŕ-€Ś"+-ÍĐÔ*QÜ,g;뙐ôˇ˝¨Ş€Ȁ…rŒ pP…*ȀYj e:Ŕ‰ß$ůŮ歜ŃJœlÍ'¸§ŠÖOÚyęľś¸•4N¨ƒÎäëť ˜Ą˝î}Ż{š€ÖúŹd­{Jt§KĂĐ~ŻLţâ;éhĎ÷• ôuŔíű/ü¤T“źŇO|>Ă_ní˛=r$ĄÂH‚„‹$ô“ŸS8Łxq椟*5ŽúUa)¸Ŕ‚"L'-¸I:đА#Ô"e„'^ORچ>ág(ö+&ô#ÝCŃłLNĄńd<ź…•S~2–ł,°ŁŠZţ2˜Ă,ć1“šĚf>3šÓŹć5łšÍn~3œă,ç9ÓšÎvž3žóŹç=óšĎ~ţ3 -čAšL¤ ˘ŃSźă Ö 4¤Żx‡NRz¸‚ްÉHszŠĐeB=\ĚA E)ź—8† ?ĚKbÚ„ÂpŐ>ţ´u đšf\@p¤#ă›Kf$>ëĐôQđIe2Ň1řľ7ýk=•ě˄O¨AŘÉś‡nF€Ÿ° €)~á‹_ôcü¸éëâě_ľş%íŒuzWÂ'ěo‡˛Ţ7ŃIΖٛÖ0 Œ^vúNoś¸2Š÷;;ĺÎ|cF>}‘saŇpV?<֕‘8ž3^Ă"ŹÔĽž8ůK7p„4ÇY žŠ†Ě Eř7ALĘKƐŸ_š>BşÖ W!˛H ۃ‚ơŤb$Şź•,¤’hQ`nŇöĺ',Q˘›Ôe>ҀռGĄň ע–ĽxĹHa…ÎÍVu•\˝n1ţßĚIÚuv€]…Ĺ.ŕ‹ ËůCžÖB!ŤHš  Ž"(ŠŰ$Ú;düym!ŠŁ„‰Ş-+œM­ ¸Q[ů \ÁŽC(ĂKŢ%AŕSFƒŇ#ţމíMMÂSÂOÎmĹą|sŽ„¨śäô*I˝Ë O˛Ň'ž~Żż!6"<H-Nöët_ëo+ą59,÷Ç—łą€éÄ ‹ä ™“ÖwôŰfYĚőٟö!–ţÉP5ra WیőĹT ¸é–Îź n1ž|_ţ᜽ÇřL^Îs•vĽ4Ę´éEţH˜ü•ÓFŘĎÉmůŒČɅŽNäÄxôŸÍ JbŕŢě`úyŕŸ %|Ua9žŤ¸ ö‡WDN÷ ĹĹŃż!…`0‰äQŢ}Îa„x ‹šüß}őIČI蕨ÄM`E˜LNčĽ×Vd”äd]xFG †EyAǸPŽ-ěĄ*ŕymGĆP† A†Y˘$A  ŐW(E×ŐĹŤ(Řń•âRČ`}DI<‡3äGT‘_ČÎÖqÝ:…DáDzGQp]’šUr@qô`8XŮ=Ű(ţ„‰ şz/G}ŘŰLI­˜5Vˆ(f )6cvQ] c8áŤńńŽýŽš˜<†NyPM“1ŸŽ ŽaP˜h82Ž™#Z #f(ĚŞ­ZŹô4L $c$9VƎ%¤ÁuÚ$­ƒ,€ÎůË"ćĐHr¤Iž$JڤJŽ$Kś¤Kž$LƤLÎ$MÖ¤MŢ$Nć¤Nî$Oö¤Oţ$PĽP%QĽQĽ;Themes/default/quick/quick2.gif100644 1750 1750 35717 6720035226 15476 0ustar denisdenisGIF89a6ç~†\>ĆŒŚž„Ćœââ䌢„ö ćÂÄÖŚŹśJ4ÖŇÄś˛”ŢN|ÖĆŹÎĘ´Ţj|f˘tňňô˛˘¤Î6$Ҳ´Â˛´FFDâÚÜn–lÂÂÄچ”öâ䎪”śşŹÖ*$Öv„ÚšŹćZtrrtÚÚÜęśÄú˘´žfL˛˛´ţŇÜö"D†‚tĆ´öÂĚÖÎÄĘĘĚö.LŽ’”ňę쪪Źî–¤ŇŇÔÖĆĚVVTÎĆźžž„ęę좢¤îNlöj„úúüśŞ¤ÖžÄĆžœňz”ę*TúžŹ^^T&ޜž˛œęŢäúâäň^t†~\ŠŠŒÎÂŹÎÎÄî>\ö’¤ÚÖÔŢĆÔöRl îćäňĘÔŽZDFş„ĆĆÄú‚”ŽŽœžşźzz|úžÄžśźňÚÜţĘԖ’”ŽŽŹÖĘÄîrŒśŽŹĆžÄň*Lö–¤vŠd6ҔΤćć䌌ŒîîÂĚŢŞ´śś¤ÎÎźţňôžB4ŢśźćŢÜĆÂźć"ćvŒŢŢÜöŚ´ŽrTśś´Î–œVŽ|**,ę¤ú˛źŢ~Œú~”ňFdŚbD‚‚„ö<âr„ö6TúŠœžŚŹÎśźŽŚŹöŞźššœörŒŢ&▤ţĆÔ^VLúvŒŽzTÎşźĆ>,–nLFŒöJlNś„ęĆԆ†„ŇŞ´ňćěň&Lţćěöb|öŢäúÎÜööô֊”vvtňîěÖÖÔîî쌌¤ţţüŽŽŒ~~|úŽźžžœŢžÄśN<ÎĆŹöVt^ZTîZtö>\ÖĘŹţÖÜĆĆ´žśœžžź––”ÎƤöNlşşźś˛¤†‚„ÎĆĚĆžŹ^^dÖĘÔÖ˛źÎĘÄÚžĚî*Lö^|ćâäŢÚÜś˛´’’”öę쎪ŹÖŇÔţúüîŢäţâäú’¤ö*Lú–¤úŚ´úrŒŚ˘ŒÖŇĚÎĘźŽŞœÎĆÄśŞŹ^^\δÎÎĚÚÖÜŽŽ¤úžĚŽŽ´ÖĘĚśŽ´ćŢäĆÂÄÎĘĚ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙,6ţe H° Áƒ*\ȰĄĂ‡#JœHą˘Ĺ‹3jÜČąŁÇ CŠI˛¤É“(SŞ\ɲĽË—0cƜIłŚÍ›8sęÜÉł§ĎŸ@ƒ J´¨ŃŁH“*]Ę´ŠÓ§PŁJJľŞŐŤXłjÝĘľŤ×Ż`ÊKśŹŮłhÓŞ]Ëś­ŰˇpăʝKˇŽÝťxóęÝˡďW€żQÉŹ°ażˆŁ%fŘ0ą‡/ž ÚdĽ˛ĺMž 0i…˛gĹ C{}ăšsçMƒžaFŮňĺʞ7˝ éşłč۸ŤŤmůąÂ7ƒ`óžy¤iËš“+gzĄtk+~OžźŠôqËĹEž†˝źťwĄ/†ţ[žđ ď/äe˝pÇÚrÚŻżËŸŸó‹ő؛ž$´nĹÂ7ćY‘݁ ˜Đ tÝ&ô5č LÁ‰gĹ šSƒŇšƒ íšśÉ čDL„°]€oڍ˘I'şVuéäNk­ĹY„Ď W݀ŔU'!+)dGĚźXmčÔ˘kƒ“šC-ć8Ü{7œ”Č Šĺ–‘V›@bXĐ^63ÄŘhĐ 9úH#vuČ߂śqiç Ĺđ3ђŁo]Ŕۛ1cŕ@8Zö…:Uş#¨T˛YŰ Ů-™%ž˜bÚÜeä…çZtŠóZ™Ś}h`×YĄĄA(P*:ţÂMhЅ™Öj'™ÇQˆhŠV8á†ă•¸ę@"‚~xb×vvAŔ†eÝ@¨~8ˇŇ.;źÉĄęš*Ët°.‹Ó;Yý Ĺ$¨3Ě[¨sŒ5ÇHŔ—Ő6ĚÁG ܞűî˝×%;í5€ ‚7ź<Âťď áú\şD_—Ú˝”ˆÂ“(˜÷Ţť› ›R)žkN „žË8ÁŇÇ ňSŹÎ ˇż°1Äź˛6^ň{/Lą@ ůŰ_˙ţ—ÖŻv@„1¤a ţů4Ó2 Ór-ĘřfIăóQ°ÚĺžUG„Ś)ŽbĺśËč$!h4^ŃÔP€Č œ0ƒ>äeţ}xCĄ†FD ÎČá^°ĂĘˆB¤!íÔÁŠLpA ŕĄúʸŽ ť1“@îu2RUf—S™°*C%Y´ÍŒŘBYNJP„hĄo X40Œ˜ma<Ĺ0¨g—ź E@QT˘řc CÂx´a†˜ ˇ˜$!űâ)á\.hmšÍ <×3ĘTË îˆWĎ„°2 bzÉzŠ3ź˘šě Ž1Œ>NB“ŕ˜]$5 LÁ>Ç!¤0Ěbă˜ÉŒ 3I`ö!y@3Ɛ‚T`™Ęě {óĘň4ŮycĘX™Ěœ˛ óţ3Ô4˘ç "áœNŚ1d‚ ™ěCWĚXXcŁxÁ(ç˛M źÁ‡pÄŒbĂĄ•(\*ú†Ŕ†x†¸ąŠ#¤ĺ`ÜěAA( é=˘š&'Ť ‚ŒĐŽc †ľ& fa kĐÂ;¸‹Ő$@Őař…qŒĽ6őŠQ}ËTŤzTŠÍydŞSĄÚ/ľü ’C Öa¸>ôá%b1 Z؂wůUWąŠT äƒěŢÄ*@„ˆ…ŞÚźűaŰD‡ŚĹWŢEÇ|čKľ UFC3bPčô•K“„ܢ{ţ#k'!fZĢÍˤěČł=ŒŮ×ţö §íî›íű*/•ŮLŐ1tď$)dQ߄of$ œ˘€Qʁ>ëłţS§ŇÔdĽgźśŹýžëeXí՛~đʋ_Žéž;hÚF“–Şć; lA şŰÂŔae6Yůgxű׹𜀠F[dčČÚ" îGp›ŔsÄroܲPÇň햁‘|!(`qÇb‚(uŸ6‚ůbvV@iň:§2˛đäŁ(8j—†ĆL@DúăüG{śĐ لS…5ĹľFH H¨„L×M8„Ex„ H…Š÷8¸uÎgIBo˝˘'hÄjąryÚG”ŃF’ç!ц%tjHľd‚lÄx•!ad9/b2qBxR|ś[ł` ţ“` #` ˜fˆ„5„…“pˆ‰¸ˆč¸‘hˆˆ¨ˆŒČłŚč@,ŒQvhRč€ęĂ !(kp6ĽˆĄ8ň„jvslŸćŠí‹Á!…A%Ąxjůň´0Š*Ôk!˘Va„¨e0‰N0 Ä0ÄPÍUË8rľăŒĐ(Ôhr‘ÍřŒ,ćŐx6—ôBd]šĺŠ€ˆ­P{ąŽí…ďňH0Va÷řŽń8 óX…é(?€5yÄg(@ Š@ ˆř<Ŕ€…ľł ِ‘˛E‘ ɐ9 )‘9ŤŔŽ}de` _Đ đčÉł%)ţD(Š’,Š.)xk“'éŒ4ْ/9’gA1Ö5Nĺ#@ eĐčč8Ý´DI F‰”JyBé”Ey”Iš”@%de N0 =¤•Rő^i `)–SY–g™–cš•j –Çđ} rz!—9Lv‰—rĄ—tٗp9˜B!\Ť@–va˜ˆI˜ŒŮ˜Ž9÷w˜9™Á?–y™˜™™šš™œŮ™žů™ š˘9š¤)šhI hyšĽššŹŮšŽůš—i ¨Šš°Y›śy›Ż)›Š‰›źŮ›¸ÉŠœÂ9œÄYœĆyœČ™œĘšœĚٜÎٜł›Ď9ÔYÖyÁ‰š–ţ‰ÜٝŢɝÚÉ?ß9žäůqF噞깞ěٞîůžđŸň9ŸôYŸăI™ř™ŸúšŸüٟţůŸ : Z z š  ş  Ú ú Ą:ĄZĄzĄHAtŔ,đú °J䀚ŕĄf`$ęĄÁ Ďđ $J˘uP$Š;/J˘/Şęđ˘9Ş.ŕ::ăđ˘?Z¤FęPPFš ăđŁÍđĘĽĘ0óĐ Oú/jć€8 Ľ)ŞŁ?*zŔĄ$ş ˀ 倡jzĘĄ ˘"ú$š 'ú)ş˘Т‚Łä0Ł5şD/@˘‚ţ^68„ ¤„Ú`Ď࣌ ¤Ž:ŁZăŕŁďĽR*8VZŠ‚c[ŔĽœš˘‡Ş, dJfZişŚŞ*ŕ7€ 7Ťą Ť˛ZŤ˛Šśz:šŤ7pľş ťŤŔšŤĂĘŤÄʞZŹśŠŤśŞŹšJŤĘJŤ]ĐŤşŞ­JŤ˛Š­ĆĘŹśęešzČŤž*ŹášŹĺjŹäZŤăşŹźşŽĎJŤÜŠ­ÓZ­ŞÚŞ˝ę3 :07üZ3PŰŻWPupq° ť•P đ@Ű pw  € ¸ ›‰'pžŕ đš  MĐţŔ0ł6Ą :Ť<Ťđ  m0´m€F‹„´„Äŕ ž`°ĂěŁĆ¨sBăUkĽç3  &aÚŞž:úęŻ;ě€؀ K°=”PP ˰ ą;ąkąŤąëą!+˛%k˛)Ť˛-ë˛1Ë4[ł7Ťł: = ´AK´E{´JKÄN ľ$ ľ tŠč‚"bg/¨ "Á!Á-ş°ŇNQƒ !‚Á Špqt†g¸JeĐ.g¨ @ąŠŻúZŘpśýęś;°Ř`°yްuą;ąwţ€ąťą빸0¸${€˛Đ,Ű0ËŠKł7:kłËł’´B[šF{šł0 ńŰđęŔ4°öiŮa(´°”/ jJóS‚ók˝¸kŹBş<(°†kB|Ŕbë.œ Pń´Á2Â2a{ŞXžĆ§!L Žk Ť§ŻŘŻ:°pŰŻo;  ˝ ąy[˝ŘۡË˝%ű˝„[¸‡ű˛č;łŔ¸6Űž8űžń;šô‹´J–ůťżýűżQ'ľ‹Fdx:áÍŃ4…Ňt›łnUBg›ct´ŤťÇ ĄŤk|Ň*ţgÜN0Œ(ƒqg<eđÇ ‡…q&ě>tŚ:AĆ‘ÇhěĄ&†m̆o<"şë:O×4A!)œÂżŤ ] ź7 °g[ĹëĘ9ěśĆ;ŘpK } Á °{ˇxŤˇ{›˝ÚËą‰˛L|˛)Ű㋸čĹTĚžŽ Ň ň;żA{´\œ´1 ''D1pŸ{&°ËÂźŚ)ÜÂU˘4Đ×+a"Eˇ*`#¨qěLJóÇc*öŒJîÄ2ÄĚjЇ!óL&>Č ’7’Gx<ΤhÎŔ¸*‡3и›Đ‡so˛‚lXÎŤ#ONR̟tĐąÚśČ[ţźh`Ă °ľ,ËÓ˘ŃëËEꎀąĂĚą;˛%+žăŤ Đ PÜĚRܸя[ÍC{͖Ť´Ű|B›ŕÍŕ "tćź9yLpŤŇ*Ow8ePĐqňbŘČúŚËxí‘$‰lůqťĄĚ ނ2k˝Ö`r×qhş­R÷VU "‡ŐľŤŐÜŐńŐc}ĄLéňđn-G˛Ś!ŃqPŔ :­Ż°ŻœŇ:€ŇąüśK0ÓŇűËŐ˷ٛÄĹ ˛<ÝÄO<ÔéťžŽ+HÍłJM´Ř\żKŰ6ž1r9$aĎč é7‹­Œ1ĎĄşy-ÂŻţ{8b œt˝Ývý:°vrOf=ĐíÝćÝtfMĆÔ}ľ7ŠǍÉMŘ/Čžݨű*ě­şˆ˛đÝ:­˜€ 5ŹʜĂ8|ÇűŮ-­q>L`Ú{ąŐ Ě8ÍąžÓƒ‹Ě°+Ô´]ŰFý¸‘+ż”ŰŰ\ěNŐ;ÜńŔsĚkĐgo*ôÖ޲ÝxMpď~´¨/gŢÍÂk]Ţn(_p,˙̇ŃQ×ú,Gđ÷ä-É0Žť2Ţăâ q6ދ! ÍtOמ‘ä´¨+Nž ě€ ĂëýŮ ~ŕ ]ě`C Đť°K˝ŠMţ×롲ƒk˛>]žM@ Î\Ôś-ŇÜł>;ż'žÍ„pÝL0/ţ!dPŽĚ'Öp&‰ěČmGŹxŢ ›#É.&ýęřĚj‹lö‘† tşćsqlĐf×¨ÂÇüílr&@Wx\ǝПNťĄž8w&MbÇqŹĎŔ~ĘýíG~ä j~ÄëćúŞŕmîí>ç$ .Ä Ťç{~áށčNž-›¸é‹čF˝č=ŤĹ~šP]Sé!AÝjé VQ­ÖF/ LJw9môđUjf qŒ2ńađRnđ/ĐFĎxˆ|ń cÁĚŢ ţđ!đębjđ}Ď1o°~Ąt6˛ňqă9Ľ IŔŁ$ŕĂ$@ >_1'ôÓ@1;Ú€mJżô4dWwĽôvEMĎôRőBŻGGĺôRmRT´óőQ?;R?öNT'%ô+â@ŻkšI`ôg_EßósĎšAô@Úzôő´sôyÔ÷'ĽPgďőyœ{řZ_CHőMűűřö|ö ĹřxŻölŻŚÂ ÉšŽćęůÎJÚáęŹÍÚůčzʍ…qúŹßú7 ů˛?ű´_űśű¸ŸűşżűźßűŤÚŚúĄ!:˘%Z§wJ,ę˘0Ł~J6ţşü=ĘŁ/pٌŞBJ¤Gj¤Ię¨Öߤ.đ¤R:Ľ/Šď 8[°Ľ8pţ_ęŁ. ŚĽjŚhęű üo:ürJtŠ˘*Šüy {ĘüQ‡š-[^źx ”ƒŐAqńJ/žŠ‹˜#Ć:u0şp1ŽĆwTv°Ůźwf,šŰ‚L3fFdĄ‹Ë–•+'KčP˘EEšTéRŚM>…UęTŞU­^ŚUëVŽ]Ÿz sC,:ą7Ȗ5[ölÚ˛ž°˝qí\š7v횛wîÝź|o0cŚWđ`Â]şxEœXńbƍ?†Y2VÂĆŞťVó\7Ĺ6 ţ>‚7.a˝kŃŽLZ5iÓ]ż†[ölÚľ{` śĚîźg¸sWŚ÷páÂgĚ(P X°öāž§Ňô:QŔŢŠ“‚; ŕ•E|–D‰Nœđäéϟ&í›Ŕ†Mú"܏ Hż -Zü° Ű@ +6In“MbˆÁ_’#vŘIě Pxƒ+´zá šzáĂŮ,IJ/Dᅡ.$ŞCmƒ1FqÓÍ8߀;.GsLޘbšƒ.:éŞűťě:šŁťďÂĎźóţPďM4i/>ůęłżý %”Ož pŔ|Ł€MŹ`ĐA%¤Đ+fA+ž@ţŠ—z˜ĄŹˆJÁMĄS–7.€SN:7š`¨76af*fÜĄíÍ8çŹóNĽňtŠ™ âDGĎ7 $Ă.(cĄB•1UU]Ł#Ź#r,lt U‡ă|ۍVlfˆ'ž`~lîč>˜Ž"?HRť$˝źóNp2=(Ý{OůŽĚňž-ťěĚ0 AâĚlЗ“ë ŻÔIT( ‡ęp(f6t—ŢÜiT¨Md‰—¨âSĐ ôź _A7´â‚;ż(¸) -E‡Ţ¤J|¸E‰­bWQ‰ű•e^/ _‹_ 2ŠbFOYˆiôю7$&ĐUgŚY1:P +GYg­őÖX{ţ+ƒÖăúČ#悅ŽŘc­SvŮ%…öŮôÔŁ–+ąĹ/żý¸Őâ˙pĚMúčCAkĘ=ˇ€t˝*Ł]”7 …37IŃ t.ؗ¨šMXSS…łá˘–ßOÚdTŔq.JaĄ!đvM~Y(Eá‚MçÜ4qĄ4EUŤÚ> ô¸çŽűÚ{e8Q™(t ՛(S)§\ôšwç+rťÁgZăyçt=gˇyČ +‘ÎŘ"TÖť%iňY(×k‚Ę÷ŹÄ2kýîÓ"”n˝`@ 9ĐOrÝO8{3ĺ;Y*fY(ď˜v’Š>t ]€vŽ# áţĐń…2,˛PŘˆŔĄŕŻc; ž<1ËĄŁpí"eAý]Ľ~vĘ_žôÇ?— Ş(üT†E2t(PŹţBE bź0$ë]…˜d$A,ťĘ•­fpŽsЊ‰Çq"6”Gć9OHԙޑ”´¤ń'ZQbO•°Uń â>ćëĎ×Ô'śö˝ĎOń›bňô&:Ý 0›ÚíP'wŹ ԗźNf7Ŕ dV(d˘(XťČ™ŞFŮD†ňF8‘QŽ'“Ĺ#/˛|1Ύšr`UćxĂOâqv–ăŁé@ćą(ęp×ŔdA¸Y ĺ .KÔ ą!öҗDé‚enţ +ĄGŠĆŠ•|3l$Ç hÎs„DŹcaçHRx°'žgĄ'Jl@•Ž6ŸliM?\S٘ ä§1¨˝ĘAł¨ý}ep‡ŠNů8–E’(" äç6Dˇ{–d˝Óá )” XC‹ü1Ź‘ŻŐ1Îc{¨™ÉN6j÷ü×VčůQ|ę“vüę狺IĄp)"[,b* ÖRŚżÄi/ŮźsđLGžIćnduœiŕ ðbö0¤jR zÖS@ť)­?ħ ­€|âCŸ2žł?ţ SŘÂĺ>7*(}ˆ§W˘(SŁ•rЈöŮÁ=•ěd¤RÔŕŒ"ţ¸ƒŮt(m‘ć` AzÉw]ć Ŕ?Žě­WYŤťÚúظ–ě¤•Ź TšęŠSůk%ŕpčל–śf@ČÍ.Hź]ÁJ8­ećŸŕ†` +Đâ‘(pM§GŞN‚’´Ü“Urr5ôŮ×ŔŞ>)ČAd[H0€¨őO…¤WýfA\RťSŁ%Ż }Ş`†Ô+g +čiŚĘ Ŕ9MľËc/`”ćkšŽ~Žť|Ľ ~ťűŚěţˇQÜőîÁë.ńşîMąc]Á4'ŮBž¨Ś4ýB†Mťašaƒč؅ϘÉÄĄí‰Ě5H@¤"MŠL͢SąÉŹţ¨6é‹Ó˘VŻžăf šh\.s@WA˘nb.„Ix…”_ô꓉R€1ůřk‰^ˆ”ý•łƒ-JdWdŠ+ …ĘxƒŠŢ0Ř5ť ̲ÔU–f'÷+ĘG9łť Š”28ŮrR™ż.ËaBĂ( 5 DiLCĹ˜FŻ]ԝľŃ Ů^ąiNw:B›ţô+’ÓiRżBÓ˘.€tOM6˛EHŐ‚u˘IŔęX÷!ŐłNNҖ6qˆŁĐżv°…*d #BŢ5ŁSä<ÚŃ$t0 !éĆÚŐ˝Ştľ“ŁęjÇzŃk˘6ŤŤ}Ö^•ŰÜ´†uâ‘mjţŁYşÉéő°ĺ=oz×Ű+ÂŚ_ü"}‹fß7Ŕ´hř=Ż-˙ćw`ţ˘pƒ7ź,â0€˝%>qŠWÜâÇxĆ5žqŽwÜăyČE>r’—Üä'GyĘUžr–ˇÜĺ/‡yŤvňš?`  ů@p š×d 4F0žńŒ ¤#)ČĐ2tu¨cč ŮHÓÇ1ŽĄƒÄęWwępőlŒ$Í0 Jć1f€ýC7‡9d’öš4="zĐĂNz˛ lćwÇťĹe΂šŰçH.xţŸ“čÁ8HŃÉqt‚!äPCň‚‡`d!ąČF4’‘Žhž"$ űITböƒŔţD&1Ă3‚=č„'äđ Pň>{ÚĎ۸&ć˘{˜F,M×K]říď‚ßŕ˙FřeöR|´đ~ßźoMíĽ?ý ßţ4Ş9‹ďƒž—8‰EřŢ_Mňďpň &úÔGúƒh}tÍ8@s-ü}“L;ď9KÍ­‘¸Łf1I<ĺ9Şš’öP„Łr …ýř*-`3)—qI“Éľ QżŘ  RŒšKą—ÇѲ śŰ“ \q?y?Đúƒ&ۊ,Šądšƒţë"'Aő÷Pđ!#-ٚŻj@1!„ŔEA“rÉľ°Ŕ‰ y“CŠŚŔ”Ś8ńţPR/ÝAÓ ą8EP„d *$úŠ28Ť`¨ƒÚĽ!’kÂŚlj–gŽ(éžö§ě*.—xPu Ä!d"K›ľAŒ™Â¨¨`ِFź–bD)4^ę+$Ż1 €A äyQüq)Ą.ܰVэPZ ĂZéŠfŤƒŁqžbŠ íˆCf™Ă¨ @ Ł÷ŘąԖ­á– <+ł*›ąYĆB€DCuA Z2 yŽ) ţ‰“vi,ڍ˜–4Ł ?ĂĆT!Ł0 A°ź)ŠÖ!†×°–´˜ş“É 4E_ꂰ¸$ţjĹVT„dž2ˆ:– y1ĽŃ­ŚáĹm"ŠąĂ0ş+#ŽiŔ6ڄ!Ť#tŸ^‘ŸÄPÄGÔ/Ďé˜ó˘ş$Y’D†şȑŞœ‡Âœ’dHü”œ™şŞ#LjĄ˙¤’ ZÚzň!fĐÇ}ě:č‚ ȀĂáa‡ĺy€8pAĽ˛Ĺ[¤$ą߲ą_\ďF=Ě­˛ œ›$i#bđC?9ŤœĆlÄG•ąrŤü‘ťjŠq¤ĐJʈ‚ L2,|ĤĆ:Gkh—żt,Á¤™QŞŁ‚Wz¨T*Šnd%ËzĽXŇZ ˜[‚”ţ\Ú%ˇ‘Ę^2Œ#*ƒQ`ƒŤÄ )ąIČ YŞĽ™ޒCˆŔäžá'ă*FýĐţ`ŔťtŽt¤Ë2IŤDD™GÔŁ–);BGz9ĽiI}ɐ€Ą¤–yDzŮ$€ MšM D fxĺQ@ öŹ ApœKb0ČŻůúŻÉ9vŹ/ňŃ|éĆm°T™3‹!3(ť'ţ‹ł‡ ÇËrQVíĽ$Hh|l#FŁFk4]S´iȃ<8—77 Ră4WťŘWđś>ŔXSóXSË5WkľYó4kٞAł\#›7xƒwK5[Ó5HBxó5Ä@dŔ&lBAąuȧDí3Quč×Çé× }œyƒ>J3Ÿu—„úYĽŘŞĽ$06šYHK´˘r6Ł4­eAkłś$ô6]“YcŮăÇŕ@'űŔ'KăćŠ1 iĹ:ލ^1žęhČ$abł´Đ´ĂáFăœS óć",ćâ..—h[B7)J9 “ءFo$”I9?JŞh!yBK6 Lž”yLŠ*üŹO‰T•R9•8–㪠Ükż÷ e*ƒXř w(Ś,€=6Ó>~ĂŚ‘C¨éŚíÎjaËăäĂnůšôid-ćbg\Dě K|L”ÉzĄDNܗrôłĄŕŤw ˜Ś4ĘĽřF$UŠqŒłrÜ nމYDţŮDr‘ŁřDĹLĚQ„™ÁŹĺŽhšŘ‘X •%Ă'`VŚIbśżľ8ܢţ N´dﱚgNd4BŸ0Éb$xdlžYmćŠs|›ĐQÇIwԛá űW~W…J/Ą ƒPB ˜źsÉMƜÍa˜ş“td֔¸YişaGŐyG˜vĐQĺš ¨řڟĺćŠ.@0<ÁbkPPĄšy€Üœ&`•ąŢňż,˜*ŔďÁů(#ňńhôY#GžćhŁŃKJśŸ˛LňŸj%b¨: 8ăÄŇĎ Ę—”  Ş—bw!J̕h­ŕIÁćěţŤţœÂ^ŇĚ*JBĘŃ $ŚtĘŇjŽ JŻFdR˘°î)ŢŔ†]=ĽJk?ˊnëŕŁ`„Sr˘k<ŁŻúčźść-QżŽ#9bRŇLSŇ#Ď$Š]p%$+í…rl˝‘$ŐŽ¤“WŽRĎ‘ÔýŠîPÚ Ědď;bŃëžU ™V˘jY`3Y2M[Â%ZÍ×Ţ Ă ăéł`î @p}‚¤"cÉ?5ľňřż FšĆE#˛źéť<锧yÚ’ ÚššŁuVoÖÉD‚ڍąéÇ椞 ‰Şj‹*OşúŃţ"ŠröŠ÷ź§?ŠŻOţ*JţŠütqTľ)˙pŞ0Œ]hż1e‡`ƆŮÖ[••ä‚^ýʰDÓVnÂđ 'őÁsęđ°R§Gv'€Ÿ8Qą”"Ľ,z‘+€=lÂÄŤ$5gƒAgś´ż€ÁbTň,|D,ü ĆLBľsśŞĚ#­,%]&ŐŹ'­T)őôJ—ŹŃÚä(ŸŠ,‹r€żšăTĎŐ)ÓZ4ć†$s\¨PˇnSö¨Ş&be5Ćźbçb>.?íŠKőîŽ1°MíŽNő›Oe†ń’Ió:vEY/fh/™ş#+PrY/x)W™ÄŻúÚŻôf)íroŹ0vôBvMĺÔďrv: UŘŐúţ˘°7ą°TUURÇ W=őr k("Ă퍭ě^őUüSë§úŽZkîńžŠ$ĆD^Ŕó`ÖaWŒxm˛yÁp”*Ë+ăôĄĺ˛쳀M 1ł2{Ň3{Ú66{3 ß AŽ2Ď3AŃWŁŕ×úWAÓwŹ Ř/>śHcśeKޏÍpkp!8ľ ľM;ľTűXŞ—Yʟ5qă؋•.PK7tëúąOˇšžú´6‚ś…]ú¤6u‹XdŁŮ>!(“Y#Űl;[\{ƒ˝‡5łU´ 7šľŰšŰłę6Ŕˇ5V[´WűČß0ađÇĹM\ 6\€#¸Řŕţł ňŁ`Çe8ČU ɕüÓGÝË- ŐGýÖwýׇýؗý٧ýÚˇýŰÇýÜ×ýÝçýŢ÷ýßţŕđ XÖ~­ćĄĺgţćwţç‡ţč—ţé§ţęˇţëÇţěˇ~k°âţî×ţđ˙ń'˙ň7˙óG˙ôW˙őg˙öw˙ćgŠď—˙ů§˙úˇ˙űÇ˙ü×˙ýç˙ţ÷˙˙k,hŘ@b 2lčđ!Ĉ'RŹhń"Ì7rěčń#ȋ˛F’,92$ʔ*W˛léň%̘2gŇŹ’˜Éœ:wňěéó'Đ B‡-jô(ҤJ—2męô)Ô¨R§R­jő*ÖŹZˇríţęő+ذbǒ-kö,Ú´jײmëö-ܸrçŇ­k÷.Ţźz÷ňíëw茿‚.lř°ĎMV#něř1äČc­PŢÄX2ć̚7s折rĺ΢G“.͡2čĹVLłníúľŮŐ°gÓŽmęĺŰşwóî=Rśďŕ‡ÎMü8ň䄁+oîüů\ăЧSŻ–yŃ$H°îý;xĎJűÓ áGřôęŠcĎţb˜ş>VÁÚąÖŞőú÷ó–^”ü1[¨óę¸ *čZ{CŃ÷ Żź˘Î0[ˆ5ÇŔ˛ ‡nć_P°ôńÂôA‚:3 ŁÁ [(ôJ~Ę8ăa Oţ @C‰'ވ2Ë }Xő oő‚’<1)Ő/ȅÂ[OŇxĽeYjiYO% ęŔc äĂŘâÄ11bIĚ\ŔĚ ĚĹ •xę¤gSÄH) v (XpfŘ {Ry%ŁFÉŃ(gŹ!™(łâ1“(2‰‘F5ˆÂŸ˛\' ‹˘SFNĽŽtjOH6I’ŠŽT:€†*ËIúä*IŞšjIĽžZRŽĄňú›OšŽtěHšKRŽ‹eœŻ§:Ű(ś@m3„™P!&™ď sL,ÖĚ2Ę nfŇƒ 3§,訆ŽbĆľ‹3éŠç˝ůĘÂď ҎDĚţ Ě ‚“¨ź;ČŻ‹mR ƒĚ9Č#šSpŔż *§ÁT^0ą”O\ą,ç+°,żk'Á#ĚŘeűĘyĹ3üďÇůŢ*Ë VźŘ JžŔ1Fďb¸şëďĚ:gűôNŤ!…-xab}¨c) ÖŘb -î<v *ËR×ŕ֌ÔŤŹśývźe´‹rťÝ˝a…’|tĘŹĘRĆÍ–ˇŇ&Ń* 1…żML­ŒN¸á€F.KwĐn’ůˆďÝ7˛Ť˘ŠÂ”N%é']žŞ;t3ƒÓVäIĽlŔ͍yź[ł:Ô˝˙€E-`¨‚Á&F8L,ÄđË$´ŘŇţ)QĆYÁ 3čd œĆíKĽöŸ]Ňâ#é :(3Ózʗ1:íSk':č‹/`ôë;‡?ëĺzÂL’žâ7żUĺ }„_Átĺ; ˘ v’Í˙F˘=&Şw˝Ó† R ;hĆ{Á &áŽĂ٘ĹĐCěČŽT(čÎÚt‚¸Ąj†ƒ„üz•(‡ßÝH(‹ŐŽTîřáŕjĺÒnˆ€J”lre=„YŹ‚BdUíHÂŞ%ÖM|Ł;Űţ`9żmâľ*Łă˛:-‚‘w̖6V!WĚg ¨™Žq @Ě`yÄP Ô㘠Z˘"‰L׏ÍţmS’ľ2FŹ áŠŒ4ߢPp?ÄáJc’ƒ1Ő8ˑd5™KYß°‰&uŽ’Ÿ;¤¨š8FŠoQŰ b;YK´] uďz™I˘ČNňIˆo„Ú$đ†Ő@5¨Á ̄‚0_°Ĺ)…2=ęŃŠł^ël÷1“ź `ĚX yfÎŐđKv&iŮÁÖŘāŹ ,ĺŹ|vNĹE.g8äĽÁ¤tĎ`˘`zôR‡IŹQ0…1c“ÍÚŔ.R4I4‰őätłŘŃ ’ÍÇ WNꥳÇ|#,~ĚôáŃÔŔ1Ś‹XĚ`NP‡ âBdč*e=˜;vÄE=ÉţJ€"j“bĹŽž VcƒBë˘Ô+hůŠXĄÚÚŤÔń=ŠąY((C6ĄTŞžJZęh]Q“ŞVžąR¨/€´B%?iu¨ËjëI-˜RYüpi4÷ˆ‚™†€ŘP^ŤX´H ĽŤ`é„ěSw–ŠŕAXŤŮÍn%™ŤHćHđĚ4˘ <ŕ5a u¨łŽ}mU`1 ”čЄŠi—7ƒQŒB­…-pƒť”žJ€śËŒě0Lk‹X”´@ŚÂ$ŽśjlS‘ŞTQFí ˇťK)î*h;&u¤ <˜jmA‹X V(šäÉůŒš>]…P„2”NđËýzˇżţAIfqaqÜh–Á“X.Za ­‹ŞB×W#-bjžżbjoU,˛+Âľě Ľţ„YHÚ‰3ŒO˙˛8)ô…€˙Ú"ŘB!<°Ĺˆ‘Ůž -0ĺ|—ăJb &‘Ě]4kÖŇd×.’ä8^ř*# LF1‹ŮNëŘŞV0\U콛Ŕ×B­G˛őQ2bJâ%™ń… lB`ł™’P ĺ1+ěČJ[Y0[ŹgŁČvoË0‰YXăŔ#Đńobťł ó'zşÝgKđՊr¸:Üćšĺ9†’”=ń›*őĆˆ2Ł]R‚ÜŔ*†ŻąĽNM.ɨeé1FŤmĎśţJ2cŒ˘-ڌĘÄŹąăž\8 ôɚĂ˝Knr‚ZŕbŹ|ż0˛Ď}˙˘`bV ËËĐ̖sÂłsrž*âĘ`Is"‡H=ë-űÖîöI_íZ<şƒNĹAZ1‰$Ú'1 ˘KňtH ‹lüÍ YN*-NˆDŹ`QpDІQ†ˆ\1pb÷'t|Áˆ-ŸN§É’tčţW ]ř“żťĺ9ůźűPƒ-Ô[_(t+xŔ`Ąp{QŢŁ[—śż-ę řŔě4ň`Ş’•œTRђží‰˜Á2vĺž­g$óŚF+ œ,ÔNeřň>Űxk;‹Śvľ Ź‡g.b´đY6ˇ°9aŠ(Cúý“şŚěÁ9Â ­”Ť•Šop‡:°*iÝ>T& iżŤ!b“Îú'Ł2ńŤűjSŁĎVŕ˙ôóÖ˙ÁđX.k8H}ČŠw,lýń'ĹŻk/Ă1^Pđ“żýî?üă/˙ůÓżţöż?ţóŻ˙ýóż˙ţ˙?    & . 6ŕmhw8 śy˜‡ęM JĆźG|ĚÇ´Ŕ4ŕGŽŕcţˆ€p‚˜Â ś aţM.YÁČP\?ĚHp xTNНrúhFŮI ş•>QĽ}¤ÁëSWq•ČŽ ƒyĄ× ¨{A+ˇ—l5d˜!˜‚í\ˇžkQꘟÉŘИá˜ŽĄŤź…léZ  ZĄŮÂĄńŰźö+Pô•Ž‘WŻ9ÁŻۜú+ÂŽ”ŸŠ]˝Ý[žíŹ"ŹżÂœŸÉÍýŃÍMBΙŤÄvěŮĽ] ľÝŰŝǖlN„ŢŒ-”Ţ饞ɾěH`Ÿö D÷É]ÂŹżšŸ=ĽßúáŹĎŽD8ŞÔĎ-Ń­Ń-Ň&­Ň.-Ó6­Ó>-ÔF­ÔN-ŐV­Ő^-Öf­Ön-×v­×~-؆­ŘŽ-ŮFm@;Themes/default/lgo_on.xpm100644 1750 1750 1131 6704473330 14443 0ustar denisdenis/* XPM */ static char * lgo_on_xpm[] = { "18 14 16 1", " c None", ". c #FFFFFF", "+ c #ECECEC", "@ c #DADADA", "# c #C8C8C8", "$ c #6EEF9B", "% c #B6B6B6", "& c #484848", "* c #A3A3A3", "= c #919191", "- c #7F7F7F", "; c #6D6D6D", "> c #5B5B5B", ", c #363636", "' c #242424", ") c #121212", "..................", "++++++++++++++++++", "@@@@@@@@@@@@@@@@@@", "######$####$######", "%%%%%%$&%%&$$%%%%%", "*****$$&**&$$$****", "====$$$&==&$$$$===", "---+#$$&--&$$#+---", ";;;;#+#&;;&#+#;;;;", ">>>>>>#>>>>#>>>>>>", "&&&&&&&&&&&&&&&&&&", ",,,,,,,,,,,,,,,,,,", "''''''''''''''''''", "))))))))))))))))))"}; Themes/default/play.xpm100644 1750 1750 1110 6703472476 14141 0ustar denisdenis/* XPM */ static char * play_xpm[] = { "18 14 15 1", " c None", ". c #FFFFFF", "+ c #ECECEC", "@ c #DADADA", "# c #C8C8C8", "$ c #B6B6B6", "% c #484848", "& c #A3A3A3", "* c #919191", "= c #7F7F7F", "- c #6D6D6D", "; c #5B5B5B", "> c #363636", ", c #242424", "' c #121212", "..................", "++++++++++++++++++", "@@@@@@@@@@@@@@@@@@", "##################", "$$$$$$$%$$$$$$$$$$", "&&&&&&&%&&&&&&&&&&", "*******%**********", "=======%==#+======", "-------%#+#-------", ";;;;;;;;#;;;;;;;;;", "%%%%%%%%%%%%%%%%%%", ">>>>>>>>>>>>>>>>>>", ",,,,,,,,,,,,,,,,,,", "''''''''''''''''''"}; Themes/default/pause.xpm100644 1750 1750 1111 6703472517 14306 0ustar denisdenis/* XPM */ static char * pause_xpm[] = { "18 14 15 1", " c None", ". c #FFFFFF", "+ c #ECECEC", "@ c #DADADA", "# c #C8C8C8", "$ c #B6B6B6", "% c #484848", "& c #A3A3A3", "* c #919191", "= c #7F7F7F", "- c #6D6D6D", "; c #5B5B5B", "> c #363636", ", c #242424", "' c #121212", "..................", "++++++++++++++++++", "@@@@@@@@@@@@@@@@@@", "##################", "$$$$$$$%$$%$$$$$$$", "&&&&&&&%+&%+&&&&&&", "*******%+*%+******", "=======%+=%+======", "-------%+-%+------", ";;;;;;;;#;;#;;;;;;", "%%%%%%%%%%%%%%%%%%", ">>>>>>>>>>>>>>>>>>", ",,,,,,,,,,,,,,,,,,", "''''''''''''''''''"}; Themes/default/fwd.xpm100644 1750 1750 1107 6703472606 13755 0ustar denisdenis/* XPM */ static char * fwd_xpm[] = { "18 14 15 1", " c None", ". c #FFFFFF", "+ c #ECECEC", "@ c #DADADA", "# c #C8C8C8", "$ c #B6B6B6", "% c #484848", "& c #A3A3A3", "* c #919191", "= c #7F7F7F", "- c #6D6D6D", "; c #5B5B5B", "> c #363636", ", c #242424", "' c #121212", "..................", "++++++++++++++++++", "@@@@@@@@@@@@@@@@@@", "##################", "$$$$$%$$$$%$$$$$$$", "&&&&&%&&&&%&&&&&&&", "*****%****%*******", "=====%==#+%==#+===", "-----%#+#-%#+#----", ";;;;;;#;;;;#;;;;;;", "%%%%%%%%%%%%%%%%%%", ">>>>>>>>>>>>>>>>>>", ",,,,,,,,,,,,,,,,,,", "''''''''''''''''''"}; Themes/default/eject.xpm100644 1750 1750 1111 6703472542 14261 0ustar denisdenis/* XPM */ static char * eject_xpm[] = { "18 14 15 1", " c None", ". c #FFFFFF", "+ c #ECECEC", "@ c #DADADA", "# c #C8C8C8", "$ c #B6B6B6", "% c #484848", "& c #A3A3A3", "* c #919191", "= c #7F7F7F", "- c #6D6D6D", "; c #5B5B5B", "> c #363636", ", c #242424", "' c #121212", "..................", "++++++++++++++++++", "@@@@@@@@@@@@@@@@@@", "##################", "$$$$$$$%%%%%$$$$$$", "&&&&&&&@@@@@&&&&&&", "*******%%%%*******", "=======%===+======", "--------%-+-------", ";;;;;;;;;%;;;;;;;;", "%%%%%%%%%%%%%%%%%%", ">>>>>>>>>>>>>>>>>>", ",,,,,,,,,,,,,,,,,,", "''''''''''''''''''"}; Themes/default/Theme100644 1750 1750 13233 6720035506 13450 0ustar denisdenis#################################################### # AScd Faktory theme configuration file # #################################################### # This is the default theme, looking like AScd 0.12 # but with a few more buttons. It now uses a 8bit # font made by Stefan Zeiger. Thanks a lot Stefan ! # I also added mixer support in panels 4 & 5. # ------------------- # General information # ------------------- name Fusion (with mixer support) release 990517 author Denis Bourez email denis@rsn.fdn.fr url http://worldserver.oleane.com/rsn/ascd-en.html alpha1 digits.xpm alpha2 digits2.xpm panels 5 background back.xpm # ------------------------------------- # Screen elements, common to all panels # ------------------------------------- ###### The counter ###### { panel 0 type pixmap pixmap back_counter.xpm left counter_mode mid mute right wings_window x 0 y 0 } { panel 0 type counter x 1 y 2 } ###### The track number ###### { panel 0 type pixmap pixmap back_track.xpm left ftrack_next mid ftrack_select right ftrack_previous x 43 y 0 } { panel 0 type tracknumber x 41 y 2 } ###### The messages ###### { panel 0 type pixmap pixmap back_msg.xpm left show_db mid show_artist right uppercase x 0 y 10 } { panel 0 type message x 1 y 11 w 9 } ###### the progress bar ###### { panel 0 type pixmap pixmap back_bar.xpm x 7 y 21 } { panel 0 type progress_bar pixmap bar.xpm left direct_access right quick_ref arg 1 x 8 y 22 } ###### the quit button ###### { panel 0 type pixmap pixmap cross.xpm left quit right quick_ref x 0 y 21 } # --------------------------------------------------------- # The first panel # --------------------------------------------------------- { panel 1 type pixmap pixmap panel.xpm left panel 2 middle panel 3 right panel 4 x 50 y 21 } { panel 1 type pixmap pixmap play.xpm alt play_on.xpm left play right quick_ref x 19 y 27 } { panel 1 type pixmap pixmap stop.xpm alt stop_on.xpm left stop right quit x 19 y 42 } { panel 1 type pixmap pixmap pause.xpm alt pause_on.xpm left pause x 0 y 42 } { panel 1 type pixmap pixmap eject.xpm left eject x 38 y 42 } { panel 1 type pixmap pixmap rew.xpm left previous_track middle first_track right rew x 0 y 27 } { panel 1 type pixmap pixmap fwd.xpm left next_track middle last_track right fwd x 38 y 27 } # --------------------------------------------------------- # The second panel # --------------------------------------------------------- { panel 2 type pixmap pixmap panel.xpm left panel 1 middle panel 3 right panel 4 x 50 y 21 } # The mode buttons: { panel 2 type pixmap pixmap lstart.xpm left loop_start right loop_go_start x 0 y 27 } { panel 2 type pixmap pixmap lgo.xpm alt lgo_on.xpm left loop right loop_clear x 19 y 27 } { panel 2 type pixmap pixmap lend.xpm left loop_end right loop_go_end x 38 y 27 } { panel 2 type pixmap pixmap intro.xpm alt intro_on.xpm left intro_scan x 19 y 42 } { panel 2 type pixmap pixmap fade.xpm left fade x 0 y 42 } { panel 2 type pixmap pixmap options.xpm left panel 3 x 38 y 42 } # --------------------------------------------------------- # The third panel: configuration tools # --------------------------------------------------------- # The panel selector: { panel 3 type pixmap pixmap panel.xpm left panel 2 middle panel 1 right panel 4 x 50 y 21 } # the mode buttons: { panel 3 type pixmap pixmap autoplay.xpm alt autoplay_on.xpm left autoplay x 0 y 27 } { panel 3 type pixmap pixmap theme.xpm alt theme_on.xpm left theme_next mid theme_select right theme_previous x 19 y 27 } { panel 3 type pixmap pixmap wings.xpm left wings_window x 38 y 27 } { panel 3 type pixmap pixmap autorepeat.xpm alt autorepeat_on.xpm left autorepeat x 0 y 42 } { panel 3 type pixmap pixmap upper.xpm alt upper_on.xpm left uppercase x 19 y 42 } { panel 3 type pixmap pixmap options_on.xpm left panel 2 right save x 38 y 42 } # --------------------------------------------------------- # The mixer panel # --------------------------------------------------------- { panel 4 type pixmap pixmap panel.xpm left panel 2 middle panel 3 right panel 1 x 50 y 21 } { panel 4 type pixmap pixmap mixer_panel.xpm left panel 5 right quick_ref arg 2 x 0 y 28 } { panel 4 type pixmap pixmap mixer_back.xpm x 14 y 28 } { panel 4 type mixer_bar pixmap mixer_bar.xpm left set mid 50% right 75% arg volume x 14 y 29 } { panel 4 type mixer_bar pixmap mixer_bar.xpm left set mid 50% right 75% arg pcm x 14 y 36 } { panel 4 type mixer_bar pixmap mixer_bar.xpm left set mid 50% right 75% arg line x 14 y 43 } { panel 4 type mixer_bar pixmap mixer_bar.xpm left set mid 50% right 75% arg cd x 14 y 50 } # --------------------------------------------------------- # The 2nd mixer panel # --------------------------------------------------------- { panel 5 type pixmap pixmap panel.xpm left panel 2 middle panel 3 right panel 1 x 50 y 21 } { panel 5 type pixmap pixmap mixer2_back.xpm x 0 y 28 } { panel 5 type pixmap pixmap mixer2_panel.xpm left panel 4 x 0 y 49 } { panel 5 type imixer_bar pixmap mixer2_bar.xpm left set mid 50% right 75% arg volume x 1 y 29 } { panel 5 type imixer_bar pixmap mixer2_bar.xpm left set mid 50% right 75% arg bass x 8 y 29 } { panel 5 type imixer_bar pixmap mixer2_bar.xpm left set mid 50% right 75% arg treble x 15 y 29 } { panel 5 type imixer_bar pixmap mixer2_bar.xpm left set mid 50% right 75% arg pcm x 22 y 29 } { panel 5 type imixer_bar pixmap mixer2_bar.xpm left set mid 50% right 75% arg cd x 29 y 29 } { panel 5 type imixer_bar pixmap mixer2_bar.xpm left set mid 50% right 75% arg line x 36 y 29 } { panel 5 type imixer_bar pixmap mixer2_bar.xpm left set mid 50% right 75% arg midi x 43 y 29 } { panel 5 type imixer_bar pixmap mixer2_bar.xpm left set mid 50% right 75% arg mic x 50 y 29 } Themes/default/lstart.xpm100644 1750 1750 1112 6703514276 14502 0ustar denisdenis/* XPM */ static char * lstart_xpm[] = { "18 14 15 1", " c None", ". c #FFFFFF", "+ c #ECECEC", "@ c #DADADA", "# c #C8C8C8", "$ c #B6B6B6", "% c #484848", "& c #A3A3A3", "* c #919191", "= c #7F7F7F", "- c #6D6D6D", "; c #5B5B5B", "> c #363636", ", c #242424", "' c #121212", "..................", "++++++++++++++++++", "@@@@@@@@@@@@@@@@@@", "##################", "$$$$$$$%$$$$$$$$$$", "&&&&&&&%&&&&&&&&&&", "*******%*%*%*%****", "===+#==%==+=+=+===", "----#+#%----------", ";;;;;;#;;;;;;;;;;;", "%%%%%%%%%%%%%%%%%%", ">>>>>>>>>>>>>>>>>>", ",,,,,,,,,,,,,,,,,,", "''''''''''''''''''"}; Themes/default/rew.xpm100644 1750 1750 1107 6703472633 13772 0ustar denisdenis/* XPM */ static char * rew_xpm[] = { "18 14 15 1", " c None", ". c #FFFFFF", "+ c #ECECEC", "@ c #DADADA", "# c #C8C8C8", "$ c #B6B6B6", "% c #484848", "& c #A3A3A3", "* c #919191", "= c #7F7F7F", "- c #6D6D6D", "; c #5B5B5B", "> c #363636", ", c #242424", "' c #121212", "..................", "++++++++++++++++++", "@@@@@@@@@@@@@@@@@@", "##################", "$$$$$$$$%$$$$%$$$$", "&&&&&&&&%&&&&%&&&&", "********%****%****", "====+#==%+#==%====", "-----#+#%-#+#%----", ";;;;;;;#;;;;#;;;;;", "%%%%%%%%%%%%%%%%%%", ">>>>>>>>>>>>>>>>>>", ",,,,,,,,,,,,,,,,,,", "''''''''''''''''''"}; Themes/default/play_on.xpm100644 1750 1750 1132 6715065722 14634 0ustar denisdenis/* XPM */ static char * play_on_xpm[] = { "18 14 16 1", " c None", ". c #FFFFFF", "+ c #ECECEC", "@ c #DADADA", "# c #C8C8C8", "$ c #00FFB6", "% c #B6B6B6", "& c #484848", "* c #A3A3A3", "= c #919191", "- c #7F7F7F", "; c #6D6D6D", "> c #5B5B5B", ", c #363636", "' c #242424", ") c #121212", "..................", "++++++++++++++++++", "@@@@@@@@@@@@@@@@@@", "########$#########", "%%%%%%%&$$%%%%%%%%", "*******&$$$*******", "=======&$$$$======", "-------&$$#+------", ";;;;;;;&#+#;;;;;;;", ">>>>>>>>#>>>>>>>>>", "&&&&&&&&&&&&&&&&&&", ",,,,,,,,,,,,,,,,,,", "''''''''''''''''''", "))))))))))))))))))"}; Themes/default/pause_on.xpm100644 1750 1750 1133 6703525162 15001 0ustar denisdenis/* XPM */ static char * pause_on_xpm[] = { "18 14 16 1", " c None", ". c #FFFFFF", "+ c #ECECEC", "@ c #DADADA", "# c #C8C8C8", "$ c #B6B6B6", "% c #ED1010", "& c #A3A3A3", "* c #919191", "= c #7F7F7F", "- c #6D6D6D", "; c #5B5B5B", "> c #484848", ", c #363636", "' c #242424", ") c #121212", "..................", "++++++++++++++++++", "@@@@@@@@@@@@@@@@@@", "##################", "$$$$$$$%$$%$$$$$$$", "&&&&&&&%+&%+&&&&&&", "*******%+*%+******", "=======%+=%+======", "-------%+-%+------", ";;;;;;;;#;;#;;;;;;", ">>>>>>>>>>>>>>>>>>", ",,,,,,,,,,,,,,,,,,", "''''''''''''''''''", "))))))))))))))))))"}; Themes/default/lend.xpm100644 1750 1750 1110 6703514313 14101 0ustar denisdenis/* XPM */ static char * lend_xpm[] = { "18 14 15 1", " c None", ". c #FFFFFF", "+ c #ECECEC", "@ c #DADADA", "# c #C8C8C8", "$ c #B6B6B6", "% c #484848", "& c #A3A3A3", "* c #919191", "= c #7F7F7F", "- c #6D6D6D", "; c #5B5B5B", "> c #363636", ", c #242424", "' c #121212", "..................", "++++++++++++++++++", "@@@@@@@@@@@@@@@@@@", "##################", "$$$$$$$$$$%$$$$$$$", "&&&&&&&&&&%&&&&&&&", "****%*%*%*%*******", "===+=+=+==%==#+===", "----------%#+#----", ";;;;;;;;;;;#;;;;;;", "%%%%%%%%%%%%%%%%%%", ">>>>>>>>>>>>>>>>>>", ",,,,,,,,,,,,,,,,,,", "''''''''''''''''''"}; Themes/default/fade.xpm100644 1750 1750 1110 6715075664 14074 0ustar denisdenis/* XPM */ static char * fade_xpm[] = { "18 14 15 1", " c None", ". c #FFFFFF", "+ c #ECECEC", "@ c #DADADA", "# c #C8C8C8", "$ c #B6B6B6", "% c #A3A3A3", "& c #919191", "* c #7F7F7F", "= c #6D6D6D", "- c #5B5B5B", "; c #484848", "> c #363636", ", c #242424", "' c #121212", "..................", "++++++++++++++++++", "@@@@@@@@@@@@@@@@@@", "##################", "$$$$+$$$$$$$$$$$$$", "%%%%%%%%%%%%%%%%%%", "&&&&+&+&&&&&&&&&&&", "******************", "====+=+=+=+=======", "------------------", ";;;;+;+;+;+;+;+;;;", ">>>>>>>>>>>>>>>>>>", ",,,,,,,,,,,,,,,,,,", "''''''''''''''''''"}; Themes/default/intro.xpm100644 1750 1750 1205 6715076052 14325 0ustar denisdenis/* XPM */ static char * intro_xpm[] = { "18 14 19 1", " c None", ". c #FFFFFF", "+ c #ECECEC", "@ c #D2D2D2", "# c #484848", "$ c #DADADA", "% c #C2C2C2", "& c #C8C8C8", "* c #B2B2B2", "= c #B6B6B6", "- c #A3A3A3", "; c #919191", "> c #7F7F7F", ", c #6D6D6D", "' c #5B5B5B", ") c #363636", "! c #242424", "~ c #202020", "{ c #121212", "..................", "+++++++++@#+++++++", "$$$$$$$$%#$+$$$$$$", "&&&&&&&*#&&+&&&&&&", "=====###===+======", "-----#-----+------", ";;;;;#;;;;;+;;;;;;", ">>>>>#>>>>>+>>>>>>", ",,,,,#,,,,,+,,,,,,", "''''''+*'''+''''''", "########+##+######", ")))))))))+#+))))))", "!!!!!!!!!!!~!!!!!!", "{{{{{{{{{{{{{{{{{{"}; Themes/default/stop.xpm100644 1750 1750 1110 6703472562 14155 0ustar denisdenis/* XPM */ static char * stop_xpm[] = { "18 14 15 1", " c None", ". c #FFFFFF", "+ c #ECECEC", "@ c #DADADA", "# c #C8C8C8", "$ c #B6B6B6", "% c #484848", "& c #A3A3A3", "* c #919191", "= c #7F7F7F", "- c #6D6D6D", "; c #5B5B5B", "> c #363636", ", c #242424", "' c #121212", "..................", "++++++++++++++++++", "@@@@@@@@@@@@@@@@@@", "##################", "$$$$$$$%%%%$$$$$$$", "&&&&&&&%&&&+&&&&&&", "*******%***+******", "=======%===+======", "-------%---+------", ";;;;;;;;+++#;;;;;;", "%%%%%%%%%%%%%%%%%%", ">>>>>>>>>>>>>>>>>>", ",,,,,,,,,,,,,,,,,,", "''''''''''''''''''"}; Themes/default/intro_on.xpm100644 1750 1750 1323 6715076554 15031 0ustar denisdenis/* XPM */ static char * intro_on_xpm[] = { "18 14 24 1", " c None", ". c #FFFFFF", "+ c #ECECEC", "@ c #D2D2D2", "# c #484848", "$ c #DADADA", "% c #C2C2C2", "& c #F9A7A7", "* c #C8C8C8", "= c #B2B2B2", "- c #F89191", "; c #B6B6B6", "> c #F67B7B", ", c #A3A3A3", "' c #F45050", ") c #F56565", "! c #919191", "~ c #7F7F7F", "{ c #6D6D6D", "] c #5B5B5B", "^ c #363636", "/ c #242424", "( c #202020", "_ c #121212", "..................", "+++++++++@#+++++++", "$$$$$$$$%#&+$$$$$$", "*******=#-&+******", ";;;;;###>-&+;;;;;;", ",,,,,#')>-&+,,,,,,", "!!!!!#')>-&+!!!!!!", "~~~~~#')>-&+~~~~~~", "{{{{{#')>-&+{{{{{{", "]]]]]]+=>-&+]]]]]]", "########+-&+######", "^^^^^^^^^+&+^^^^^^", "///////////(//////", "__________________"}; Themes/default/stop_on.xpm100644 1750 1750 1132 6715100140 14634 0ustar denisdenis/* XPM */ static char * stop_on_xpm[] = { "18 14 16 1", " c None", ". c #FFFFFF", "+ c #ECECEC", "@ c #DADADA", "# c #C8C8C8", "$ c #B6B6B6", "% c #484848", "& c #A3A3A3", "* c #F40E40", "= c #919191", "- c #7F7F7F", "; c #6D6D6D", "> c #5B5B5B", ", c #363636", "' c #242424", ") c #121212", "..................", "++++++++++++++++++", "@@@@@@@@@@@@@@@@@@", "##################", "$$$$$$$%%%%$$$$$$$", "&&&&&&&%***+&&&&&&", "=======%***+======", "-------%***+------", ";;;;;;;%***+;;;;;;", ">>>>>>>>+++#>>>>>>", "%%%%%%%%%%%%%%%%%%", ",,,,,,,,,,,,,,,,,,", "''''''''''''''''''", "))))))))))))))))))"}; Themes/default/upper_on.xpm100644 1750 1750 1455 6715105163 15024 0ustar denisdenis/* XPM */ static char * upper_on_xpm[] = { "18 14 30 1", " c None", ". c #FFFFFF", "+ c #ECECEC", "@ c #DADADA", "# c #0DE0E8", "$ c #55E2E7", "% c #C8C8C8", "& c #53E0E5", "* c #B6B6B6", "= c #51DEE3", "- c #A3A3A3", "; c #4FDBE1", "> c #919191", ", c #4DD9DF", "' c #7F7F7F", ") c #4BD7DD", "! c #6D6D6D", "~ c #49D5DB", "{ c #5B5B5B", "] c #57E4E9", "^ c #7A7A7A", "/ c #484848", "( c #22C6CC", "_ c #BBE9EB", ": c #363636", "< c #2C5B5D", "[ c #242424", "} c #1E4D4F", "| c #14A1A6", "1 c #121212", "..................", "++++++++++++++++++", "@@@@@##$@@@$##@@@@", "%%%%%##&%%%&##%%%%", "*****##=***=##****", "-----##;---;##----", ">>>>>##,>>>,##>>>>", "'''''##)''')##''''", "!!!!!##~!!!~##!!!!", "{{{{{##]^{^]##{{{{", "/////(##_+_##(////", ":::::<#######<::::", "[[[[[[}|###|}[[[[[", "111111111111111111"}; Themes/default/autorepeat.xpm100644 1750 1750 1572 6715103273 15346 0ustar denisdenis/* XPM */ static char * autorepeat_xpm[] = { "18 14 35 1", " c None", ". c #FFFFFF", "+ c #ECECEC", "@ c #DADADA", "# c #E9E9E9", "$ c #C8C8C8", "% c #E0E0E0", "& c #D4D4D4", "* c #B6B6B6", "= c #A3A3A3", "- c #DBDBDB", "; c #BBBBBB", "> c #E3E3E3", ", c #919191", "' c #E1E1E1", ") c #AFAFAF", "! c #7F7F7F", "~ c #DFDFDF", "{ c #C7C7C7", "] c #6D6D6D", "^ c #C1C1C1", "/ c #979797", "( c #A5A5A5", "_ c #5B5B5B", ": c #8B8B8B", "< c #484848", "[ c #B5B5B5", "} c #D9D9D9", "| c #5A5A5A", "1 c #363636", "2 c #868686", "3 c #494949", "4 c #9A9A9A", "5 c #242424", "6 c #121212", "..................", "++++++++++++++++++", "@@@@@+++++++#@@@@@", "$$$$$++%$$%++&$$$$", "*****++@**$++$****", "=====++-;;>+>=====", ",,,,,++++++'),,,,,", "!!!!!++~{++{!!!!!!", "]]]]]++^]/++(]]]]]", "_____++;__;++:____", "<<<<<++[<<<}+}|<<<", "11111))21113))4111", "555555555555555555", "666666666666666666"}; Themes/default/wings.xpm100644 1750 1750 1111 6714716523 14320 0ustar denisdenis/* XPM */ static char * wings_xpm[] = { "18 14 15 1", " c None", ". c #FFFFFF", "+ c #ECECEC", "@ c #DADADA", "# c #484848", "$ c #C8C8C8", "% c #B6B6B6", "& c #A3A3A3", "* c #919191", "= c #7F7F7F", "- c #6D6D6D", "; c #5B5B5B", "> c #363636", ", c #242424", "' c #121212", "..................", "++++++++++++++++++", "@@@@@####@@@@@@@@@", "$$$$$#$$$+$$$$$$$$", "%%%%%#%%%+#%%%%%%%", "&&&&&#&&&+&+&&&&&&", "*****#***+*+******", "======++++=+======", "-------#---+------", ";;;;;;;;+++$;;;;;;", "##################", ">>>>>>>>>>>>>>>>>>", ",,,,,,,,,,,,,,,,,,", "''''''''''''''''''"}; Themes/default/autoplay_on.xpm100644 1750 1750 2002 6715104323 15511 0ustar denisdenis/* XPM */ static char * autoplay_on_xpm[] = { "18 14 44 1", " c None", ". c #FFFFFF", "+ c #ECECEC", "@ c #F84E4E", "# c #FF0000", "$ c #F66969", "% c #DADADA", "& c #FC1A1A", "* c #C8C8C8", "= c #E28D8D", "- c #D9A1A1", "; c #B6B6B6", "> c #F24848", ", c #EB5E5E", "' c #A3A3A3", ") c #D17C7C", "! c #F04646", "~ c #FB1919", "{ c #919191", "] c #C97474", "^ c #B56060", "/ c #B77F7F", "( c #7F7F7F", "_ c #EC4242", ": c #F52F2F", "< c #C16C6C", "[ c #E05353", "} c #6D6D6D", "| c #5B5B5B", "1 c #B15C5C", "2 c #E83E3E", "3 c #F32D2D", "4 c #975F5F", "5 c #484848", "6 c #E63C3C", "7 c #F22C2C", "8 c #6C5050", "9 c #D54848", "0 c #363636", "a c #E43A3A", "b c #BB4A4A", "c c #D14444", "d c #242424", "e c #121212", "..................", "+++++++@##$+++++++", "%%%%%%%###&%%%%%%%", "******=####-******", ";;;;;;>#>##,;;;;;;", "''''''##)!#~''''''", "{{{{{]##%^##/{{{{{", "(((((_#:<<##[(((((", "}}}}}#######~}}}}}", "||||1##2223##4||||", "55556#75558##95555", "0000aab0000aac0000", "dddddddddddddddddd", "eeeeeeeeeeeeeeeeee"}; Themes/default/theme.xpm100644 1750 1750 1356 6715103177 14302 0ustar denisdenis/* XPM */ static char * theme_xpm[] = { "18 14 26 1", " c None", ". c #FFFFFF", "+ c #ECECEC", "@ c #DADADA", "# c #E6E6E6", "$ c #C8C8C8", "% c #E0E0E0", "& c #B6B6B6", "* c #A3A3A3", "= c #D3D3D3", "- c #919191", "; c #CDCDCD", "> c #7F7F7F", ", c #C7C7C7", "' c #6D6D6D", ") c #C1C1C1", "! c #5B5B5B", "~ c #BBBBBB", "{ c #484848", "] c #B5B5B5", "^ c #363636", "/ c #AFAFAF", "( c #242424", "_ c #A9A9A9", ": c #7C7C7C", "< c #121212", "..................", "++++++++++++++++++", "@@@@@++++++++#@@@@", "$$$$$++++++++%$$$$", "&&&&&&&&++@&&&&&&&", "********++=*******", "--------++;-------", ">>>>>>>>++,>>>>>>>", "''''''''++)'''''''", "!!!!!!!!++~!!!!!!!", "{{{{{{{{++]{{{{{{{", "^^^^^^^^++/^^^^^^^", "((((((((__:(((((((", "<<<<<<<<<<<<<<<<<<"}; Themes/default/upper.xpm100644 1750 1750 1356 6715104557 14336 0ustar denisdenis/* XPM */ static char * upper_xpm[] = { "18 14 26 1", " c None", ". c #FFFFFF", "+ c #ECECEC", "@ c #DADADA", "# c #E6E6E6", "$ c #C8C8C8", "% c #E0E0E0", "& c #B6B6B6", "* c #A3A3A3", "= c #D3D3D3", "- c #919191", "; c #CDCDCD", "> c #7F7F7F", ", c #C7C7C7", "' c #6D6D6D", ") c #C1C1C1", "! c #5B5B5B", "~ c #CBCBCB", "{ c #7A7A7A", "] c #484848", "^ c #6C6C6C", "/ c #363636", "( c #5D5D5D", "_ c #AFAFAF", ": c #242424", "< c #121212", "..................", "++++++++++++++++++", "@@@@@++#@@@#++@@@@", "$$$$$++%$$$%++$$$$", "&&&&&++@&&&@++&&&&", "*****++=***=++****", "-----++;---;++----", ">>>>>++,>>>,++>>>>", "'''''++)''')++''''", "!!!!!~++{!{++~!!!!", "]]]]]^+++++++^]]]]", "//////(_+++_(/////", "::::::::::::::::::", "<<<<<<<<<<<<<<<<<<"}; Themes/default/lgo.xpm100644 1750 1750 1107 6703514432 13750 0ustar denisdenis/* XPM */ static char * lgo_xpm[] = { "18 14 15 1", " c None", ". c #FFFFFF", "+ c #ECECEC", "@ c #DADADA", "# c #C8C8C8", "$ c #B6B6B6", "% c #484848", "& c #A3A3A3", "* c #919191", "= c #7F7F7F", "- c #6D6D6D", "; c #5B5B5B", "> c #363636", ", c #242424", "' c #121212", "..................", "++++++++++++++++++", "@@@@@@@@@@@@@@@@@@", "##################", "$$$$$$$%$$%$$$$$$$", "&&&&&&&%&&%&&&&&&&", "*******%**%*******", "===+#==%==%==#+===", "----#+#%--%#+#----", ";;;;;;#;;;;#;;;;;;", "%%%%%%%%%%%%%%%%%%", ">>>>>>>>>>>>>>>>>>", ",,,,,,,,,,,,,,,,,,", "''''''''''''''''''"}; Themes/default/options.xpm100644 1750 1750 1303 6715077013 14662 0ustar denisdenis/* XPM */ static char * options_xpm[] = { "18 14 23 1", " c None", ". c #FFFFFF", "+ c #ECECEC", "@ c #DADADA", "# c #C8C8C8", "$ c #797979", "% c #B6B6B6", "& c #A2A2A2", "* c #484848", "= c #A3A3A3", "- c #6C6C6C", "; c #919191", "> c #606060", ", c #7F7F7F", "' c #545454", ") c #6D6D6D", "! c #555555", "~ c #5B5B5B", "{ c #3C3C3C", "] c #303030", "^ c #363636", "/ c #242424", "( c #121212", "..................", "++++++++++++++++++", "@@@@@@@@@@@@@@@@@@", "############$#####", "%%%%&%%%%%%$%*%%%%", "====-=====$=*+====", ";;;;>$;;;$;*+;;;;;", ",,,,'*$$$$*+,,,,,,", "))))!+*$)*+)))))))", "~~~~~{+~*+~~~~~~~~", "******]*+*********", "^^^^^^^]^^^^^^^^^^", "//////////////////", "(((((((((((((((((("}; Themes/default/options_on.xpm100644 1750 1750 1325 6715077247 15373 0ustar denisdenis/* XPM */ static char * options_on_xpm[] = { "18 14 24 1", " c None", ". c #FFFFFF", "+ c #ECECEC", "@ c #DADADA", "# c #C8C8C8", "$ c #797979", "% c #B6B6B6", "& c #A2A2A2", "* c #00FFB6", "= c #A3A3A3", "- c #6C6C6C", "; c #919191", "> c #606060", ", c #7F7F7F", "' c #545454", ") c #6D6D6D", "! c #555555", "~ c #5B5B5B", "{ c #3C3C3C", "] c #484848", "^ c #303030", "/ c #363636", "( c #242424", "_ c #121212", "..................", "++++++++++++++++++", "@@@@@@@@@@@@@@@@@@", "############$#####", "%%%%&%%%%%%$%*%%%%", "====-=====$=*+====", ";;;;>$;;;$;*+;;;;;", ",,,,'*$$$$*+,,,,,,", "))))!+*$)*+)))))))", "~~~~~{+~*+~~~~~~~~", "]]]]]]^]+]]]]]]]]]", "///////^//////////", "((((((((((((((((((", "__________________"}; Themes/default/autorepeat_on.xpm100644 1750 1750 1727 6715103767 16054 0ustar denisdenis/* XPM */ static char * autorepeat_on_xpm[] = { "18 14 41 1", " c None", ". c #FFFFFF", "+ c #ECECEC", "@ c #1331F2", "# c #5B6FF0", "$ c #D4D7EC", "% c #DADADA", "& c #2944EF", "* c #C8C8C8", "= c #4F63E4", "- c #8B95D6", "; c #B6B6B6", "> c #495DDE", ", c #7F89CA", "' c #A3A3A3", ") c #334AE0", "! c #737DBD", "~ c #233DE9", "{ c #919191", "] c #213BE6", "^ c #6771B1", "/ c #7F7F7F", "( c #1F39E4", "_ c #374BCB", ": c #6D6D6D", "< c #3145C5", "[ c #4552A7", "} c #5B5B5B", "| c #2B3FBF", "1 c #434D8D", "2 c #484848", "3 c #2438B9", "4 c #1933DE", "5 c #42455A", "6 c #363636", "7 c #1E32B3", "8 c #263389", "9 c #32354A", "0 c #22339D", "a c #242424", "b c #121212", "..................", "+++++@@@@@@#$+++++", "%%%%%@@@@@@@&%%%%%", "****+@@=**=@@-****", ";;;;+@@>;;,@@,;;;;", "''''+@@)!!~@~'''''", "{{{{+@@@@@@]^{{{{{", "////+@@(_@@_//////", "::::+@@<:+@@[:::::", "}}}}+@@|}}+@@1}}}}", "2222+@@3222+@45222", "6666+7786669'+0666", "aaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbb"}; Themes/default/autoplay.xpm100644 1750 1750 1532 6715104263 15027 0ustar denisdenis/* XPM */ static char * autoplay_xpm[] = { "18 14 33 1", " c None", ". c #FFFFFF", "+ c #ECECEC", "@ c #DADADA", "# c #E9E9E9", "$ c #C8C8C8", "% c #D4D4D4", "& c #CFCFCF", "* c #B6B6B6", "= c #D3D3D3", "- c #A3A3A3", "; c #BBBBBB", "> c #E3E3E3", ", c #919191", "' c #AFAFAF", ") c #A4A4A4", "! c #7F7F7F", "~ c #C7C7C7", "{ c #6D6D6D", "] c #DDDDDD", "^ c #5B5B5B", "/ c #8B8B8B", "( c #CBCBCB", "_ c #7A7A7A", ": c #484848", "< c #B5B5B5", "[ c #5A5A5A", "} c #A2A2A2", "| c #363636", "1 c #868686", "2 c #9A9A9A", "3 c #242424", "4 c #121212", "..................", "++++++++++++++++++", "@@@@@@@+++#@@@@@@@", "$$$$$$%++++&$$$$$$", "******@+@++=******", "------++;=+>------", ",,,,,'++,,++),,,,,", "!!!!!~+=--++;!!!!!", "{{{{{+++++++]{{{{{", "^^^^/++;;;(++_^^^^", "::::<+~:::[++}::::", "||||''1||||''2||||", "333333333333333333", "444444444444444444"}; Themes/default/mixer_back.xpm100644 1750 1750 2632 6717703062 15303 0ustar denisdenis/* XPM */ static char * mixer_back_xpm[] = { "42 28 6 1", " c None", ". c #575756", "+ c #121214", "@ c #E0DFE1", "# c #050406", "$ c #919191", "..........................................", ".+@+@#$+@+@#@+$#@#@+@#$+@+@+@+$+@+@+@+$#@@", ".+@+@#$+@+@#@+$#@#@+@#$+@+@+@+$+@+@+@+$#@@", ".+@+++$+++@+++$+++@+++$+++@++#$+++@+++$++@", ".+@+++$+++@+++$+++@+++$+++@++#$+++@+++$++@", ".++#+++++#+++#+++++#+++#+++++++#+#++#++++@", "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@", "..........................................", ".+@+@#$+@+@#@+$#@#@+@#$+@+@+@+$+@+@+@+$#@@", ".+@+@#$+@+@#@+$#@#@+@#$+@+@+@+$+@+@+@+$#@@", ".+@+++$+++@+++$+++@+++$+++@++#$+++@+++$++@", ".+@+++$+++@+++$+++@+++$+++@++#$+++@+++$++@", ".++#+++++#+++#+++++#+++#+++++++#+#++#++++@", "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@", "..........................................", ".+@+@#$+@+@#@+$#@#@+@#$+@+@+@+$+@+@+@+$#@@", ".+@+@#$+@+@#@+$#@#@+@#$+@+@+@+$+@+@+@+$#@@", ".+@+++$+++@+++$+++@+++$+++@++#$+++@+++$++@", ".+@+++$+++@+++$+++@+++$+++@++#$+++@+++$++@", ".++#+++++#+++#+++++#+++#+++++++#+#++#++++@", "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@", "..........................................", ".+@+@#$+@+@#@+$#@#@+@#$+@+@+@+$+@+@+@+$#@@", ".+@+@#$+@+@#@+$#@#@+@#$+@+@+@+$+@+@+@+$#@@", ".+@+++$+++@+++$+++@+++$+++@++#$+++@+++$++@", ".+@+++$+++@+++$+++@+++$+++@++#$+++@+++$++@", ".++#+++++#+++#+++++#+++#+++++++#+#++#++++@", "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"}; Themes/default/mixer_bar.xpm100644 1750 1750 1407 6717655543 15160 0ustar denisdenis/* XPM */ static char * mixer_bar_xpm[] = { "41 5 33 1", " c None", ". c #F20E0C", "+ c #768A64", "@ c #B24E3C", "# c #3AC68C", "$ c #CC3424", "% c #56AC7C", "& c #8E7254", "* c #1AE8A4", "= c #DA261C", "- c #62A074", "; c #9A664C", "> c #26DC9C", ", c #BE4234", "' c #46BA84", ") c #827E5C", "! c #0AF6AC", "~ c #EA1810", "{ c #6E946C", "] c #A85840", "^ c #32D094", "/ c #C23E2C", "( c #4EB684", "_ c #8A7A54", ": c #12F2AC", "< c #D62A24", "[ c #B64A34", "} c #42C28C", "| c #06FEB4", "1 c #7E865C", "2 c #966E4C", "3 c #E22214", "4 c #A26244", ".~~3=<$$/,[@]]4;2&_)1+{{--%%('}#^^>>**:!|", "..~3=<>**:!|", ".~~3=<$$/,[@]]4;2&_)1+{{--%%('}#^^>>**:!|", ".~~3=<<$/,[@]]4;2&))1++{--%%('}#^^>>**:!|", "..~3=<$$/,[@]]4;2&_)1+{{--%%(''#^^^>**:!|"}; Themes/default/mixer2_back.xpm100644 1750 1750 2560 6717700565 15372 0ustar denisdenis/* XPM */ static char * mixer2_back_xpm[] = { "56 21 5 1", " c None", ". c #575756", "+ c #121214", "@ c #1E1E1E", "# c #E0DFE1", "........................................................", ".++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#", ".++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#", ".++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#", ".++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#", ".++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#", ".++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#", ".++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#", ".++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#", ".++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#", ".++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#", ".++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#", ".++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#", ".++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#", ".++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#", ".++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#", ".++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#", ".++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#", ".++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#", ".++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#.++@+@#", "########################################################"}; Themes/default/mixer2_bar.xpm100644 1750 1750 1016 6717676114 15233 0ustar denisdenis/* XPM */ static char * mixer_bar_xpm[] = { "5 19 20 1", " c None", ". c #F2100E", "+ c #E51C16", "@ c #D8291F", "# c #CB3628", "$ c #BF4231", "% c #B24F3A", "& c #A55C42", "* c #98694B", "= c #8B7654", "- c #7F835D", "; c #728F65", "> c #659C6E", ", c #58A977", "' c #4BB680", ") c #3FC289", "! c #32CF92", "~ c #25DC9B", "{ c #18E9A4", "] c #0CF6AD", ".....", "+++++", "@@@@@", "#####", "$$$$$", "%%%%%", "&&&&&", "*****", "=====", "-----", ";;;;;", ">>>>>", ",,,,,", "'''''", ")))))", "!!!!!", "~~~~~", "{{{{{", "]]]]]"}; Themes/default/mixer_panel.xpm100644 1750 1750 1157 6717700333 15501 0ustar denisdenis/* XPM */ static char * mixer_panel_xpm[] = { "13 28 6 1", " c None", ". c #575756", "+ c #ADABAB", "@ c #1E1E1E", "# c #E0DFE1", "$ c #848383", ".............", ".+@+++++++++#", ".+@+@+++++++#", ".+@+@+@+++++#", ".+@+@+@+@+++#", ".+@+@+@+@+@+#", "#############", ".............", ".+++++++++++#", ".+++@@++++@+#", ".++@++@++@++#", ".+@++++@@+++#", ".+++++++++++#", "#############", ".............", ".+++++++++++#", ".+$@@@@+++++#", ".+@@@@@@@$@+#", ".+$@@@@+++++#", ".+++++++++++#", "#############", ".............", ".++++@@@++++#", ".+++@+++@+++#", ".+++@+@+@+++#", ".+++@+++@+++#", ".++++@@@++++#", "#############"}; Themes/default/mixer2_panel.xpm100644 1750 1750 1050 6717700507 15556 0ustar denisdenis/* XPM */ static char * mixer2_panel_xpm[] = { "56 7 5 1", " c None", ". c #575756", "+ c #1E1E1E", "@ c #ADABAB", "# c #E0DFE1", "........................................................", ".+@@@@#.@@+@@#.@@+@@#.+@@@+#.@+++@#.@@@@@#.+@@@+#.@+++@#", ".++@@@#.@+@@@#.@@@+@#.+@@@+#.+@@@+#.+++@@#.++@++#.@+++@#", ".+++@@#.+@@@@#.@@@@+#.+@+@+#.+@+@+#.+++++#.+@+@+#.@+++@#", ".++++@#.@+@@@#.@@@+@#.++@++#.+@@@+#.+++@@#.+@@@+#.@@+@@#", ".+++++#.@@+@@#.@@+@@#.+@@@+#.@+++@#.@@@@@#.+@@@+#.@@+@@#", "########################################################"}; Themes/default/theme_on.xpm100644 1750 1750 1417 6715104407 14771 0ustar denisdenis/* XPM */ static char * theme_on_xpm[] = { "18 14 28 1", " c None", ". c #FFFFFF", "+ c #ECECEC", "@ c #DADADA", "# c #44F4B4", "$ c #7AEFC4", "% c #C8C8C8", "& c #78EDC2", "* c #B6B6B6", "= c #76EBC0", "- c #A3A3A3", "; c #73E9BE", "> c #919191", ", c #71E7BC", "' c #7F7F7F", ") c #6FE5BA", "! c #6D6D6D", "~ c #6DE3B8", "{ c #5B5B5B", "] c #6BE1B6", "^ c #484848", "/ c #69DFB4", "( c #363636", "_ c #67DDB2", ": c #242424", "< c #65DBB0", "[ c #63B194", "} c #121212", "..................", "++++++++++++++++++", "@@@@@########$@@@@", "%%%%%########&%%%%", "********##=*******", "--------##;-------", ">>>>>>>>##,>>>>>>>", "''''''''##)'''''''", "!!!!!!!!##~!!!!!!!", "{{{{{{{{##]{{{{{{{", "^^^^^^^^##/^^^^^^^", "((((((((##_(((((((", "::::::::<<[:::::::", "}}}}}}}}}}}}}}}}}}"}; ascd-0.13.2.orig/ascd/themes/default.tar0100644000175000017500000012000006734174577017333 0ustar hallonhallonDefault/ 40755 764 144 0 6734174557 11075 5ustar denisusersDefault/back.xpm100644 764 144 6541 6716050770 12614 0ustar denisusers/* XPM */ static char * back_xpm[] = { "56 56 1 1", " c None", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "}; Default/back_bar.xpm100644 764 144 546 6715065371 13421 0ustar denisusers/* XPM */ static char * back_bar_xpm[] = { "42 5 5 1", " c None", ". c #575756", "+ c #121214", "@ c #050406", "# c #E0DFE1", "..........................................", ".+@++@++@++@+++@+@+++@++++@+++++++@++++@+#", ".++++++++++++++++++++++++++++@+++++++++++#", ".++@+++++@+++@+++++@+++@+++++++@+@++@++++#", "##########################################"}; Default/back_counter.xpm100644 764 144 1114 6715060665 14345 0ustar denisusers/* XPM */ static char * back_counter_xpm[] = { "43 10 4 1", " c None", ". c #575756", "+ c #121214", "@ c #050406", "...........................................", ".++++++++++++++++++++++++++++++++++++++++++", ".+@++@++@++@++@++@++@++@++@++@++@++@++@++@+", ".++++++++++++++++++++++++++++++++++++++++++", ".++@+++++@+++++@+++++@+++++@+++++@+++++@+++", ".+++++@+++++@+++++@+++++@+++++@+++++@+++++@", ".@++++++++@+++++@+++++@+++++@+++++@+++++@++", ".+++@++@+++++@+++++@+++++@+++++@+++++@+++++", ".+@++++++++++++++++++++++++++++++++++++++++", ".+++@+++@+@+++@+@+++@+@+++@+@+++@+@++++@+++"}; Default/back_msg.xpm100644 764 144 1425 6715057312 13454 0ustar denisusers/* XPM */ static char * back_msg_xpm[] = { "56 11 5 1", " c None", ". c #575756", "+ c #121214", "@ c #050406", "# c #E0DFE1", ".+++++++++++++++++++++++++++++++++++@++++@++++++@++++++#", ".++++@+++++@+++++@+++++@+++++@+++++++++++++@+++++++++@+#", ".@+++++@+++++@+++++@+++++@+++++@+@+++@+@+++++@+++@+++++#", ".+@+++++@+++++@+++++@+++++@+++++++++++++++++++@++++++@+#", ".+++@+++++@+++++@+++++@+++++@+++++@+++++++@+++++++@++++#", ".++++++++++++++++++++++++++++++@+++++@+@+++++++@+++++@+#", ".+@+++@++++@+@+++@+@+++@+@+++@+++++@+++++++@+++++++++++#", ".++@++++@+++++++++++++++++++++++@+++++++@++++++@+@+++@+#", ".+++++++++++++@+++++@+++++@++++++++++@++++++@++++++++++#", ".++@+@+++@+@+++++@+++++@+++++@++++@++++++@+++++++@+++@+#", "########################################################"}; Default/back_track.xpm100644 764 144 455 6715060642 13754 0ustar denisusers/* XPM */ static char * back_track_xpm[] = { "13 10 5 1", " c None", ". c #575756", "+ c #121214", "@ c #E0DFE1", "# c #050406", ".............", "++++++++++++@", "+#++#++#++#+@", "++++++++++++@", "++#+++++#+++@", "+++++#++++#+@", "+++#++++++++@", "#+++++#+++#+@", "++++++++#+++@", "#++#++++++#+@"}; Default/bar.xpm100644 764 144 667 6716051040 12432 0ustar denisusers/* XPM */ static char * bar_xpm[] = { "41 3 17 1", " c None", ". c #F30D09", "+ c #6F8F67", "@ c #B54B37", "# c #31CD91", "$ c #8F6F4F", "% c #D32B1F", "& c #4EB280", "* c #13EDA9", "= c #5DA171", "- c #A15D41", "; c #E21C14", "> c #22DC9C", ", c #80805C", "' c #C43A28", ") c #04FCB4", "! c #42BE88", "))***>>###!!&&===+++,,$$$---@@@''%%%;;...", "))***>>>##!!&&&==++,,,$$$---@@@''%%;;;...", "))**>>>##!!!&&===+++,,$$$---@@@'''%%;;..."}; Default/cross.xpm100644 764 144 321 6715065635 13020 0ustar denisusers/* XPM */ static char * cross_xpm[] = { "7 5 7 1", " c None", ". c #A5A6A6", "+ c #939394", "@ c #EFEFEF", "# c #747575", "$ c #575756", "% c #3F3F3F", ".......", "++@+@++", "###@###", "$$@$@$$", "%%%%%%%"}; Default/digits.xpm100644 764 144 27677 6734174177 13244 0ustar denisusers/* XPM */ static char * ascd_digits_xpm[] = { "1343 9 3 1", " c None", ". c None", "+ c #30FFCF", "........+....+.+..........+...++..+..........+.....+...+.....................................+...+++....+....+++...+++.....+..+++++...++..+++++..+++...+++.................................+++...+++....+...+++.....++..+++...+++++.+++++...++..+...+..+++....++..+...+.+.....+...+.+...+..+++..++++...+++..++++...+++..+++++.+...+.+...+.+...+.+...+.+...+.+++++...++...+.....++.....+......................+..............+..........++........+.................+......+...............................................+..........................................++...+...++.......................++...............................................................................................................................................................................................+...........+++.......+...+...+.....+++..+.+...+++...+++.....................+++..+++++...++....+....++....++......+.........++++...............+.....+++.......+.....+.....++......+....+.......+....+.....+.+..+.+....++...++++...++...+.......+....+....+.+...+.......+....+....+.+...++.....+.+..+.......+....+.....+.+..+.+.........++++..+.......+....+....+.+.....+...+......++...+.......+....+.....+.+..+.+....++...............+.......+....+....+.+....+......+....+....+.+.....+....+.+...+......+....+.....+.+..+.+....+...........+......+....+....+.+.....+..+......+.+.", "........+....+.+...+.+...++++.++..+...+......+....+.....+.....+.....+........................+..+...+..++...+...+.+...+...++..+......+........+.+...+.+...+.................+.......+.........+.+...+...+...+..+...+..+.+..+..+.....+......+..+.+...+...+......+..+..+..+.....++.++.++..+.+...+.+...+.+...+.+...+.+...+...+...+...+.+...+.+...+.+...+.+...+.....+...+....+......+....+.+.........+...........+..............+.........+..........+.......+......+..+......+...............................................+.........................................+.....+.....+....+.....+.......+..+..+....................................................................................................................................................................................................+....+....+...+.+...+...+....+..........+...+.+...+...+.+.............+...+........+..+...+......+.....+....+.........+++.+..............++......++.+.+...+...+.+...+..+............+.....+....+.+...+.+..........++..+..+...+..+...+.....+....+.+..........+.....+....+.+.........+.+...+.+....+.....+....+.+...+.+...+++..+...+.+..++...+.....+....+.+..........+....+.....+..+...+.....+....+.+...+.+..........++................+.....+....+.+...........+....+....+.+..........+++..+.+.....+....+....+.+...+.+..........+.......+....+....+....+.+..........+...+..........", "........+....+.+..+++++.+.+......+....+......+...+.......+..+.+.+...+.......................+...+...+...+.......+.....+..+.+..++++..+........+..+...+.+...+...+.....+.....++...+++...++.......+.+.+.+..+.+..+..+..+.....+...+.+.....+.....+.....+...+...+......+..+.+...+.....++.++.+.+.+.+...+.+...+.+...+.+...+.+.......+...+...+.+...+.+.+.+..+.+...+.+.....+....+.....+.....+...+...+........+.....+++...+++....+++...+++...++....+.....+++..+++...............+..+...+...++.+...+++....++....++....++....+.+...+++..++++..+..+..+..+.+...+..+..+..+..+..+++....+.....+.....+...+.+.+..++.....++..+..+..............................................................................................................................................................................................+....++++..+.....+++...+.+....+.....++........+.+++.+...+..+.+..............+++++........+..+.+++++...+.....+..........+..+.+++.+...............+.....+.+..+.+..+..+..+..+..++..+...+.............................+.........+..+..+.....+++++.+++++.+++++.+++++....................+++...+..+........+++...+++...+++...+++..+...+..+.+..+.+.+.+...+.+...+.+...+.+...+.+...+..+++...+..+..+++...+++...+++...+++...+++...+++..++.+....+++...++....++....++....++.............................+..................................++..........++................................++++...+..+", "........+..........+.+...++.....+...+++++........+.......+...+++..+++++........+++..........+...+...+...+......+....++..+..+......+.++++.....+...+++...++++.............++.............++....+..+.+.+..+.+..++++..+.....+...+.++++..++++..+.+++.+++++...+......+..++....+.....+.+.+.+.+.+.+...+.+...+.+...+.++++...+++....+...+...+..+.+..+.+.+...+....+.+....+.....+.....+.....+.................+.......+..+..+..+.....+..+..+..+..+++...+..+..+..+...++.....++..+.+....+...+.+.+..+..+..+..+..+..+..+..+...++...+......+....+..+..+..+.+.+.+..+..+..+..+....+..++......+......++....+...+++...+++...++...............................................................................................................................................................................................+...+.+...++++...+.+....+..........+..+.......++..+..+++..+.+...+++++..+++..+++.+.........++....+....+.......+.........+..+..++.+...+...........+....+++....+.+...+.....+....+.+...+.....+++...+++...+++...+++...+.+...+++..+++++.+.....+.....+.....+.....+......+++...+++...+++....+...+++.+.++..+.+...+.+...+.+...+.+...+.+...+...+...+.+.+.+...+.+...+.+...+.+...+.+...+..+..+..+.+......+.....+.....+.....+.....+.....+...+.+..+.....+..+..+..+..+..+..+..+...++....++...++....++....+++...+++....++....++....++....++...+..+.+++++..+.+...+..+..+..+..+..+..+..+..+..+.+...+..+..+", "........+.........+++++...++...+......+..........+.......+..+.+.+...+.......................+...+...+...+.....+.......+.+++++.....+.+...+...+...+...+.....+...+.....+.....++...+++...++.....+...+.++..+++++.+...+.+.....+...+.+.....+.....+...+.+...+...+......+..+.+...+.....+.+.+.+.+.+.+...+.++++..+...+.+.+.......+...+...+...+..+.+..++.++..+.+....+....+......+.....+.....+......................++++..+..+..+.....+..+..++++...+....+..+..+..+....+......+..++.....+...+.+.+..+..+..+..+..+..+..+..+...+.....++....+....+..+..+..+.+.+.+...++...+..+...+.....+.....+.....+..........++.....++....................................................................................................................................................................................................+...+.+....+.....+++..+++++........+..+.......+.+++...+....+.+......+.......++.++...............+....+++...++..........+..+...+.+..............+++..+...+..+.+...+.....+....+++...+......+.+...+.+...+.+...+.+...+.+...+.+..+..+..+.....++++..++++..++++..++++....+.....+.....+.....+....+..+.+.+.+.+...+.+...+.+...+.+...+.+...+..+.+..+.+.+.+...+.+...+.+...+.+...+..+.+...+++...+..+..++++..++++..++++..++++..++++..++++..++++..+.....++++..++++..++++..++++....+.....+....+.....+...+..+...+..+..+..+..+..+..+..+..+..+..+..+........+++...+..+..+..+..+..+..+..+..+..+.+...+..+..+", "...................+.+....+.+.+..++...+..........+.......+....+.....+.....+..........++....+....+...+...+....+....+...+....+..+...+.+...+...+...+...+....+..........+.......+.......+...........+.....+...+.+...+..+..+.+..+..+.....+......+..+.+...+...+......+..+..+..+.....+...+.+..++.+...+.+.....+...+.+..+..+...+...+...+...+..+.+..++.++.+...+...+...+.......+......+....+.....................+...+..+..+..+.....+..+..+......+....+..+..+..+....+......+..+.+....+...+.+.+..+..+..+..+..+..+..+..+...+.......+...+....+..+...++...+.+...+..+...++...+......+.....+.....+..........+.......+........++++........................................................................................................................................................................................+...+.+....+....+...+...+.....+.....++........+...+..+++....+.+.....+.......+...+......................................+..+...+.+...................+...+.+.+...+..++.+..++..+.++.+.....+++++.+++++.+++++.+++++.+++++.+++++.+..+...+..+.+.....+.....+.....+.......+.....+.....+.....+....+.+..+.+.+.+...+.+...+.+...+.+...+.+...+.+...+.++..+.+...+.+...+.+...+.+...+...+....+.....+..+.+...+.+...+.+...+.+...+.+...+.+...+.+.+....+.....+.....+.....+.....+.......+.....+....+.....+...+..+...+..+..+..+..+..+..+..+..+..+..+..+...+....+.+...+..+..+..+..+..+..+..+...++..+...+...++.", "........+...............++++..+..++...............+.....+.................+..........++....+.....+++...+++..+++++..+++.....+...+++...+++....+....+++...++..........+........................+....+++..+...+.++++....++..+++...+++++.+.......++..+...+..+++..+++...+...+.+++++.+...+.+...+..+++..+......+++..+...+..+++....+....+++....+...+...+.+...+...+...+++++...++.....+...++.........+++++........++++..+++....+++...+++...+++...+.....+++..+..+....+......+..+..+...+...+.+.+..+..+...++...+++....+++...+....+++.....++...+++...++...+.+...+..+....+...+++.....++...+...++........................................................................................................................................................................................................................+....++++.+++++.........+.....+.......+........+++....+......................+++..............+++++....................++++...+.+....................+++..........+.+.....+.+.+.+..+++..+...+.+...+.+...+.+...+.+...+.+...+.+..++...++..+++++.+++++.+++++.+++++..+++...+++...+++...+++...++...+..++..+++...+++...+++...+++...+++........++++...+++...+++...+++...+++....+....+.....+.+...++++..++++..++++..++++..++++..++++..+.++...+++...+++...+++...+++...+++....+.....+....+.....+....+++...+..+...++....++....++....++....++....+....++.....+++...+++...+++...+++....+..++++.....+.", "..........................+........................+...+.................+..............................................................................................................................................................................................................................+.....................................................................................................................................+.................+................................+........+.............................................+.....................................................................................................................................................................................................................................................+.......................+....+++.................................................................................+...................+......................+++....+....+++....................................................+.............................................................................................................................................+.................................................+..................................................................................................+...............................+...+.......+..", ".........................................................................................................................................................................................................................................................................................................++.................................................................................................................................++................++.................................+........+.............................................+......................................................................................................................................................................................................................................................................................................................................................................+..................+.........................+....++.....+...................................................+...............................................................................................................................................................................................+...................................................................................................................................+...+.......+.."}; Default/digits2.xpm100644 764 144 27677 6734174423 13320 0ustar denisusers/* XPM */ static char * ascd_digits_xpm[] = { "1343 9 3 1", " c None", ". c None", "+ c #FFFF80", "........+....+.+..........+...++..+..........+.....+...+.....................................+...+++....+....+++...+++.....+..+++++...++..+++++..+++...+++.................................+++...+++....+...+++.....++..+++...+++++.+++++...++..+...+..+++....++..+...+.+.....+...+.+...+..+++..++++...+++..++++...+++..+++++.+...+.+...+.+...+.+...+.+...+.+++++...++...+.....++.....+......................+..............+..........++........+.................+......+...............................................+..........................................++...+...++.......................++...............................................................................................................................................................................................+...........+++.......+...+...+.....+++..+.+...+++...+++.....................+++..+++++...++....+....++....++......+.........++++...............+.....+++.......+.....+.....++......+....+.......+....+.....+.+..+.+....++...++++...++...+.......+....+....+.+...+.......+....+....+.+...++.....+.+..+.......+....+.....+.+..+.+.........++++..+.......+....+....+.+.....+...+......++...+.......+....+.....+.+..+.+....++...............+.......+....+....+.+....+......+....+....+.+.....+....+.+...+......+....+.....+.+..+.+....+...........+......+....+....+.+.....+..+......+.+.", "........+....+.+...+.+...++++.++..+...+......+....+.....+.....+.....+........................+..+...+..++...+...+.+...+...++..+......+........+.+...+.+...+.................+.......+.........+.+...+...+...+..+...+..+.+..+..+.....+......+..+.+...+...+......+..+..+..+.....++.++.++..+.+...+.+...+.+...+.+...+.+...+...+...+...+.+...+.+...+.+...+.+...+.....+...+....+......+....+.+.........+...........+..............+.........+..........+.......+......+..+......+...............................................+.........................................+.....+.....+....+.....+.......+..+..+....................................................................................................................................................................................................+....+....+...+.+...+...+....+..........+...+.+...+...+.+.............+...+........+..+...+......+.....+....+.........+++.+..............++......++.+.+...+...+.+...+..+............+.....+....+.+...+.+..........++..+..+...+..+...+.....+....+.+..........+.....+....+.+.........+.+...+.+....+.....+....+.+...+.+...+++..+...+.+..++...+.....+....+.+..........+....+.....+..+...+.....+....+.+...+.+..........++................+.....+....+.+...........+....+....+.+..........+++..+.+.....+....+....+.+...+.+..........+.......+....+....+....+.+..........+...+..........", "........+....+.+..+++++.+.+......+....+......+...+.......+..+.+.+...+.......................+...+...+...+.......+.....+..+.+..++++..+........+..+...+.+...+...+.....+.....++...+++...++.......+.+.+.+..+.+..+..+..+.....+...+.+.....+.....+.....+...+...+......+..+.+...+.....++.++.+.+.+.+...+.+...+.+...+.+...+.+.......+...+...+.+...+.+.+.+..+.+...+.+.....+....+.....+.....+...+...+........+.....+++...+++....+++...+++...++....+.....+++..+++...............+..+...+...++.+...+++....++....++....++....+.+...+++..++++..+..+..+..+.+...+..+..+..+..+..+++....+.....+.....+...+.+.+..++.....++..+..+..............................................................................................................................................................................................+....++++..+.....+++...+.+....+.....++........+.+++.+...+..+.+..............+++++........+..+.+++++...+.....+..........+..+.+++.+...............+.....+.+..+.+..+..+..+..+..++..+...+.............................+.........+..+..+.....+++++.+++++.+++++.+++++....................+++...+..+........+++...+++...+++...+++..+...+..+.+..+.+.+.+...+.+...+.+...+.+...+.+...+..+++...+..+..+++...+++...+++...+++...+++...+++..++.+....+++...++....++....++....++.............................+..................................++..........++................................++++...+..+", "........+..........+.+...++.....+...+++++........+.......+...+++..+++++........+++..........+...+...+...+......+....++..+..+......+.++++.....+...+++...++++.............++.............++....+..+.+.+..+.+..++++..+.....+...+.++++..++++..+.+++.+++++...+......+..++....+.....+.+.+.+.+.+.+...+.+...+.+...+.++++...+++....+...+...+..+.+..+.+.+...+....+.+....+.....+.....+.....+.................+.......+..+..+..+.....+..+..+..+..+++...+..+..+..+...++.....++..+.+....+...+.+.+..+..+..+..+..+..+..+..+...++...+......+....+..+..+..+.+.+.+..+..+..+..+....+..++......+......++....+...+++...+++...++...............................................................................................................................................................................................+...+.+...++++...+.+....+..........+..+.......++..+..+++..+.+...+++++..+++..+++.+.........++....+....+.......+.........+..+..++.+...+...........+....+++....+.+...+.....+....+.+...+.....+++...+++...+++...+++...+.+...+++..+++++.+.....+.....+.....+.....+......+++...+++...+++....+...+++.+.++..+.+...+.+...+.+...+.+...+.+...+...+...+.+.+.+...+.+...+.+...+.+...+.+...+..+..+..+.+......+.....+.....+.....+.....+.....+...+.+..+.....+..+..+..+..+..+..+..+...++....++...++....++....+++...+++....++....++....++....++...+..+.+++++..+.+...+..+..+..+..+..+..+..+..+..+.+...+..+..+", "........+.........+++++...++...+......+..........+.......+..+.+.+...+.......................+...+...+...+.....+.......+.+++++.....+.+...+...+...+...+.....+...+.....+.....++...+++...++.....+...+.++..+++++.+...+.+.....+...+.+.....+.....+...+.+...+...+......+..+.+...+.....+.+.+.+.+.+.+...+.++++..+...+.+.+.......+...+...+...+..+.+..++.++..+.+....+....+......+.....+.....+......................++++..+..+..+.....+..+..++++...+....+..+..+..+....+......+..++.....+...+.+.+..+..+..+..+..+..+..+..+...+.....++....+....+..+..+..+.+.+.+...++...+..+...+.....+.....+.....+..........++.....++....................................................................................................................................................................................................+...+.+....+.....+++..+++++........+..+.......+.+++...+....+.+......+.......++.++...............+....+++...++..........+..+...+.+..............+++..+...+..+.+...+.....+....+++...+......+.+...+.+...+.+...+.+...+.+...+.+..+..+..+.....++++..++++..++++..++++....+.....+.....+.....+....+..+.+.+.+.+...+.+...+.+...+.+...+.+...+..+.+..+.+.+.+...+.+...+.+...+.+...+..+.+...+++...+..+..++++..++++..++++..++++..++++..++++..++++..+.....++++..++++..++++..++++....+.....+....+.....+...+..+...+..+..+..+..+..+..+..+..+..+..+..+........+++...+..+..+..+..+..+..+..+..+..+.+...+..+..+", "...................+.+....+.+.+..++...+..........+.......+....+.....+.....+..........++....+....+...+...+....+....+...+....+..+...+.+...+...+...+...+....+..........+.......+.......+...........+.....+...+.+...+..+..+.+..+..+.....+......+..+.+...+...+......+..+..+..+.....+...+.+..++.+...+.+.....+...+.+..+..+...+...+...+...+..+.+..++.++.+...+...+...+.......+......+....+.....................+...+..+..+..+.....+..+..+......+....+..+..+..+....+......+..+.+....+...+.+.+..+..+..+..+..+..+..+..+...+.......+...+....+..+...++...+.+...+..+...++...+......+.....+.....+..........+.......+........++++........................................................................................................................................................................................+...+.+....+....+...+...+.....+.....++........+...+..+++....+.+.....+.......+...+......................................+..+...+.+...................+...+.+.+...+..++.+..++..+.++.+.....+++++.+++++.+++++.+++++.+++++.+++++.+..+...+..+.+.....+.....+.....+.......+.....+.....+.....+....+.+..+.+.+.+...+.+...+.+...+.+...+.+...+.+...+.++..+.+...+.+...+.+...+.+...+...+....+.....+..+.+...+.+...+.+...+.+...+.+...+.+...+.+.+....+.....+.....+.....+.....+.......+.....+....+.....+...+..+...+..+..+..+..+..+..+..+..+..+..+..+...+....+.+...+..+..+..+..+..+..+..+...++..+...+...++.", "........+...............++++..+..++...............+.....+.................+..........++....+.....+++...+++..+++++..+++.....+...+++...+++....+....+++...++..........+........................+....+++..+...+.++++....++..+++...+++++.+.......++..+...+..+++..+++...+...+.+++++.+...+.+...+..+++..+......+++..+...+..+++....+....+++....+...+...+.+...+...+...+++++...++.....+...++.........+++++........++++..+++....+++...+++...+++...+.....+++..+..+....+......+..+..+...+...+.+.+..+..+...++...+++....+++...+....+++.....++...+++...++...+.+...+..+....+...+++.....++...+...++........................................................................................................................................................................................................................+....++++.+++++.........+.....+.......+........+++....+......................+++..............+++++....................++++...+.+....................+++..........+.+.....+.+.+.+..+++..+...+.+...+.+...+.+...+.+...+.+...+.+..++...++..+++++.+++++.+++++.+++++..+++...+++...+++...+++...++...+..++..+++...+++...+++...+++...+++........++++...+++...+++...+++...+++....+....+.....+.+...++++..++++..++++..++++..++++..++++..+.++...+++...+++...+++...+++...+++....+.....+....+.....+....+++...+..+...++....++....++....++....++....+....++.....+++...+++...+++...+++....+..++++.....+.", "..........................+........................+...+.................+..............................................................................................................................................................................................................................+.....................................................................................................................................+.................+................................+........+.............................................+.....................................................................................................................................................................................................................................................+.......................+....+++.................................................................................+...................+......................+++....+....+++....................................................+.............................................................................................................................................+.................................................+..................................................................................................+...............................+...+.......+..", ".........................................................................................................................................................................................................................................................................................................++.................................................................................................................................++................++.................................+........+.............................................+......................................................................................................................................................................................................................................................................................................................................................................+..................+.........................+....++.....+...................................................+...............................................................................................................................................................................................+...................................................................................................................................+...+.......+.."}; Default/help.xpm100644 764 144 320 6720024701 12577 0ustar denisusers/* XPM */ static char * help_xpm[] = { "7 5 7 1", " c None", ". c #A5A6A6", "+ c #EFEFEF", "@ c #939394", "# c #747575", "$ c #575756", "% c #3F3F3F", "...++..", "@@+@@+@", "####+##", "$$$$$$$", "%%%+%%%"}; Default/panel.xpm100644 764 144 321 6715065200 12752 0ustar denisusers/* XPM */ static char * panel_xpm[] = { "7 5 7 1", " c None", ". c #A5A6A6", "+ c #939394", "@ c #EFEFEF", "# c #747575", "$ c #575756", "% c #3F3F3F", ".......", "+++@+++", "##@@@##", "$$$@$$$", "%%%%%%%"}; ascd-0.13.2.orig/ascd/themes/themes-manual.ps.gz0100644000175000017500000024105006764325341020721 0ustar hallonhallon‹áŞŃ7themes-manual.psÔ;kE’ŸÝż"O+$ö$OU>+˲0‰=Ţ˝ă„řĐÓ]=nÜÓÝôc<ĂhţűĹ#ť2#ŰŘg {Ü. UQ‘ńĘxeTőG˙öí‹ÇŸÎ7—Ăc{ŃN>ú~űínš> ťÇß̇Őőĺ°v˙JŕÉG}śڇÍî‰úŻĺzŢüS}żĺGę?‡Ý~šY+{Ą/Zőńjš>ŢţU}üŮćzť\ ęůô0x8]Lš€ Ŕs€\7ťëÍÍpبŢŽLłť÷W{řgz3¤ťü3ěÁř °Ţ6ëáővzxÉ÷ű›&cďö@>ʚĂnşŢŻ@{†\šëéaˇźM̛հž:ŃúĽ!Íčzސ‚x94Ăí,ĄL›én7˝K73¸›Ľë5^Żůć˛!ŁđÍvŮl˛âÍt•k„ 6MiýţŮm^%‘ˇÍt>OOšýń’/gÍő1ťąotŰĚV›ýPŘgŐěgÓU˘ľX4 ؚĹfÔź^€=^ °_4űáďqÁ*1ÚżĆg(ęëĺ|d0;gÓmýtý´9Ya…°ŤŃvűWËćŤß| žžÖŸŻg›ůr}Ľ^żvĂývłU‡Ýqx¸_LWűáašŕ?jŇĚć÷‹9âJý˘.ďľu†[Ő|ńŐsľîç´ţMŤ›ÝhFç\çjvÜíŔýiű!NŘQŕşú-(BAŞôd??(c@€ů//aCˇ×ęú€"ś‡ńjŸŽfŰýäžŮîŒÔěfľ$ŕv§ËŰővŚ´RˆŐŔm ž]N$JĚnn',Őîú6ń[ě€_g`%Â@ƒéquH~?§ˆŤ\Oš;ˆaޚŰt5Ą ´ďLÝĺË­Ú˙ź;0°Ď˜ šoŘ_ƒuÉnڌ‰aŇ|7u‡řXÝŤÉŁóœ8=€Ś'Óő|=˝FA0ސ?Dăăżœî‡ˇ>`%Öčú’´+ާˇ)'ŒÚn‰ˇ÷đď#f öI·0ÔţGĐŃż†Ÿ ˜ž=×ç‹{ţçJˇopPôwŠÓĎlł˝cě‡DDeq~ “˙ĂaÁ×'XĽ$|đŤăaRR%šżŽ5‘ÓŞ€“ƈđ 8Ń '˘Íđ÷?pwʍfg~1ĽJ´Ď&ľZB:<íŃČf´ĺŐpŚÉƒÚ [¨š…\ëB˘*La<°g4ł—PO‡ýÍ0S?Léđ—ŘŞf8î6|cTóóqsöŔz…NÄ`ŤšĹjłC÷Ç[—°ć—Ž:ŤŐrť_îT3Ÿ^]AGBˇÝéV1$ŞfśÜAS°X ˇ ęUłv‡—›#ŠaSŐź˜Mw›ÄüR5WÇĺŠ$\ ‹CgŞůćsžTóKĆďuvÄíOJî–W/Čf2^Ąf z^+݂–`ßéţ%߂–ĂužË՜MýÖ÷ůp=Ý˝bčś/d-u+X‚r›D˘RnĄš˙ž/ĄĄŐä=†|ÜŤÉ}Jőűí‚2%ôW”<Á Rň´ĐáőÂg„‰;ĘˇŸa¤ä™jÔ š†l‰đĺŤÄÝ%ÔÎÉé žÜݨKč =ź| KŃÓČΞ%ŻÄëéţřvwzz˝™Ť˝‚ëýËĺ1!7@y€¤5ćôćrż%Y–ť$󿅺q tĄýÝ.ˇˇ ëÎÝÁŁťâŃÝřáSVkłžTř/bΕ~@Đ@‹¨}˜¤DQŘh8@'Žľ›ía™ŚWŤd0_lďNIn˛]!ë5B†p1A:HľN›t9Őđä qv’WoqWšƒ)$Ü.gČĂĂĆĂ)WOšĺzöËďŒqž{ľWë-đľĄUS0ĐV-ÔŐ.=ţ:=†ŽkTĆß}ůě8îŽ.gЌ'ŕgˆ|Pű—›×'D,Ćk,żčKÍwŸƒąĆZżžąúë×Ég/'—Z@ç7ŘMÁó…B@Ž}H l€r…ƒ 8Ťl cí Ő UŚ×D8ƒĽ†‡§nmĽKŠŇâcŞF}r ŔťŐ)ßßă‚_Mň“”á‘`Vö̰Űöl_¸Â3ƒ03”ŇÁ(“^ ‡ăötó08îŕ ÷ďxčú@p2üÔM”zú´AЋĺ/ƒúÁCƋÎü¨šŻŽ§°ěęٳͭZC üäE5̇›ĺl`މ,ߜ"š'  lHŸ6}XBҔžö78›śę1ýÝŻ&:Ňm4ö2÷a•ô×ÁÍqfšňÉńj?šÚ)řۂŕßŘz$>ë}ź€ź}hń|}U |ŇcX]üŸ4ŸŢLׇ/§ťůđřůp˝T5ŕńß_@먊J+şËÉŻŕƒg˙ŕęŠ˙<^ţ¨Ž RÝS§?QFˇ.*ă…qęłÉSočŰ  `@`/‚+îeľ˝0mţAú۰‚ÓârŐmź|§UjL´ď=ŮcźíáÚĂ –ž‚Yţx…JŮôE’l§ËźWd 1ËöÔyZsŃ ŕ€yŐ˜Žżˆ…jOM‹[Ý!ŤřţVs¨}ů÷TŢŞ_f.t(Ľž!Đ_xSŤÔT‰=îҪ҃GÇReqŃş [Jí ‹sŐVYŁĺŽ`TZŤĺNŁkZŰ_„ö˙Ć5[ô1Ö÷t™őŰi;’Í‘†˙RŮÂôA´ÓU– ]Eť‹XHöÔ ě/l(č~Ƒű@J…&Px@ň4ŰR’8ƒÍ GŽď ň6íHŁ'oÍ2S ;A˜œŁ_ŞŒ˜žVyŠŔˆŹ>@;˛Q0Ňîƒ9xňë?ĆM|k~Ł c)3˛= h ŽĂúVÎ>Ľžô.ŘĄ÷ôP]…óĄezOi cbnUťP-ˇmOiUpˇşÚ3CŔž>`j‘ĆŰT܉&8tFÓL4M[š ďŒĐýŮÖx@÷zňϰE:ĂŐ ˙ü4áCĸ-(ďcD>ÖyNUo¸“$ >‡ün9Ң=O|ţő9ňÝůŰ÷äç!őĘŕ] ¤†ął¤Ebь-•ťźiĆ@îwžo~Ł,Ňsy+ˇ[žjşŁ€Íâaljmč ż@OöÜba1)ŢMO!“¨u2¨šďÉ413¸@ÍĘ4˜ =GJšÜŒUÜšd‚Ěĺ –ş˘ĚˆRn/iv”Ö¸ČĺÖ¤FsNkR#ô^SźËĺ}ŔŘ)Q3ä-BŁSZÖ#NŇ §´&—Ă Źć\'ŹdűœÖ$0Ľľ Ä]íŇqňťér5ě&ť}}ÔQ9rď^ÁŠq‚‡b<¤ţIÁ†Ţaţ?:wĐËż˙űän#űţ=¤˙zaŒüL‹Rß3–Lë%ľ”úNäđźabąţŔ *Šl•žě‘˙žŻULěPΓé‚Ű@áV҂_ˇŒ t)vÔcĎźŕ÷śĚť†&Ď6›WŞźĎФŔ§zB1Áőät™ë‰ć!ä*O'ˇÔ-ĽĘ1ÂčDÇ¸6蘀1}ą–r4ƒ 3\‘Á¸y-vűĄĂť Ł*[­ő\ď\š–zɀÖ|-8tŠG D)ŠJžÖRzXKzżăˆćmŐű O-A…‰˘ÂK=•˝„ít #–Öë‚ŔBe#ÍSbiťH‡ŰXš¸'OĎXP?űˆĆĚ ŔŇmE §ľd€Ąľä€˘iCƒIĎjĄ(jĽmĹaNK‰ ‚Œ¤=͉2 ńź9×Ăw茒o ŃŸÔšCąaŕ’Ü9W­íi’"ׂ# ™ŃšŰVʇ­Kë…|!üŰJf<÷ ;ĎÇîNŽľhÂŚúv[Ég \IOMœŘs fWŮŢj Ľ|ŕÚTňuŐ~PżíĽ,‹ńe"°ŇŚ(KO#ákXDLa"Đ^Ę2p?VŽĽY•‘ž‹=ŤľTk„ýŹ“žK|]{dąçóAؔŽ˘A ›R¤Ěyt­ŕK}ilĎ|ČF'ýPn%^ŻĽ_!ßž“~|]kdjńë„íQ§­´ŘŮ}GÎTžŰĚVńĄĎ|Č9Jţr­wgvq`SĄ/ĘčP,e Ě9ëĎbÚuU^F}ť(ů˘,1žĺ!×{oÄŁr0ĎCě—ňĄŻq9č)8ÓRO;9‚ĐR' zőŽÓ:Ű“B¨uÔě Wˆ "ĹrqŃĐĽ\4t…'œžë˛T4číKF¸”<1tSÂÓ´ů‚[ŕ9LŢ[ËÂČ×ĐĄPŘH[#x0,ঠʹí…TčœŚŁ$§3•|ž& Y>ÔÍĄGQp„‘uˆBŠŠmĐEé%†‹™ “Ggϰ!š„ץş˜îĽ,”Đ[JŔb­iĽ,tň×NÚ´’ŽĺZă„o[‚uŇϛKžÔÉZ/ý |i­ B_›&ĘĄĆó^x=î%¨Ö”Ö“Ą C ţ)ĂĐŐš{śNŽĹÄiΚaČ7V<0Yôˇ¨X‹>Ԓ@ÇÁՖmŠ$]’¤3Ô ˜zlŢ  ťˇbůllß î¸ÜY‰Éąc*a‡ä˝Ä$ď mEsŽ@J!fGů˘2H¤€,€ FŠ&…xď¤H§=ĺš‘ŚĽœÄ4-͑¤šFS­—܍ŽrƒŠ â#—4ž›‘˜Ž_“HŸĄš\e::v9 :iĽô>\Z çrí™đü"´>8éKÄ(Ô!Ţ€Ćz;đ„gbM3R–ہúXťé;CÔÄ´mý8Ź“4mŰUFîÇ7™Śö•ŰtüzS•8—;çn+î]D`Í}ÎŻú3źŽREę%Ľƒa“Č˝@ľźŤb“4ęęŘĞ•Ëľź×Ňmđ ęÚśÚŁˆŔš&öNşŚ9G`WŮ1Mž„ŕŹŻźŽçŢPbΰ9lŤ‚4ÁžśNkÎuҗ¨Wĺ>RZÉů*d0UşŢ@łŤüSĽëŞĚ€ŠŇĹĘC0UşX{ľ‰ŚňĽČý¤4ˆçćQf°0'Cn–,çŠ&0ŕíŮž Äe šXŔ*b(Œ Ç‡’ Ă菵,X°t%˂ŠXg*XČ HEŒŽ &Ö]ąŚAE‡šŚŚî]*­!éJKĐŹ‚Ú’Š;N Ěȓ‰3Cj×ÉĺÄ݇j9 ą+ě1ç&PnU6Úćjyň ɨçü*5ęƒÜ JĽmMgm_-Ď_Hî郂ŚçńƒŘabdŠuŽa@מ€S áp]ę̤Ç-¸^yĄ{ŕˇôí÷+áăřzźR“_WËcxĂňŘżay_Ť9çŇÔŐ^—Ţ„g Io…'ťž ÎYZă¤ŰĐ ÁVžĚ/˝+OŚQƒŤ‚‹f Ž .z‹ĺ­tł†V.GƒX8Íč35CŹb_šwľ{÷<Ոu’˛‘ŰFI3ÖFFáűÚ?qĚŰ÷UlbÎnýyh;]s×<ܐÁ…C×Ń1đČÉdeš˛őgŒŹŻDŠ\ŮÎ<ÇŚÎKÎŰólă|ľĹTByňQ şót‘ffç+{×UŽŘsesuťhŞ}xP"s2böľHXÄZ{ž‚RełýéC Dä„>¨ŠŃY­Ŕ3tCcdĹ82ŒbŚÄKG1]ŇŁńWÔ h>KzŘ-ö•,4!ŠeĄÂFł0ÉXˇœ20U;!Ű+yxLB/fŞĺÉSórÄLž*–+“°­N=˜¤éčÝ˝´¸vô ŁZ>ńšś–ÓwR$ŞßĄ­vvČĹR.•H<ˇoĽ‘ypo+#SYíĺ–Í褯Ń'vŇČŢňQhDœ–Ď˜j­Ž}φ‚&Î °ÖúÚ㌩=$żŁŤńüż.ĆŻ;*FüuG!ŇŔĆR¤?ËW=ůMşAg䍲ćOďĘ ”áŽ(JźŽž<Í0ôQž¤gnSŹyhjdŃôy­Ąá§ŤeÁégŹ âřӊՄIŁY)@ť3L(B]¨ÂŇ4ŚâÎ@>ofšqéĚ%ĺLÇ+š< s2p1G  §Ł•œŢKá)`ƒŽ„§ąŤ¸&7^RÎŽćŢóŒTn9ćt“ËŁé÷ůg›Őü›ËŐňçă Ţ ~WÍçŤŢýAk1“žŐÓK”ĘSžnRÎ†\đgÓ‰Đ_đ'"¤xƓ!á/8 Öľżŕ)CČI4mĺ˜ÄÝVŽI39ëe ň{N]EŞÎ™OŞémĺYžd ÷`dÖĄŻ ƒ—Œč ¸ÎTť8áě&:i%bÔki%ú8ąŻňőämĺě|ô2ëŃ!E›jšçĎ)b­á3ă řžŚřĺŽü ŤL¤Á”Ź2–ŤL†ĺ*#đR•aE•ÉxššĹXň ŠÂN!či~9[gü†”zÁĹŁ|U&äáG¨J_gxScÚŽ2…ɏ,{ĎÝ^ŠűÜĂ kœz¸Lłż˝(€CNôŘqN9}~!—Ó÷Ü0I5{n˜NŔL­sĄřZ Ł}eÍČďbí0Ćp)ž•~ŁQaZÉč7üRŔŽ?¤’žƒ?Ľ’Ą_FTŔXšžÎ“ą{é‡ŇĄŇwHä=¤ă—HC~]méŔßœĹ!Î\B"é‡ĹVľüń­žŚśň2ňŰ7ĐL“)’ă'Ť9đ÷"ÂtôŠwU€â($ř7čÎŻüe0Ů:‘đ]íR žüˍĂéLä3ľdÔżIŁţ Ü]kE0ńŕ ­R Wt•Űp$ŽCĺu3žšœeßô™‰ô%œšœew–ąhćҟgçźž^[řśJ˘ĹĚEęꐹü:ŕ\÷ŽJ<ńç™'˙g }6RpϓţĘä4ůç™D†ĺ)˙ŁW՜š^ÇąšaŽJ™)éŃáˆ#UЋôiž”%•ˇŒçhň/dÁIóÁG!Ž­ăŰŤŐ§ůˆPĺ4‘4“€žö5ĺTIi[ $)-G‰”’ż9)€ó|Ž’˜žfD‡-NooĐç=~ćŚ'ŠĚݍϸČőYŠŰńĐI#ϗ2ž.aÇÎŔż…›Ўy÷ćů­zÜń&H““zhrb¤'sÝí¤+óo#mĺetŇŇËčç*NËýŁŞŸŢżK‘|-ÜZ¤aü9s!ŇŔ?–)Eúó5Ď8­ňăY›ç Cłró\ŕiú€Í•x”qhTQÁ¨šHzÜPKz‘j‰ÄëiYŕá;IœdX—Ć6P }YCÓűč8ă6ÜySV,€sۘZ r‡XÓ´mežœ4  _JVŒř“É “Űń‚;|”öŕ +ƒŘqSĐěycښ{G…˝XŢňœUdĆsɨç9ŤŤÝżO“ĺ"#ĽÎŐL)Dj”^tĘí0:H#Ÿ>]‹ľœ8Ź8çÎyĽbÄyĽ ixXqśĹřž4Ö>‹ż‰–ţéĆßDKWLyĽbä+‘čkţاŇ(„ó}OżĚ+€żQ5gFî¨#˙CÝżőؕ#עđť~EFśţzN’óÖhŕ>ÇŢđÓ6Ü~3ü eŽ,koYŞ]Rľ ˙ú/ÉŒˆœ™))+wŻóPYľFq2. ރ/?ˇŞ%ëşkÝY”h˛ugąĽ(ůQX8RiG…lőôäˆÚĚSćVoˇŕ”­S܇B)Şřˇš4xősś¤ć>‡Ż\LHĚúú—›mÁ"Ô¨/íúĆ@ěAB‡i^đk™‹:[|ÝněQÉâhäę,đ\?âH'ŢGů#NwpT?˘˜ugÁĂt†÷‘ďßwnU˘WóćY7u`Řm§€~J˜L˝†Ýös+Ăj×ĹŠ+ˇv×ĂŞŠá:Ÿiě˜ƒA ™Ž­ž˘Óą}{ßß"ńˇóÔÂǸ‚Y_(ń×óÜ|(s~uŕĄÎ݁LŃÄeŸ˘›˘Iî>Es2E[YŃÜçł^š:đ—ŚGŠÁG[v†Z`i+ÜfIŚčĹ^űçźGęť^„:á;ř„ď,—ŹヾĽ9s5wžye-aŠ>‚–nč=2JÁBÚŹ°faęš°ąˇ}ŢFkO%Xź–VÖgݐ×WĚŇĄ^K,Ą$0ż–ZÉË(f~‹=ć@x+nŽ‹Ć5Ÿď [Hť¸ŘKíâ‘>¸ÇŐwňs”¨zŮJŽ— TgóZ’iŇJ^lš´’łM“śi2m#”—0ěÍęzË­)Á+‚D8•c›ĎKěGő\l śś{^ŽŃsuÝQ]=Œąßý°7Š'‚<šëŰG\˝Ř3áĄ×Ž{¸ ĐçˆôМÇC+6A\ç†× ďoŢéĂ>.™çP˛ľˇ•\Ńމ˜?4f‰›“[ ˛/֊üżóěŰ7n˛Č^)Föލ‹ů^îř¤mÁ´aOĹÚűůŽUŻÂńÍkL­ľ ksq[ˆ9,őůŮ}{ßíV0ƒp]@˜+™1ëΑtőÁ­ÄŹä öH¸<ŕbifřĎ)řk*}ë#Á8şë4tL؊ <ŠUp8ďĘímĹő-íÍvŽőÁÁĚaGw0s؃”ââQ}ÇÂüáäáYŹŕ ‡â°9nÍü9\"XŸ2–Ö`KMö­pť§Œc‚c%ąŠwŕ.¤ůĺ€K7ąlęŠcm‹îß]ÉŹQ?™ů—0Ĺţ–I.™Ł}ŢbWÎJś7ă̧<gÍç%vĂ –$ć–Őńš-9ăń!CŢň8Jĺm ,%8^oƒD;bóąěÇ|ÂçZs}‡­:÷¸[lŐšáuźć:Ëź„átQÇkVˆ8^łŮ”œ¸w´MpźfKŽŽ×Ěü‚K@b~k݇VŽłm}†Î]Ś˝MśŕIŃmŠlQĚöP(ŠŮޝ砺úů&˜Ćçf˜öbušÇAUŚťÜ(Ţ ÔaŘĽÝ!Vmvߢ‘LţŰv4Đv@Ž\î0DVúsWĂj‹íP„b5ž#îݡł>/w`Ö÷ĺÜq 0Gvę5ŕşůęŽ?‘0n“[ VˇÉ•Jşăwuę-ó ĄľůúćWŒ{Ěü†ÇŔUÝauąoŐď1ÔšoŹřŚĎc[źşró^ŕűBb⏟„6:4xI(™‚ě˜ďVśËž_–ň$Zń06íąN™Ĺ Ülă:qÝĆZ’m ëS|řBÉ=v‚›n ưX MҧœB3óâĂÇ Šţ-D=żĹ›"ęZmĐN큤ßálybĘŚ™Í[6ÍĄÎĺÄňmžčV8|Ž]ořŻ CÉ#v™„‡m~Ă{UjÍmÁűîw˜††‘Ąş •´ónóH‚Úëδ„`&3ˇQ]H—˛ŽmT–yě†o%ŸpŠ „peϖ\đŃśšiρ%y…: ,qčNđE)ąoĘ_4čB¨AXÁŐ=d´´br0BIoƒDŰʍ ďűZ÷ĐŤa^ôj8|~Äć¸ĹŐ0Y[;'€Ă„“hłIŒřŹ.ë¤Ďś—š×Đp‹MS\ÖYŸâ˛áa,KTßĺuLb9’sç;K˝đ%1ۄł,cW“:nâzĜbçčĄě;ř+œ[m͒řÜJąZNέ+›ž[)VŰZ:łaő<Ş9H9,ĄßNž°{OÇ5ĘCqǢôۍh›ËW¨3C×^ô•œ%|ĐąĆϗƒ…DÇkÎn,eďcV2é‹6čc¤Ltź#đY4uŞpŕŞqxXž ’˝ş>O%–L˜śHLńŸˆ%÷ Ľ{Ģ”ÜĂÇ[Ycý8ăz‹“R}ž‰ůM.gŘlv}g´´+Ćĺ Ć,ŤsÂ= ŠŽőŰýLĚ1ĎÉ>뚰Dc¨÷0Źş ž LhÁÉZŕoŕ;ÂKÜż ŢźŃŰ ‡é´aížšŐhآî_\"˜q}{›hv×ÎFS¤{´‹KŚ[Kg"˛Âš”š>ôŔԁˇ˙’éԙ? „đlš”g7‹‹é@ ŒéŔ˘‘1!\.;Bł^.ćáćęÜt9>_KԆ<(|nÁpšÜ–ŽÎŹ;UŢëŚÔÓ"Ȏ˜OÜ8sĂŐCXś™ Ťĺh„r9ĆuÖńkJŚŔŇŰw#– ,ár9…ÖLƒ"Ő¸áę Ć=ă^ăd8pÓA Ź>ä`›_4›E`^]ž{‡3Üi,y°)nv†šc )ě‰űşDşgBr§ĂŸ×ƒ]–}Ç>yŠcEžŰ†<Ô9ÇţžjdvVrÝ<łŐÝ"ĘpŽ#C}1RbkÖm67džĂbnšŤĚą#Ô(Klâş÷žâh“— Źmň×hKí°xe>Ű&KŹşĆçľt.nŽ„ĂbîĹľŽĐFíŘ"ŽÉuz.đíQđ˙ʋÜř÷ßŕ~ő“ŤşŢEƒaő(ŁĚŇÖ.ťkódľ5Ăę*TÓąoŸ¨ťűןëޒÉŐËťäKöŚöK1ľë‰P'NÎC89gYgp %$PGtWň‚§9ÖcĎ˝DBX÷Bxä|ŚÖoiÜjűҸyuŐ#p›Ăn{ W.ˇśmŻĂć~ilXí5¸4ćoFVą—†Őě ƒČuĂPІ1ë ƒëĂŕ:Ĺ0 t†Á%Ĺ0˜ş†Q_Í0řsœzš’ ~mÔJxýŽ…}~ŔZ¸îő!Š/yʁOÉRJΑĽEˆ˛B$BŞ“†Ce1낂d‡ [&C‘C‡-´ćŽUÜçNÎYĚ{ě’H˘mŃ@‘vIîsyĎÍşu ZBV—P稡ϑę…űœ¤zá&ŽžFS”Hސ2!yCʄŞ_S/Řdą%\/ŃhŤ÷QÇkәÍîßelâ\&nâVgY¸‰áěśs߄ŸSb1á;ŹxDmk”=XÝŻmäs[FŤË{lŁb &´ęMKG.,(f˛Ă'ƒă7ÍÝłďew–.k-ÊÎ݊ŐÄľźĂîűáśű6őpŠŠ˝l('úPn ĘôC9 ՇrŽS†rŽS†rÝPÎ%e(gę2”[ÉنrŇ}Ÿă™O™ă™OĘIý}â'ýKtÇҎWD+ĘÝĕ<ôŔ‹%’˜żŽúĹv‘$ŚÜw˛ęęřžŁęä¨8đYVsËÝ:đ){Ă;űŚ^ąhŻX'Dzô Ăô‘ŸĂ=ĺ1ěś˝4Ř]š—őŤŮő]PĐ÷}ŕ:ĽpŇH'˝pIéL]zŠŻ÷cÉőćSzó)=Ŕ@×ěs׌%×ʤëVŇő’¨÷’˝÷+yg=€T×W8¤‰îÎ%GžlQ5šÉžG–ŕáęDĘÍy@$= ŞŰNŒA‚ęśĐFxśVXKIâ2őEł †Ď`!éŔéˆ'ô˝ťëč[rËÖUąśťÁ^żcß÷NEVń˛X§60idBË­>ž7ń1dšEs68 î5iCř|MLČů:ĐŽxąžn`ąžÎ„öv7ř”žnŸďx_OőŒi¨óˆ,ÝârgĽ:k˜+ń‚aZDH|Y]ɌťŇAÉâŰĂ,É])ŤŽž˜]RP]?F%ÍË*7\?FeB%6ńʍĐ›¸ŕĹ,ą„˝ĚIg¨Ç¨Ç Ľő¤‹ˆ+l( WŘŔ§ٞ’÷`óŤ¤Hb–dLX˘ć똰FKĎ"Ö§xą˜ŐłhJ§YnwyÍĂF+Ży¸Ýĺ!3/ÉĂĄ|b`’Q<*Auî%Źďԅ)”DŞŚłq웖HYGν8ŐĘi?9ô#Lývdľ§đmőš„ĺďţ\îhOĹűž‘Á~ąŮFbâ@^c8 “n –W؋Űçn’Ű´Tž *‘ąÄ—U/ŸćůDŒbVՌŁO„s … ‘c!‹ ĽÜóN€öČRJ§i(šŐÝc|eť`%ĹV2c%Ef‚˜ŠXؒěâPÉm$o u„OtĚOęeÉĆ Ď˜Ô%ˆšĆ†Űl(Ýý1sJYu{°œ–p#ľ…\42™WLd?VVĆ×Äś„ńuÉI ‘œ$ĄÎy śth 3fžşlKšíň´$AŘBęĘ4ÔYb—×’9ö8É^â˜?4{ÉŮ@ôg0‡?´’ĄTąć`ˆëŽĂŸ˘­°ÓƒŽŘљŤď會žýžaá SnWzœągGěÇŮ; ÚwĽR/Xƒ[Iɰ”ˆKI)},eBç˜%DwqŸŻ6Ŕ2KxMĹ-'Ąľƒě{{˙!ä‹ciŃDe´Le\§¸,9°hŽ2&$Ń]X˘ę˛D Á¨ť°ćq‘?łćű#ó˛c¨Ł.I„ř´K„łž…%ęűץ5ëąÎź†Ö”ř´Ü5văDŸ_°š¸>2߆:ˇ=4ń-öŻsěˆňÂ7ˆ)Wţ\çrQç&n÷šw˝LAö<‡Ž çŚÄÔۛś@ýŔb“z\âđŔ‹Rďě‰zKKlŽEcąp7Ěĺ`›oŸ/ąkg;Œ?~­ŁëeڇaÓ06]96ŚĂŚaŐmĂŚb/6™˜ ›Ě˝Ź6ű’ЧŻ – ™Mşu%/8!H%RGŘň@‘˛!DĘ2ÇŤcibÝť°ĺŽäŽaË]É;ő‘|ů„ĐŃćfIRŘšĎW8E­S`IŽ+YóâéɲKřŹ@(MĄ$6ą„7={`iÁVŇ|πG˛c‹¨Ăq:î˝fŔcc×?ĄÎĺ}Ab}V׳™SŻŠcé(ŃśrkÂýsf1{lŽ9…&–}hŽŁm^šÝë‹"–}GÄ\Ň<č­Ď .6™ĎžRÜw¸Ř:‚lÜYL ËŔV–Ü26îÄ.6ˇąćeMQvó܏äARř|-ĄÇe8Eů!č{OL'uÓ48ű8ěŇ÷ý[Ú Jţöś'y7ŹůƒŔJÓô+Œş‰oKŚŔ•E\p,lşÇw%ďt ĘÂËK?#/łŤó°ŇŔI݆:wŘ× gvVŠ,Y§˛\dĽ&¸•9°čÍ+D":°č)ŚMRá“Ĺ”E`ŕ‹@–˝q̧ši˜ÍMĂŔrą‹%ڂ˜}CḾށź9ŁŃh u8>ŻĂ›âĄK;ŽŘO{˝GCUM.šho&œ#ÎąÝë>w‰˝ŁŽâˆyŒ<ąÝ!iiž?Óß Ěȏ–ćń´ÍťĆꌞ ŸˆÂ}Ó%yg}J–wŽłL…YBđźöȏ%’÷‘ĚgIŃ“>…dŮŤ+ĆŔź<…d%—ËŠ;÷Řß śąÎćgMpƝK"p‡:÷Řľ/xR?Řź,ĆšoÖ'ődKéšĚx`9lP͚ ţφj7TpsŤVÓfŤVűüVߗďËÝç“ĆSq%w\v%ú|֗莥UŸ"š’ ęŞy&§÷yQ§˙ ;ž§‡ĎwtCű\žűMžd[ĆiŠNy´ÄĚK$XWňŔV!ً¤c1%C ó)WX,füIÉP+ԉ 5źS§˙P‰uźěsÔ3ĆyjÍ拏‡ěAv\V摡ƕ̘F‰dF`–pšęJÚó&6ďęß?PŻţýÜÄEO¸‰%Ăł/đď'1Űr§Ě§œ‘BЌöYĎ űŹsÇŽ^LMąk×j÷'ŽĄÝÝÜÁ„ÖĐF-FË{ą›PX˘-RWţĄWĎť2€Gh„x ĆPů,ˆ2ĹśzŢą˜u¤Ž`Ţ-ÄK!^˘ěˇš5š›¸ŕš´‚/_ąăƘWě†ŮŠÝ0[ąf+vŖ{]ą+&i_ŽÝŢA~ŤďžÇAqĺě­ş‚ß˙ Źś•˝LWĆĂŽ,źźre-ő™‰D­L×=~Ž ^Ź€z üçIšÎCI˙/lŸóPrŰ\ÝՅ‡>ň,푥{<ňfUOˆkěu-óoűńÄ9™ëŹWó´TđÖ=֙ĐwHKAœ­¤^îni1_˜őꂚŁČ^‰m$÷¸ŽÎŒ Ś^4Xx`~KL˝Ÿë‘ć1˙b‡`ŸKPfę4˜Ó؏‚ŠW§Á9śŚä %‘g”ÍF"m˛ćŤ`Šú”eĽ,š{ýŸ˜K°Ăî \1ŐŚĄä†‚ţ˘šmžmĂć`óBœ•8şdÄ>dű”H›"m˛ŐI¤MCĘ´}îśă˘:űŽ‹¨÷—m› 7\›K°6˙"‰7\=Â[˘BŠlX"ِ–ĘT×b]nQu„+uhĎÁ>[PÍćĐŔFŰç_#äć_bžÔ[ۅë˝5Ćűš^]#hůÜç‹ćp`ąŃťƒßë Ż•—Ł]ĄńTkXÖŠÖ°wíer•̰­?Ü1Ź=gƒIXšűßӕ[Z::ŢYšK ŮRˆnAȖŐyŃë Wľůa9Đü°ł“ĆŞv%;[ľ’ârľžî4ž+žÎľÇ !Vľ+šâÄtN‘:2B:đV}ZƒDGhşîHľ˜á&JřźokŠUúĺ?ITďůK‰uŚ(fŃtÜőŒ%O(ÖgŇG;şÜޓ%ËŁ6ĺzʄ6ť#cîGždÍől0gy´Ăö\<™ząTÁ– b ­Y›AIuâ‹ĎĆP§Ő5j^˘—°)Ö@%G4Ĺz –cgŹ™{l÷zý^bť×ÖŹ˘áGXuueSLŘŹň0r €5uĂşí×ed!ň„Ř}žęâPňˆF{AäĐ;WÍbK˝ŁvÂě,ŚdąeK.ó őN”úQ›s´ä kší'şĆÖ,ńČÍQ–hÉŽËؒ%rčÍť aPВܡąěű2Î'EVö,ёÇŢQóݒD=V5 ˝×ŠMě˜``‘ő`KŽäŽ^´<Ôóˁ€¸él`Ű­M"ZV&÷ůʉŸă<ąä\kŸp­ bî…‚;´śŤ ŸăJ3P‡ŻDřĆ\ÉEŒńçőôs&>ím˜‹ž cB’•%’<ÜĒç |Ž<Ľź††[ôb-B4­P'nŰBÉ%h ÉšŃBČŚę\× şM#bpIâD6ńő^Đ'6oAKűÁöŮ!Ŕ4łT/ֆ֬kKőđ”Íć­&ubŮĹGĚšŐGĚŔę{‚€+%D@†ę•“Š€  żś•Ąa-ˆ`:ůŰm 4D°v žż7'ţöh—ŐLăhGnĚËўͭ!żJbA™~ ’ěˆ!X5KdjŇÉךIŇ×l×ß)Rż×ü9+eĐ¤ĄdŽ,m8IšüçŘľȩ̌ËF˜G6ę@‘Ş×ČĽ­ĺWĘöPÍ=ęX| !ř¸’węc˜ÇŮęĘYhŽ@ƒuŔ]6´Q[tNčQÄg=s:bkJ*;óŽŠěh9dĂçđ`[’˛lKň‡MQBţ°ŮHşŘ@H8ŇgŕBv—úéncçlŮĘhŢÝÇŔ–a/ś!Ë,Ą9úAiŃRcÔîx]ŐÎŰBs ŽˇŃš“Ŕƒ‚ÎÁBîŐëŒ{œxąŃÖ÷ Ź.¸‰ĎéYFŁ• € žR˝˙çÓ/?żżü|Ó˙ăŮČy\îů“ńÜĎVäćëYżwĆjĆŃźa=Gƒwš#Ä}=i4WWňÖFb ýĚ ŐE)-`|„°ţL'u–ý„ĎĽœ”\§ęk$´bÔdĐ1÷3BG TmMĺ]ɋ62÷)u؝6a‹5‚Ýaçtî'`*'`>#”Ď•3BĺŒĐ-ŮČÄźXxo Ŕ@ŽĎgP)Ö@TgÁÜ4kç@¨9§ŐŐ –˝čóbWçŽnÜîőĹĆ` u.”\!;W\%¤żŠßvŤ&GĺşÉ8›É)ŘÖó ™nr z“c0Ogŕz–tžZ!8fBy6“łĎ/frV˛˜É1Ą˝ŒZľSPqQ;…NľSäôŽvd/jç@ös ă{zÍ_NŔ<ë XΕ3BK Ԇ÷u:s „úvŹs „ĘŠ‘ëét~ „JąžÎńĺçHhłžNĚKŁc“$=UÝ0˝wŘanŕ­5ş‚~xŕ~Śrćé <#TΕ3BK”(YŁ“č˝Ń t}Í@××XK{ „˝H T&kt+™ŹŃ ĚÖčÄRotóbn%Wމů>źsy?Šł”“:—é„ů%Jd&wřŒÍbr‡Oţ-&wpvřé \OŔ9ű ˜Îĺ3BůŒP9#TÎ-†”@Îë ¸EĹšqFÁśŰŁD÷frŒ„63šƒ’ĄOűŘlÝäNÚ­ĹLî ¤í9ZĚä˜P „6grüů˛ž|žĆ6şč+ů ćv&Ń~Fh„đĚ=Jt#ăđš˘e–đѕĚúŠůŹ[Uďô-7q /;(¤:2Í!ŽŒĚźD’ u.ű(ťřL„:ˇ3‰śu´Dž10ďgŞ‹#CżÜôYâČŕÜšs•82´;—tb ĺld(qdXuoťMĹ­Ö!ĂtëĘ t\t sŕE:ŰX1:n  `žÎŔő,é <#´D‰lnu|.:Đćˇ3‰ś}ÔŚ tA!G$”u c>e sŸ:Đq2Đq2Đ9ĐśNĄÎ%˛´ ÜÄ2Đ9°č@˜_ÖQÉ2Đ9B$|žBý nĐź tĎăLuljęd c>e ă:e c-É@çJn:ĐąD2ĐX˛tîó[čő%šu  ­e,)}.nƒ*]ąjŇŮ­œížh›VŰžodÜŞ&€Šœ€y:×°œ*g„–(‘ížxXg7płÎÎ%ˇ¨šbÝŔlľtD‰.ÖŮíóÝ:;5QďěĆҝuv’˝wvj8ą„äçĹ’÷KHyÜG;ĐY‚‚ŮöŃzK`0•0Ogŕz–3BĺŒĐ%r–čĄÎyKŕ’[Ԝł„Dď|ŽéDKG”ČY‚}î,š¨[B˘Ç*éDuÝʤdm9ťÝ¤X‚az¸í°wf nf şWňŢ,ÁJÚáś+y1K0С ô–Ŕý\"!ˇ utK }tK`…l‘ĐĹ,ÁÄÜÍ ´ÍľŤóÎ,JJŤ•äÖśŇj†]´Ő łăGڑˆîřŃ@ßLĺĚÓ¸ž€ĺŒP9#´BŮő_cŢT´¤áRŔaŚ˘%—t*Rpš7)¸9ń穌 uŮ燩hI'+Űî'ŕá0vů!Ž4ŤČ0S‘aNE:)čU¤ L+ĐicfŠ„îMEVŇY‘‚^EÜOŔ%ňVÔÁzí]ďío˝qŹnZÓÍç˙|óŻ˙vóđď˗ťˇŸ˙ýÍĂÝÖ?˙ë͏Ÿo>ţô°'Źéőú8í7_ÜĎwœˆf <|€›Ďű›Ď_n~ü™j”…ę÷3ű NéÉ×ć„óĹýÜw_ÁđđŻ'jÄóŚ/îçJœe¨ńç7żůÍ?˝ýńň/?ż}˙áňó›Ÿ??üôËÇť÷üă§˙úýĂŔzÓ^Ćď†œß|ţ÷O˙ůÓCůZęňăűş|ůĺ§ţă.ożüňóĺ÷7[ŤüçčÓǛż+onnţđ‡ßUčOď˙űróŻËąÜě%ýŰÍďţń?ŢţXé<şůřˇ?üPŰşÖwůóűŰJĺď?ŢIľřŃ Öę~“or'Ţęo˙ówuűé§÷—Ď7óÍÝĺţÍç?ż™Ť­ýśýýüá 2÷üöAœzţĺ*śďƒţúí—ËÇťżyĐţŻp˝~LéĆ˙ýVcÇßŢę‹ŇCÇß(ő¸ŐŠpY­ë $†ë)¸ĆGœB é›GrJ?îDđâÔxyK)¨Ęšg V¨Ü÷Ô ľŐ9|šgń…§€ł_ž"‘avíeŘ™c'˙m6“ŔDĆ40Ť'ţś¨Ç—aî•ŕěםDăĐPąĚŸźŰ§rëÂZ‘„ŐDăŔŁAŇË=œ^‰ç |žžŹéL:f/>n†Ç_“°ńksÝVů˛Gmoś˘Đ†Ä}?’„Ć}Á>ĚÍ=ą¸R-†f{“fĐĽ˝B&ŽkgŠí˘­-" *=H;AŐîJ`lžÚčcüˇsŔć$mßî°ĹÍסŔ1ĹúR{ShĺŞ=Ľć`Ej›ń^۰[8zĹkŢŃü-!ĎÉĘś¨đú”ŘF†mڈĺ@d#ÖßÖ|­X[sľby÷™yś =ćeź0żĹö@|ůPnLąžŮńmŮsz›rYzkIĐg2Úżt:ÔŻ.Ź=´…au /`WîŽ?÷vŘŃź{*÷¤ÝÖ.ţśů-D÷{ŸqOL­™RY[÷:î2ŻŐ`ŐŔő ŢłŽŰ˘Ţłîó6[ę[¤^`ľD˝gŽÚŠÎ]Ÿ8ĐB):pÂK€}Ŕ ę–ĺ ĎBÉy;ŰčĎbJLV]}œ=ˆY㠐˜éOËHÉČbYvç(ËZŞ>ąƒ–$ľkIg‰b+‚…Íćݤ aŘj´XÖ猊 ŸČÄDnĚPňhOMX"yŔUďٙJŢâP~YcÉ9*dEˆ­­Ž†Řšcď[áóź3KύaG´XDúńýľ$/Óx‘—i<ŢHśěPçV‚Íg Ł$ÚwŽłyůÁęđŕűÄę$Œ S—ˇÝl´eÔŰ5矲ęŞSIą‰wDÓbB|“’Ű3îŰ˝‚Ľ-Íä¸ÄqY^Ś9°2—TALźLcՕ­E‹ ,íŃlźífŁ]ńmÝcG”¨rlçŒ]ű°q~Śa81p;4Ż+y§ŐŹä‚%v57}0ć>ŸuńěŔ‹†śrŸ éÇ:€í\€Y’ˇ,˝™ĐŃ› eŒŢŤsł¨‰îó[—a`É6~& m…`]3]–J†ĆbyŔw~+ä| šbd7ŽXą$ a¸a¸ŕ:ˇć‹>‡G,$˜ů žŹ•e6_‚"Ü ó)á]É{XîŔUă2„ĎîČŔźęŢ/”LíČ"ԉ:#9Ů%ëÍ>ԉŘćŹ%ńh™éJť/ČIu’Ą1ԉ Ü5Zˇ‘dm=˘ć%Z!7qő}á6*šľ5|ŽŹ­Aö=P_‹f Ěąá,ƒł$ÄX!uđ_I!„F÷JţŢ˝řĄ{ńěĂáÜŘa÷=GŒĂ.=GŒa-ĚZćoëÂW îŰş{‹}Ăő†˛2‡—śĚˌHćLDNšüΝűbÎřÜĐóÉ$ĐÉ1­2KëŔ{äf%Ëk+Ńm"CÁúr vśÉS{RB`ˇ“nV˛ä?`–jރĄIŞ–˝.ćęSLH‚§…ĎÓʲ#ĎßuOs`‹Lƒ–Š­đHöş—^ÖČŇ:Bß6sG¨Ns[°ś܃)"ú(†l˛ĽşÂ[cßĚÇ>*D"Sł}Ä:f…ˆĎ/’¤LHRBy’”›Xbˇě%¨Ž”8 śŕikh÷< ťYf~Íc?*˛ á’[”ČB˘–ÍuË­đl¸¨3Ç41Xe—8içăgĄđ2~„°Żđ¸$œ ċXŹ/‹Ů'ůcBHˇíJŢjşmzXęÜ[Ü WgŃ8ŽäŽi ˜Ď$ )VQöŇŸ“źYĚRTwúü˘1QK›Ÿ ŸĂk8|^˘˜™7RČ=‚?§=’ĺÚ0MPĂI V„Î „ö5ÔyWbVČ­ŚłbŐIž{G(áԒ˛iŽ+n#‰_Â|ÖA•›ř^3Vł…ÔĘ9ÚRM HíŽA5ćM*Ăm$a˘ƒ˜H Jâ­f¨S( …žÜb—š×ץÎ} Ôď|’űfBđɁş„Îâ:%tK$Q˛Ř î™zÝKł’3öŇ+Őůg‘D˝`%ZœE6_äޅƐ:¨rŤÔˇŘăę8żĎŁy9ă:ĺ<ŽĚť{hₑvŇUlĂő’‚}QZ )Ř#śěTŇň;0k@~G¨ Ş8nć:ˇv;PGú.÷ůŽĺë˛Ć:ážęD„0ĂVçžűđţ˙ürš9‡żń“żz~żđWbĹóŒwr…ŔďۊÔ}|™B×}<é}“}ü ÷žeˇĎeę̸2đbÓ 5FÍÎ,ĎH,aŽŮŘű>ž Ń_Ź‘}ô‹5&$kd5Äą„7,Ą´IŠ‚ě{°xż'ëěűx#t‹CÜĄô}U4żcPճ䨡 żhm?ÂÔ_~Œ˛ůЊrŒ˛ůȊrŒ˛ůІrŒ˘˜;FŮ|ČS9FŮ|¨Ĺ}áoŰŤʐ6ďôŔvlóáNë1JňśG”O\×Űě?ß$$F5^’ĽzďDźŔČkç;f2Ł…Ŕ-QÉîňMALxXńo1~ďŰm– Ť`C K€RÁb^œ˛6Ä-[§H}Ę!ćSîîĆV9vćsú É^˝¸ůď4ă×Y3Nąý$š™Ílĺh‡Ć`t|fx^uĚ/XůmÔwÔ%- Qߊ>r Ôţו\‘s$Ú0no>Ţl[śF[’˜Ŕ:cş:wM„XB"ô Ł°ćqx|ŤťˇsĽÍw헄 NŁÍ×ůe會-á\éĖęˆY:찉$’w—ás„=㥤NlÉŢƒŐő¨#Ÿô÷š‡ ~ë؏$SNř\vPĚŇçÍËYó)~d´ÝďƒU'X4‚őŹÍÇC–ÔjĚg‘cď#ëŃ˙ˇ¨Ď˙ÎP'ěŔsą„{Kěr™PnĄcIŒŠ¤Ľ:ńąD‹íŒ¸NŮ)¸ěś32pÂG Wî̓…딙˨Ż6sQsô™k÷Oçj.úuŠĚďAKý†“¨Ă˝%hŠ'f–î4sę› "Ô7A\§ěc¨ős:ţ<–×$Ą9ŕHˆŁXfŠ„ć@Ä͙mÁJ0°„3ló&)’h“Źžk‰ZÚJĐ炩g‰˝CBŁ1Ĺ80„%C/nŕş Śž“.ÓýhHŸŐ9q‰úŹgÓPg mÔłLS!l~č2ýęĽÄŃŚ”ůD˘Y’SBféĐź5 žü!RuŰXżD2Ź>‹ÄS$Ăě-’auşÁc$‡˝íŻ‘śhljśŘÔmŔ5C6ţźMKŠő[ż}Wď—EřÜFôîQ á CŠCĂŞ] ĂĄ+W÷ŇmOë°şGnvę°…`Ńć°Ľ?pXn{éâżľtŹË- x^H[ĂźĚSshcÂőkaÓýľ´Ë|Á{œi ÄëƒŇbŰqŚČҁçaëdŹkVP XŰúq TÚ îJΚo.”D§á†•Œ%xG1ń\'¨ŢĐ­*ŤË›‹D „pĺrDęł^ů1ó w \guŸZłŚŤZS^é°1Ô#^jM¸jÍŹdlÖs°byÁJ–tu‡çłűÔÎĄ’‚DŽx™ú„…L"[z§o'BI`[ęŘÖłćĹŠ+ˆš†Ţ ˙­‰ĹL“şv°-‰SW¨s,ľ:‘‚6Ôy,Ěň-ěÁÍęĂ&*¸ÇŐDćC?’WŹş<Ç&–Ĺwí;MŤçęÜôéEĐš.Í<°” ›wŮąŒ"cX}¤áXJš=”\ňŘľ%nĐgœÚr/N8ŘCkΚ•/”ÜÂŔ'ăië2V:đÓɟۊŔq°’‘Ş/Ž! üRHĚúVŻÄĄ-ŽfŚţęŘkŢŰâŠ˖7ŘÚ:A?‰ŢvљҰĽ-OťŐ4¨Âo>ˇ0ĺ3đ8óĄľŘ%ŞýVä†[ƒŒ˘"ˇa“Ę­˜“[1—ţ5€ó|n'`ĘgŕĄ|F¨Ě#ë]năÝŇÜš’âÖČ%ďôáŠgÍm'Šď‹ó&+Vi‹‚­Ü*ذŮl;+čĚ`Ęgŕqćĺ,ó őae”O˜_Ąí0Ą‹)˜tÔĚÔ÷ÍÉÁ S—Ś8Úą]Vś1ÖVșąś>FŹ7ƒó|n'`ĘgŕĄ|F¨Bž)LĆٚÂJ.Öfk ű|ąŚ0ęk ű|ˇŚ`–ö@¨ľĎąœ´EŁ#ągzĐî-`koĂ$`aŽ}8ĎgŕvŚ|žĘg„J äÚÇÉc]ŁÖUÜçÖU\É;UۜűôŁ#ŒĂÔŹ 3łfŹŤÁy>ˇ0ĺ3đŒP>#T!—WցĹÔfBޛڬädj30ŠÚp!Äj3lSľśŤÚkěˆÚôj ŕvŚ|'`>#TĄÍf|.Ś6źŤ%ZĄÚÇEmxÖÜc{l#&jc칎6çů š× us:őUý€ÂçŠÝHš’qY#ó5Áőn81KX8äŔŇ=ź‚ˆ%\¸–…`|Ş[c‹'u |ÂˆŰ­>Ţ™GśWWňf{ ŸďAums´ŢëŔMƒ´°ě’¸M]ş’’Ő{PH}ŃżGć%qĄ+iרáó›cŃą:âąBĺ¤9äe˜/ú2,|ŽăCś:yÄ>_K8> ,!D“ŘŞ/)łôVoLƒě{d)kşV)œY’珺zĐ8ŒőL‘ŠŻxîŔÍ!éĂy¸¸ Ć:ˇŃăĂ}ŕ3‡ą^A‰-OĐÚYr T ĐRžÓ=łpĎ,a§ Ĺ<^1jśôˆSťíS¤bß>%áŢeŠÍšE(ar!-€X€ˆľ?†m7¤´ž}ÉՎoő}šăHÁ$”ÜÚɲ+YlčbBűÂ,Á×?jő^=@ E‡îC—omč˘:ŤCăLŸgx€KđJĆ(5Z’çěĚg}šž‘’}UĹm$ŻŞ ĹĐNK>S$–H$ C]ý:c?vśpšĎ 9NZł=ħ¤W50YzUf^ü Ÿ\ Šd;Oëh`uœ(QÉuœ`[ńŞŠ;íq‚´Ô˜/z+š4_îóՉœŰ}ÓkÖgFˆÇ ‘Źđ¸ä^‚}^pOŔ,-đÁ˜bkV÷?î2¸[ěÍnŽfs‡œ59XÁ2šŠW' 2Ú怇űŕBŐŤuŽö€ Űn¸‚ŒOÜň˛)ÖWU%*šlůDöíp‰đTwœtír4×ćsA˜ nÍ>&˝ËY°­ú,tIŒ˝b5ڎč |ű›ÂuŠ% V b§cŕ’+ŒAÁwďl5Jbü,tżŽ rŽXVűäϑ[ۉyč­šűüCúśF-č›\'bXş’›ruÎGЁ}ŚŻA§HĚdo BI狿g­ŁĎťp%7}vÁژ‡žÜŢńE-]ŕ8hIŢńqK Ş Ńž†žy؞šŁžăzq}˛—b—đ(ŹĎžg§6ŞĄFIööĆW”ĄÎźŽV'1§Âç˛g'‰Š\ƒpxw>G^6V„jfŐŐPŁlÉőhb„fź¤c…ˆ„’bkĘK:ś>¨b§ŞžîíAŤ/¸,Şmd ÄéŻ#­H%ůĎqŽŠiTÁćŰ#ƒŞĽr‘– ]ôa¸o1ŇΞNěÄŰým t Ë0Ÿr/DőĄ•”ĂUbž^@ITQW2Ű˝Q—8ýŹyy^çŔUƒ÷‡ĎńŽ\Á—ľ@>Ý äꮟXyFsQ?w—{lăY’ě6Wt˛\*Ĺś@ف%$Ů „đ€üLGßKć(Ü&í ů؂•%MŔœ‰;i˝[ZR,9ç`ăüŐš3-X?˛˛l܉OlÜ1ó3!d`‰$Vľ-’!7•ź#u.'íWƒn,­‘ĽCßíqżŠgĆ{4üqKî' Ů3jíĄƒ6_ý#‘ě/ż-;’NnËŤ­Ü.“ ›őśĚžŐ4ˆŠ}GŽ&ˇœÖš‰RíRÁúBś$/6ř°ubŹ.§és\ţĎŹ’ćŔ‰đ‹,żDËbô]?ڃúK{ÔߊAž¸Ęĺ!Bˇ-ˁ‹žśfBő(€´ŕ(€[ô^sš„ĎçX*š €ůŹÓÁA­Ÿ5V,+¤_Ŕ‘Dőn0(Éŕ>?ŕ;×S“úŚ}âÜ;Ŕ2y[ęVő…}˘bßqČ5Ť359äbrrČĺJ.z ěJ&M•ĺJ^'‘X3Ě}‹rUsO!D[0°_9Źždë–.ŕ@ńuĄ:[ˇÜŰÄę<ÚZÁą4Áˆ™Ľ/íHuHŘÜśUŽäž´cŮëÝđ@HŐ1Kň¨Î}žęî1°„ cnÍjŻÔF¸r@ ÂÉ{ŠË $PÇy–Ó§ě3ŮlźŸŁ:q‹œOę\ƒ=ˇé61M~$ÚS0Ĺ[—ě@ í锼éEÂYĎůŚžzŤ}uöÇe8ÓqŘŞ}uö‡ep÷Pě;úośţ;óyt›áxg]5€í¸Á3Žofe§Ńr1Ž~÷‚,â&Żé5ԉ†Ó@֝F#us6sŕŚ/˜OÉ_ŔMR§–2ć%.3/łˇ”Çe%׎:Č^ƒă’ě8әYvřv´ jŕł` ŕ:˂ě–ţОţ°D zĺ˛ÓŤ›…i,!'l ´ÎŁŮČś"Ⱦņ[p$´–ĐšľWrkŠÚ¨ş#JŘ%°Ů,8ežŁ’ëŤÖ56œě˜ů<— ş v ŢžwL¸Ó1!ůó\R9ĚúڍţŸö“ţŸö“ţ@ô˙´Ÿô˙´ŸôĄ÷}˙ç:Ľ˙§ý¤˙0Rwý?í'ýŸřěý?í'ýŸ˜ďýŸ˜ďý?í'ýŸ”Üű?.ýŸ?—ţŸö“ţĎ|J˙ç:Ľ˙SĂőţOZ’s Śtu×HýVoňKˆKXBtŸŔ˘ű-í:NuœţžP—ŔĽL]—ş’ {n8ÉČÔ öţL]2ćČź°ÉŔYżýŚ­nґ˘ř}ü‚ľsńGŢ㰽ŊÚ*~kŽř#Š˝lD)ÓɈb Q™u#J™NF”2Œ(e:Q¸NQĘt2˘0Rw# )ş(ÄgQĘt2˘ó}D)ÓɈB-ŐGRrQřsQřsQČ"úˆÂ|ʈÂuʈRč4VFҒ¸˛–Ä…4PÇ%Sŕ—LúşśTǞmPČv„Ö\lOM,—LAvř1uń r%VlK‹Ţ<ąDuń°–ÜXŸđ š‚>/pňŞűŢÁc×Ácůî3,ôktö%y/ŮţřV=¸¨‹łŢˆ íČĆŔîăR¨Î >.L}Ńěiź××ÎźĂiWí­ü9n/KG—Ç”¸3#œ-Ą5rt˛D}űżđÁÖ˜ß5*.óYĂŚëLčƒ ŸaÁIóő €™OęÎ!'Zׁź™Sdi ԡɜ˙ÔF}űĎĚËöĄŁş-P‡sá²Łäd—ű‹}`~–ŒĆ<ÚRß},ţ賎CsôÝń)wÜĒ„•Üw\§ě>ˆĽęq8ô͜öąo֗ŽCߏ—ÜCߏ.ěCߏ.ěCßÇJ &˘žípC\cGĚ›ú ě^/.ˆ€ƒlÉŐٝľ ţ=Xş¨˘dp*ç#ć7˝ęĘłŹß}ôÚF{×?bwU˒ k€ŐmŐÇ6ľkçœ+Ç"k§+YlIś–pźî§‚}“Š6UŃśţÓÓF'Q2=mäC)ÓÓćÝEűô´Ńń"ĆšĎWܸTç˝émóţd}zâ:Eo­áyŚő}wuf¸š—}ąHŰč —1Üŕć>íPš°DÜŘł]ş:BĹN§IuŐs'–&ux „˛3J;‹ŮS}Pľ9ŢŘą2PÇô´„†ËväĹ- Ëר•ÜŹŻ™•Œ*Ööü9˘Ü… ŤGŕs;‚˜mYĚC_Cą)ÖÓi–čĐ'Ŗ<ĎtŸďú<“5ßg"Ťsł™ˆëLÁlÖ;Ű1oěCŰ袎•Ěź8VB%ZHF@[Vݎ'Rű@}MPBž#vÉě!ł3›MŢ#őŠś áq<[ˆDš b˜Ýˆź°â6Şáنćç§ŽdŃgWlKâÂĹ,Őë%mIq`Š/—%ƒU'Ż“¸5‹LFŰ OJm ł˙ čĹ戝O@1Gěä-*sÄN§•x4ĺJ.úhʁYM9B‹MŁ;‹b:Ř÷_é2xüN—Á†Ő9ÝAąďX‘,ŞJG-Ť*9ť÷u`Ń{_ť›ƒç žČˆ˛ď>Ÿ5—ś/zďáŢ7B”}Wň^ƒĘ‡:e߁ˇxÜ0{1ąń›™ĎţŞŒ‚}ă¨/Ř"RKÁé8°´-šĹ}~ŔÁmŽ„Äż8Ânľ$ ŽůC=X"‰ď>O?ž"ńăĂçKťŽu%ef ‘ĚZŠDćל ubşu%ďô,:h ÇΎúŽ/’!ë› ÖҊ7k$Ľ- ŐĺśD%ç8HšC*n89¤â†“CŞP'vÜp9ŽJH€‘‚ě›l"¨żˇľýz1r]Dęłn ¸9j˜†)ś{Ý,ŃB 3°>kZ‹Ą—˛ónĹ7š{ň[6ďúfcÝŘź¸­úŒ×K4°rD )ˆČ°F[Śy˝eËPřžGˇ3ŹŽtkŰtÖ˛F`Č>1€ťosÜĆŘŢÎYݡńŇaɎ%‰a—¤mňüaĂ"ÉŔ‚xlÓ¸Ž! W/2âąĄŁ$Žař<Ľ ő,vÁxxޓmćŹ@]ŠŘßş ŠŁŕtóů?ßüëż=,;>_žÜ˝ýüď˞ϷőĎ˙zóăç‡ĹĚMnúÇß/ýW[Q×Ţż[),Š–2_n~ü™jĂQ÷űuřŻO~ŻOŐVw­ňĹýÜ'÷ý)đđÁă5Ö}Dśe[aœy¨ńĹËČeJ7ţď7ˇÚÚ.ž¸Ÿe÷ít<|đ¸fäžŕ‹ű™¨‚3`jüůÍo~óOoźüËĎo߸üüćçĎŔ?ýňńîýÇ˙řéż~˙°čŠŽĹ#GyčĹůÍç˙ôŸ?=|P‹]~|˙ńO—/żüÔüĂĺí—_~žüţćok˙ü}úxówĺÍÍÍţđť ýéý_nţu9–‡emúˇ›ßýăźýąz tóń—~řĄ*˛ÖwůóűŰJĺď?ŢIľřŃ Öę~SnJ'Ţęo˙ówuűé§÷—Ď7óÍÝĺţÍç?ż™ëřŰö÷ó‡7HĎřŰÎÉ_> bű>hŕŻß~š|źű›őżÖ†$Ä+˝y$€é㊞3ŕi}H‡)Ë YŹâŘĄˇm Ż‡Ž --ÚéęĄÜâ°ŽŽŽś}9čC IKĽQ× CźgŹů­#ją1Ď8JÖrYŁŃv,œWݜŸ_}mbóo|üóŔ/”goŚ…äéĎĂHbĽđňçpĽäáĎîJÉťŸlĽŒĎ›a‹ű5Â}ĂÓŔzĘXœ`›—=Œ3ŠŐD(â;aĺ$-ăżE “w×ma yşÍ˝ŽS¤+ń›bşűNüuŻ)Ď R'ś+KĂî5 =ѕ{&ĂŢjş!âšîŰ" q"Ô;ŚTgĂ ¤D† /ę™.Ô[{ÜjŔ$űvѐž¤+IÄőá1˝aĎŚ(2°ţöuUôŤ}k&Š-ĹÁĘmęMíQý Ś [uƒ\G;`LŁ?ŠÜ˝źMÂCş’<ü-δYśľ°ËeÎT źđŁ6Ď{-kڞŤŒˆĆDˇ` Ľś,ˆg°ƒíô˘IrHśšUxIxFO}đ˘9™Fý÷Él§Čß†Ä öXGhˇ˛f˛Ó\'?ŠŐ÷Rqۨď×0xq$.;Mxeż˛žgě¸Č†&<§_ø!ă$–^}źZÚ¸aŘ[}'i؂łŽŐ›ő•¤b;۸aXÖpIöíŽń‘ ›Ő‘Ěž]ՏŒyÁ˜hŘ'WžœQ5›$^ŞočäiLúd‘hÔóýľ°ź’Ö0ɀNtg}ŽhŘ­žXśjž4Śťlƒ^ę>éĽŕËëoDfjŁv|†˘L‡údrReßÚ˝¸•+F„ę“pC$›D"9$9ń,IHW’‡œä­'T^ä0c^ʁCŤ=Řd=Č÷ziIŃŕ–EśQoÍ˝˝´§e#ŮĎ Ű.ň”-CŐâ9ę '˛?‰DBvUýЍ-wM2nĺî4Ç8ѐp˘DCŽľŠJJÝzíuߎŻÓhCޤc×r7Ň3ĹR3Jź2ŃZniApY|FĄŚ•ĺŹÎ•MŞŠ ŢőÜđ˘ĽnUŕDKŚ\‡zßýZÖ˝L˛wŤmŃĄž‡f őG;´ăS†]4”arÁ^‘]ÁٕĺŔ˛–ĺ€ƒŃÄrHmę7ą”9ôË—$orwÖi[ŽN,ďŠŕPS°ľ:ţy^ęVKâE‘Žj¸¨=Řx˙bű–%đ2cYť‡žU—ľdWőۍi´ĺůž˛ÚXl|Cě¨)ęď؆ţťLÁ6Ţéř'‡đęWƒÔń ś“Œ€ÜôŔ}~ŻIŠ]ɤ1˜]ɂg5Łť•l;ţ6Ł˜$IńćYJ’)nőuśx G Íúzʁ}=Ĺ,ÉëŠđ9.qŸE/qYöşDŢK˝şœć5čS X" źçę|§ÇÜFŐ†´Ôę\ÚFƒő)î.–ĘAĚ56GŇĹr žchoQ°\„öT7鋈@/"BŤëčZóޥԚ-T˙|’<Ňd–$˜ŸŤóĐ`~ŽäŽQ?]É;]ŠłDŐ[f$T‚Ů4>Ş_ÁďőŐËýđR’xőËÂ6ś!VeŘĘ]úyą+WÚĹ` Ź\M……ŢdĺjzĺůÄŚœ%ŞËÁGŤ‚¤†üy]KmÇ9Ǒ!ă¤s‰KŽ:YKŐ§d°ĽšúcčÚĽ,c“}1ŰźlŒˆœBA˘-ŽÔmm†ęś8DÄĐ &V‚AŸÇβ|„qIFZä4é#"a9đkźĘ’‚›9깒’ƒš˛d%‹&ţu%ź5JT2iJ@yJd÷ŐŢnqš U?gć3ĂĎyŕłFÂÚ˝Bšł^˝X=ňdŮeĂěęĚşc„JŰŢ>Kۏ9pV—fJ$É7‡{AäMpT.ąáę9ç‘"K˛HcęGb>ˇIߨť’‡žQw%w\ö$bţÎVYDHÂ`B9ZȂ‡Łl!ívg „ ވ’Ńśqi ƀ žc¨ 7ÇŽ!+CČbĘ–áÖ˖œ¨ůёK´Ľ™¨c—;lsŞ  ×:zŰŘŚ•ő‰§5ąs]ŕTÇćÝ<íbçšqˇC̡qi ŞŰ$ÍŃÍŚ€Ô;ژŒ%Dô 9Rh×s?ÖŇ2 nЉ˜îĺjíGŢŮR“Aţ9pśĐ@Ë|î@Iˇ{ęýŽťvX‹:%>‘&ŽKJĐbWr×,<ôr›ŠK†KZŕđyĆJŐJî¸ô!ć hľT#!źÔ0i(&ÖRšÓhÂĄN\iłćëZ‘[ł`­8 ,ášcĐçŃźŸYó’ΕLš΁‡úťĎßáj‡ő)w;Ű?OĄ5ጕ1ßw”Ě’ě(™Đě3ËÍ iiyJ˝=w<‚ć/çA"Y+xŤ×7މom­Hś”ĐăÚ†ăDÖRu5^˘Ůȁ˘Kѧ‰Ü;úZ‘˜Żç‡L¨^dä#XňńCĎ0ÄĚ×ăÂ9Ž!e‰Ý°NÁę&.JnK .Łâ94 ŸĂ՘›C\ŮćÄÄeŁíC%^Á…]š‚ţĐ@wHhŸťCB+é ­¤;$´’îPAœâĐ>Ÿí É4Á;‹ŮcŠLÄŇĄˇ-Ü4H°/ú&„e—ťufŠžŸx‚•)DB,9>/ú&DÁ—埪-łˇÉ˝żö„çŻbUł+ Ë= ˜ĂŢőwTťôwTŽF=U tkżkšĂRĺ°Šž‰A$XoĎ|ٙÓ+1&e ;“â’ˆ$äę”3Š-EBHšíŔ[M2ëŔ{˝Räö;En8 0Ć,ő#r+yhś,&$Ÿ¸Aë™T‰,ő%…+ }¤.G䤐žÎ …ô#rţ^sÜü5l؍V."YKâLÇf+aĂX4Ľ`ĐŇ,1G1¸8ÁËnBkĘeŕóˆ˝đĐÇOâ *ł’—ŹŽ&\gß}Qëgܤäžű˘&–|ÜĒo€›Cň „:‘o€ľTˇdÓů„} ŽW+ÜĎV‚Dű¨ˇă§ľ„QKÇOCs”y ăK[RŹ,{;š0$[gPk–´VWň26GݒíŃꖌ­ŽnŸ–“n(ށĽ54\“}ݰ–mŸĆ ‘Ĺ—”Ĺő÷rÄwűÉq’A,ó0TĘđ‹§í}¨D.xäżű’xůži%' îAěč ̚ÖЁ÷Čžú’íDL–)VňbË+Y4­a`OÄ\ɤš œD–)ÇŔ$‹9’]0ő~Lfŕak%Áążč#°tQÇ@_ˇřeI ÓiśľłaŐԐdƒą­Ý~şoŤ˙}›SśľÇŮ?˜S+ö˘Ľ×,KÇŞ-˜Y*„’puuZbÍ@)6xűCďLź×5ąłŽ‰Y}uUŔş—×Ϥ|,š— ĎR^4ž`(™śĐđ’^`Ÿ"őŇFVHu%Ýc›Öƒ†L%ďpŚPŚX.FÜâcÁX§d™ç:7ő „ŕ*Ɵ×ăRźÚ|ǟ‹ˇhřš) lŤ‚´rĂ-ÇKTÜ*qkJBy–]Îő%ŞNźćs”=Ç> §ŁŘi„;šbsČń%wüůʎJCgOZ#6°šrŽ{Ç=ÎOËđ9ňě0óňţ8°Tłmő‘„;lÁ kŠ #ĂĄnô\1YŸo'm$ˇJů=śŃ˝^5ąć 6,Ś\5qëŁbŚř ˜Ź ÄŘ&늘™BJŕI‘7앦)ƒđ9f[^tśu`щձ$NB+}~Ż[}f^fFW2kLW2i֔PgŢšN¸Č—Ŕü-.R‰|.Qu;âłç´$Y‚ě¸@bŐÉR ´Ÿ´‘xů80Š—O( /Vxů0Ÿy Ôq׎I>ŸupŕŞ.˜Źd9i ÔsŰMGúƒ™o[­Ň^"°DÔÁwÔ!H´›o%ˇśĆ uîAKëEݚ¸á$T^ݚ††ŤĎ‡¸áî1*RĂľábŢXvlać`´ďp­žbĂIvÎđy ĆĐś0ŕXZ‚Í7––cě°r˙Ä­Y†áBFĹĄĂÖQqŠf#[˜Ŕś0̒la\ÉÉŔ˘á&}xéŔś€Ä@](ÄÁ‚ľMńąćëâƒ.Ěđ3p% v+…ęlŁ"ÖŮV2!ŚQoŰ äh‹ ćoqüĘb&¸cځy¤cc>eˇâŔCď´X!’ˆ“딳&WňN_g†’9hž Ô%ˆ‰ĽfŰŠš:gu˛tŕ-nĺˇëÄőU`„đ\ÖĐ’ 3|.#­•\5ż…+y ˜ôD|řž“˜T1‘˜âýÎFŰGZSł˝őLX‘ŮČąRS°Ďwpd–\tą’,Jš‰7¸Áf“q`ÍJÎ8ąf-Ջ.ę\HNŒ]‰ť BxîÁ> <äŮl=•â^\×´$QťŸć@}ÇŠT‰ĂE}ýÉśa .ąwˆ˙ˇťÄÔa– łćË%Ę“çůÄYS „ř‰ÜrýJĘ@̈́ö ş6í‘ú˘ţń义űň•ÇO˝5K0+ŘŁLîT˛¨O•=€2Đ/t œlĄkŸßÚB×ŔY Üç‡@9>͙>0/gîęLÁĽ•?—VWrU—VÇҢáŸY˘ęڰ–ÄŒ ÍÍSĘŐšŮŕOJŽG S ÍQŁŹ%_§{°ďJîúb?P/90‡ľ77Ǣ ÜÄrŃ@\4°’% ’7¸Ý/)Úg3‰‡ý2ÔšÁŔŚ Śžŕ˘!§đš\40ĄzѐŁyç9qť#šYPˆË9!ç@(™KyŃ׎\€Złš”ŔRűŽcáóĺŒú¨ˇYf Ô{ d—ShŽ‚'ŽSX2˘ąB{č2ę\Be8™Ľ82ôóbŠž‡lq+sÇ%šćŕŢŃWţÄ|=$٢–jDÍFÜ)œćŰv ąD­$^_ą˜őädč°eiŰ,GÚ¤Ż˛BÉm bfĚG4~b–‰Ôë,ƒxžĚGŹĎ8¨Ö¸}>ęŕ÷Ąëý}]=fBżĆ0‰yZÇ *'ĆkXjÇęG ĺvčĘęŤq„ *+WŐa%{Ůą:Ő܏ŐI¤~ŹN|őcu. 7W§˝ „śH]^…d*yŻÉ˜˝yPł$K`–$Y‚+yh &”$lšőô %ńŢׁň*$G…Ôłöe ЇRĽ…ôxĺU3?ĂŠo­S`~Vf6ź~yP]ß*Q÷­óšGę÷ęŰÚHîŐ]ÉdÓ鳞?Ľ)Cîś4€Ř‹SkÖ]Sl8y?ěŔM˘YögřDř@–˝Nw%ň`ŘŔvŚľ͡‹‚8^´‹‚u Ş;4ą+šę—Řp~40/gZĚŸąƒ™Ś ú҄ľt ˘ţî™oÁóÓlV˜ůőĹěüšÜ 0K Ć%fĎ÷XK'ځď4=s „řÜpâKb}Jí^sŐŹ%J„‡~üyż= ćk"WŽó>Tá:ĹUŠÍF\Ľ¸jV]ż= óŽţS3QżÓ˜;y¸[rkö1™ů”Eœ‚ËŚ.ف:RČ>‘B&()d ,wšB†őŮGZŇR˝=` )x“R˘-‰Ë^Ó˝”PŽÍ‘ěö€KĘÁ uòDcXěNŐ:×ĹîTMŸ FZú^QÁć7ٰćgħYăVŐyŔŘ źéŁ,ÝÂO{.dř•7Zü¤Ĺ@Ü4ł1ůĂÚ&Ő}nAnBX';ĐFZW熇~cŁ^ôJ!PßK¨[9pAřGfiQŻ(f^ĎLH"@2K’iŒĹŹq!ˇČ§¤>q%w Ô$âę´NGhŐk^fžÔ)6G=…܆:KłĽPr‰Ô‹FůŸcô˛cô%ˇ)č3á•MJî)č3cô^bĂÉ+›ŔüqB]^ٸ:í• ×)ŻlÂçˆňďÝę5S—§7á󴲒q!|b´őš‚ZłĚšŔ@ܡ#G(ëڛNÂőBxĂ˝X‚ř>ˇt˘Ľ-4jň8Ôť &T0M°1X”ľ@č8‚ć']Ľť’wzţğËQóYš¸e=j↓ nú ;*‰›GM퐏šĺŕqŠžňޢyKć€Ŕ纍cˆśtŸŻzÔ¨oÁşçÎ-šŔяŽŔýŸŽ é¸e–٢…Č}óŮg¸˘éiL›v8ë}ˆ[Q.zâŔ„#š}Š„°ë1°]hˆę œp›˝ř’%á>¤j‰Š#5{ŕA†C}ďX:đ“ęDpĄv˜ĂŸËŐęó‘}žŰ|D˛×'ęe¨ńĐ]ɌVÝŹ™/őŹ™/Ą’N•-şGćK&´ęn"|ŽÝ„+y‹ůhÚ#Ÿkť5bc¨gAńšé#0Ä́ú^Boú”[łŢ‡¤Ą5•‚Ÿó¨z@Äśá€čXƒćë|Ė|‹Ôě)jž^}°–ÜĽŃh%Jrřa’ŮB$Nr`ž[ÂŁűhޡđo"ꘚśękâćhQŸ‘o‹NÂ*‡ĎˇŘăf¤ˇ)CÉ=˛$7'dóx‰ŸƒÍßk€P–HŇa2!I‡ÉÍ!ž¤áó9˛´hΖH!:q—XjӄĚqüy‰,íz“¨Ëg„V›ă˜ůućnŘ­z۝ŁÓY Žë”@˝ń)sówÔ ž8ĆżdŠíÎ[Ř))֒ĹÁT Ťi.Á}‹ŘŽÜŇĂ­D—$i Ž; [î[n…DőŐÉ > Ź“ěÔu™›yÎ$Ęwä 0ĎGďĐ@Ř,ÁŒçÍœpœG˛âä.ą°đćĹŃ>?Ôo-ÂChMűćęÜŐɁ[DźŃ˜Őŗů”g2̧D“a–$šLw– ^™:Bt1óňň‘MQ^>rK×]bÉ.ŃJžľŠšë\˘Ý^ŕ LF]â$šmVfŐmĽ’5œ‹&`łŠÂ%Š)ᴙů>×Rçěs-Ž´—l rœÇ Ws°ěY]Ô¸7Ęť Vˆź›ԗ@÷.a$¨é*ŤGA‰í.iß!Ůё-ő5\ßё…ô:rč=řăĎëćm‰ARpkŠŰ0+¤¤8Şšó€+šŞó@ .łE= ¸‰%@C(šLÁė˜Űýи]áó-L\g¸ę n¸˛‡Qqľ-AuK–bkĘ˝ ےDmpśdžň2ů` 2Óš7đV48pAÎăŞdWÍĎi`űľű’đžĄ;ÍđâŔCŁŢ>ńžĐ÷đވzÂÉ1+–˜?l§dŕŚa¸kŘSÂ.¸’ďô5:ŤN܆Ý燺 ;pÓTÄAL9c‰ä<Ž´$a°]Ɍ+–ۨ>Fő)çqÎŽşĆć¨7Ü,fÁeö:|ż_f?‰zM›IĚ#€őĚĚ 펗ăQóÜFŻQKy ś„Ąň5__Xěx7Zł­Yž•Ű]‚ѸĎ'Í(Ŕ­Y—Š×=w„ ×!ËđyI'ÔËÂ6że \Á5XrŇ`4ŹäŤŸ%J¸cž˝%'‰PCöéÂő1ńřÔŐiqť˜Ď>Ź­mó­ďÁąt7đŢ.9ÄI.9Źä­:9ĐŢˆC%ôMŽs“ě fťä°:}úę”Áß>/ú-ˆ‰Ť ŽS"ÔpuTô ;Ľ˙ůîĂű˙óËĺćţĆÔjüŐWí,$5äŔš™Őh÷âAd„q źŞŰ÷ F‰JfŕâŇöůl iŽSÖĚďYÂ:śŞŒřÄ âD|~űŢŹ50bŽÎö9ČpŻĎđx§Ďđʎ.dń~č7đbC?u˜>ô“!ö-j•~ E|ö-ţ<ŻŁĹW'n~IňE͏gxSĐRÂĘűHač+o&´fî„8ĐjţVAvDĚeƒîkt2hIÍɝZł.Üi¨ÂUĚKGÔҝ]Ւű­ _âőËfZ㼹é/X¸ďqL”7Źůžp'‰ęÂ}‹ýśS1!xý––'3˝%čÎ_ ŮçöDƁöD&†'2´'2böĆĄŽ‚%ă8ąT NHט¨őMŽ„rSRô°‰Hę5ś‰>Ÿuy…MBޗď˙ůîx@†RߗOŃPę—5ÚźD}wu^4@q „HžNŸMB‚|•l }ŁĂun™őŮ6OŰĘŞ[->|¨sýŽAKÝ=˜ísą-ľť\ŠF0h 9ƒ R9{}öŰâS’źąDňf݁E˝Î¸9$ßÄYgţžĄPS ‡ÝöĄĐ°–Y˘Ýşr“ŃÖÖ Cź?úśg˜ň\šďŻý9lFžá쉴Áej›G_tęíčŮŠˇŁg§Ţ´SoV“œzpşä>ˇSď@§Ţ,.ÝŐšëa +z>˘ö3ś ÇšNî˘Y­’7‚;3uy›ôxÁ3<âëň``íŒтXô,›Ĺ”jÖ§œP>Ă•,8Ąf–6]<‡:÷Ą?™#-Ášic–Zj°iš—bƒ…ČËjnqYâŽ$ăS‡SŰxPB')łńa“ĂhW窗´yźb…d<âŽPŸFS_†ż˙:ó=žFSťˇsüc ö™4_Ë^Bˇ—ĺk°ţ’˜_îői49ő0úˆV×´ƒ1Ô,bd =SoĎێĐa%°5\[ŻĄáÚéb~–pôŔVWö4ŽśrîĚÝPňE„q~ VˇY y1ĄŤ9  öpUv+šb‰ˇűϹăŮhł¸ ŢŮę a5׎œ\ÉYNCI<Ěr%-Úz`K<ŢŠo)ƒŐ—‡Ä„k?/ę1ĘbĘšłăó‚7X9ćeáfŕ˛čÂÍ)9덎aŒuâÚĎ}^ô0Ú}.#-i‡AóIŇMŹŽÎ—5_Ů-6Ű˝>wvŕ­.đœ<‹.đBłÁ“‡ĺŠďüçßw$S#fP“öä@ëd¨Ż –5čO2ĄłAŐg`lzˇ8)ĄžŐ/g*%°´Ů´ŔÔËĆşĆ;„)(k×ŘAƒ˛8ä:Ž[ĽF#sîNŤlz‹Üŕ!'ďz’ÄŔk4çŒŘŃA!Gb‰p|˛…q(kv–˝O5ÔF}ŞĄN_§đ6}ÁbĘ+fI^A°Dň "°”Ögż÷܆:nŽćzŚ2G-Ő3•9Z¤ňĺÖ,kTȝ&ó ,!‘9xe´ă}_ŕĐ*¸EłCŕPĂj ŮąXšę¨Óî\šęЃiHąşTؚă—ű6ľĂ›BőÍíŐóş‡úđ0_ą—íMHĘ> 9ˇ71ĐíMěsˇ7! úŢÄ>w{&´`Ÿłž™Ž%w&„ ˇmâYL EĘ­™&̘Ԝ}j&ý‹G-S—ƒ–¨´Ě)hI^x–đÚ—Ç,űňCXĘĄŒĽ |oG>ńÄYŁŰĄoAöú)@—`Íw5ˆšłišG Ô@Pƒ˜{č68}‰ý5kt*Ţkv>^đ„Œsm ­™4dj¨sŽmtŤ‰=™O‰ŁĘZ’lŸŽĐ˘§/lK’›%đ‰w؁Đ2…†K˜kˇ¨äz󝢅Թv}S"Žň ĐçZŽsŰYuݝhč†uDzŞ;Q(‰"Đą˛ěpłCG˜ôqĄc~Sß[&T}Œćh 5;ŘŽ÷îPŠZ*šD:|.ł2I$i¤Ca ~ᕩ=ld㖇ŽĄMw_0ŐŔŠ7Xn í(Ó=+`›Ćš˘nLy$ŘŕéËúť×ç‘A°#ˇEc¤đx)Y­MÚżűóۏ_ţÇ۟ď.Şţôż˝ĚíŽ2÷˙T™ëˆŠČ?ňˆSÚ|iQCîÜjZŠU}!Žąaoßľ5Dľ!*‡ř>Žžš$?|š:Áϰj”öCTRöŽ&ěA–u.(ŽÂŽJ-)kWoFV9GťNţ)ÝRűŕÁ•űź˝8Yeí¨@?ŹdąŁ‚~ťĽÖ|ŒhľyÓĺ:o~ć†ŮjЕŤaäŰĹau5ؔÇĺś6_¸úp~˝řoŤD{›˜ě.\š{œ_3Óu)…Á́ľŮđ†€IĎxCŕŔú9ްĐ3ü‡XOcr3VG¨•l+^WRœˇů\ÚŐG` I&Küd_ŚŢ_oQ›’&4(1*‚˜ˆQáJîęDčJŢaĹ8ˆYĎ˝IŸŰ¤qXuráĆÔ뒏KŢę-kINxŘ@äÜەÜĺ™JşÔyás\¸ąćĺÜ&|žŽĄ.8ˇa>“†ć÷5­D´?˘…Ô5K´čű]n⌑˜ŠWĎlR2âćŰiv^B‡Ëš&”"puxfskJždÖRu™1ˇ4Ú§ä¤ ˛ďaę9ڒŤC$SŸpx?íĄ‰ëÝőYĎÖ8Ô BLH­q\‡ˇĄNÜé†:ńđÖYrÖÝ糖dKĎśTˇôlKÍÖĘ˝Xź™yń>dŐYËR×KYśĽáÚ¨ső›Z갘œJ`IAđ°śaëL˛ˇ9c=ŽyÍ›ßě¤<ˆǐśŸŽc"9D}ŢÚäŔXĘ:9!)í6ëädŘĽ;A:lkž?…ę[ú9şam_ŒE‚bUhY١÷=˘(‹$@ü-öĹ,Ç ÷fFöĹ\Ł8K˛Č3ÜŘ&ś™…iž9 ]—ë„O‹3§#čöbó‰$€ĄÎXjťr1_–],•ëKeębŠLIĄ g˙$;BŁÎܒý쟚ÁÉ1Ž[ÉC•Kp˛dË'KÇçEĎţüńç›?żŠ§_ţ٤ďç›ei§v0Ő˙žýéćöĂűŸn>ţôfú˙=ŹÝnüßţ|SˇĽÓÍç˙|óŻ˙öđĹç˗ťˇŸ˙ýĘçŰúç˝ůńóá7bĄýýŇ5‘+=Äp~ˇRŕáţć󗛌Úp°ńĹ~ţë“ßëSľÜč|q?ž˛ďO2=U#ÜLž¸Ÿ…*8ŇPăĎo~ó›zűăĺ_~~űţĂĺç7?~ţř闏wď?ţřÇO˙őűăŠ× ]nö”ß|ţ÷O˙ůÓĂľŘĺÇ÷˙tůňËOýÇ?\Ţ~ůĺçËďoţśÖůĎЧ7WŢÜÜüáżŤĐŸŢ˙÷ĺć_—cšŮKúˇ›ßýăźýąz tóń—~řĄ6r­˙îňç÷ˇ•Ęßź“jńŁŹŐýţfšY:ńVűŸżűŤŰO?˝ż|ž™oî.÷o>˙ůÍ\{ßoŰßĎŢĚm úíŽgâ_> bű>hŕŻß~š|źű›ő˙ Vž5űśż/łrÄ/Źô8ţ>ľňËp4îíďˇĘל.&$3ÔřĽmÖz,ý ˘éŚZĹô 2ŕHöY_úOx§=PéůüÚrě*ţ~łŕSĺŔťÇö¨`WbSĚח‘ńzÇQÓČŔëHňâŸÚ"[;Gu 0*ؕľHd`ź7ŔźŽ$/îëXTő‘8&Ö \›e Ÿ*Ž!œ ‚]—eŠ ăbH#đ:’ź¸EŔ§śHi,× ‚]Y‹tAĆ{ ŔëHňŇž.¨´Eđ‚Á5ŔŕƒŤł,đŮĺ¨q}˛7¤0ÁŽĚ˛ş ăbHđJ’ź´E„Om‘ÔNŠ\‹ € v]-˘‚ Œ÷€×‘äĽ}˝şrď6úŠśk€ŔWgY‹œ.ČĎŁď4:۰LŻą§zšeuAĆť! ŔëHňâ9hw(aźŹŔť˛é‚ ŒK Ŕ+IňŇž^đ_[‘}\‹ >¸6Ë>ť Â'Ű`‚]—eŠ ăbHđJ’ź´E„Om‘”ĺœľ 6*Řuľˆ 20Ţ[d^G’—öőiFľE–$+ô.ŘŕƒŤł,đŠrŹíşÉą=*ؕYVd`źŇźŽ$/nđŠ-‚OŽ@ť˛é‚ Œ÷€×‘äĹ}ýhwć˝EVd$ąůŕÚ,KřT9ŕŞîäěş,KC×‘äĹ->{‹lS⠝0ÁŽŹEş ăŇđJ’ź´Żopс˽k‘Ŕ×fY§ĘQvžĐěş,Kď–5Ż#ɋ[|j‹Ź _茀 ve-Ňď 0Ż#ÉÔÚÂţVIü“ą˙÷ňďo"đl@ÔóňíőRóĺŔëĽţŸúz)ˇ×Ćđ:onw݉)‰ť“`-8^+Öbaŕ°awöđƒ°Mó:6Űť Ĺ.žĚ°‚ˇž>Ä×-%°řäîć‘7x_Ľżoył—Ő_aű“ŔöŹZĄ<ˇˇ_ŐĽŁCekńfWJ˛•ŻŽTU ÜŠÔ /VĹGąÍLVŽz˛Í͊װ 7x_~­š\nÂV]óÁěÝ!ďńw§ąv ›5m‰VdeŻ *f˛eÄÄ9ʜ=ŇťŢë}MČŕŻ|Ůgď1gŒů”HaŽä­&w% 2b KđÇ–čîó]# >“‘ľTsY,ą…ę3Ô2Eę†ţ| Zj݇Ž$đš‡ÖDÖżĐpXřĚÁh&D!%ăĽFŇg}ţCśÔž˙ -'„G 6Ât1‡6ş`˜ŻsˇŃ-ޕćh^>Ň@ÄoC‡-]Éluď§Đ‹ž+uથˆYř|‹m”“ŠřDTÇĚ|bhĆĐ&:BAaV˛DuœŁ-źwç'ůÉcɃYJ›íŹůH"š[—h!őY*}ŽŹmęę<H{¤iĺĎ/Hć´ ĚĂםMą÷bôŰžnBú4^4Sš͔ćŔ[͔f –œm˘v%ďěn"B+ÖĄË?_"K–ž'ԉũm׃€á´€áĚ0<ˆ‰”–ŽĽYłí0uřKë#4Ľ;L§tĂlJw˜Néł)ÝUhSşnJç*eJç:eJw MéAH¸M.ŢŁHh˜NéÓ)Ýa6ĽˆVmJ70Ď&"—œŰťjW2!ŹŐ<”LŁœ1Ď/CI\¸’óü1–l' Žd{žŰ"˙81mE°ˇ@ˇź"PĚ­ʜ­ʜ[XAˇ"°’nE` [đç˛"0Đ­ t+[”Ją6+šk4M\<ďYrŮӆ’ebć󂃍)*Š&˜'–0´şď4-WɁ3ŚtâłOȩ́ŏ`‰ú‘#ä„ůş-d-­HÂÔäÎ"BHҞ-˛>%ď{(‰ďĄÎkćsćŮV-7G4ą¤`u’❕,ŮÜĂçG Žˆ’K¨3kl¤ƎP0Ľćݧt.‰lÉ’Y’lŸť‹Fďu%ő# „ňƚGÖş…‚ŹučL}‰ÍQ~čفÝç›&B`%gÄŚ „ű‡•\÷ŹĎ{ě;ŠÝqčź13Žáó›'+8ruJ‚ 6Ú‹ćÓÂrĂIŘC֒„=d-•ĺJ>Ěp*QLÄőfK–óe—ÍzœĽˆ=4$iČ›'N~ZG“L¸eáĎąYj[öPr‰i|„$-1ÇkÝ,MӆźĆ­sm1ŻqÂġŒšhó˜šU"ks’)`RÇÝ;L÷džŮţŘaş?v˜í]…ś?6Нs•˛?ć:ĺÔ؁vj̜‹„8XƒŮ‘8ðĽ-c'*w§Rš*ÍáA,c[§0ÁHšŔŸ§HçVςcIčŇŔŹ1ŠĄ‚elňÔm+×9´Œ5Ě–ąŽœ.c]9[Ćş‚śŒu%më@[ƆϱŒu -chËX_ÉIűŰ=H“Y­Éť˜Ő’ÝjI35CÓDJ°Ťgn>šzŸKšEţ\Ň,ňç~ě@;– %1᳥ČřJs ~kijCIIDĺ ­&Eœ˘DjfŤŕÇl“šbiwÓĺ°%|ŸŚđ9|š¸ár>BÉŹK–¨^Rł– ’.khŽş4 †ë‡×$ŻV]ci—ÔZÄüžŤKXĄ§=şx[Yě#ó7b,{źĆ:ëʂ ě+‹ĹěůI̞ŠçĐÄ8ćŽć],ő-^˘%ďH^´,-AöśZó‰˜XYđ¨Őű;rhέ‚čÚH§k%wKÓfŕbiÚřóƒ=žŹL]Ł˝w–A•KJžS#”q¸Zí“K˜% źŐ#S.)>ŒĚęĂČŐ^źK÷aNĚo–žĂ•<,˙(1ßóZIÉ@Jd^21!Äł Iú3Žs„ĚßĐŐy ď%BŢ.–+ÔęźXŽPeKÍ ‡ÁPrŽŞŰô ĘŔśýMĄáŞ{UO@F )e Mź éĆľT×ňlЎHĽ1GŤŤ |Vň˝îž IÍnÎłw~͛oIöšŮĽrM4ş[ęCÉłl࢝ Ţ!ű|mn.)Óş‚Ë˝MëVň˘eáóyXtˇ-,?tż/?›dFpL´#‚v¸ŘÝŰᎋfF0°'eœÎ9űćÂó˛ĐB¸˙cĹŐuĆĐBŐďmhĄ<c ‰›´Sń„ó=j!,)6n!ÜĘBí:˝ q›•ŹǂůĆŔ{˝$wŸ‹3›‚äb,/kő‹:ĘYŐ~k†T5akŚ &=,r­ä‚ްř’íI‡Ź|íóC=łĄłŤ•\°ňmiéç)ŰšÎXä&˙9rRa8gpÇpÎÔw ç,ć!Yíˆ%Yů˜őF‘R§Ç#ŞN.]ÉšŸ'$lçĎsf>Űç™ů󒂖{[cIdř­QuÍ"@ýÖÖł\rŰŘz"Đ)*šŚý vG~mt<+™pŃW¨ä‹>*ŮÜ!ŚŁíůľIueŽś$ž˜¤ĽvR–Ú‘1[ŸąÉńY¨ł”Ŕç­^ß9°M/ĄÄ3E ŠžÔFîl:Řü,ąfçÝ)nnEÝ6 lz–üf3ůSKŞ=Ş3#鈁=Ĺ„I]8;?ĺş^}Éś_$ŐšJš,➘ĄÎ5°„iďŒ%ě‰()ěŚ넏vPČ~%żĂ{Ч,ą]ɢcË.^ ŽĽŒÝóB|NşÄvŸßş xžyšĘrŸpńŚćHm¸‰wIÓtEç‰siÂ:fç‰ÓóD‡Ůy˘ŤĐÎ tţ6\˛gW´:Íß&”ěiŠ:čümÜçćoă@óˇaÁĹß&Ô V›ř۰ŽÄßƕ´ +i;O1b&›ŔŇ~%oęoăę´ëSî|¸áä· UÓÜKĐR=Řa‰v‹Ŕ„R°.źK ćľe}}>/ëłuŒ˛1ÝQ:0ëŽ20żěAö{—KK&}ź˜ß"K‡şÖ‰ś…ך)t­Y_4ć%‘,3” űĄ^4Žd{űpŒý¨Lђő(zAl:‚w˜Á;LŕšœÁčŽŕ ôi L–&ë”ź_VrEâ¤ě?Gś[ ďŢ#ąíB„Ä{ň„Ú@…h îsÓĐęS^˰šúdë2lŽ>ƒş ‘ŤOm-‡őŽ Öť’vXď@;ŹŸăÁvXď@;Ź7Đ˝Úr„ěŐę bЇ&!ŃĺZ܁vtÎʔ=6kSöŘb,ŢĄö”k „}břÜć1ˇ´´č–9‚Č‹EúěÉ™OI&HÔ{N\RˆD fBňšŘw‹óKŚ` mčIô‰Ľz—ŁŐɎ˜%އě9j^ܰ‚Dؔ‰$!ó)ššNvšNÄňuŽÁBܛą %IÔÍ%÷`ŠđSLÁB2îôSüź>fŐÝb§˛—Ąä>v„"ŠäHĚ2 Áí°ř)ŽĄ#\ŕŠÎ,ŮúOx}g˜­ďsë;Ăl}g˜[ßY…n}§ ;”ŕ*űúŽę”C Ú}ą×.áŠîŃ'°6Y9,5Š,ذ:Ímič°Ü\!Ôç°wH~›|…˜Ŕš“ŽŁ"‰wú|ÁHźűĎq‡Ül-”LÍҙŁ9ˇĂąu™‰÷űz– |.ÍÖ\IŔV¸4Óf˜M`ޜN`ޜM`Ž M`ޤM`´ ,|Ž ́69Đ&0ŻđśŮÉkˇÍ,…ŘNjj˝—ýHF¤ěýÉ Ä›ŹśKs`Ö§‘|§çx<4$ W=˛sÔ Ž+˜z;ŽXĄëćDŸgźŻS,yLú-bë°D –Č91óÔ6zĚg=IۉĽ{‹Ŕú”¸ʐşć’Ůş6i^Ž˜ůęcJbâ^:sXăbNĺ:ń4ҁmťłB69E Íă^z Ô=cwu^ôŒÁ‚gŹɌKFŰđ˜†Ú÷Ň[îĽS0ĹEÓˆăt֒ÜKłćĺ^šNîĽŮää\Áďźśl=Eú)61z´ŽáÝŔ¤ŰcŃy1ăh‘;řNJ \,ň+yQV.˜ëw_'ÎĄf~mqĹüŢŰf ,íÖÎŁťÚŇŔ‚Áböœa—<‘_ŇlGfmâKqjśžÎ Aę.|ŠÍVwáklśş ŸcłŐw'd mŞNő˜zĆF€ÚRŢiť’+–ľú 7bÇ„dĂM„p5˜Sřˇ\AËčĽUťÝފ¤¸źŰ3Đ]Ať’vm ť‚vŸęćIą’‹-‡­dĆüVˆúŹá x+Eíľ Ę"—ŠË"—Ĺ<Ň K8Žw`ÖăxVˆqőś9QÉAXĚE]*Ăç¸mv`R—JVˆĹˆ™Ž K¸‚v%í ÚŐiWĐŹĎ>çQĂÉ4’+h֒\A3!š‚„R°.wíJŽzÍ ‘'ÁÜî-'°T0ö1!

ŔĚˈŔźŽ3ő‚´5VrŐ@}ŹĽ‚Ül`ű6<'ŁË ‡éĺ…avyá0˝źp˜]^č./\ɋ^^8pA„4˘]‡zyąďńDÜçzѰA#tŃ`˜]4¸rzŃŕĘŮEƒ+h ޤ]48Đ.Âç8™t ]48Đ. tű–QŚ G}×}ł$S†X!ľ%c(YÚ] +$•Ŕ&— ş5ëóžűĄ§Ô 5‚móĘŞŤSĆT‚–ä` |ž­ÜpX!Áë‹ţÜ9 Ü Đ>8ӊ¤›šńúQÓO͸ŁiyłT~đĹY=´}ű—rš,’@Ź35­ŕă5 o_ôçĚąN€é$í;É˝ˇţŹr'xś™˜ _<Áej Č/îçę3Šĺ)MĘłÇ/îçćó0žcúäÓv@~˛˝5‹úInk8ŇGŕ<:ĽĎnݘĐüą4ŕ‹ŽŒŐ¸´)sL˙<ävŔ4=%÷‚°œ_ÎňüBîŔOpšRBúŻH‰ź>ŁÉw&c*Ü!ĎŞć'Ű[łëžäY€.:ăO2GŠ­ŠFŔEÍŰiöŁîó5ĘOÔŘ2oëRz‹żŸ_Yp}ńĹÔvéGŔm­+Pq”úąĺƒ'jĚ4cŰRGôçgćëX_™íOGjězÒÎô¨Ţü]yssó‡?üŽBz˙ߗ›]Žĺf/éßn~÷˙ńöÇJçĐÍÇ_>|řá‡zFUëżťüůýmĽň÷ď¤ZüčkużżYoÖNźŐßţçďţęöÓOď/Ÿo曻Ëý›Ď~3W“úműűůÛš-)ű NŰi~@Ĺö}PŔ_żýrůx÷7Ú˙éVÍI?×!]Ÿheˇ´ =ąÄřűt’}ą ťĘ€żß*ĂÚN’ť {Ýăo”ţľe8Śtă˙~˝ Ä֗kémĂŽőU¤xiK€Kݙ¸ÍťäÍ€Ju]mŃĹŘî[žźŽ/íŰ3O<łN]Ž8xţâV5÷ŮN~–°îÓÉî/oW*ČŔx7ŹxI^Ü"ŕS[ĝVA°PÁŽŹEş ă˝ŕu$yq_ßÚM śČQäTť 6řŕę, |ęĄL.˛ęg00ÁŽĚ˛ş ăýä'Ż$ÉK[Dř´c˛™O!F@ťŽQAĆ{‹ ŔëHňŇž./ţ´EOĎ5ŔŕƒŤł,đŠr °Ÿc{T°+łŹ.ČŔx7¤xI^Ü"ŕSrç"ű˝~rěĘZ¤ 20Ţϋ#đJ’ź´Ż× ”îúşú,?ý@:ťžţ‹[–đŠrŹß­Œ€ v]–Ľ‚ ŒwˀבäĹ-˛ŇuŹ u 0ëŮuě´Hd`ź7ŔźŽ$/îë;_Mý*F˝€ \›e Ÿ*Gę×Ď]Ž˜Î.ţň–Ľ‚ Œ÷۲xI^Ü"‰\ę ˆŐO#Î\Ž E;Bă˝ŕu$yi_ŻI3Ü>ˇćÜZénwđÁŐYřT9Žˇç# ‚]™euAĆť! ŔëHňâ9Č­e™ޞ€ ve-r°óŻ1ŢoÄ#p*ÉsÁn†đ _“éâ‚Zô¸mîşźÓói\%֝Oű)Ąî(ů-BL$÷tżşÓôš.Îež•0w”7wT%{š'‹ ­n‹ŃĘtĚĎɓ –P=îGZI×űÍ=~;\’EyĺâŸ_Ë#˙ô[Ţłřwăýá›ÍÝß˝ůwŰýٛˆŢ_˝ŃˇňčÍ?ĹîoŢüĂřţä­cËdfč];bߐ°őń˙äęŤÍ/a=řEžźvŁ—˙x4mßśw+˖ń:ÚˆÇŃ+ɁWÔÇ Syž÷/$[{9ˇáá=ÄGZŚ‹P ƒWÉť7w0@€œNü-űłpŒąowź˙'ŰhĎŠYWxĆĆşB×Đn3‚f-ÁJë+˙)ŘU}ä?Hš.‡w˙¤{‰<ÂtËDő­’ʍ:Ń;'Ët—…Ű×˝g#˝Čs6 k€z\n›š2^OGť’ĚËdťnŕ,/ž@p<„#đ˘OăN˘!œC8‰…p á,ÂY Ĺܛ8ŞNžÄQ}ň".DFhĎ :v5#ňÜľ;Űťe’gzË ýÖ´Ů~¸r&̉ ŢbX~0ť™žk‹’Ýçâ'˙y '9Ă7Ӂ^\ĎCiaę˜#'ŚŽpąmŚ`d6éŠšL§ĄNř÷Ďü\|iaźž™w>yv>Ÿ<;ŸOžĎgĎÎçłgçóŮłóůěŮů|öě|>{v>Ÿ=;7Đhw„,@;’p;sxvŢ"Đąč }ć÷؈6;óÓkD›ećk âąęŚžî5ÜNřĄŤg~΍ $ÜBťő/ŹÖEƒŐ†:—…H°Ú őL!ë™BÖ¨ö˜<(¤ŐšíÁh/š,#đ‰ăLWňNĂÚ2u ĺβK(wśI:Ĺ#H™C—A@ĚB2&Ô‰čGŹĄ„ŹŽčˆôѢk`…?‡¤Ş…eGLŁ|BhŰYď}őN˛ˇAÁýfÎóz–¨'QŢÖĐFÁš Ië9¤_ÍA˘IçXɋFü u"â+¤ŽĎËL)#6ŔĚŠR ŢÁ1ĄrŒfSű‰Ş“‹‘9ädځ3­Ž‘ş¤r,DÂZ‡:pćtśűŽ ˙§hKЕ\:whM‰ ¨ŕľ,xjČŕ˛ď= hÍكő…a÷mpŠjQŹÚł $ŠáÔ§ŕšßîBśÎsóŮv`;÷ibŘÖ°H[áŔɖ1F<#jPŠœĎOŹKH潹i`ŠřÜçuąź´ŕîóĘüÚvěŹbŽQöşZ[#őĘüz°ěíó­íÚźžuqÂ;uZfëbWN×ĹŽœ­‹]A[ť’ś.v ­‹ĂçX;ĐÖĹ´uąn]ěJîş.ć:ebs,m:ąš:ŰaT[IšĎ ÂŞb)!ČŇľYƒÉNS$´ái)É^c Z’#$n 9C bbšĘí+'FĚR Ťž×  &ËJΊp§{Ě")ęSg:pĹÔš—HĆK bJŢ\–¨Á#ćű1ď˘Ř–p:$:BsÔŔćK,fŠŕœ›Ű¨†ĄŰƒk°[Í=ĘĚËڐ™—ŕrÜÄGŽ{œÄ‘c1Ë2Ů[vƒ5čóaŐçŘa%,kŠf7ŕ:kř÷uç:Űjw JöÝpnŁF膺n¨ ď† únhŸĎÖ ís× ,X5&úü@Ş0Śž5jzř|m:–’,ş” –’Đ~°˜M!G[ˇąDľĂ!€G`iŃ`eźC\˛5_ă‘Ÿmé“ó‰xäm–f…ČŃ,7ą„„Ÿ/í°U'ĄÇƒDˆ$!”%7\Ý rťgo>—YĎ>ż ÂК5”%XŰ5ĂZ°mŽ™$G`%×čĎÓKŚ5hŠN'­YSœK›Œ lÉ#CŽRpHXZÖ`!-ˇB ŇŔr"ű”ěRœó–A ľyECBˇGÜLŘyoâ—/8ÍĘţóuӃ+ÓĂEĄĎu.űOڅ;Lwá†Ů.Üaş w˜íÂ]…ś 7Đ횤ěÂ]ś 7ĐíÂ]Iۅ;Đvá,Łü ubÎ’]8ŤCvᎤíÂ]Iۅ>ečdB2t2K2tZIۅť:mT‡]8ˇ‘왐ě™Oم;0ŰR‰ôY—J)„v%WÍÇČ|J>FŻfšhˇAbLî6„IˇQŹĺ‰ĹnĺşHUŞl]Mj`ݡÍXěó gâŢLü 7^XŸóĆK1ˇń˛rśń˛rnăeÝĆËJş—năşËĆË@ˇń2Đmź,–'‡?—ÔUĚźÄd)ŤcŔT‚ŠęXĆe n †­™Gž,H!%=€pÔ×H=aŘâŚĚđ8čóY3Ćć‘16:őž1–¨ˇ+i „[R×P˙kl÷ę0P—÷ ,fŕŽhęŸůŹ^9šbÍŚ•˘ŮÔ bŽbĘŮcŕŠnÜç;$×h!1Ô gWňN˝Âçkh8Ź"[âƆkgŃl6dá†[ôŽ?đ‰œÜ\§dčâ搐B\gMABŞkŸĎ+ˇŚ­zdť@áĂtŐc˜­zŚŤ‡ŮŞÇUhŤÝއKĘŞÇŐiŤݪǕ´UmŐĂ2ĘüęÄŞ‡5$ŤV‡Źz\I[ő¸’śę |bŐaŐXªǕ´UŤÓV=AuXőpÉŞ‡ ÉŞ‡ů”UmŐĂú”UkIV=ޤ­z˜OYő(x5łöĄÝ&oÝAçĄö6s:ěA­;ä2Źv‰`ś‘_ťkt] ˆówhÚ>ĎpŮčówpa†LĐL}‚çĺąĆ:sëźžE“Ü.ѢÉ0[4šrşhrĺlŃä ڢɕ´E“mŃ>ǢɁśhr -š ,‡ …VrÓ$ üyJ+Žłłv@ÉbŚÜŽ6XoâOɊëCĄ‚đžl§,ťä›qu „°’ ub%eŕŰw8?†’đŤ |nGč‹ssˆ%ˇf:‚!ay-Šh&%S2)1!ɤÄ|J&%&$y!ä ŕ†“ř‹ŽĐŹçďlÝrţÎ ‘<ā:ňřîŇŐ¤i(š )šë4°´fž­zÖ :¤}Ă⁠mAKŤä:Ľ†[%yŔĐpő8nŮpĐĎ wŻkŽ dŹšXuuÍE•;]sąěםĚgÁu'óYd¸ľ’g|Ôa‘ömávoG„H-J–8%¤}KCÉĽđ‚TŠÁpœ¨ăL?RˇU$VÇźŠ4ĚV‘ŠšU¤aśŠ4Ě­"­BˇŠTĐŻ"Šd_EZnŠ _EZIˇŠ4Đ­"IĆ>tr˛Š$ őU$ŠŁŻ"­¤[EZIˇŠd>eɄdÉ,É*ŇJşU¤ŐéV‘Ź:YERőU$ęŤH⳯" tŤHŇg_E’–ú*ŇJşU$ńŮW‘ź>ߌWaQ |3 Ť‚Á7Õ[ZIîŰë[IrKZfŤ3WNWgޜ­Î\A[š’ś:s ­ÎÂçX9ĐVg´Ő™îӕœőÓQ_uˆamÔ!&MA˛3ǘŸőHˁˇş‹ŕĘĚcזŹxqźu,-HíTŚĐőŃ É°őü ćůźč¸Ăm$םO~-mâaBuuFuŰiŔQ˝1Čó泎PÜÄF(˘ŽĂŻćŸŔĚׅQwގz^N¨ç``Xˆĺ@ýo\nâ{őĆuŕE˝qٖęá÷ŁŹoaŘBň[łh&z6†ęq‘†Ď÷Кśp¨Ëœ5Ü8L†ŮÂÁaşpp˜-\…śp0Đ˝má*eáŔuĘëÚóŻfLžUEŻĹ9‡ŕŔÂas?°pXéŠ]áTS˙ľ‡ŠF17ŐX9›jʜ›jŹ ›jʤ›j tS .SnŞ1ĐM5 –[3Jú\R*;p֔Ę”çeę¨SÍ4 ŕř\4Q2‹)‰’¸&ÖœhJ`éjĄv´ą…&ÂöžÝş’ŤŽQƒBŮ}žŘ\AÔ墄ľT犙—t˛ásbv„.š˛ĎŔtŻ—źŕucŠ WóŞ&+—lłŐ˚šcľ$ąlÉuם†Ďe\g–ÖĐîeÖźęîó[}ŇÁ A–×h` <é¨ápŃöüĚÁć—zŽnŽ2'îGpˇŮšľ-n ÔáD3…Ž]~čx÷ŃBJ™š‰KĽ=;aóŽ[ń)šw݊“ěmžćĐšÜëśA![ěqn¸8˛ómŠç†ľ¤‚}G\Ĺ4°ŘÄŚ`ó—ÁÓlŽCď2OƒżŒĂtę6ĚŚn‡éÔí0›ş]…6učŚnŽRŚnŽS$t MÝ ~dpfn1´ăďőÉ4|=ŃŰI8k$ݲU=ščMăeťLĎĹü~.QŐ̉Şć˜—ęx.QŐUÍ1/Ő<—¨jćDU_ůŮDUGö1ň,ŽęXUüXŠ7ŽŽűĺ,ČŠä Ŕy<ÝGŐĽ{>Ź|đDűäŁ0[LÉ!ȤŚ'-\C‹ž|Ä nÎc‹†˜’óY”ĎGccâƒ'á$|Œ‰8Üs@zŇÎ5ĚâIđ;Č=é™42ˏ¸>—pqℋSĚŻx<pQCΝC~ĹœÇœ ąĆňYôˇGcŚáƒ'j\)UŠĹ]19ŕ‘TĽMëËYP$ŒÜ8żâ.šţýńŁŽgRŃqnŽ9äŸK€Ĺľ-!ŕŰÉďňdʸ>ľöĚ{ĎćHx|víňQ"Ÿç+œŸKäó„Ä=ĂďçůÄúbޞSŕéD>sHäóńçŸKä3s"ŸŻ¨ń4‘Ďăąĺmęë‰öř÷ł3aŒUż­BßMž°>™XJŁ­÷D|ĎĆö>śNé)ëÄWD _ži™ˇŰŚRI´~??ł†8ŕkćt'ŔŁ5v˝őHÖ=ßóq“O#YűypڈţĎ×(<•‘c"o!aaüýěLęK+§J8­ąë­G I{%ŘsšQĂŻ¨q{&aŒ7ŤS˝$, żŸůC}yů OgNœŔđ+â}NĎ$0Ź_”łX¨ÖXžK-Éą[Ł|đ= ăňT—hé3Ćm7Ű˙ˇ2Ć}\N8}ăďů÷˘ôŚy/ů7JýşąEqw–[Šő;b¤"˛Ś-5CŒÚ8Ś““—ż|ޜ‰"˝Öxa;Ľ[€é:#˝Ş ăşčŔëHňňLe+Ŕ-1÷¨`זŠlĽs cź7Ŕź†$/ďéóşřӈyOak1ëňy@^lY;%ٞƒ3sŽŔž~ý‘÷×°Ź.ČŔ¸nĚ"đ:’źM‹×Ë˙ĽŒÇKé6°m.}ŰŇ<= zĐóÚ^X*TYސKԗÂcW…Şâ‘;ČJĺö^~qĽÚ#ČŞŻĆźCЌ R†ÍH™ł{삗âĹËTÔxH‚š§ćWÂőĂ3ŽßˆăŽŚLˇ,LŁŇEćĂŞ.HůKő-HIźšôt3ž°2+ó‚|:HIěŰpŢfj‹ÖYŕšĎőíÍUąŇ y!hş:Ú–ôrŹl;őáë„t­žFš6âš´Č/ń\‡úř4śGO{źš\~)mlAˇݘlCÂĂء‡Ľ=öz‘ŕ0ÔFňb€yY˜—=jŮkî)ŽI/[°ƒEƒł{°żĄ^<ÝüśžÉŸ|ť]M8ŚISe!„ˆ%yř Ó†Őć9ô=ŃvĽ)O“ďÜSŰúwŐ=ľíä˘ŮK0+çRž&˙˘ť§P ´ç1÷ƒ•Œ|ZHŽJÍ!IśXvI¤ŕ–Ż•Őh—™Jn:™úŽ$Îe 'Żţ˜Ľš3Ą”H(ˇEË^# í%2_¤'öŞËecól-yl#‰XBnęëŰč wŰćBŮKOVŹWғ Ë=Oűvą^ŰÁ+\ńíÉ5Żřs+>+g+>+çV|VĐ­řʤ[ńčV|üšŹř t+>݊OAżâł’€Ów6’6zBj1–¨ĺí,čfüůŇ6;ÜVsš"K+r›B$uýT‚Bjv"Ś~ë3!Ký60ż/ÜŔH4XBÍŔRĎ)C ŠqŘó„q‡JÖPi¤,1îő[ÄOËk`)Ď[Pȁô1Ó@(폐 WxĄd^Csd …LýŢRW“…ôÔŐ .;[2ŽĄ#\,!ľĹRŸ’>Ĺ&î9g—A@fyçsyç łźs†šźsVĄË;§ Ď;G%{Ţ9ŤÓĺă’=;gÝĂ}nK Úƒ—%F¨s)şKŕD:ę œŹ¤-1\I[b>ˇý„–%,1¸5d‰ÁÍĄy<˝ěšÇS Ůƒ ÉÕ´%†ŤÓ–Üp˛Ä`–d‰a‰Á˛Ëƒľ$K WR20í{°źŹ',­zëB+SżžČÝbŘb§ˆÜmXëÜ!jšŠuÚɕťÂdt˜Č8b.•łdtVÎ%Łł‚.•tÉč tÉčřsIFg KFg KF§ O?L„zúaŞSŽŠ˜ĎžŒNAl2‘@LÁśÉ,°i‹%ŁłĎëp° Ĺ)Qďyw~Üó*.î ˝çU옛 łiÁ07-X…nZPĐO T˛O V§›¸¤L úiÁ>wӂnZ Áű´ŔuĘ´@jëÓé¨O VŇM VŇM ̧L LHŚfIŚeZ`–ä97pŐl4üšdŁa%K6֒œäą-ôlŚÄ|žŰńIňœSK´[ mŽŕŐ k‹%škî•ߡ–äNąEłu–5[—b­Ď!UKÇŽ03ňqf,Ĺ\f,+g™ąŹœËŒe]f,+é2cč2cńç’Ë@—Ë@—KÁâŇťXɡ:‚łŕőDëlcQâ:q؏ĚXF(c—G˛‰}MԓE´v%ďőFŒ%Ş×_%˛ÔSFórÜÎÍ!ÇíĚ|NA"d‡jwˆŹů ď:fIz.ˇŚŹÝ\É[]ťB8ƒ,­…-¤]5`AÇížWt&s[¸9ڎlۙů6čEăŽ'Ö SÜçáŁŮ[˘Ěś#cŮË`Š NÖsT]OÚĄrdţ°¤Mü9NÖ¸![űľ$™ŐĂçˆ˙ěŹÎâ?×F]mfA¸x&˙lŕ˛áź|ŚĎď-Eœ‚[˛Ď™ůląŮ”&°T&V]ť+Č,f`íďK0°ĆŇ:‡ŢąŘ @Ň6oJOăMN[17•ÔĆd1\´ ‰ű<#ťDÍVßc;ä>—ěFD˝MĐŘ…’Xí;0[Ž4f^ŇLňç’f˛řl%=ͤńyą4“…ňŸ`­´Î=ţ˝e­3̲Ö)ć˛ÖfYë sYëŹB—ľNAÁžŤěYë¨N‰`ď@‹`Żŕő–HN:-1ĚNK\9=-1 9p1ÖŮNj-J | M"ÝJʢÔŔŒlšiLöőgŻ0ő RQręĹ\ę+gŠoʜK}c]ę+éRßčRßđç’úĆ@—úĆ@—úFAŸeő,kT§œŐ0Ÿ28š’rŔ×@˝Ëě^ĚU†œ5,'|‹|ľ¤$?KásYˌím %éDĚcá†këâiF*@e…Âć! mČ>ĐiUˆůşĽŕ6*XŒPUžšĺf/Áćr™ŮÚR¨ŹĄÎ{KhC וńçČë>ߑťfhŁş!%—Œ45ÔFu3—6)9B’ϰ’Űa ˛`5Q˘%8ě˛DŐۆ-äŢ6ÜeZĘ×#|. âłm)$˝cęKěîm‰4J¤ůžR†˛-ľ~dɝëEŇ\tâ?°XŞ™ÝNJOÎçTÚXďŔÖÉיZ ĂŠçó&:–š o×@źëBIx×90ŤwcžŕVv¤žmzK0=1őŢľIö~U›IKŽjŐšS˛Cç"" ŹfňǐV3ű˘$ЍKĎAh|Öź†ÜÄ÷6Ěäa"ƒƒ20Ÿ¸€ĺ&Ž+0˘ŽÄ„SO3é˜_rĎ()ŕŽmĘ ,/іflS¨áp„0őd‡ŽĎm?QÝ-¤ÖšŻAu‡ #óG°ś{˜‚…´E˛KE˛Re.l!͑nÖÄŞŽPJŹĽÖßSč\—N:WÝа–ň_q׎|–Đľőe VW0.‘ęK‹fž4KÁŔüšÇIôčđůú{} ‰[ôՅ,$Äé 2zhŽŔâúbć:łd„އ’ËÄ`ž,ąž•źXb=+9[b=3NW"thňgÇźĽŘ,›;á’u˘a–bS1—bÓ0Kąi˜KąYź×TOąŠ ťHâ’=ĹfńV=q.—ÄE’î"É}nI´‹$\.’B’M—Ô&űM֑ě7]IťHr%í")đ))™.’K¸Hâ֐‹$nń/`ŮĹżŔ2˙&$ţޤů¸:Íż€Nü ˜%ń/„ŕ_ŔM,ţÜF}Ú Ů3^&łęú´@l9˜Od9°čqtŕÇсú† Ű%xřK˜KśŃź{†Dß"Câ2–Œ=.Ű´AZ*S` ‹Ô9Pˇs0ŻďśŽlŤ;= ڎuÓŰ:ĂěśÎ0œ `łkgŰ×h‡ŽĚĄ‡L§žÔ+îó+<,8ÚŞ™ s‡VÎ ʜ;,°‚î°ŔJşĂÝa.6i ;,0Đ(čŽ]IťdÁĺZĽ”kAćSŽ(3‹}žă6¤ě‘Đ‚őˇń)‰ÖIďíVqÝő /{¨d#´Ż\˛:°č!-IÎ;nŽşO ć€ŁćšcśüçöůaůĎŠáäšSŻůlXóŽç54q=,HŃŔúa3żä>—#|.c;žąúT×Çv‹^RŘŽ]vŹ­ÎŤ‰n÷ ćaÇ dKeZ¸ápIL8!ćKšB7œőR’U'—’,AĚv*Q‚˜¸žlsÜeęB¤.kz–h MŒĺ{Ą.ôYvˇŚçŢ!_§ć4ŁƒńŐŔĹ2žxąŒŻ "v[8°h/vŸßc}Ř2ŘiÉşB[Űr(‚KŕsŃWľ,úŹ6ÂŚŤ3é&×YĎ™Đ[ř˙0ĄE˜őpeŻ <Ňxš=óő\`ń%‘íşš8°]J}âİ٧ŤsÖsŢáppЧŹĺÂç[¨ÓÝ?1v„Ęś$/ůĄ#ŞnÁá óůvŕłnKšÎ–™:sŘĂďÁhíŞŃ•l›đIJˇĎ‘Ď6€č°l`őţ‘%jLjGčG˛ßf‰ěţŃ@ˇß^ć6)ň~Ű@ˇßv íˇ tűmÝ~;”Ä~ە´ýś+iűmWŇöŰ´ýśűÜöێyˋ”ŮœŰ0ˋ­˜Ë‹m˜ĺĹ6ĚĺĹś ]^lÝ~›KöQŇę´ýv(‰ýśnżí>ˇýśmżÍ‚Ë~;ԉý6ŤMöŰŹ#Ůoť’śßv%mżřÄ~;Â~;°„ý6ˇ†ěˇš9dżÍ˛Ë~۲ý6’ýś+iűmW§íˇšádżÍ,É~;Â~››XöŰÜF˛ßfŮeżÍŞ“ývw„?%>eŒ6ĐöہO¸™:öێíˇĂçąťšýśmżKĆgűm֒ěˇůsŮoł˜˛ßVđjnç“XkꇆuoŘFsĂŞEíşÉ°ş&U6éퟍpňUí‘jœ‘:ڕ”˝áâŔëŰF/ˆ¸@ŰhĂlíĘé6ڕłm´+hŰhWҜѴmtř\LÍ@ŰF;МіŐ& +)+ç5™Ň$*ú´Ţ@x mŹ7řžH™uŮIĚ łH^cKs† |.m{Ębֹ᠒WöD÷z-1Œ+šbÂŘ÷ Oy‚$ÚŰMz`÷řĎc b&L9ňY÷ël!śÄ8ÖîFfK Ăl‰Ą˜[bfK ĂÜĂ*tK ăWٗTg߈hŽK ^MżtEŻiŽÍ ŤË(ÚaĽ+Ő0ç¸ÄĽż;0AӇ/‰˜amLt`s\jśäŔwľkˇë6Żo]Krű"QŞb6ˆşr:ˆşr6ˆş‚6ˆş’6ˆ:ĐŃđ9QÚ ę@D ,v6ÁŸ‹WĽ=>I^KuM‘zDIGXŠ%mâFąő.N%Ş˝nŠŽĄN ˘,fÂt>_7–¨-š|"ѨcÝ6ĄäŢŚnâ:˛NÄŇŹO)Ř@ŞÇkţzL8ęâ11MAÉb›Ť÷@Ű\˝c ŘŚb6˛:LGV‡ŮČę*´‘Ő@7˛r•2˛r2˛:ĐFVŻ/NJJŇʢhĹŞ Xtşr3ň†łr­ż7‡iޛŚíëĹ4m`DŃălŁ5ny\Iq Ý#ç5 ăęKśŃ:G–2b|ÖŔŔ:ZÖĆőÖ†S­ łŃڕÓŃڕłŃÚ´Ńڕ´Ńځ6Z‡Ď1Z;ĐFkÚhm ­ůs­ tŁ5ł$Łuř<šŃ:|ŽŃÚ}nŁ5Ť]FëP'Fkn ­Ąucćq2%×áv[Xɏ‰öv–dßŰáW­Ăç8Ç„đ6'(ä@lWRHžݕę̰cśÄę wDťŽ˜oŤđ”š9ŽA˘é¸Ý/h7¨Nn¸Ÿx‹Kn,&îŽ`Ÿłžť1—hóďo°äę8Ëľ#–90ŸÉdd^Âă2ó{PžöŹcť×óö#ÚgĆĺ=ˇ{ŽcÜă_–ęŸ9C$œK$>sĄÎÔfW˛†čKk0ďz ŽqĹŹ/ƒˆĽv2Ÿ#K>s)6G)GhÍ{řĚqGh'óg YŁB.ęŕËuĘpžÚŮ$-pŚ Ălă0]ŕ8Ě8ŽB[ŕč8\Ľ,p¸NYŕ8Đ8 ÖŚÎxö÷ëcŚçÖđ÷K˙ŐsG.“źV ż÷“¸ďŽśĽžą_‡˙úä÷úëG‘?[ |Sęi÷y‚eRvišĎ€1ťŽKpRŸŻžŔq–Äó˜)„e‰ŇĆ;`Ě2ĄťÜ>–|Hî€1#eŔ^9{žOÝ=#ňOγćěŕëYžöGłœăƒÇk”ˆŇcvë!u˛ËIvĘÜfŸ¤1†Üpš1›2%7Çô1wőŁŸńÁă5Ć ššŘ׼‘€9=)wO|’Ňp#pž=˜˛ĆśN>ćń}4ű->x˘F<Żłž)50=içšHő$˝%<Ÿ"pžI5dĐt­ó|&Půŕ‰÷ŮgОl‚CzA¤'G5M*y’ęOn„pžU2dtš\ŸĎŠ(xźĆ˜QKš´S°=Ůż5ŮŘI (Č=§ŮƞČ2ő|śŹňLĎ Ů…,)’Śŕ€łœ<$÷Ö.ížœĽĂAę†Čs3î<›9č<㎫ń ćśš$ţ~n}Áľ!‰ÜÉďGjŤÜ]C}ŃßĘNŸŚ@Y­ŕÄ3 ühřŕ‰WĘZl‹¨,ţ~~­Âő՟”vóx¤ĆŽ7,ÂTĆSŸö#`ËśÇVóę›úůĺƒ'jěËůŠ‹ŃcüýěÚ'ԗvĄď–[đH]oXԙ•§.äč2đ1.ˇĂ;_Q#>x˘Ćžœ’•Š.ž ˇřűŮľT¨O<¨Ú΀Gj˝é"˛˙Vžúâi_Eš˜Ó™ÔÖ¸>Ó2!Ď˝-Ć ˇřűŮľY¨ŻzéPjĘŕŃťŢzćwůý|žńóĚď~˝‡Ł”QęG3—ăƒ'jä✸ƒŢâďg×z1'9œŁ} ňx´ĆގžU[~?ŸĂů<Ťś_™ĺ“”úŃŹĐřŕ‰9?ł-ĄˇřűůľcČ÷źLBß-W`zr|ԌĹňű+ňăžf,ö벉2ˇ?_Ł|đD!÷­.>Eń÷łkŃP˘ŃqęÜHOŽş￟Ď=šŸY™­ř×(őŁ5˘ŕ5r^Q[̢Śřű<ŤčyJˇ~ĺ–Ó°<9>ę˘^~?Ÿ×ń‰U}sóŁĎWdŠÄń´ňÍo~óOoźüËĎo߸üüćçĎŔ?ýňńîýÇ˙řéż~˙°ť9–‡}jšŮS~óůß?ýçOĺkŠËď?ţéň嗟ú¸źýňËϗßßüm­ňŸ OoţŽźššůĂ~WĄ?˝˙ďËÍż.őí%ýŰÍďţń?ŢţXé<şůřˇ?üPĎ6kýw—?żż­TţţăT‹`­î÷7űÍމˇúŰ˙üÝ_Ý~úéýĺóÍ|swšóůĎ-yíÍoŰßĎŢŕéˇâ4 ~@Ĺö}PŔ_żýrůx÷7Úż‚$şý¸ťŸ蹌djçß§ÇÝů4ěŤ?+بŤLW–‚]„ˆ\÷Ţ~żŽ/Nœ›ýœĎ ÚÓo•éʒ抑kŃ|üýRźź_W' iƒ‡no=řŕÚ,JřT9Š ‚íPÁŽËŞTń~21Ż#ɋ[|~Ă1Ž ve-Ňď 0Ż#ɲלŘĘüđ7ŻÇˇˇČśůˑůčgă]°ŔWgYŕÓśúvBĎą`‚]™euAĆűYW^I’—śˆđi—Á“ŢWB°Hg[Ŕż|‹¨ ăzž×‘äĽ}˝>ô×óë!Ç^]°ŔWgYŕӎ‡W>“ěĘ,Ť 20ŽÝxI^Ü"űęöä-’ŰűEŔť˛ŮůzŇ×3÷ź’$/íë§Q[$§°|pm–%|z§ڑ€ v]–Ľ‚ Œ;÷^G’ˇřô—J´3ěĘZ¤ 20înĂxI^Ü×7r˛”géŽ`ŰŻqż.|ę%֜x{>&ؕYVd`źß”Eŕ•$yi‹ŸÚ"éŕíů¨`×Ő"*ČŔxo‘xI^Ú×K™É™qŮy{>ežĆýşđŠrl‹zůíPÁŽĚ˛ş ăݐŕu$yq‹l‹w/GbÇ´Ř^ĺÉÁË[¤ 20Ţ`^G’—öő+çŔ›ŘfđÁŐÝą%:wXňĄž­âëô*ç/żgë‚ ŒŤżJŇUž Tżçř°,ŤžĄŻ–ŕƒëk‘.ČŔxo€xI^Üם—PwZďOş`pę$ô—ˇŹÎÖ)ąßŮČ×gY]qőŠ Ŕ+IňŇ>Íëŕ‹˜Îœ˙ň-˘‚ Œ÷€×‘äĽ}=>');_„ŒŔŠ#Ű_޲Ęî×'Ő[ŽŽF ěŻą>yšeuAƝ# Ż#ɋ[d]üÍČş'žušĘ›d`ź7ŔźŽ$/îëü„ŞžE˘‹8wśüË{gOďâI×# ‚]™‡Vd`Ü9Ť2đ:’ź¸EŔ§ś’źšěĘZ¤ 20Ţ`Î$y.lŃÍÁčößß~üńňůϗۛžüýÇŰOw—?ýÇŰž'ÖŃŞq› óboŠ jaŞ­AĄÜ˘TMîĂ@Ď:´ VF ŸíJő°¨žţUŮhŠIkSąłjAĐňŽľ¸͑AąŁuNˆ9ŹX­nűöVăU1]„5!agD5a9 "‘zqçUËáY Ëť,#ÝeGDu//ź°źëŽůŔŽ0Ěa“ƒŁvČ9ÔRăPKš‡ZĚE8Ôr.ŔĄb.ž!}+á sŃ sÁ ;ćcúo{hÎůȆž—ؐžÍŹ֐ž•¨†ú­ jč•ÜcR}ŇPË­ŃĐëĽćjHë^ÂfQŤŐ¨Yž=k!=# ě>čšF=ôrřř†ô­„7Ôoo5^–ałćˆ$ţzŔCĎ_wčiäiÇÚ̗C2⯺łFĎ"ӕŕY†˝ÓÄL7gî÷N^vn#IÁß"49óŒwđd5yńźhúHŽoŠżľdąHiXŃŕXöí1É˝ž-ÂŇž¸<+č÷;E‡mސ…W2HŁ+dÁ•Ź2‹­¤˜ ­DŐId%ŞO+í>Ä­ÄUÚŻ6xl ×h7Ą^ĂÚ$ÝźŹ\šĽëÜau°mó űś¨Š DčŢ6ÜşŻgM/ÎUÎsুHÉÉ Ő°‘DÓkë#Ř \Á+l’<‰Č łŠÎ•ӚΕłÉδŮΕ´é΁6߅Ď1á9Đf<ڔ§ŕľhÚĽUaJZ•ŹXtëŠEĘŁ)č0cŽM{PlXÓt˜–Ř.× Qßu ,m- ƒou† „˘#ˆ‰lb­˘ĆŹ"Oi´ŠTr° IŃÁ†Zg@6Tɜ>($§űČ&ń#K4ţ: NudR„0:°hĆ$&dH›H!‡NqĎ- 'Ů8u¤Qr`MÍ´cĂĺ#í&K´ş‚˜çL¨`Č3°…6œĄ%#ÁqŠĚ×ÄëS4ښx}X*™ľ„dh;kiľ4JĄNdL↫öץέ%Úáć¨i”ČŔjĂőţ^ÚŞOłBu śĹ"ŻزąçYS†:KsTt`[pę.ńşŤsÓÄëîóś–nkAW˛`]{ą•Ü‘üpY#Ą-ónÄüă§w˙ó݇÷˙ç—ËÍ9ü ÇăW_żZrľ9éƨDjź×ľ˝7]ȇϏƒ5†ˇ™Ű ëűo˜œ 7b]śHbwWgBĆ jÄśžĎ37 †Ł$úöy Kö™U€5{fÎÚ¨„´lل‚c)ěkůÄziĐÚ6fAŰĚ ĐŇmzOO-Ý6:8 íĄý\zxÇçEÓĂ3Ÿ˛ŽZ§X\wÓ­ƒaśwp˜nfťWĄm tűŽR6\§ě h[ŻfÁzŤŠŢty¤†=„bľA‰*Řő­ĂÓ䓫Ŕ~ łu¸+§ëpWÎÖᎠ­Ă]I[‡;ĐÖáásŹĂhëpÚ:Ü@ˇfŢeĚÔeĚÔkŽßĹłTc<ËŞŘ•Ź„ňÁĚ÷¨´ ×#¨y Őó&âImÔu%ĺÔhŹsŸ‚BfMüdG”ŞŔçѢ•ُ(ŃŞ)C™P=(:˘ě5€z‰|֔Ąy(™‚Íľ5dn'äáóÜF-Ţâ(‡Á{D@çÖźG"Đ4SĚëZ3aYËŕ˘ůäó{0ږŠoF۲ÄeÖ|ĎJ i‹ŔŠpsl–Žľ$ËZŽł.k§Čg]Á2¸U0X][—–Řu şěÁBw*¸†.3iÎO{ߜ÷ž(ý^Ť•˛LłŠůiÖ>ŢlšĽű4˟Ë4{P6唐HŔçlŽŢV…ęl΁z›Îr Ţ>Ďí JÁë›ĎË´ .X†Ů|îĘé|îĘŮ|î Ú|îJÚ|î@›ĎĂç˜Ďhóšm>7°źŐĺľůźÁîóťzÂćłö¨}ęˇq¤Ú̄%JČŔ̋CTř|ŮYup{ˆ ´Ť—ˇZş§ĄÎ­ PŽä­ŚT,ímCÁ“†“t&Đqb4rPĘĺ i-ŒĐŒ˝4ˇQÂAé Ď<ŻÜî8==‚)Nđ§$Ş>Ĺ$Q[MŔИmIňńęČÇë¨_4/’Ž•Ęp'ď0U łYĹa:Ť8ĚfWĄÍ*şY…Ť”Y…ë”YŁ6Ť(x}łJYšł Í*kłŠa6Ťćf÷ąÍ*\ŁĚ*ásĚ*Žä˘łŠ/˜U"TđlŚ8BW8WlÓŕ&`˜›+ʜÍVÎÍVĐÍVŇÍşš‚?—šÂ@7Wčć ý\a„Ü\aŸťš‚řěsŠŁĎ úš‚$ęs1ßç ţ\ć ţ| äć jľ>Wp2WXI7W0K2Wđ¤áú\Á„Ž`4đV ,ľ1xŠ,É3“Š„:ë´@,m2-”h ůĄÝh6âQ¨ç`ČŘćľ˝ŠŁ~ћ6&$ÝeoĹ3€a6(ćfĂl0ĚÍVĄ›ô3UŮgŞłĎş ƒ×7,s;Ľ  `m0ĚfĂÜ ŕ ˜TӎLťykˇË”§Ěä;˝ySđúű%űW'°^Ăl°wĺt°wĺl°wm°w%m°w  öás ö´Áށ6ŘčúXF9čcęrĐǒËAŸî /|Žƒ>GČúuô…:qĐçJÚAË.}ÄA+Yú!ôćˇŔűÄm_‹ŔŇ&§ÜF;œ˜—Aó¸yă:ëéßBunzóĆuĘKCćłôQĂľÓŞ´°}âőĹĆÍŃ_˛ě-Ř>ݰ͋Or—ČR;Ӌ ščë Ö§źž|ŽA!ÝׂlžQßđ,;űÇh‰Ă‚˜{bKnO2ă`ݲ´9&:‡éDg˜MtӉÎa6Ńš m˘3ĐMt\ĽLt\§Lt´‰NÁ+œčśŽ”':Ć0Ń)ć&:ĹüDgÝDG5vMóç8b ŸăˆŐÉ&:ŤłÎ“Š=Xr`ţĄ?cq`'3쳃W8ObIËó¤bnž´r6OZ97OZA7OZI7OčćIţ\ćIÝď=Ѝ÷Ľ ŚDŒmVň@7+QoŠ´SëPgiNĹĄÎŇîXĹi Şk›7™'IuŐ×)íRĹ܂Bš7ÉŠ}Â$ÚCĂáB,ŘLsC=‚ŃŘȺμ;ąęČę0Y ł‘Őa:˛:ĚFVWĄŹ:;ŕ*ŸNąÚČŞŕőŹkiD#kŔÚČj˜Ź†š‘Ő}źęČęžś-“‘-„ďt auuDĄŒ V珯Ă˜菋XÇಓDW0emď‘9bŠb.dŠ•ł˜)VÎMą‚.jŠ•taS tqSřs œb ‹œb  ˘ ď{ôyď{D˝÷=ÝěJÚĚz“18ԉ18ԉ1˜U,c°m fŐÉÁ¨ƒšd |b íĄáÜě$˛1˜Š‹qÁÇ`Ăl V̍Á†Ůl˜ƒ­B7+č퀪ěv@uv;0ЍÁźž1xĂ IcpŔÚl˜Á†š1Ř}lÔźUj.čĹ•œŃaĎVˇĽĘŁŕő [ňˇ°^Ălhtĺthtĺlhtmht%mht  ás ´ĄŃ64XěǕźŐ.Á‚§ÔĚށ3žöĄ6ş ůźđ栐˘Ď‡\ťžîęKťFu.í!0żś‹%VˆźŠŕÜâ^óuź\BűÚ(ă‡XÂxŮÂ31@˝;P—)´f=Ća%_ŕ@Í Ůôš ł$ĎóuâbŮĹ´Ëä<ČÄ´ ӁŮ0˜ŚłĂl`vÚŔl ˜šĘn…T§ Ě´YÁoĚc킟Ez4>:>xb<ß˝™ëÚę ?QökëĘ'Ĺ~?Z[ÁŇ ă/ý§2#˘ĹßşŽ~„ťcň 1žŤí˜žqtQ*?u U żŸ]‘†úŚÄiFNGj…ÉR[h<ő%ččâü1.×ĹgřŠńÁ5öEnĚD/ĎRĂďgW¸Ąžú“R8œÔŘőQTĎ瘡ĹţcëŃ2ůÖţŠŹőřŕ‰9ź-‘Ľë†ßĎŻ˜C>ú%¤ł;­ąë­gT—ß_‘ż{}tohbÎgšÍŤQ>x˘Ć›[—ܢÇřűŮx¨oŠÂN€ň̸¨ŮŞűďçs#ŸfŤö\ŽŤż˘F|đDœ÷ؖđĐ[üýěŠ>ćQŢBŚSŕéńQ3ËďçóΞgöëďtřńń+2Ůâƒ'j 9euK zŒżŸÝ!„úJHqs <=>j–ŐţűůœžË3gRő‹íLęGkÄOŹçCžNÝb@oĂďgwĄžŠpbőSŕ‘űz§oľúďçó%ŚgFńeY|†ŁŻ¨ś'űľf^뿟ĎóušyÍs ŸĹQęGkÄOÔrxé– z‹żŸÝa…úÖŁp˛ŐŕŃEošŐŞ˙~>‡ŇiV+ż, Ú?_#>ˆůĽŢüć7˙ôöÇËżüüöý‡ËĎo~ţüüńÓ/ďŢüńŸţë÷7óĂśľşĘ§›=ĺ7Ÿ˙ýÓţôPž–şüřţăŸ._~ůŠ˙ř‡ËŰ/żü|ůýÍßÖ*˙ůúôńćďʛ››?üáwúÓű˙žÜüër,7{I˙vóťüˇ?V:„n>ţňáĂ?Ô{”Z˙ÝĺĎďo+•ż˙x'ŐâG'XŤűýÍqstâ­ţö?÷WˇŸ~zů|3ßÜ]îß|ţ󛹮~Űţ~ţđšM~ű N;9ů€Šíű €ż~űĺňńîo´˙âkăš]Ďrmź~GZ1Ţ`ë†WGFţ}şÁţË'Ą])3ZyĐÂďÓMý$ ]9+Ú3—fŻ#ŋ“ÔeVěŽ ăľ"Ëxe ęDˆČő#Ç:Ż!ĹËűu<üŃc˜~F1§‡?q‹Ň'ťVĽšrNœţňVĽ‚ Œťű`^G’ˇřôvtÚ0*ؕľHd`ܝ42đ’ü }}[ą[6GĘš>řŕę, |ęáҕ2•€ ve–Ő類x%I^Ú"§9w„ąPÁŽŤETqőJ‰ŔkHňňž.šě}ăœë#€ŽÎ˛Ŕ§Ęq„3™PÁŽĚ˛ş ăݐŕu$yq‹€Ď/|Ëpv‹0Hze-Ňďgîx-IR•!ˇ”ňÝđŰ÷ć‰6ś’ɾȤŤÜ ŸvÎ G@ť.ËRAĆő+Ż#ɋ[|~ᛰł›ŽAŇ+k‘.ČŔxo€8•¤Ő‰Ó-‰Ů÷E~Ö_póY&IG€|đzş™őAȡ´q˝esăyM9ȡp€ŽÍV…Oť›ÂeL°ë˛Ud`źŸéEŕ•$yńy+řÔ™ˇpÂ:*ؕšvAĆ{‹ ŔkKň}}}It™¸”5Ü@Ú_c<ąeOťŽ(ź˝ěĘ,Ť 20Žç÷xI^~ˇRü9ň‚lŽ\áýJĄ'ƸŢŘGŕľ%ůΎź&ć80Чłř€@>¸6ËZńzŐÜ ÂrdđÁŐY– 20Ţ=ŕu$yq‹dZi­ńöwňuŽ´TńŢđڒ|___׍cě /ŹF\eíôˆh›ořŔť2Ëę‚ Œ÷Űŕź’$/žŠŸčŮć–&ŢđŔ”Žň@×÷*8“äš 7C,†ŻÉ˙ľQ *6šLAç­Cőať„yS(ľˇîł+՞ľ#ÂŢDů‰f8Ąö/3b8,ţӌ×ÄÇląÄ$+˛R.,Đ>Ś*˛r.(Đ>&*âo%$Đ>Ś)2ĚęXšľ80ťKŁ")sî˘sŠžšˇşě,Ž<1lGÖꊰňjˆęeeíĽ…uĐÂMŹ3kš ő@c]1”RjĄPĘAä=4Ů5ˆˆLwßI^$l.¤űšÖˇ/âNܖ-­A&ŮZ´ĚŠ=„ŁöDŻÄŸäyeŠ ¤~e+EćW„Ú]r%‰hŠ^Ô ˝”¨şJ}‰ZŞ%×ú{%´ÜÄ-ËޖؼŰ<#ݰäBťuĂ žĄ VűL°d۔KV°ÚRʰd+y œŔÖ lÉŔ‚éşxęIćëD%ˇÚ ۂÂj}3R—)jcRŁB{f…`&_ƒBfLۤtíŇכKuÁY˘’ë”LÔ< ô)SÄÚćZü9LW†ŮňĎaşţs˜-]…ś4ĐOă*e ČuJđ4Zđ4Żf.žSEďťK($Ë ĂŠ*UąśÄ@wěú–iZ]€gÉM­˜-1\9]b¸rśÄpm‰áJÚÁśÄŸc‰á@[b8Ж–;Kxm„Ƙş cŹşÄ ‰Ňý=đB¨łdV\3ô˛3ómhÄVĕźÓa,Ôš"ń9óšÖ'Ćś…Ńš°.žd ´šˇ9́ĂŘ2|~Ą9ę|>E[˜ußĚĆP‡1˛UůN¤şMsü…:S ŢęĚ-d˞sTň¤éüÜçuŃTőśźÂŚÚˇXśP×@Îި;MĎXڂěmßڄĚÔĽ "¤§‡7ĚŇĂ+ćŇĂféá séá­B—^AŸžŞěéáŠÎžŢ@—žƒ×2ÖmşK”$]ůZ ťí‡Ż†ľĄ‹•{hwŹśŘ¨ÖÁ+ë,…ÇzĹÜXoĺlʎrnʎ‚nʎ’nŹ7ЍőüšŒőşąŢ@7ÖwđZ4íŽÂX­˝‘ţĺ0Œ5#'_ŽäŽG_ásœ}9đVłGąëŠľKŰ)#H‚g,’×ŘXr°Ĺ•övh!v;7V=ş%‰pvŰ~ąD}v!ę}v1pŃü\§ädęuĺ|DÍ×ýo!ć öż}žp6K†Úö•ecćŸKŰtpĂe„ĄÔ×%˙ćob}ĘV7ȎŤl`ůh9$˜P™˘–ęĆpĆB‡ŐLë[4ڒ–ą Rf‡:‘2;€Ľ–ÚVˇÝ„:—ä‚?ÉJĽŹ‰eŻ+•šqŽJî=nŸiŰΑ lV‡s$W˛ xxöŸˇ}en›¸P'ΑB8Gr%$ü$–ę$Ů\É{,ňˆ:2vfŚžÉ"ŻęÓJŢĄ.)RߌŽÄ +dÉčq31żŁÇí‘Ďz¸TŚŔRď\Ä|ď\¤äz˛NąÎź†ćhy8ąlĺ:AŇQ?4 ›+™4á+DŽćˇŘFYOœÂç8OaČfSϑXĚŁvĂ…}"ľ2ESÜ­ovĐÍ@üôáîžűđţ˙ürš9‡żá{üęŤQő˜+ĹF,Šr{•œXşvN%Łp)˜›Háe™řóză]–5´BÂ(Á˘ž’­XrP?-–'şýZkŕ‚ד°ŕ°ĚŚü*­‚ý°ŹN &Ë8ěJÖqĎü˜0%*ůQw‰ ˜5QăłhNfy_gAś–€ůÄÂ2O‡Ë䁅ĽĂtc˜í`Ś;‡ŮĆUh;݆Ť”Ĺ×);ÚFÁŤŮÁ$UtöˇÓX8ěňƒ„łpXU~›9&$UűŮ_YĎx c rśݕ|[—ŕÓŢZŽôv ęL; ’E„ęÉĘ\ÚI@řźDęľäŇ&H–rĆë V–Öö6PÁë۔ĺeqIšĽď(f›2WN7eޜmĘ\A۔š’ś)s mĘÂçؔ9Đ6e´M™žCŇç˝CőŢ!t9Ż\IËyĹz“œWĄNäź u"çŤXr^9Đr^ąędÁ¨ËyĹm$9ŻŸŘ7‰öĐp.ç;ÚڐĎc°a6+ćĆ`Ăl 6̍ÁVĄƒôMNUö&§:{“čĆŕţîďţüöă—˙ńöçťËĂşĺÓ˙ž‰Ŕłëžóň­‡śĹzh˙OíĄůAŔĽMueęYôę4¸´‹_Ăjš5áiaÇ n f_Žiť-ˇ Ťţ%G[›şr‹ć˝r“vZÇÍ˙žÝƒpúk÷ťꇇ1ŮF×<ą„rۚ́3†ÜL|VŤXgVF‡×6r:ć+KˆĄŹŕwŽmD,—E3ü{ĐÖű†UMm­FWîAR™Ăน=VŰhoĂÓŘwŚŃ|7 Ó¨tv ěžÍÖžŢ#ŻQFĆHIxÁ`Ű˙:°ĺâmÝցľrëślš%[ˇuʎŒ‘Í݈yŸK T79ó+&­ÉäëŔ[3fćłZŰjٕL0¤-Ş}ŢÎřÜÚj9°´'ÄĎU°2ż—`BUKÇYsĽ6|OÁ:ڐ5•ŔgŰ)L#Ÿi^F>Óź>WÝS„ĎSP]™qE†¸Hb{śsŽ |–…űîÚ§`Ü5ؒgÜ\ó}ű0ÇţWˇ)j^ŽłXó I˘]7WsŠu"ĎYóˆ]ćÇG ýHRš9BÍ]ôŚxŔ)n0oIiĆĆ 7Źdq¸aćĹᆕ\ÓՓěz ĆĐKźęŮM FŰ-ó8°ä%ôŁFh ]fŰqzÂ]ŚŠcďČ[ĐRŁžŒ6kśs–5PŸŕÄCś0Žuő€` c]ŰöO‘z;Maœžŕ Ôëój6šŻđ v=}ţ˛“^ŐUÇŽołSśyČbi˜mv\9Ýě¸rśŮqmłăJÚfǁśŮ Ÿcłă@Űě8Đ6; ^á ŤUହbÍČɓ+Ůn błˆď}ލ-|~Ż×RÜŞim;{ś¨v~XÂŃ77V˝–Ú÷HÇ{ÜXu'ľŹÁ~$ńeč˛ăޝş9pŃk)ŽSœ˜ş8=0!qzp`›%vśŢv Łńˇ CóšÄ:›fTňňC™âŔv5…Ďď1xSÉÍÎĂŮŔä<<:–Gßeěe5 ˍśĚíNë,)qĂmâlÉ6ߎĽJ°zƞŁ}6gËĚMÜŽŚ—şL=̗%­ÚŐ3Ô)ŤW˛"ŤWîŇa÷FOwĚ˜Ţ źŕŤj^AtŘvŃćŔ¤‡ĘĄN¸.9đ ŔÍÂyú‘“zGťĎźZ=ő~š<“D.—g’hŐC’Xrkć̈́6ě0 lŤÂÄLščÖ1/9mY˘Öľ#Ą%1ĺU„‚/ťM‹SáĆh#üžmˇ&<ĄýľôŢŮz‘ĹÂĹŤ*/Q•‰ű]2(šĘ2lÍ9*očô 6Ÿ¨}b‹hw’űĚdÇ*p0ç çJG}Á*;S˝šÚľłTćhší:+v‘ nšUÚWłŞŽä%őďf͋w`~9é‹uČIŃËş†~ÓŽÇqD ×G—cń=L– śšľ]ÉÝÖ â\łJ_Ř{Y#—ČÁí¸Üą7Í$O;ŞĹžÇJ&ÍÁmŕrUGíňöyÂŞcŁ:gőŞ uÂŤňLňŻ”6Mú&$¨Ăh/ĂhĎŔXâ=à ՗)Vň^˝gXâ=ăŔˇXŚuŹ]0p˜mŕ"‰r–Ü<‹3çž 1>ĺ֟@Ďľ—9 ŮÁŚçچٹśĂô\ŰavŽí*´smÝš6W)ýˆë”smÚšś‚ײcȋ*W(őHŰ­XZTŃťžíe%´…ť4Ăl{éĘéöҕłíĽ+hŰKWŇś—´íeř\ŢÝhŰKÚöRÁŤŮ^ÚjU(uëNĽ‹vŹţJo^ŘŻôŚąäęÜ1%ˆfĄ˘šquâJϕźÓ+=úŚÝQßőJ/‚c–+™Ô1+PÇjŐ}žń°}˘:ďő ӁWŽŞ;VV]wš$Őá}`B&0oąŽ=˘–d]ëꏣńÜV…œđÂ}ŠšĎŠ­ YĚ:ě3K†}–}…łWKA! |.š9 ē1ŕ`3qÁláćhKÚubchŸcőƚŻŠ9Úňs›ƒě́lcŮ[{ۄ+ř+ěđęšMĄîśŠŮÚ>á(¤Łď[›ˆ×¨ŤúŽŞYâĂڎǨ…ŹŹ>ĽDę ś\ńcÁŞç›‰ř—Žąń%ë ˇž8Bp: Ÿ/ĄßdY“éՙ°ŹS0=[3!™„śféź`1Ě,Šš‹aś`1Ě-XŹBˇ`QĐ/X¨Ęž`Ą:ű‚Ĺ@ˇ`éŕŐ,Xf ƒƒ9Z°0&AaKx‘WŁ|tě #ݤ6Şq¨Ĺ\Ź+gÁnʜ‹vc]¸+éâÝčŢđçńĆ@ňĆ@óڃW¸ˆYq ˋÝ"&‚mˇę>ßŐ)Ô $ŢÁ3QÉCĂ 8Bť:…:ą q%“š’÷ŁLčÇci÷`[…B8Ó4BrfĆuJpŢbK9yBmÁ‘AČŔI—,f]F,Q˘zJuâ~tédą^i„’KhÍFËĘ{Rr[[Źjk‹íÄlęŹÍZŞËˆ}̡3ňÜ{ýňëŹęűž‡f+s‹těho˜Ź˝}|ßÉbČSl=9cU•ź+Ű~čqĘŮ J ŃdX˘EÔ) ]م?u"üu*é#A.2tĺÉÂpq¸L‹âRĐÖëâo!e_ü…Œă‹ż`Ŕ:Ŕaşp˜­\…ś0Đ­¸JYp˛p ­źšuŔdĄáŚkuî]áýĹsšbn.ˇr6—[97—[A7—[I7—čćrţ\ćrÝ\n ›Ë;x-švüWhů;ĐůčůؐĽ?Ç#÷ůŽ ~šbKŰ/†:p̕źÓ›qzöŕ¨ďz3m Âő̄päŒ Íöy[`Ž4đ^ٚ8đ˘QMX!ՄŠçieŐá”âčÝaÝm}°°>qJX¢Óś“:UąBÄŠŠĹ”łV˛38pĹĹzK[ę7gÜNUd 8Ľ8¸°’HÜ8Ľ– ˙)„CdÍoK°ä]=­Ÿ{aŮqJqôŃ żÂ)…cÎdŻe ľ°J‰tô˝§{hŇw¸Ń›ŁjÄ&śOŮV˛˛M$ŘrëŢ{XÉG0“‚§l;5~˝:,Ą+Űú`ƒĂ­ŚëĂl}ŕ0]8ĚÖŽB[čÖ\ĽŹ¸NY8ĐÖ ~cŚg— 2ń>ů=ŸgúątÖëYŚßęľű LüâO¤PϔAý™ Î(ýxmâ´=fđŇĂ: íOÉŤIORľÎźÓŹŔ” –˛Ć}EV۲=–ÜžgĽla–sH•ŠŔYŽ-’ť'H=I[9#ZIÎ3¤RfLĘ ő|†Oůŕ‰1ݏ™‡´˜ĘSrk˛Č“~°čœg‹ Y×é$oăŁŮńÁă5Ö)tÝO˛Ü )Ô°>içš8ď$ä€ÓĚy!cÚv–ĂîŃĚořŕ׎—^ÚŘţ~}źôÓěfőgŠÉĚŇóŮÍ\ň\ýëóĽÉżśfÎ6ߚglN'ů҆d\˜Ÿw4ŰIb,\FDŕ<[Č˝5ŸeC{,‡˜|đDĽ-vÇÜQCb"¤'ÇMGu’$rŔi>Ş'ň=ŸOé4{Ďůg4mŽKŇ2ӓă΂Ŕh_ÎŚ`Ľůâ .3YĺWä–ɏZĽĺâpËËO1$ŹpŔ#+—udÝĎr0ˆ˜ _<ą–ÂńŘ1äą<ňÁ#xžz…şś[›Çqř‰˛_[—jźO7ń÷ŁľUŢK_Č~é?•-ţ^ž™Ť0„’>R›ř­Çú˘Q~ęŞ~?ťb őM‰SşÔ( “Ľ°*ĐxęKÄĐĹóc\"Ŕ(őŁ5Žĺi›ŃEhĚĽ˝ĹßĎŽ@C}ő'Ľg>Šąë­ç­—ßĎgI?Ď[ď׋i÷­ýy×Óţ´ý„ 趄•Ž~?ż˘ ŐKH|3×ŘőÖs‚ËďŻČ@}š܏8sń­ý|ňÁ5†ěŇş$=ĆßĎŽC}Š[›[”@y˛_kžĺţűůěžĺŃ˝`s#ëyžF|đx!ĎŽ-é ˇřűŮ^ĚۋÇő>Mďx˘ĆMz˜ü<úiXŻ`śGכ¨bŚ%ů™úŢF*|đU]4¤˙÷ňďo"đ-á”\ůvi×z .íúšťF <ÓâC,>ŞŕŒwpŠ--’›Lń=ĐŕŽ@nĹc- {ŤąqövÓLĺjĐu_Ž˝pńf€"1ŚvoߍËőáu,סâҖ;4ş‰a›Fl5ě‚T_eg^ę5úąňˇ˛)0ş "Ť/$9Ş;ńˇ˜WźbˇźžëŰgjŁöŹ}ߙFsŸ¨Ýđ†›ôň)g Œ’›x…ęë:ăÚ{ô¨ÍNJGđ¨Í‡…ß\âöR[ůEu!J‡B•/ź‰WhÉƸy’rW[ěqŽhÁ6ÔJJxżŁâéőюá^ e$'ŹšŐŤlåą<]a€3[a€Ę¨3ÝkćŽČUHŻń­ž|g"ňWƒE׹[ ¨€Ux’îšo?Ćá|°ą[ í侅gßżřľźŁ;qɲěBŇÂCű2ˇ3ŠÝâ)ś{ĆAŻí„w¸Ř^ót¤ŹDóĚ!˜E;VŕĺbAާOQÖ`aQ^ž ‘Œú.´ Íýx{,,n!ĎźG-ŤƒUŻş—+÷ľŞşDßÁxGßcgŞîĚJúbú˜ő…X7ލÄ簑h.ŤĄWĎŘqĘĆz`Ež‰–ř€hî‘+$ów7 Řá…D¸oeČ×´˛’ůłťaÍUž}yěĄ%xěň >!h„ôŞzĚHčKߙÚJëw?Á×&4wŘĹňčăŮA<ŔŕÝšC cf€žćE…Z#,@Ż´ĂÎď Žśç¸4RÇsL”ZÁč ~ęÂËr€úQxř:7ţeTÇZ7î¸"éW4űˆlóűƔ­Đ ŸĂŔş ŐüąŽńŽ˝!nWďH;ülh–z>`}˙Bi Ś•)‚ž 7œE„Úo8™{c/8’ÎŘG΃h™nˇÔŽžHp›ľ¤'˙[q*‰vn=›rƒŢ~KYĆi2čť<-ѡ!‡ ńĽß„n8`ZäžHaË}‘Á–xo7&RQŰŤˆ§–˜ń"/!ÉĂL6Üefé+łx nw0-Č{Ë´ úÎÂúˇ{ń,nט[TÉ šľš.Źë™˛~VĆ|ÂúÜ+cNí`0uŘȀmÎŢîu'ŠęŇxí źHĘĹă]cEâńÍœŰől× 5<Ďt‚Ľ§Ŕîľsƒœ)ÎËmLœ-Ľ;—Š{óÓ%“iËB>űşş/X.âî°s",ĽčĎ\ŚN…,pČĚÜü˙—ăŢsŞw ć¸X”<Ź~ň„íuźfŻQ‘šŚL<8\$‹ I ś ‚ˆ´ą'ľFĆî”Z><zjiF.ŚrÇ]bË$áâprËí +ţš)ńű¸= "XşdĚC§šţzzÉÜς×ě{dű`oSsá ^Šĺ3îÜ˝/ëŘǙK="ž*—Ź`“d|xšfâb:-Š[ZĹo’űfĽ6–ŞÄŁ4‘ĐyŞÜ­Ö-iÝiÉÁY=WŘßIÄĂŘžˆÂQxéěwâ'˘Ó„KăD]ŢPZŤ`+ˆęÁ †ş´ăŕÎ3*;3Dbš´ZŘ– ű˘ę Đßs™iϚŻ$ŰÇ~ŐuŇacoZĽ/Žkn7 ń#ťzŔş’7¨^´{ĚLŘŠ]őZÜD‹Ů7RĂ ÓL͟üŁymŠ–Ž<ź˘SŰméK6­vOÝÇłŔc03eE‚v1Bű‰Ď˝^ÇąSW$– `ßĚz˘ÚM霅ßIžć Ȉ,oů5{Oýľ4!ž§ţ:T¨=őq'@ÁŽl8[Dw[bZS:Ď]4´"ËWťaoÂyÔT2ŕČîE3°Ä0É݁¨1 ŸŠĺ†J5ˇ„ÜąĐDLŘĆň4ć ö›- šă‹u`–;Ń9ĺŔr':­#˛ŹĹŠű…#~Í݇ŒŞtî^[§ŮOô1yw“Tjš…ŒŽ’‚-ž-Oœ –%××:N㒻CšĂ˜‘şoř`[fFě"<ć)$ÁřˆcJŒů‚ö :x!_sË,M˘sJ3!MâRßţ7EÔďk]ÄÄş.͖™^ďRËćĎw ¸űűóÓnÝĚĎíqŒ‡Ě¨ółťˇí‡đÓ¤ đRâwĎq›€ Jr“ąĚϞš–DŒ ,5ot+siÔ3€ß\s…_ČR…řîMGÓÄýü’X‰$,€ “„ô/ăřš€O^8A!Ď+˜•e Ş)ˆŕv+SÎ$5waDýeŐ&j$0“{Y–U§Y7Ńş™Q…´n,ިI(݋|°ă 5 đŁżđ ˘ý”osĹ_SUʏ–ą†t—\’űxJl+/cĚv˛8F÷k~öőó éŘwÔ”ŐĆ@ÄĄy˝M|„5‚q›ŔfÝqŞ ŕ§Ęź6őϐ[ś•aŠÄVÎŔ gZ&>ϩ娝8î2 ŘW›eçi˘Lâ"ˆĆŤN€č%ΟÜ}CQxnšŐě7O€Ę@s7S&óÓ<ó\ó„N$#Oݛ'#Dđؓ1á˛ŔąP#7hÇBĚź řŔ]†ä>jX$XpÝčyÇ~á㊖gœTƒř ˝Ę!\ęćѝŚY˝‹Ă ` "Ŕb’úšĚ$UŘL™¤—8Órw;ӒÎĎ3-ɨŻŢˇĎ°ŕÁMډˇ<ązó4Çę-ŘgŽđĺ6#s’Ú)şd CËmĚŤązősŃosTÚŇos‡ťFQŻŤ`ǙV°Ł&—¨"’d ö‘ˇŤčşôŒĹ˙öÁšwëRÝWů6w,ţümvâáběŔ?ŃŽÝýƒ`ל+ä´acu>˛ŤűĹ™`'žűčť/žÎŹ#ťö7|ő„™Z6Ţ\Ąy4ěÚ ďć>z<`ˇk3–>ĺyz_eě|0v'`ťšaô乚ą;ucwęĆnĆnVHť0ŒÝLf2ŚÓĚd,x3“Ľ1›ťťťS÷ӍÝ„ElMʍĘF 9Ě厒lĐvlgt&q80Ů S˰A0Ů 0lĐ Ä˝"Ć t† :€YDçG Jâˆ1“8űGtOâp`Gt_CŃ=‰ƒćŢ] GˇZ2öâ劤ű) I&lóÝgv† ;ÄŔdÂ`2a§îaÂNÝÄ-cžBR2a§1ĝ€aÂ`V˘s*‘4•!€V˜†çžŕ›ć>kĐtEË eÉâ|qvŽ8ö‘Œ>VE;B5{ˇšˆűů+ŠćőŰÂëŢŔŁřú™€z@Hłń˜eÁúY¨ĺĂCîRË՝ĄpsohAt!Ú4H•Ö‡=°śđŒžźŇzq…’p…Xeű3ŽĐÓԆć>°—…áś0Ökˆ´Ź‚hÜ+đT™°WŞ”î‡bŻî !s?eîXCtî ˇ…VEÝŽMs ŕ%ŘÇxó:“Ô=ŹB´ýzţb]˛”&LźUwŕWű#˜ů{úÚ„€ ŸŮq˘M°2ýçěăôŸ Řđ[ÝcúĎ%źű ŔHížÇYŽčKč2ž0p8Ŕ.Œy,őëN¨żęÜ&řpnKŔ8ˇ%"â Ŕ<™ëO ç6抝ŰdLœŰˆ/żlw'澝Ű˜öŚÓöžŚí Œ}~ů$€ţ埇čRˇČň˜ĹTY›şԑÇđb“i>ÜNŔ22;A"ŠylŸťŹ{SîľŢý0‰Řé,˜ZĆY0€é,˜€qTŕ8 Ś1ă,˜€q `1Ń9Eݓˆ űq“ˆŁ{q“ˆ˜DěŔ,â@TBÄŃ}÷şt řäa¤ĺš0“Içqg˛…Ÿó4§2 .O §ĆŒScÓŠ1€éԘşÇŠ1uSٌy IéԘƌScĆŠ1€YmˆÎŠ6Ń=Š aŸjŔ¤6Ń=ŠM“Ú0ŠłÚ˘%ԆąŠ}÷ŠÜŠĺŠÜŒýr_Jćç<(ŒćA!€% ŹG(Řٲçü& ÷°$% éŇÖnŔsć5Ë؏k°xy~ôÇ@! îÔrw w>š…›[ö3kUěݽ,2#‹&OŔӃ(xFS‰NťŔ¤–—Ű­đá΂˝^3•rr|Ř7F Č=€5ާŃ}ă)Ďݎ§Ě%[–1ń–(3şVŚ4DÄĂoo‰~Kť“d•(ťŕđ›Řp˛wŕ8Ȣŕejš" fg ™Ü.Dšť…”łÖ5ˇF3ë̝Ć␏U1Z6,Ô}őv`zŠ”îxŠ”îdŔ ő~ołŠĺ÷ɋĆ\‘¤ĺ1ąz°!ɸĈŽv'~ć“ŕćÁڌݜ>°¸ÓG~ô‚Œ˝ŸCŽCˆďçćüGŽ>Ásś.ˇ–řŽ˜$˜2ešśřG˗Xüyîű)2zŠĹŸgdçžŃ‘ÓŇű‘C´n,é§j]qWM™&J öv‰†\(mÄRńzŠ2Xěxjš ­ éxšŘš.qőÜ'B|;-ű +ŘxW[=‹xKăoł§°˘Ofź%.ĂӓIŞČĎäŔŻÁ3żŠÁ XˇŠ"/`ű:cđÖĎ]ˆĚ ŘČ÷ѸďX—q°Nˆaž őŢźrŁéőăîcnc}QŕxŻOcž ó•u ř@ vnů5šżzjÝ]’1 ϸÁĆ3nj×fţŻó`Šo˘{*×ď:“*áxŒ*NľŤxĆ­U:ݍť° s  Fž°ąŠ1=ËěąóÔA’Đ„š‹×v5入\afXżÔ˛ŔŔě]qŘŞđÒ%ŕ†˜÷ăFgƒv1˘ëD~ć,ď~CcAž`;'ěcŁZ.Ážű3šßĐĘ&tnČFœĆźźÔ ÎŞ ŚîŢ Xš'˘$xîÍc^XÄ󠱔+ÂXŽűŠ$€JŔ€*7⛪9Ćóg`Žń,Ł\ۘÎ\@Ťjr/0ĚŘűޏ çÇNł çÇU°ţ‚Ç˝ŤĘŒę‹;Ľ–‹ű ąÜ ’&:‡,ł„ŻćŘYU? r< CÚÁŸá¸Ięş2Ľ]Ş6¸ÝV%Ť,-WQ›Y?×Ľ~÷¸­!Ăął2ăŠUŃwws74Ńρ}e@F—MÖŢ>&Ž‚ýÖ%oOłŠÖíîíÉßQ˝Ú}ůí÷.â|?DÚքKć|•ĄJë¸mkŠv‡oMŃîF}ń X/U ć9_ʟĆý á8G>—ëvö*•^HůĹŚ‡ŚŇcőĎMčé;NĄ1ű6dÚB3ěąúD:˘°’ PąG|–`‡QŚyvd˙Z˜™îÂÍ'\JkUâqŸOŔâ‚oă2ŁëŐ¸ümœ™źÁľ8ţ6.-×qđ•–۰×3öž‹Uĺ§Ĺ˙3?-Mną‹ńýŞÉrß<•XO’vU†%ś6âgżU2ńˇ3 ń°3˛4{F–%3y¤iAú€GÜKąxgi§ŮĘŔY—X7śŒuiŽ`ľyń d<Ín‘$DĂTg[ńÓ,’źXq[槙ôʘˆů \!…xŰŒ2w;F3štš{]ʝκČ'Sw8¸ö˝o(uÍ"„hŻž“,!ęöťZXc˨íţi÷_7qÔýźÚ=íĺr›Ń!ŹŰĺ‰Ű }ŢĹę]í MBmŞŸ+]ý6ťąiw ďâďÝö;PkwDŹS /ŒÔîiza$Ř>2EtIĐxđ˛ćvMpŒ+ֈQIx‘żlÉô /[Á;ďĘ' Ř<­Y^p×XizIl: Oß-yŇťĺFcž ŁóÖdÚ=Ľóˇ–Ů&WlŒÇ"ÜčvÝ5“„çţĆ3‚]ˇĘŒâNčÄœt?q˛ăîgc† ~"î„%iq'2&kŚ17ŘuyFěş$őqó°ŁaďťĺmšÝ“ěh‚ÝŇp2ç7ÔČa†˜ 7ÉXC,ůĎ˝żßÝři)tRKs@$~"#‚bŻžôBőŽuöjĚjcŻĆBňœI÷ŚßŞĺ•&ÖMkíMCŹ˝ČčÚďb†YÓ łÄóßĹ3wžU¸T-BeÉâwž˛ÜW‹ţŇGŘÇE°\üō]˝Š~"y´¨bĘ(Íü4s+‹ĂĚ­‰¤*Ég~ţ'ËĆI‡•âĆI‡Ő͍“łKǒŰő5I$죇0$ŕ‰KaűŇ!_ îČŔÓ.GžĚX|€•L$Áł ÷ëłŔýĽo Ńý‚ƒT!:?ŕyě¤íXFs÷/7xî.¤/K‘{É –]ţóDŔFVé1"ˇCÔiŔúůA§Šo™N햙.÷˜ţ ö2sr_ËČH,W`VXAšňŠ­ˇ5ÁÝÍԕZV¨Çľi÷íäií*‚}t/ă^&ÄŁr›Ä\Šű{éI3ú€ÇW&É.Ş×K°u¤–‡§e›eUfËŞŒ‰S˘0š-ÂälS…Y‘WĆD)÷ÔňŮ]g˜ó=t[„KĘŇ´'UFdqô‰řWÚ­é˜[Ö=đ¤zTqߏWĺgߏŚˆęÉď7Ń˝ŢbÉIҘ^O \gvAT=c‰ŒiUf˘ĺĺ÷\!žm,Mxq ĂŹŒ Ă,k˛ÝsYúÖ{CÔˇ^b2Ž´‚}<+Ž‚ŁĎo˘Ş!›GŒ˛*š]WşŁŠ/k]żü.Ş6˝RÎ~kšËW<ŢÚ/؏ˇ°Šý7bfHO~ž!ŽţüÉęmϟ›Şbio(­EŒĘ˜¸äđ×aŁüÁÖEžâqŠÄ}†YÄ(sÉ"F™řîÍs*“+vgţ6-bTşWů`Njl-Ěş”$œ•ÖrČÜ÷*ëRÇŽËďȂ˘Ë︲uďŇzĘw4č<ĺ;Ş^&bŻăkšWglšÉ~ąŹřڰ:š]_’PQ‚qœăŕ`ÇŘÔŠo_PŹÜS´{™ŮŔSť}^lÁV˝’'ĝžš7öo°&€OëËó[a‘a‚VXdpœäđpKXdĐ,y’‘Á—fYăÁ2€#ë&Éâ…$ÜhӌN7ő˛xz~Ž}“š[҄Բ!i׎tšŤ‹ˇ§B8”Ÿ=?!šŽFu ´ü6Uoť)ňÜ팘Ć<ýŚČ‚+şzŒ’§ňÓlľ§~2ć#ÓD¸Ż\ćĘÄW<,1öţ š)ë*Ş0ńeřë¨HřÍR‹ęüŘoťĽâbě[l<&.~ŇýЕ÷Œ ƒgtę÷žyz™f;„É >ĄŤĘČkçiZ!Š–Ř„VďŻěú…ßaý™…'RťcÚjš/Ţ!siźeFĚěˆ ‡đÂ~›Úí3#B‚YŐ˘%ˆ[ä𸸐ˆ-ʜ?ˇyľ ŕ3XFŹş<Íę5™„óí­ ŤŽĐ w[ÓŹşŹ´^ĚÝͪˋϼo°Ĺ}“–•ţŽJ ÝíjÉÝË[؋`GÁ§íž\ô°;údĆVż/÷UŇÂ?˜uU›eĚcěęüiôXÖĽ~ßdD[\-ImzĹW–掭ţҕÁ G ˘ëb]ˇČE˛¸c77$Ć^W‘ŃĚPtű:ú}“H~˝eee@†"Ů´vÄÜágŒ‡ <`'RŰwE XŚÔ+ˇţ¤0ĽŇxđĺńොÚ=ů†°:|GÜN;8ŻQçžľ5ĽpnmDÎş^<—T`CZ"Ą_Óvą“°ď0ˇ–;–bb˝Mƌđ6)Ýń6™ZěMDLé.tn>Ş@˜Ô˜x8ƒ Cŕ &$áĹ1€ă*fېÇľi]ê‡gd…“˜řďˆ,ÍÍÓn3ń=)(aߞq?ŰnÝĄřŇÝvŇĽšăpK-łŕ,h™ľÎâŇĽ; xŔ“‡?ĂElŤ.VŐNפ!˝Haťľź”!}gDÝ žŃžČ§=2šbgÄIoÚ-!!‡őÇ-DŽŚvą[:ŹďÉ'ěŤ(RFíúʉ؟4^ńëaŔŞď–űčUژ{Yŕ )ÄT8č\7ö;([tońtČc˘Ŕz?|tĎŐÔň%Ţţřo4K+[Ŕă.Ćt"=ŠĐَťtúľ‹Y÷ěQܲŰ#‰K((UY’\W.Y”ăąˆŒć“\O˜Ü¸šë,GWjš{ŽŽÔň[ńsnmŃÝҰmUtÝÂ"XŮ{…zăRÁÍşÄůýňzT<ŁÁ޸cc ia$Î[ěÔý@ěUuž'ŠYUmznUšćźÎpËâž+‚}o"Žą‹~†óĽ,Zڎłé×1/)Ěť¤†ôő˛‰ÖŐEgԐľ(竝™IîŽ{2&jĽóŒşC)Í}8jęrqŽ^€gÔŁ˜¤Ž]— ě8şĆŽŘ›Şę|EuRÖy‹fçŐŚÇJđg¸"pýNgS&Gi᢯™óŁÎˆlsš†)ĐÖłGlu{dŔŽY 7ÁĂwtĎ}‡= šĂ:'ÍF}›Ű(śť’Ćť„+Ź~ćvČЊ}7|AěĺĄ3žćHîžB0ćĽ)đŽŁ<ëGź”Mŕ×;ˆŰŘČA,`˝ÄVŸŚ˙PŔ†ĺwĚ,Áž§˙ˇëžB%w†[Đ0r¤–v&Ş2žëdĚU˝řd><~%Yܕ́_˝zŔ/ĐÎ;ĆP‡$uăú–`uŇK°6˜Ü¨]÷ÂËW‚Ąh^k2’ 'ؓ{ć%ŕ/š7, c×I-Ă3qwËÂvCT Ěóň!łB˜<ć>„B'ëĚIKD'c"fž{LAÔ6ćNZç\BOjšůËoGÝQ”a’z’ ćç™ńWEdfë|ö¨TiYdLTä’1g™ŽőEę9NyL+ÓuŢH‚‹ątGţZfH+]TpÝÄ\oÝ[šŻţtË\˛§[Öî˛.Œ5Ťđóě ĚĎ8*ąÜťĺ—•vĂݞˇ"̆‰/Vš€qˇżĎ[ëg9őëxv˙ĄÜü¨$3ÂQIˆG%fLJŔq*WV3Ý&ŕ‚z!<÷'ˇŇ2—z%âü-UTńđz!,͊˘ž<Ł^E‰ÇŹ~9çľłoŹuýĆNŞ8LȂ+ݑšGH‚ŻŻĚýj˛.íţJËtÚöplšÎę¸%Ř>]…ěyl]7ŠÝ9Œëű7jq%Ř2ŽÜ;ľCľçJ8ŽąWw>9‡ĺ5%yźk\’Rť#öô#'Ő´—Ű,ž‘"€ŘÓ ă+)ŽJŒ|ĹQ)_ˇ§3Zě‡vߔřŔř2Źz̎n/ÄŁŠçÜFB|r—s–XÎ%’Ć^‹(1ĄóáN§ŕeQ’N/22á8Äc6ÁŽŒ‹Â‡ýC¸t)Cv^MÝ7^eěörËsŸ[  ;:“ÔíčÇmĚí¸ĎȂ_Y?{ ‡K•Á‚_,î÷BiôšŚ{qËůfí`Ürú^řC§vçHŃ9ÔrŞŰßGË }σqŒ×zh2áhXt֓ƒ"˛-ľ{ sĐAíÖaŞš]ą§…&ˇ `Í–Ÿá­’şďă”p?yŒޏ3ĚĹËßőÓ´_âöÝ(1s´x̊cWËš-‹|FYť|xY;‚=…3ąČěCH:{Ăq†ř‰´‘;ółŰŚű=t—÷…9ś5dˆL-Ÿ=C$ß#—HFăŒmFd‘K‚h՜:˜ŸÍË*ó4­Ź23yžG‘GBÁ"0+ź%ƒŕ!ú‰CJ’^}÷ĂëPcwxđÚáđôăű×çç÷ßüÄ#Â˙ĂGŹă~œ¸F‡ß?bwŹ1˘EDÄoę/ާôĎégĽŢlż8"L[>"˘‚Ó7:üˆ×řŢ>§Ÿx °˙҈Ç:śˆĎéçëĘź xíđ #"łŇçôs§Ţlˇz÷Ť_ý݇o˙řӇoż{üôî§OŻ€ßüđó÷Ďß~˙Ío~ř÷żx=ô‡Ł÷{iďŰVŢ}úíżűńľCoöřćŰď˙áńůç珿}|řüóOżx˙ßű˜˙ úáű÷˙Łž{˙ţ/˙ňĎ;čžýż÷˙´_űűVˇ~˙ç˙ë_?|Ó˝bz˙ýĎß}÷ë_ż˙ôřÜÇ~üۡOËß|˙lĂâÇD؇{Ľn}ýßD?0Œ˙üç˙ĺ釿}|zżž~źźűôoďÖŽ6ţ~úîÝ:Ž9ö:Ąž.ţCGáÁýđůńýó{Ŕ+ÇŢżţí÷żĎŻ˙o˸2v.ďĂ\~LÍ}úîŰ_Ľ÷ş.œËö>˙íëBˇ˝öťw˙ôĎŻ=^YđüáÓo_ą|zęţ…$żSđđşîřP‹AŁ•Jýkçp ęăď—ÎáhyYi;ňú­aÝCś_÷đ„Ÿ–š~˙ˆÝŸ%­RVš=¸–?°JkÍb;đ8“ćx ŘW˛žŸÄßÎůü>ţ׏ýö˝ţ 5číöĂŢ1žŘ;ć?ă}G…îá´eÇĄÁŚÖÓűŁűläq§˙\vFpć´Óa*×oľăýNĹNO8Ůy]ŇÉj˘ďH>Lš¤Ş’ŢsůR+ˇçЍÝ,w¤ńÎ3"7r5‚;ŘŹ\+> ďSĂ%Ł/r‚اm™ZÉÂAýćőÔrđ€pĐH–2îłYʆîh›ĺă˘ăË žPuׇ蹻çC´+xúXŠ%…Žv—;ŽZK†Bs°ü9†ž÷7›ßcAýcSáœS+ôÓhÜź6"ä‡Â§vmZ‰6źOĎźO_E›úÂűtË}ÍűôUFu5q  ŕđÇAθÔruKO$;"şaéŽti‚—‡Č'ŠLVÜ2â2x>+Rď&ŕęŢ ř@}&fÇć၂虊בŚZgawłCŞÇP8• —~†ťGŘąÖU˜™!΃Jw8> vřź3?-ŰłŽžÇ썒ť7ÁׅE”ႏ#+ĂĂËĽđ˜ś5!Š w$˜wlř=bíŒv×Ě›`š°€˝¸•;`ą…•MpŘvE}íÖD}MՈf+Ą’|„)ażţŚ_0‰D XÔQ Xő:Ş3“ţ’Ç;=ŐRjwĹĢááEÓRËHPĎCZĐŠŒš!č›sĎ0‡Ä´—Řrj~§î-ވŒ(IąPŠĺsěÁhGqóÉŤž I¨Ý)sGN’„}¤žŔBÝOĎřÇÝ{VĽKYׯˆ…€ö "i~P÷ČLúĐy$†ôZfÄÄclęoŠĚůţ˜š§ů'<‚šQe[T_BŔ"aYj÷<–q;, VćR`u†§ńę|•dZě䚀ńޕ€a+LŔÝm… ÷é)X˜ Ľ&S÷ć)Ą0̂ fÁ<Ý,ČÜ0ł `?ű ü•7e’=‚É4ąÁ—T•€OţŢĹ 1ű OłÇOQwŘOĆbĂ\ężhFăěˆäŃL’š&§17cÖYžŚepâw‘ć őXF=*ŠšdőŒ˜K/ţÁ ˘SŚ9Î÷­0I3Y˖Íd-D˛eňîUQďşqތ*2ć&ŹcaRŽƒ3¤ý Ÿŕ|ŢÁ9X€pNŔ(€ŔL^=ƒ +X9Em3l]jHë˛ë‡`––~iŚOŃĽÍyYm̑—UŃyŘs&™Q…edy"yšýäʈžÝ=7u_—Ľ*ç-gOÓr†1—ę!’ŻűwT‘ŕPHB‚CiŮDF8¤Ş2 K‹(CR{ÜE"ĚŠ‹CjŔúŮ ‡Ô€§­q§JăÁí˘kAŔę şaşIí<č&`3˲’žƒĽ2ť9IđňjiĚËQ1#ě0—¨|Ŕ¨rT!}5] ţXY\ĆN2#ܒ¤Ľ) #2$&ő ›íĆĽă-ě([%cÚÎÝŤŰd„Ÿ,–1X,c^ ó3˘,fY`q>źŞBž°ŢI,~ƒ¤m}E$ÎĆLžŐ˙Ę­{Y˜É¨6T˜ŸŁ;’G°×éžzůëűzWÓ7żřŘYüÍŰNŔó6Ţż6>řă°‘šfź? lŘ;ŇxËȓ{ćń†ąuX;R_OŸ`ű,öÉă­(…îŔ˙dAŔó¤ó(~iNŔ~LŔ‡ß-¸G5ŃÄĂÓŤ‰Śî—§ń•1mĺ!QYC! Ľ`âMŢbř[( ŕCýۄ/BYcşQx=tś”1ŰÉJ8óţ_°T)I—Çr÷ Š4š{ŻŕBHĺGYľçŞDşmšeLäV”1QMĆDMR5IđŮFĽĺ.ڃrgű¨ő"5ĘşČW’$ŕ“'1–ç0-$ŕéO¨ Qä¤âń„Ęë–=Ą:đ?Í:ťů:‹\ËźÎ:,­łKë,Ă ’ űúUËÎ끤Ě0 ö2sŔ$Řé^ˆÂąd!=kjšyzÖ\Ă`@¸-˝X~ôç<=Ŕ9€8V ĂÓŢ Äń3RłČŒŽ…ĺuDý䡘ţÇ2ú~%ă+^ź°ú‹W"â‚3Ćv›žÁdxăîsɢ–ÓÂ@ŘíĹ+ľlîQ›€;V§{÷ŇŢč^×7şWŐůgD/łüvxÔ2—,žtⴘdŇ Ź98pąćëĆęt‰JĄşńpb†ôĚ'UIęáÇŹ‘/^ëĄcšÝ€Ç4ťŤŽ /^űmĚ—ßřn›JŔŐ§ľęÎ7M.fd$­łz†ŠeCZń}šwż ŚsEć˛Kuk@ŐOŚÂ­ž™Ü“”ą‚mžş•bŠ[YĖŔƒedďXŇýPĽ­ţŽ%3‚󕌉LĎ2ŁKÇlž•ąŰësŢö“sO$fî ŘËôKM°Ç̢°Č˘‘Úm~ĄŘęzÂ{)ޏţ撀V3š°Ŕ/"{ŢÝŁĽÝÝše˙dě×ôŽÖ1Ĺ Й¤˙4Ç÷ƒŮ(#ľ#"ű“‹ró˘˜äF9€Oč&Ľ6seśÓ%žđŠ-Ëń‘ÇŚA<ŞA™ˆ Ë4ĎpŚtäd<+ňŚÉœžŕuŁÄËŤYý$÷;.IœSÝ.IŒČĚ3řu­ń*†¤ĎBşŮvŢ@óE7Ź"üłLФ3óÚŐH Ďq2a ŢY•úËŢzˆŢXţS–ž•‰NL}ö2Ń%ŽîKš/Nk‚Č|š7NÖž‰œa¸ŮXGaŁŠŹPăQQ¨(‡)$U%éOˆLŇ—Š;I‡tڎó8YFˆć,"٧ŚUż6ΈßTC"%ëĆŐŽĘ Ż‹č.N;+ҲœŹ g$oÝ$ů=ÎE<ćÚî˝Učä/§‡žŢ>úTtűčça‰ąYąĆËKÝéŁ÷Ş_GÖuŸĄŰÇl ĺěcFçƂÇżSąŰËËŞŸa1óş´lÂäÉVˆÉ}ăčŢE™É_ďČQMŽë9ŽOĐCŃ6ŢZěňšY řđLŁ xÂw’şĎîţâšľpCVЃ(úŕi´pG-Śł¸]-€đŕ_š;žĽ‡Q\čÄł´t?ť]/ďÝąˆKw<)ĽîÍ#×yF۲ Ŕ?iĺ‹YćČÁs7GŚÓ|ýYpćČ!ˆP+ľ\=YgšŃćKł›¤t?˜Ÿ_¸l™f@ň0ľ%Ř>‚”űŹöF×2`᳑`ú^ÓgƒÇťĆi5ÁNÂtŀ'/Œ×2AZ:oŕśZŠ Xđ0ĆEmo&łÇwö=rÁ':Oěˆ/”1áٞ€QUHBˆł ‚ű`jůŒ@˜ëÖýŇ1+>žűŽD¸4ć𣵏#ZŽžó6Ÿ<ç­wž&—W!ŠŔLŘgŐ–űîOSÜQŤşÓnݏ*2z‚Afšyn2Íg„87Öľá`*ŘŻq6gMîöŢUż;˘0“ËŇî ąŸą÷rŁ[›AFş—Uˆ_˝v+˜eÂŕ™#ŤˇEÇHË˝ąŒÍŹŹkpAfD;*Â1?Ÿ‘ŚŐ{u+tľűbSQŽ™§Yađĺî˝ęÎŞşÔ“ŻÝ˜\7UŸ ó’x˘řŤâ†ÜŤ,#3Ý—PugX–…¤CÖcř%7Y—*b”oë’ůlȘMÖiŘsV‘{ó‚ß,8K%ψlËAÔű ށ,ö2Ťˇ%Řc¸öó˜Ă6Řé‚tXÉ€Q `Ýťo¸ V§ áh㽖iŮݐ:ŸŘq¸÷ŠˇĎ­ jËšč~ňL'‰đՋšpXŠ—Yf%LpďŒ}ě8ˆbNÚK€Œ‰Š|ň(Ë4#KŇ~Š˝)ö¨>’şŻ>ÂŹłŕanŮC‚™Ÿ űÜ}Í…f47bČÜ\;Źý<÷žš°ˆ_bs ŕ›K? ¤[Q]ęÖ͛4­>6kgŻSÂŘ?âR̂K;iÝÜqHiˇ ë3ÍČŹýŠĺ†×EE\ŃŽéěÉF™!ć:¸)“ű­–?ţŠÍ…ťW/LʂłäK‚Qt<ŃKě8܁tźŘ]•™\š`Çć˘:_ŕ%X•ÉU×lC˛R͇çţ@ń’EżŁşÉ‚ˆŹ‹hňŽTLҊźŕ—ЏâÝQˆßU-“Ě\{óâ%BŇŠŤţ3{s÷/—~ĹîÇĚĽÝîy¤óśă9:Ćv—#Ç Şy‚Őqńé2?r°’ŤŹă@n•€‚&Ăœ`Č×M´Ô㑚pœű,ߖ`Ĺˡ%`uˇĆbŠŮáęÎółÔNÄ”ŒšAڌéćS÷CCĄ1wźI´Ű˜H7ďŔ˙×%¤ M¸ š0;^â"F*`öçˇú+öŠěˇŇ¨Ě~ Z!NărÖ˛‚ő§ôŁęŕ~˜Znî~Č"ľRŕĚ~ŤkÂ_†ůĺ3_ć6ĚÝ-%iÄźř‘F˜i›çnŚm•ÁxšfÚNŔÍMŰ řVě}SDť’TÜ%HˆGš0!é8…!5ވŒčÜű63šąžyŞbȑvqŚĄŤÚň¸kHÝoşĐőb'EWŤžß7űÜEž,^]ć!ŕ čĎíý´äâŹuOr=UC,)ƒ„¤ ,ÍîŔŘ_p2¸}Ĺ췌šH؝^Ë)kÁ_ýđóOß>~z?˙ń1šÝ\:ΏžWľšœů †ËĘ,SÚöŮśĎ N ö4ă.6ňţ™Ḿás_áe‹'Ř2,'Xq$ řâUiÄÝË_Ś–O̔ZVŘč¸ĺî6şÔr8T)˘ćS\§ÇAقLž~mľX ičŔÎ]kˆq^„›ŔgšĂF%EÚ%Ś01-z'ŚEËÄ4Â3™FDNŚEËÄ4k玈žąŸŢé<Ń0l^o`?÷ű˜ĆKD¸LűAXu^ě9řćŔ3ŠŤ'` žE÷=ř-ÝŇl2LOŔN§'`Íeë°¨ü’`gĐMH&Ý|݄zŇc–ˇ‡‹ Řëţö}}ű.ˆŽňŕKț‚č yî=ë+b7OéŠXŚA+b‚ůŠ˜`ą0ĚWĀ!g*¨v`Zá'Ŕ+bŔbEtXF|˝ą"0}Ü1bú¸Łeú¸Łeú¸ ův´Lw´ô…nGĘŤiŸk{™SL°ÇœbŔb…ÝáÁ gc…Ýá(ÎŰRĆGŔXv÷’×Ů%ç4˛KN_hd—œanb.”‡Ď0GďLj’a<&&Ň$“Z†d˜–ÝÔ=–]ĄóPDąě ösżiźŹçm™K0_v,–ÝŚe7cŮMÝcŮM-}Ů݈Ëô̗Ýóe7`ąě&XŇ´&ş 󤛆œt0řxĐň?á‰Ö—œ˝]łx~ ˝€|Ŕö™[:`}݇Ľ‚۝Ă×<ÁĘĚՙ`/ÓR‘`a/ďĹçV‡Ă\ÓńÖE‘źŔţđʛDĄĽ*źĄ1Ÿ†Ô22ƒód̝>ľÜܝ>OźĐRËšą]|rG2ŁÍ“P I°Ź3“ćgĆtśá˜ZŽH也ptŕšo5EtÁˆ~4iŮ3pRwDů DVŹfX™QżoM‘&Ěí2Ít{’p{ŕx^ޕŸkTŕî(řĹLśL‡Ě:Ťí%ġáýÇ"î×ď˛Ý€MˆĚQ2÷ëőŽ~Óć1­Ź(“TP&?FĽGY/1lđM”śym/é^DîăN1ÖOó:á/–€Ďxő]U“ËmEÚđŔKt"ńTšŤMiĂđÁrďžůŤ~qĺژΞŚÜxšĽŐ1J؛żú˛4+ęHwŘŕ™ufƒgqÔ"ŘÔśĄäÖĽ3Şőĺ˘îEËŸ‚đ„ažżâ扅$xeą4-‹ŁćiĄŻÓ—h2˛Qí÷…Ú\űyý´âšH\aCÂ<ÁęȉŘëz2 ĽW6ޤĂB`Ż4î°a„G1VĎ*Gߨ4°ŐŤŠS_Ť*N8fUńhxFUńńň8˙|ÂărŻp&Ŕʓ†­Ľé˘ĺ†g蓺ď‚+Ý‚ËBX­8\‹'ś–1­\+Œđ„Á˙‚}lęČ>ÁběŰęră'ޕR÷Տ´B<ޕ„ɸ? öśą"LOC҄ń.@śŽwůKtklČĹ ™UĹŃ#jsv3´'ěWT'â͇DePŇĽYžœÇ´ňĺLŽ‚¨Âşń pąŒ`§×ľpóĐ<łť8T“ű9ƒgÔŕÁÎüÜqθ”ÎîŹNüœĺ˙Ÿ ŽdźÚŹp$ăő3AěóœŃT—Ę.ˆ٧‚[á—Î:y¸ŸżŢ üŔł9ŹÔé°ą'đ€˜d+Ňç°ç‰Äíćná@<í˘q´\˝¸’´ÄiEĆ\ы_^đáaGiĚâŽHiŽ~=ö#˝ÎĐG‡Ý•¸ŠžSlţÂK“v(j”Ć+ĂqžŢÝóápž|7ĽfľúŠź'ŕOH!ˆŹţt “Ş3:™řŻÉŘw íeě XděKíŠK3`ë0-t>ě1ÜîúĘB0„F0^„Ň&źiRńŘŢáđ€Ĺó¤!Ăű;+źż™ČŐÝ;*HK{7wc–°-°Ö Ç[ŘO,Šźp´Ůˆ! |ńˆ!3ŻŃMś=4â¸áXŔî.ŔcÎS éÁ<Ĺń˝–OórĎVóړîEą7÷ ’€ZYÝpŚ ¨™!ć $‚f„"؇a&?€šŹşA°_•鄃ž|€x›?˜¤˝ĆNN\ęƁMšÔĂÎNý¸J‘Á%ü:WŻeĹü´ZV řƒ›2˜÷7łŽŘŽÁ-í˘-Ÿ<ěLft4VĹáĽ~‡tA?qfęw´F9ojYmˇ&ěćßÇÝťm§9üűv–\ůţ´‡K8ŇľńÜkMÝQ‰…eÔK+,MDÜÍ<÷¤d⟐ `šÍýĐďh‡Ó1ő¸W‘Śš™ßöKŔĘ`őX˝­cˇRX čś÷Łů9Çsl”óv ÉŞS_/ɘ`çŒvbř0Ë Xt<$ŤNx7ĎéĚö܀ë&˝ű1çP4˜€-NŽ†ížŕVĆÄťFjYa3¸M|ELƒŒYW™ú§¤FgPŰCyLŰCű.$mVŻáJˆţÔKŔîŻË'ÎÔó;Ž, Ö_—Ç­<Áöan:¨ÝÓ4-Ě*A] ö5Ń{'25Rô^‚yô^‚yô^‚ŐŠĎ;˝VHjˇÎʰŠÝ9VSť ćŽâ~yKž^@$ iyś*󳴖ĚHHVŔaFB%{Ął)?+2'˘ Ő%´!ĽOłGďU咕ąâiög ’úLáĆ$5Żš&ÝË)2zˆˆGŘÄ*2ú“ϝ$¤&a.YôžĐ‰Ľ2ÍSž äV(éŢvQĹÍĎo ¸{R!é]‚yFąŹ;Ď!}Ë}îýh=DÄÝá’[>đ TTmúIŻéˇ^ęvWďR›¨w%†wůĄNĆDnfó8î2˛ Ź!a[2&L(ÂĽk{ƒ!¸Bň˛dĎ@Œ˝(ĺď˝ynf&žÂŽž€ĎxńaĽ˝üq'<îlşŹőǝM—m;Ş vÍKÝ/<îëşíÓNeĚ%;•ɘČâĚœŻ§ŞĘn‹@˝śű"PŻýžěHBÉşd;"ç‹v˜€mł –Ŕ°":Ě|Ş:×öđ-8úÖi›K0”!ŘŘŮƃ‡¤ Œ×ň&ŕ“g ŞlŻ<•˝Â2AŔšłáŘŮ.Ą|ó¤OŇ抄ýôĐÁÔ˝ŔščPŽ­x]LŔÄĽ3YP ’+ű‡„’ŇUśđŁgrHŔĂ„$$g†Xč Ë܂ՙιݝO˜€—çdâíՄIęń„Ź!<“ÇłG=YCĆ.´Â2•8Zv’ŕI$-O™ćiĽˇ™!;‹¸3äZŢó‡qł?<0?Ÿü!+B ˛&KXć5ţ„Ćt8Đ›Şeáaméž§˛ążaÜäŐŁŞŞzß9łś|ů~<ě§,+Ź"ŹsOg(D žHIđdm˝ívYAdť*1Ť.ŠhřQœ÷% â›?-+ŕşVÝdÍGâĂʈŞ^…q”Ó†%łnnľÜ}Ic…ě‰Kć2!3:tŞ(ƒŔßۂ^w’–CHBŠDAté:ű„Ú’7qŘŽşŸ); Be6ę €í+đT^níđůĆxÇĚ˝Ç8=3`㞈ĺ„Ćk8YEßŐw߀=ůî˰Ęsö°0Ú]Ó 1ÁŠ×Z`˘WSÓ>Ü݂ŃXjFéŽd~ ¸y2żü€GĆžcë^Ľł\,ŹY8ëĚÂÖ}˛hĆcžMw‹=wŻ/pˇ¨‹"˛cbÔŕYąÝˆ?•$ób$éÂaąˆ ]ž @f„Ř^AdŞ3zň ą§’&[l˘ ˛ŁC´|Ć-g´âBÎßć… JMŐĆr&3"˙̫Mľë sśŒ‰Ü_Źó=ćlS]˛ւE܄¤]ô˜Š´˘ÖRSýʇ~2éAş4´ř[f!Š1IÝBŘS÷ĆߞŔˇ/>ËűOż{÷O˙üzýôřüüáÓoß˝ţëŠ˙ů—wß|z˙ýďQĂ :ó9~˝*`OźŔÁĺţťÎ$ÂŻ§ŰĎďżů‰FCćĎńŤćŢoüŢ~i4s†řœ~ž >úż (Ű/ĎžĎégĄŢŹż4bż<Ľ)÷Ÿ4Ç7ż8뾄-iDÜtŇo–_ńXÇqׅźÎ9MŠŢŁĂ/ŒÇ0ąŒ5* pŹ–Š:řŐéŤ÷e{Ÿ˙~ąö×qjűœ~Bż'Ůo0ąßǘJ}ÄcJ{pŒżÄ‡ÝĎé'‰˙MŔ/ęÉŘ/‰i€;`tPé˝űŐŻţîĂ7üéáß=~z÷Ó§WŔo~řůűçoż˙ć7?üű_źž_ßcĐޡ­źűôŰ~÷ăkű×Vł řôÚr}÷řţůő÷_˙đôóż>ž˙ü?˙řăwß>ž˙ţń釟zęm^˙ëßüďż}÷˙Âe҉4ascd-0.13.2.orig/ascd/doc/0040755000175000017500000000000006764325354014463 5ustar hallonhallonascd-0.13.2.orig/ascd/doc/CHANGES0100644000175000017500000005002506764325260015451 0ustar hallonhallon===================================================================== AScd Change Log ===================================================================== ------------- 09/05/99: - updated to latest libworkman snapshot (1.4.2, 99/06/20) - Themes doc updated ------------- 07/05/99: - added panel_stop and panel_play options to Theme file format. ------------- 06/22/99: - [fix] the track number is no longer drawn on every panel. - [fix] the mute function called the fade-in one! ------------- 06/16/99: - updated to latest libworkman snapshot (1.4.2, 99/05/29) ------------- 06/03/99: - [fix] small redraw bugs that could cause "flashy" screen updates - [fix] fade in/out mode was broken in previous 0.13.X. ------------- 05/25/99: - new pixmap sliders. Currently only direct_access and volume are implemented, and only horizontal ones. ------------- 05/24/99: - [fix] th_icon_window was not correctly set in fak_init_theme() ------------- 05/19/99: - [fix] %s instead of %d in -debug theme summary - added a -debug level ------------- 05/19/99: 0.13.1 - code cleanup - a few changes in Imakefile - more messages in -debug mode - a couple of fixes ------------- 05/17/99: 0.13 *** beta stage *** - [fix] horizontal volume bar bug ------------- 05/16/99: - added "quick ref" support with quick_ref command and a button in the WINGs main window ------------- 05/16/99: - added support for vertical sliders (CD direct access, volume and mixer) via vprogress_bar, vvolume_bar and vmixer_bar. - added support for inverted vertical sliders via iprogress_bar, ivolume_bar and imixer_bar. - mixer support (FreeBSD and Linux only. Please send me a mail if you compile mixer support on other platforms.) - added -mixer commandline option to specify the mixer device - themes manual updated - man page updated - reorganized the WINGs src files ------------- 05/13/99: - [fix] Track name was not shown for track #1 ------------- 05/11/99: - better database support: CD default volume and CD autoplay are handled (CD autoplay if for WorkMan, AScd ignores this parameter) - better WINGs handling. The WINGs window is no longer closed by the program when CD is ejected. - [fix] WINGs windows crashed when CD was stopped - [fix] big bug in database code that oftent crashed the program at startup time (cd_curtrack = -1) - [fix] bug in the song title scrolling (hardcoded length) ------------- 05/11/99: 0.13pr6 - small updates in the man page (so outdated...) - the theme manual (in PostScript) is now in the archive and installed in /usr/local/share/AScd - added alt pixmap support for eject command - added database panel which can now be different from message one - changed the themes loading mechanism: themes are now installed in /usr/local/share/AScd/Themes. There's also a Default/ dir that can contain pixmaps. If a pixmap is not found in the theme dir, AScd also search in the Default dir. By default, this dir contains digits.xpm and digits2.xpm. - the theme selectors now use dirent instead of the '.dir' file - added alt pixmap support for mute command ------------- 05/10/99: 0.13pr5 - [fix] Less "floating point errors" should happen (I hope) - [fix] the "°" in the counter was not drawn at the right place - added icon keyword for a premilinary separate window/icon window handling. See sample themes! - added no_icon_window and icon_window prologues keywords to use with big window themes (that cannot fit in the icon window) - added volume slider handle with "volume" command - [fix] bug in direct access bar handling ------------- 05/10/99: 0.13pr4 - [fix] string truncate when its length > message panel width - added comment keyword in Theme files ------------- 05/09/99: 0.13pr3 New features and fixes since 0.12.1: - |fix] ./configure didn't work when using an alt pixmap path - [fix] a STOP order is sent to drive at the CD end (!autorepeat) - changed the global redraw time offsets - support for 8bit fonts - added a line if WINGs "about" window - added autoprobe mode, activated by default (+/-p cl option) - [fix] crash at CD end on Linux systems 0.13 fixes and additions: - added a second debug level - the redraw routine has been redesigned. Screen updates should be less 'flashy' now...! ------------- 05/08/99: 0.13pr2 New features and fixes since 0.12.1: - a few arrangements in the WINGs windows layout - added a timeout for the theme and fast track selectors - the fast track selector now scrolls the song titles - support for loop clear and loop CD from start to current track - mut be linked to 990505 LibWorkMan snapshot - [fix] cd_control updated to 1.4 (added security in direct track) - [fix] there was a bug in the cd_volume() calls in mute feature - [fix] the messages now have priority on track title scrolling 0.13 fixes and additions: - the buttons containing no command are no longuer parsed in case of mouse events - support for introscan - support for fade in/out - support for theme selector - support for fast track selector - support for mute - WINGs module works again, but the visual theme selector crashes :( ------------- 05/07/99: 0.13pr1 **** BACK TO ALPHA STAGE **** It's the biggest change since I begun working on ascd. Everything that appears on the screen is now 100% configurable. Put the buttons you want, where you want! - major rewrite of AScd. The source code has been splitted in several smaller C files. - [bug] the WINGs support shall *not* compile. I didn't have time to update this code with the new features. - added -debug cl option All of the CD player commands are not yet available. Check the next pre-releases. ------------- 05/06/99: - [fix] redraw problem at CD's end when autorepeat is on. - [fix] redraw problem when selecting "PLAY" with a stopped CD. ===================================================================== ------------- 05/02/99: 0.12.1 - [fix WINGs] the themes popup didn't display the selected theme - multiple-mask shape mode, to allow transparent background with non rectangular buttons - added a theme selector in the main window, activated by right clicking on the message line - [fix] when a theme is not found, ascd try to use the default one instead of crashing. ------------- 04/19/99: 0.12.0 RELEASE - added runtime visual themes management, with -theme cl option - added a popup menu in configuration window to change the visual theme *without* restarting the program - [fix] there was a bug in the mouse routine that could eject CD if the mouse click was outside the buttons - [fix] a couple of typos in the WINGs windows. ===================================================================== ------------- 04/17/99: 0.11.2 - the volume is no longer set to the maximum at startup. AScd now uses libworkman to read the initial volume. - [fix] clicking on "play" when CD was ejected crashed the program. - [fix] changed the WMCreateButton calls (didn't compile with rh 5.2) - added an #undef OSS_SUPPORT in libworkman's plat_linux.c - again, small changes in libworkman's Config ------------- 04/15/99: "Le Chien" - added "+/-ia" CL option to ignore avoid tags in WorkMan's database - added a button in WINGs window to control this parameter - cdcontrol updated to 1.3 release, with a few cleanups - added "+/-up" CL option to force uppercase messages - added a button in WINGs window to control this parameter - removed the "counter" popup, replaced by radio buttons ------------- 04/14/99: 0.11.1 - added lowercase letters in (r)digits.xpm. I had to make a few changes in the background pixmap to display the new letters. I also added a conversion that remove accents. - added 2 buttons in WINGs window to switch on/off song name and artist scrolling in main window. - added a field to edit the cd device in WINGs window - [fix] with a songname <= 8 cars, the artist was not shown - [fix?] autorepeat ------------- 04/13/99: 0.11.0 RELEASE - song title (and CD artist) display with scrolling - added -showtitle and -showartist command line options - in ejected mode, the "eject" button is replaced by the "quit" one - [fix] redraw problems with panel switching when CD is ejected - [cdcontrol] fix with track n# after eject/load - AScd now supports WorkMan's "avoid track" parameter. It has a better handling than XfAScd: try it with Prince's "New Power Soul", when you have to skip tracks 11 to 48... - the database edition fixed (didn't save!!!) ===================================================================== ------------- 04/12/99: - added the "fast track selector" by clicking on the track number when playing. Click play button to play selected track. - cdcontrol updated to version 1.2, fixing a bug in autoplay. - [fix] event handling should be smoother (especialy mouse clicks) ------------- 04/10/99: "Human Being" Well... Once again, the screen layout was redesigned. And the mixer is gone again! ------------- 03/30/99: - added -xf command line option - first attempt to add database editing. Ugly! ------------- 03/19/99: (known as 0.10.1 RELEASE) - added misc/default script to generate a default config.h file without asking any question. ===================================================================== ------------- 03/17/99: 0.10.0 RELEASE - switched to current LibWorkMan, which is no longuer included in the archive. - added a lot of settings in the WINGs window - added a configure script - updated cdcontrol to 1.0pre1 - changed the pixmaps selection - code cleanup - [fix] foreground color saving was buggy! - [fix] the muted volume was not saved - [fix] crashed at startup with no cd (WINGs option only) ===================================================================== ------------- 03/16/99: 0.9.4 - added the optionnal WINGs window with WorkMan database display, volume setting and autoplay/repeat switches. Still very experimental! - the timer handling was redesigned and should be more efficient. - added fade in/out functions (right button on play) - better volume control, the min/max/current volume can be loaded and saved (~/.ascdrc) - "-save" commandline option ------------- 03/01/99: - "blind mode": in this mode, once a CD is started, AScd never updates the counter and never check the drive status. - changed the idle timeout to 500 ms (as in future 1.0.) ------------- 02/26/99: 0.9.3 - [fix] autoplay fixes ("-1" track number at startup) (1.0 tree fix) - [fix] pressing "eject" when the CD was already ejected crashed the program (1.0 tree fix) ------------- 02/10/99: 0.9.2 "p control" * All: - changed a few things in the Imakefiles. The "Config" file is now replaced by config.h, wish should be a little more simplier - [fix] a few typos in docs, man page and program. * Ascd: - added the -mdevice command line option to specify the mixer device. - the mixer_device is now saved/loaded in ~/.ascdrc - [fix] if LEDs colors where defined in ~/.ascd, the commandline -bg and -fg didn't work -> "not enough color cells" - [fix] when paused, selecting first or last track didn't work - in mixer mode, the "track nbr" now displays the value for the current mixer slider - added an alternate pixmap set, "fusion", which can be set in the config.h file. - man page updated ------------- 01/28/99: 0.9.1 "Late at night" * Ascd: - [fix] 0.9 didn't compile if NO_D_DEVICE was defined. Thanks to Gus Hartmann who found the bug. - [fix] 0.9 entered a crazy loop at CD end when autorepeat was off. ------------- 01/27/99: 0.9 RELEASE * Ascd: - code cleanup. ------------- 01/26/99: PR5 "If U need a fix..." * Ascd: - [fix] ascd crashed on launch with no cd in tray (since 01/22) - [fix] up/down buttons didn't work when paused (since 01/22) - [fix] track nbr was not properly redrawn when using up/down buttons when stopped (since 01/21) - [fix] window was not properly redrawn when stopped (since 0.8-R) - [fix] it was not possible to access the last track when stopped - [fix] autorepeat works again (and fastly than in 0.8) - the time display mode is now saved in ~/.ascdrc * Lib: - [BIG FIX] ascd now ejects CDs under FreeBSD. And there should be no more device locking (it was necessary to quit ascd to eject the CD and/or to mount a cdrom). Think this works with NetBSD too. (bug found in 0.4+, 0.6+, 0.7 & 0.8) ------------- 01/25/99: PR4 "If U need a mix..." * Ascd: - 100% new mixer section, with access to all the 17 mixing "sliders" of OSS. - the back and foreground colors may now be different for the CD player and the mixer. - all the mixer settings can be saved in a ~/.ascdrc file. This file can be loaded at startup. - Total rewrite of the command line parse function. Added several new commands. See ascd -help for further details. * Lib: - [fix] I forgot to add the plat_openbsd.c in the Imakefile! - added an option in the Config file to compile libworkman as a shared lib. Tested with FreeBSD 2.2. ------------- 01/22/99: PR3 "The Bug Factory" * Ascd: - Almost total rewrite of cd_control() function. The code should be more reliable (I hope!). Some clean-ups two. - no more uses old ascd variables (currenttrack, maxtracks, playing, paused). Only the WorkMan ones (cur_track, cur_ntracks, cur_cdmode) are used. - on launch, if autoplay is disabled, the track nbr panel displays how tracks are on the CD instead of "01". - when the time panel displays the global remaining time of the CD, the track nbr panel displays the number of remaining tracks. - new alpha pixmaps. - adjusted timing for checking inserted CD in autoplay mode. - Middle click on the display switch the mute mode. Muted/Unmuted volumes can be set with 'm' and 'v' command line parameters. - [fix] in autoplay mode, launching ascd with an inserted audio CD in drive didn't play this one automatically. ------------- 01/21/99: PR2 * Ascd: - The mixer code was removed once again, due to the big XPM code changes. - XPM code redesigned: each button has its own XPM file. ------------- 01/14/99: * Lib: - added O_RDONLY | O_NONBLOCK flagsto the cd_device opening function in plat_linux.c and plat_freebsd.c. Thanks to Jens Axboe (axboe@image.dk) ------------- 12/20/98: PR1 * Lib: - using WorkMan 1.3b (BETA) code instead of WorkMan 1.3a - patched plat_freebsd.c to compile under FreeBSD 3.0. Thanks to Stephane Marzloff (secrer@le-bar.fdn.fr) - plat_openbsd.c added (WorkMan) ===================================================================== ------------- 12/18/98: 0.8 RELEASE * Lib: - added plat_aix.c in lib dir. Thanks to Erik O'Shaughnessy (eriko@austin.ibm.com) who wrote this driver and sent it to me. * Ascd: - Pixmaps are back to 48x48 pixel size - Small fixes in buttons pixmaps ; new digits pixmaps - right click on STOP button kills app. - mixer section is back again! - man page updated. ------------- 12/07/98: * Lib: - srcs moved into subdirs, as PR1->PR4. - Imakefiles are now working on Solaris. Makefile.solaris removed. - WorkMan code is compiled as a library. * Ascd: - ascd now works with Solaris 7 i386 (gcc). ------------- 11/29/98: - lib should now compile on Solaris 7 with gcc, using a specific Makefile. - added NO_D_DEVICE option for Solaris Volume Manager. ------------- 12/01/97: * Lib: - [fix] it was impossible to play an inserted CD if autoplay mode was disabled. ------------- 09/25/97 -> 11/25/97: * Lib: - 'Config' file where all compilation options can be changed. can be changed. - now recognize WorkMan splited tracks. Try it with Prince's Lovesexy's album !! * Ascd: - ascd now includes asmixer! - added a "mixer screen" based on asmixer 0.5: clic on time display with right button to switch to it. - added -v, -1, -2, -3 command line parameters for the mixer screen (same as asmixer). Removed the old -v option. - setvol() and setvol_command() from asmixer src merged. - added -t command line parameter: autorepeat - stopped CD's display CD Length - added "-b" command line option to specify the LEDs background color. - changed "-l" option to "-f" ([F]oreground color) - when CD is ejected, track nbr shows "--". - all the XPMs are now included in ascd.c, to allow to define the bg color. I also fixed a few things in the "old and quick made" ascd+ buttons. - when global time is displayed, clicking on the progress bar give access to the whole disk. - added a "#define VERSION" in ascd.c - added the new options (since 0.7) in the man page ===================================================================== 09/04/97: 0.7 release (denis) based on 0.4+, but with the WindowMaker specific code taken from ascd 0.6 - added: "-v" command line option to specify the volume to set when right-clicking on the time display. - added: the time display now show a "-" before the remaining time(s) and a "o" if it displays the CD ellapsed/remaining time. - added: folding tags in the ascd.c for the jed editor - added: "-l" command line option to change the LEDs colour - added: clicking on the "DOWN" button restart the track ; another click plays the previous track, like on a diskman (from Rob's ascd 0.6) - fixed: redisplay of the XPMs was buggy with 0.4+ (but worked with afterstep... this fix is primary for WM) - fixed: when autoplay is off, ascd doesn't scan the CD drive until you click on a button. No more thousands of "cannot read audio disk" in the FreeBSD logs :) (but there's still the problem with the "-a" option) ===================================================================== v0.6 - Most important: WindowMaker Dock support with the -w flag! ===================================================================== 03/25/97: 0.4+ release (denis) this is a bug-fixes release. - fix: when first launch and if there was no CD in drive, a click on the play button crashed the program. - fixed a "floating point exception" when the track progress bar is clicked on the very top. - changed the "0.4" to "0.4+" for the "-h" option. ===================================================================== 03/23-24/97: 0.4+ release (denis) Based on Rob Malda's ascd 0.4. All the Workbone Code has been removed. I use the Workman source code: ascd can be compiled on several systems with several kinds of CD players, but tests have been made only on FreeBSD 2.2.X (i386) and Linux 2.X (i386) with IDE drives. Should work with SCSI drives too. (note: I removed the Workman database code) - Imakefile has been updated for the Workman code. - added: several new features (loops, introscan, progress bar...) (see the README file) - changed the XPM files for the new buttons and the progress bar. - added: 4th digit for songs longer than 10 minutes. - added: -a command line option. Activates the autoplay mode: ascd automatically plays the CD when it is inserted. - added: -c command line option which sets the value, in seconds, for the intro scan mode and the cue/review function. - changed the indentation in the source code with the auto- indentation in jed. Sorry ;-) - when a DATA CDROM is inserted, the display now show "--:--". - a few fixes in ascd.c - the default device is now /dev/cdrom. ===================================================================== v0.4 - 1.15.96 - Thanks olly again (Does this guy sleep?) We have a few very nice bug fixes, and a nice new feature. - ascd now stops correctly at the end of a CD. - 'Next Track' used to go to far - When ascd is paused, the LED now blinks! - v0.4's secret code word is LLAMA BAIT ===================================================================== v0.3 - 1.13.96 - Thanks to olly@muscat.co.uk, if a CD is playing when ascd launches, it detects this and starts following it. - Thanks to the 9,000 of you who e-mailed me fixes (thanks guys, its nice to know people use this crap!) a Data CD will not crash ascd. - About 15 people sent in CHEEZ DOODLE's to me. Thanks. The code word for v0.3 is ORANGE NIPPLE. ===================================================================== v0.2 - Fixed Certain Neat Error Messages - I Think it should now get the last track from CD's. - It shouldn't *lock* the CD Player from other devices once you press the 'stop' button. This is especially useful with ascdc. - Now includes the correct README file. Thanks to the Hundreds of you who caught that. It's nice to know someone reads these files. ascd-0.13.2.orig/ascd/doc/NEWS0100644000175000017500000001262106720054466015154 0ustar hallonhallonNew features in ascd 0.13-beta: =============================== (it is a big big big release, as I had to redesign or rewrite nearly everything in the soft except the CD control functions. So, I'm considering this code as beta stage one.) * Visual Themes: Visual themes are now 100% configurable. A theme consist in a description file and various pixmaps. You can place any screen element anywhere in the window and the icon. Available screen elements: - pixmaps - counter - track number - message area - database display area - direct access horizontal, vertical and inverted vertical bars - hardware volume horizontal, vertical and inverted vertical bars - mixer control horizontal, vertical and inverted vertical bars For each element, you specify the *command* to use for the three mouse buttons. AScd provides commands to control the general options, the CD player and the mixer. AScd is no longer restricted to a "dockable" size. More: In -w mode, it's now possible to have different screen layouts for the main window and the icon one * Mixer support is back (FreeBSD and Linux are the only supported platforms) * New documentation (PostScript) about making new themes * LibWorkman updated to 990505, with early CDDB support (but it is *not* yet supported by AScd) * database support has been enhanced * Quick Reference gif files support with an external viewer (xv by default) * the font used in messages and database is now 8bit compatible, thanks to Stefan Zeiger who made an excellent 8bit new font * added -debug support, which could help when making/debugging new themes * Speed improvment for a few features (fast track selector for instance) * Better messages hierarchy * CD control updated to 1.4 with a few fixes * ascd.c has been splitted in several modules New features in ascd 0.12: ========================== * visual theme support!!! With the WINGs configuration window, it is possible to switch between themes without restarting ascd. New features in ascd 0.11.X: ============================ * another brand new look, with a lot of enhancements * the mixer was removed once again * better volume handling * size set to 56x56 as it's ok with AfterStep's Wharf * CD control updated to 1.2 with several fixes * database editing (ALPHA!) in optional WINGs module * AScd can show and scroll CD artist and track title * a few commandline options to control this feature * Added a commandline option to launch Xfascd * The "avoid track" WorkMan's parameter is handled * fast track access when playing by left/right clicking on the track number * a lot of enhancements in the configuration window * fixes, as usual New features in ascd 0.10: ========================== * Using LibWorkMan 99/03/07 * New configure script * CD control updated to 1.0pre1 * Enhanced WINGs module * fixes 0.9.4: ====== * optionnal config window using WINGs (WindowMaker) toolkit. * fade in/out * blind mode * volume settings are now saved in ~/.ascdrc * -save commandline option New features in ascd 0.9.1,2 and 3: =================================== * 0.9.3 is a bug-fixes only * fixes, fixes and fixes! * alternate pixmaps set which be set in the config file * mixer device can be changed with a command line option and is stored in ~/.ascdrc * in mixer mode, the track nbr displays the current mixer setting. * full mixer section added to man page. New features in ascd 0.9: ========================= * Lib code updated to WorkMan 1.3b with: - plat_linux.c patched for glib systems - plat_openbsd.c added * Added an option in Config to compile libworkman as a shared library (this works with ascd 0.8 too) * plat_freebsd.c patched for FreeBSD 3.0-STABLE and hacked: Eject now works and there're no more device locking! * REWRITE of the pixmap routines: there are now one pixmap per button, and several pixmaps are new. * REWRITE of the CD control routine, which is now in a separate src file. * REWRITE from scratch of the mixer. * REWRITE of the command line parsing function. Added a few new options. See the man page or type ascd -help. * ascd can save and load its settings in ~/.ascdrc file. It is also possible to save the 17 mixer settings in this file. The .ascdrc settings can be overidden with the commandline options. * added drive volume control with a "mute" switch (values can be changed with commandline options). Note that mute function controls the CD Drive Volume, and is independant from the mixer module. * The LED colors can be changed for the mixer (Config file, commandline & ~/.ascdrc) * Autoplay and autorepeat modes redesigned. They should ok now. (still a few little problems with autoplay detecting) * a lot of fixes, including redraw problems found in 0.7 & 0.8. New features in ascd 0.8: ========================= * 'Config' file to specify compilation time default values * Hardware code (WorkMan) updated and compiled as a lib * Compilation on Solaris 7 i386 with gcc * Compilation on AIX (Thanks to Erik O'Shaughnessy) * Optional Mixer module (similar to asmixer) * New pixmaps, size changed from 56x56 to 48x48 * Text messages displaying mode changes * LEDs colors can be changed from the commandline * several fixes * updated man page * french translation for docs * direct access to every part of the CD with a single click! * right clic on "stop" button end the application ========================================================================== See CHANGES for details. Denis. ascd-0.13.2.orig/ascd/misc/0040755000175000017500000000000006726774714014657 5ustar hallonhallonascd-0.13.2.orig/ascd/misc/default0100755000175000017500000000027506706663421016220 0ustar hallonhallon#!/bin/sh # This generates a default configuration file without # asking any question cp -f misc/config.h.default config.h cp -f misc/dirs.h.default dirs.h cat version.h >> config.h xmkmf ascd-0.13.2.orig/ascd/misc/config.h.default0100644000175000017500000000024206706663355017707 0ustar hallonhallon#define PACKAGE "ascd" #define DEFAULT_COLOR "#2FAFAF" #define DEFAULT_BGCOLOR "#000000" #define DEFAULTDEVICE "/dev/cdrom" #define THDIR "/usr/local/share/AScd" ascd-0.13.2.orig/ascd/misc/dirs.h.default0100644000175000017500000000015006706663274017401 0ustar hallonhallon#define CBINDIR /usr/local/bin #define CMANDIR /usr/local/man/man1 #define CTHDIR /usr/local/share/AScd ascd-0.13.2.orig/ascd/ascd.c0100644000175000017500000005403306740162113014760 0ustar hallonhallon/* =========================================================================== * AScd: the AfterStep and WindowMaker CD player * ascd.c: main source * =========================================================================== * Copyright (c) 1999 Denis Bourez and Rob Malda. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Denis Bourez & Rob Malda * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY DENIS BOUREZ AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL DENIS BOUREZ, ROB MALDA OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * =========================================================================== */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "ascd.h" #include "faktory_prot.h" #include XpmIcon alphaXPM; XpmIcon ralphaXPM; XpmIcon backXPM; XpmIcon iconXPM; /* External functions */ extern time(); extern open(); extern cd_control(int); extern cd_control_version(); /* the various switches: */ int debug = FALSE; /* verbose mode */ unsigned int autoplay = 0; /* if set, play a disk when it is inserted -> see -a c.l. option */ unsigned int autoprobe = TRUE; /* probe the drive, but do not play (autoplay) */ unsigned int intro_mode = 0; /* play only the beginning of the tracks */ unsigned int autorepeat = FALSE; /* zzzzzzzzzzzzz */ unsigned int blind_mode = FALSE; /* no counter updates = no drive LED flashes */ unsigned int loop_mode = 0; /* loop from loop_1 to loop_2 */ unsigned int loop_start_track = 0; /* track of the beggining of the loop */ unsigned int loop_end_track =0; /* track of the end of the loop */ unsigned int loop_1 = 0; /* pos. 1 */ unsigned int loop_2 = 0; /* pos. 2 */ unsigned int show_db = FALSE; /* do we have to scroll song names? */ unsigned int show_artist = FALSE; /* if show_db, do you append artist name? */ unsigned int show_db_pos = 0; /* internal, used for the song name scrolling */ unsigned int show_icon_db_pos = 0; /* internal, used for the song name scrolling */ unsigned int force_upper = FALSE; /* all messages must be in uppercase */ int ignore_avoid = FALSE; /* if set, we play *all* tracks, ignoring 'avoid' tags in database */ unsigned int fast_track = 0; /* the fast track select method */ unsigned int xflaunch = FALSE; /* do we launch xfascd when right click on the display? */ unsigned int time_mode = 0; /* display mode for the counter. see function RedrawWindow() */ unsigned int cue_time = 10; /* nbr of seconds for cue -> see -c command line option */ /* internals */ int lasttime = -1; extern char *cd_device; /* the hardware device pointing to the CD ROM player */ unsigned int datatrack = 0; /* is the current track a data track ? */ unsigned int direct_access = 0; /* pos. to reach with the ruler */ unsigned int direct_track = 0; /* if we want to go directly to another track */ unsigned int wanna_play = FALSE; unsigned int do_autorepeat = FALSE; int wanted_track = 0; unsigned int old_track = 0; unsigned int anomalie = 0; /* cd_control return value */ /* let's talk about X... */ Display *Disp; Window Root; Window Iconwin; Window Win; char *Geometry = 0; char device[128]=DEFAULTDEVICE; char xv[128]; int withdrawn=FALSE; GC WinGC; int CarrierOn = FALSE; int screen; /* everything dealing with the hardware volume: */ int volume = MAX_VOL ; /* CD volume */ int muted_volume = 0; /* CD volume in muted mode */ int unmuted_volume = MAX_VOL; /* CD volume to restore when leaving muted mode */ unsigned int muted = FALSE; /* is the CD muted? */ unsigned int fade_out = FALSE; /* do you have to start a fade in/out? */ unsigned int fade_step = 5; /* the fading speed */ unsigned int fade_ok = 0; /* can't remember. sorry!!!! */ extern int min_volume,max_volume; /* from LibWorkMan */ int cur_balance = 10; /* ? */ char led_text[9]; /* the 'help' messages */ unsigned int text_timeout = 1; /* messages timemout in seconds */ long text_start = 0; /* timeout */ /* misc, have to add explanations here...! */ int selectors_timeout = 0; int redraw = TRUE; int has_clicked = FALSE; int info_modified = 0; int big_spaces = 0; int slow_down = 0; /* ==================================================================== Faktory: theme subsystem ==================================================================== */ char theme[FAK_CMAX]; char selected_theme[FAK_CMAX]; unsigned int theme_select = 0; unsigned int theme_select_nbr = 0; unsigned int panel = 1; /* current panel */ unsigned int panels = 0; /* how many panels? */ unsigned int but_max = 0; /* how many buttons? */ unsigned int but_msg = 0; /* which one is the message zone? */ unsigned int but_counter = 0; /* which one is the counter? */ unsigned int but_tracknbr = 0; /* which one is the track number? */ unsigned int but_db = 0; /* which one is the database zone? */ unsigned int icon_msg = 0; unsigned int icon_counter = 0; unsigned int icon_tracknbr = 0; unsigned int but_current = 0; /* last selected button */ unsigned int panel_stop = 0; /* autoswitch to this panel on stop/eject */ unsigned int panel_play = 0; /* autoswitch to this panel on play */ char th_name[FAK_CMAX]; char th_author[FAK_CMAX]; char th_release[FAK_CMAX]; char th_email[FAK_CMAX]; char th_url[FAK_CMAX]; char th_comment[FAK_CMAX]; char th_alpha1[FAK_CMAX]; char th_alpha2[FAK_CMAX]; char th_background[FAK_CMAX]; char th_icon_window[FAK_CMAX]; int th_no_minus = FALSE; int th_no_icon_window = FALSE; struct fak_button thdata[FAK_BMAX]; /*****************************************************************************/ /* ==================================================================== The optional modules globals: ==================================================================== */ #ifdef WMK #include "wings_global.c" #endif #ifdef MIXER #include "mixer_global.c" #endif /*****************************************************************************/ void mouse_events(XEvent Event) { int i; int j; int do_it = TRUE; for (i=1 ; i <= but_max ; i++) { if ((thdata[i].panel == panel) || (thdata[i].panel == 0)) { if (strlen(thdata[i].xpm_file) > 0) { if ((Event.xbutton.y >= thdata[i].y) && (Event.xbutton.y <= thdata[i].y + thdata[i].xpm.attributes.height)) { if ((Event.xbutton.x >= thdata[i].x) && (Event.xbutton.x <= thdata[i].x + thdata[i].xpm.attributes.width)) { if (th_no_icon_window) { /* Special Icon Mode: we must check in which window the user clicked */ do_it = TRUE; if (Event.xbutton.window == Iconwin) { if (!thdata[i].icon) do_it = FALSE; } else { if (thdata[i].icon) do_it = FALSE; } } /* no commands defined? We skip this one! */ if (((thdata[i].left != 0) || (thdata[i].mid != 0) || (thdata[i].right != 0)) && (do_it)) { if (debug) fprintf(stderr, "** User selected button %d with mouse button %d\n", i, Event.xbutton.button); j = 0; switch(Event.xbutton.button) { case 1: j = thdata[i].left; break; case 2: j = thdata[i].mid; break; default: j = thdata[i].right; break; } but_current = i; if (debug) fprintf(stderr, "-> command = %d\n", j); if ((j >= 1) && (j <= 49)) fak_event_handle(j, Event); else if ((j >= 50) && (j <= 99)) cd_event_handle(j, Event); #ifdef MIXER else if ((j >= 100) && (j <= 199)) mixer_event_handle(j, Event); #endif break; } } } } } } } /* ------------------------------------------------------------------------ GUI control ------------------------------------------------------------------------ */ Pixel get_color(char *ColorName) { XColor Color; XWindowAttributes Attributes; XGetWindowAttributes(Disp,Root,&Attributes); Color.pixel = 0; if (!XParseColor (Disp, Attributes.colormap, ColorName, &Color)) fprintf(stderr,"ascd: can't parse %s\n", ColorName); else if(!XAllocColor (Disp, Attributes.colormap, &Color)) fprintf(stderr,"ascd: can't allocate %s\n", ColorName); return Color.pixel; } void create_window(int argc, char **argv) { int i; unsigned int borderwidth ; char *display_name = NULL; char *wname = "AScd"; XGCValues gcv; unsigned long gcm; XTextProperty name; Pixel back_pix, fore_pix; int x_fd; int d_depth; int ScreenWidth, ScreenHeight; XSizeHints SizeHints; XWMHints WmHints; XClassHint classHint; /* Open display */ if (!(Disp = XOpenDisplay(display_name))) { fprintf(stderr,"ascd: can't open display %s\n", XDisplayName(display_name)); exit (1); } screen = DefaultScreen(Disp); #ifdef WMK scr = WMCreateScreen(Disp, DefaultScreen(Disp)); create_big_window(scr); create_db_window(scr); create_about_window(scr); #endif Root = RootWindow(Disp, screen); d_depth = DefaultDepth(Disp, screen); x_fd = XConnectionNumber(Disp); ScreenHeight = DisplayHeight(Disp,screen); ScreenWidth = DisplayWidth(Disp,screen); /* it's time to load the visual theme! */ if (fak_load_theme(theme, FALSE)) { if (debug) fprintf(stderr, "-> back from fak_load_theme!\n"); } else { fprintf(stderr, "ascd: fatal error\n\n"); fprintf(stderr, "The '%s' theme definition file can't be read.\n\n", theme); exit(1); } SizeHints.flags= USSize|USPosition; SizeHints.x = 0; SizeHints.y = 0; back_pix = get_color("black"); fore_pix = get_color("white"); XWMGeometry(Disp, screen, Geometry, NULL, (borderwidth = 1), &SizeHints, &SizeHints.x,&SizeHints.y,&SizeHints.width, &SizeHints.height, &i); SizeHints.width = backXPM.attributes.width; SizeHints.height= backXPM.attributes.height; Win = XCreateSimpleWindow(Disp, Root, SizeHints.x, SizeHints.y, SizeHints.width, SizeHints.height, borderwidth, fore_pix, back_pix); if (!th_no_icon_window) { Iconwin = XCreateSimpleWindow(Disp,Win, SizeHints.x,SizeHints.y, SizeHints.width, SizeHints.height, borderwidth, fore_pix, back_pix); } else { Iconwin = XCreateSimpleWindow(Disp, Win, SizeHints.x, SizeHints.y, iconXPM.attributes.width, iconXPM.attributes.height, borderwidth, fore_pix, back_pix); } XSetWMNormalHints(Disp, Win, &SizeHints); classHint.res_name = "ascd" ; classHint.res_class = "AScd"; XSetClassHint (Disp, Win, &classHint); XSelectInput(Disp, Win, (ExposureMask | ButtonPressMask | StructureNotifyMask)); XSelectInput(Disp, Iconwin, (ExposureMask | ButtonPressMask | StructureNotifyMask)); if (XStringListToTextProperty(&wname, 1, &name) ==0) { fprintf(stderr, "ascd: can't allocate window name\n"); exit(-1); } XSetWMName(Disp, Win, &name); /* Create WinGC */ gcm = GCForeground|GCBackground|GCGraphicsExposures; gcv.foreground = fore_pix; gcv.background = back_pix; gcv.graphics_exposures = False; WinGC = XCreateGC(Disp, Root, gcm, &gcv); WmHints.initial_state = withdrawn ? WithdrawnState : NormalState ; WmHints.icon_window = Iconwin; WmHints.window_group = Win; WmHints.flags = StateHint | IconWindowHint | IconPositionHint | WindowGroupHint; WmHints.icon_x = SizeHints.x; WmHints.icon_y = SizeHints.y; XSetWMHints(Disp, Win, &WmHints); XSetCommand(Disp, Win, argv, argc); XMapWindow(Disp, Win); if (debug) fprintf(stderr, "-> calling fak_maskset() from create_window()...\n"); fak_maskset(); if (debug) fprintf(stderr, "-> calling fak_redraw() from create_window()...\n"); fak_redraw(); if (debug) fprintf(stderr, "-> Leaving create_window()\n"); } void newtext(char *txt) { strcpy(led_text, txt); text_start = 0; } void show_icon_db_f() { /* scroll the song title */ char txt[256]; char txt2[256]; char dsp[9]; int track; int red; if (!th_no_icon_window) return; if (icon_msg == 0) return; if (theme_select == 0) { /* there is a message to display, we'll wait for the message to time-out before handling the track title... */ if (strlen(led_text) > 0) return; /* if in fast track selector, we show the title of the track to reach */ if (fast_track > 0) { track = fast_track - 1; red = FALSE; } else { track = cur_track - 1; red = TRUE; } if (track > cur_ntracks - 1) return; if (cd->trk[track].songname != NULL) { if (show_artist) { if (cd->artist != NULL) { sprintf(txt2, "%s: %s", cd->artist, cd->trk[track].songname); } else { strcpy(txt2, cd->trk[track].songname); } } else { strcpy(txt2, cd->trk[track].songname); } fak_icon_text("", MSG_PANEL, 0, red); if (strlen(txt2) > thdata[icon_msg].w) { strcpy(txt, " "); strcat(txt, txt2); if (show_icon_db_pos > strlen(txt)) show_icon_db_pos = 0; tes_sncpy(dsp, txt + show_icon_db_pos, thdata[icon_msg].w); fak_icon_text(dsp, MSG_PANEL, 0, red); show_icon_db_pos ++; } else { fak_icon_text(txt2, MSG_PANEL, 0, red); } } else { strcpy(txt, ""); } } } void show_db_f() { /* scroll the song title */ char txt[256]; char txt2[256]; char dsp[9]; int track; int red; int where; int longueur; int i; if (but_db > 0) { where = DB_PANEL; longueur = thdata[but_db].w; } else { where = MSG_PANEL; longueur = thdata[but_msg].w; } if ((theme_select == 0) || (where == DB_PANEL)) { /* there is a message to display, we'll wait for the message to time-out before handling the track title... (but only if there is no separate areas) */ if ((strlen(led_text) > 0) && (where == MSG_PANEL)) return; /* if in fast track selector, we show the title of the track to reach */ if (fast_track > 0) { track = fast_track - 1; red = FALSE; } else { track = cur_track - 1; red = TRUE; } /* warning: avoid weird datas: */ if (track > cur_ntracks - 1) return; if (track < 0) return; if (debug > 1) fprintf(stderr, "** Show DB TRACK = %d\n", track); if (cd->trk[track].songname != NULL) { if (show_artist) { if (cd->artist != NULL) { sprintf(txt2, "%s: %s", cd->artist, cd->trk[track].songname); } else { strcpy(txt2, cd->trk[track].songname); } } else { strcpy(txt2, cd->trk[track].songname); } fak_text("", where, 0, red); if (strlen(txt2) > longueur) { strcpy(txt, ""); for (i = 0 ; i < longueur ; i++) strcat(txt, " "); strcat(txt, txt2); if (show_db_pos > strlen(txt)) show_db_pos = 0; tes_sncpy(dsp, txt + show_db_pos, longueur); fak_text(dsp, DB_PANEL, 0, red); show_db_pos ++; } else { fak_text(txt2, DB_PANEL, 0, red); } } else { strcpy(txt, ""); } } show_icon_db_f(); } /* ------------------------------------------------------------------------ Loooooooooooooooooping......... ------------------------------------------------------------------------ */ void main_loop() { unsigned int no_disk = 0; long int dodo = RDTIME; XEvent Event; while(1) { if (debug > 1) fprintf(stderr, "** [Main Loop] mode = %02d track = %02d \n", cur_cdmode, cur_track); if (cur_cdmode == WM_CDM_EJECTED) no_disk = 1; slow_down++; if (slow_down > 10) { #ifdef WMK /* in 0.13, we no longer close WINGs windows if ejected if ((cur_cdmode == WM_CDM_EJECTED) && (en_vue)) { WMCloseWindow(win); en_vue = FALSE; } */ #endif if (no_disk == 1) { cur_ntracks = 0; /* 0.13pr6: what a hack!!!! */ if (autoplay || autoprobe) { dodo = RDTIME2; wm_cd_status(); } if (cur_cdmode != WM_CDM_EJECTED) no_disk = 0; if ( (cur_cdmode == WM_CDM_STOPPED) && (autoplay) ) { newtext("Autoplay"); if (cd->volume > 0) { volume=cd->volume; cd_volume(volume, 10, max_volume); } cd_control(PLAY); wm_cd_status(); dodo = RDTIME; fak_maskset(); fak_redraw(); } } /* The Loop Mode : */ if ( (cur_track == loop_end_track ) && (cur_pos_rel >= loop_2) && (loop_mode) ) { cd_control(LOOP); fak_redraw(); } /* The Intro Scan Mode : */ if ( (cur_pos_rel > cue_time) && (intro_mode) ) { cd_control(INTRONEXT); fak_redraw(); } } if ((slow_down == 1) || (slow_down == 6)) { if ((show_db) && (cur_cdmode == WM_CDM_PLAYING)) show_db_f(); } /* Check events */ while (XPending(Disp)) { XNextEvent(Disp, &Event); #ifdef WMK if (!WMHandleEvent(&Event)) { #endif switch(Event.type) { /* ---------------------- Redraw Window --------------------- */ case Expose: if(Event.xexpose.count == 0) { lasttime=01; redraw = TRUE; fak_redraw(); } else { if (debug > 1) fprintf(stderr, "** XEVent - expose, not handled, count = %d\n", Event.xexpose.count); } break; /* ----------------------- Mouse Click ---------------------- */ case ButtonPress: wm_cd_status(); mouse_events(Event); break; /* ------------------------ Destroy Window ------------------- */ case DestroyNotify: XFreeGC(Disp, WinGC); XDestroyWindow(Disp, Win); XDestroyWindow(Disp, Iconwin); XCloseDisplay(Disp); exit(0); break; default: if (debug > 1) fprintf(stderr, "** XEvent - unknown event type = %d\n", Event.type); break; } #ifdef WMK } #endif XFlush(Disp); } /* check event */ usleep(dodo); /* ----------------- now we have to redraw the screen: ---------------- */ if ((slow_down > 10) || (has_clicked)) { fak_redraw(); slow_down = 0; has_clicked = FALSE; } } } /* ------------------------------------------------------------------------ So... let's go! ------------------------------------------------------------------------ */ int main(int argc, char *argv[]) { extern char *rcfile, *dbfiles; /*printf("AScd %s\n", VERSION);*/ /* CD device: */ #ifndef NO_D_DEVICE cd_device = malloc(strlen(DEFAULTDEVICE) + 1); strcpy(cd_device, DEFAULTDEVICE); #endif strcpy(led_text, ""); strcpy(theme, "default"); strcpy(xv, "xv"); /* the WorkMan database. It's still not used in ascd, but we need this to start the WorkMan code */ rcfile = getenv("WORKMANRC"); if (rcfile) rcfile = (char *)wm_strdup(rcfile); dbfiles = getenv("WORKMANDB"); if (dbfiles) dbfiles = (char *)wm_strdup(dbfiles); split_workmandb(); load_rc_file(FALSE); command_line_parse(argc, argv); #ifdef WMK if (debug) fprintf(stderr, "** [WINGs] init app...\n"); WMInitializeApplication("AScd", &argc, argv); #endif #ifdef MIXER mixer_ok = 1; if (debug) fprintf(stderr, "** [mixer] checking mixer device...\n"); if (! check_mixer()) { fprintf(stderr, "ascd: can't initialize mixer device. Mixing support disabled.\n"); mixer_ok = 0; } #endif if (debug) fprintf(stderr, "** creating main window...\n"); create_window(argc, argv); if (debug) fprintf(stderr, "** checking CD status...\n"); wm_cd_status(); if (cur_cdmode != WM_CDM_EJECTED) { if (debug) fprintf(stderr, "** reading CD initial volume...\n"); volume = wm_cd_read_initial_volume(max_volume); } else { if (debug) fprintf(stderr, "** CD is ejected: volume ignored.\n"); } if (debug) fprintf(stderr, "** checking autoplay...\n"); if ((autoplay) && (cur_cdmode == WM_CDM_STOPPED)) { if (cur_track < 1) { cur_track = 1; wm_cd_status(); } if (debug) fprintf(stderr, "-> autoplay: play command\n"); cd_control(PLAY); if (debug) fprintf(stderr, "-> autoplay: checking status\n"); wm_cd_status(); if (debug) fprintf(stderr, "-> autoplay: redrawing\n"); fak_redraw(); if (debug) fprintf(stderr, "-> autoplay: done\n"); } else { if (debug) fprintf(stderr, "-> no autoplay\n"); } if (debug) fprintf(stderr, "** checking current CD volume in database\n"); if (((cur_cdmode == WM_CDM_PLAYING) || (cur_cdmode == WM_CDM_PAUSED)) && (cd->volume > 0)) { volume=cd->volume; cd_volume(volume, 10, max_volume); } fak_maskset(); if (debug) fprintf(stderr, "** Init passed. Entering main loop.\n"); redraw = TRUE; main_loop(); return 0; } ascd-0.13.2.orig/ascd/ascd.h0100644000175000017500000001052206731227266014773 0ustar hallonhallon#ifndef FALSE # define FALSE 0 #endif #ifndef TRUE # define TRUE 1 #endif /* These #defines control the main loop timeouts */ #define RDTIME 50000L #define RDTIME2 75000L #define MAX_VOL 255 /*#define ACCTABLE "éÉčČęĘŕŔâÂůŮűŰîÎôÔçÇ**"*/ #define ACCTABLE "éečeęeŕaâaůuűuîiôoçc**" #define UPACCTABLE "éEčEęEŕAâAůUűUîIôOçC**" #define COUNTER_PANEL 0 #define MSG_PANEL 1 #define TRACK_PANEL 2 #define DB_PANEL 3 /* ---------------------- CD control ---------------------- */ #define PLAY 0 #define PAUSE 1 #define STOP 2 #define UPTRACK 3 #define DNTRACK 4 #define CUE 5 #define REV 6 #define FIRST 7 #define LAST 8 #define LOOP 9 #define DIRECTACCESS 10 #define INTROSCAN 11 #define INTRONEXT 12 #define LOCACCESS 13 #define DIRECTTRACK 14 #define GLOBALACCESS 15 /* CLOSETRAY added 990417 */ #define CLOSETRAY 16 /* new modes added in GMan experimentation. They're also used in AScd >= 0.11 */ #define STOPONLY 20 #define EJECT 21 /* ------------------ FAKTORY defines: ------------------- */ #define FAK_BMAX 200 /* max buttons */ #define FAK_CMAX 80 /* max lenght of infos strings */ /* screen elements types: */ #define FAK_PIXMAP 1 #define FAK_COUNTER 2 #define FAK_TRACKNBR 3 #define FAK_MSG 4 #define FAK_DB 5 #define FAK_CD_BAR 10 #define FAK_VCD_BAR 11 #define FAK_ICD_BAR 12 #define FAK_VOL_BAR 13 #define FAK_VVOL_BAR 14 #define FAK_IVOL_BAR 15 #define FAK_MIXER_BAR 16 #define FAK_VMIXER_BAR 17 #define FAK_IMIXER_BAR 18 /* 0132 new pixmap sliders: */ #define FAK_CD_PIX 19 #define FAK_VOL_PIX 20 #define FAK_VVOL_PIX 21 #define FAK_VCD_PIX 22 /* general commands: the reserved range is 0 to 49 */ #define FAK_PANEL_SWITCH 1 #define FAK_QUIT 2 #define FAK_PANEL1 3 #define FAK_PANEL2 4 #define FAK_PANEL3 5 #define FAK_PANEL4 6 #define FAK_PANEL5 7 #define FAK_WINGS 8 #define FAK_COUNTER_MODE 9 #define FAK_TSELECT 10 #define FAK_TNEXT 11 #define FAK_TPREVIOUS 12 #define FAK_FTSELECT 13 #define FAK_FTNEXT 14 #define FAK_FTPREVIOUS 15 #define FAK_SAVE 16 #define FAK_LOAD 17 #define FAK_QREF 20 /* general modes toggles: (not yet supported!!!) */ #define FAK_TOG_AUTOPLAY 30 #define FAK_TOG_AUTOREPEAT 31 #define FAK_TOG_SHOWDB 32 #define FAK_TOG_SHOWARTIST 33 #define FAK_TOG_UPPER 34 #define FAK_TOG_ISKIPS 35 /* CD player commands: the reserved range is 50 to 99 */ #define FAK_CD_PLAY 50 #define FAK_CD_PAUSE 51 #define FAK_CD_STOP 52 #define FAK_CD_EJECT 53 #define FAK_CD_STOPEJECT 54 #define FAK_CD_EJECTQUIT 55 #define FAK_CD_REW 60 #define FAK_CD_FIRST 61 #define FAK_CD_PREVIOUS 62 #define FAK_CD_FWD 65 #define FAK_CD_LAST 66 #define FAK_CD_NEXT 67 #define FAK_CD_DIRECT 68 #define FAK_CD_LSTART 70 #define FAK_CD_LEND 71 #define FAK_CD_LOOP 72 #define FAK_CD_GOLSTART 73 #define FAK_CD_GOLEND 74 #define FAK_CD_LTRACK 75 #define FAK_CD_LTOTRACK 76 #define FAK_CD_LFROMTRACK 77 #define FAK_CD_LCLEAR 78 #define FAK_CD_INTRO 80 #define FAK_CD_FADE 81 /* these two ones are not yet supported: */ #define FAK_CD_RANDOM 82 #define FAK_CD_RMODE 83 #define FAK_CD_MUTE 90 #define FAK_CD_VOLUME 91 /* Mixer commands: the reserved range is 100 to 199 */ #define FAK_MIXER_SET 100 #define FAK_MIXER_50 101 #define FAK_MIXER_75 102 #define FAK_MIXER_100 103 #define FAK_MIXER_0 104 #define FAK_MIXER_LOAD 110 #define FAK_MIXER_SAVE 111 /* -------------------------------------------------------------------- */ typedef struct _XpmIcon { Pixmap pixmap; Pixmap mask; XpmAttributes attributes; } XpmIcon; struct fak_button { unsigned int type; unsigned int panel; char xpm_file[FAK_CMAX]; char altxpm_file[FAK_CMAX]; XpmIcon xpm; XpmIcon altxpm; unsigned int left; unsigned int right; unsigned int mid; unsigned int x; unsigned int y; unsigned int w; unsigned int h; unsigned int arg; int icon; unsigned int ox; unsigned int oy; }; ascd-0.13.2.orig/ascd/faktory.c0100644000175000017500000016316006740161326015534 0ustar hallonhallon/* =========================================================================== * AScd: faktory.c * The theme handling functions * =========================================================================== * Copyright (c) 1999 Denis Bourez and Rob Malda. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Denis Bourez & Rob Malda * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY DENIS BOUREZ AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL DENIS BOUREZ, ROB MALDA OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * =========================================================================== */ #include "ext.h" #define MAX_LINE_NAME 16 void tes_sncpy(char *out, char *in, int n) { register int i; for (i=0; i<=n-1; i++) out[i] = in[i]; out[i] = '\0'; } char *tes_xgets(char *chaine, int nb, FILE *fichier) { char *r; r = fgets(chaine, nb, fichier); if (feof(fichier) == 0) chaine[strlen(chaine) - 1] = 0; return r; } int fak_parse_line(char *ligne, char *key, char *arguments) { unsigned int pos = 0; if ((strlen(ligne) > 0) && (ligne[0] != '#')) { while ((ligne[pos] != ' ') && (ligne[pos] != 9)) pos++; tes_sncpy(key, ligne, pos); while (((ligne[pos] == ' ') || (ligne[pos] == 9)) && (pos < strlen(ligne))) pos++; if (pos < strlen(ligne)) strcpy(arguments, ligne + pos); else strcpy(arguments, ""); if (debug > 2) fprintf(stderr,"++ input: [%s]\n key: [%s]\n args: [%s]\n", ligne, key, arguments); return TRUE; } else { strcpy(key, ""); strcpy(arguments, ""); if (debug > 2) fprintf(stderr,"++ input: [%s]\n key: [%s]\n args: [%s]\n", ligne, key, arguments); return FALSE; } } int fak_use_alt(int i) { int use_alt = 0; switch (thdata[i].left) { case FAK_CD_PLAY: if (cur_cdmode == WM_CDM_PLAYING) use_alt = 1; break; case FAK_CD_PAUSE: if (cur_cdmode == WM_CDM_PAUSED) use_alt = 1; break; case FAK_CD_STOP: if (cur_cdmode == WM_CDM_STOPPED) use_alt = 1; break; case FAK_CD_EJECT: if (cur_cdmode == WM_CDM_EJECTED) use_alt = 1; break; case FAK_CD_STOPEJECT: if (cur_cdmode == WM_CDM_STOPPED) use_alt = 1; break; case FAK_CD_EJECTQUIT: if ((cur_cdmode == WM_CDM_EJECTED) || (cur_cdmode == WM_CDM_STOPPED)) use_alt = 1; break; case FAK_CD_LOOP: if (loop_mode) use_alt = 1; break; case FAK_CD_MUTE: if (muted) use_alt = 1; break; case FAK_CD_VOLUME: if (muted) use_alt = 1; break; case FAK_CD_INTRO: if (intro_mode) use_alt = 1; break; case FAK_TOG_AUTOREPEAT: if (autorepeat) use_alt = 1; break; case FAK_TOG_AUTOPLAY: if (autoplay) use_alt = 1; break; case FAK_TOG_UPPER: if (force_upper) use_alt = 1; break; case FAK_TOG_SHOWDB: if (show_db) use_alt = 1; break; case FAK_TOG_SHOWARTIST: if (show_artist) use_alt = 1; break; case FAK_TOG_ISKIPS: if (ignore_avoid) use_alt = 1; break; case FAK_TSELECT: case FAK_TNEXT: case FAK_TPREVIOUS: if (theme_select) use_alt = 1; break; default: use_alt = 0; break; } return use_alt; } void fak_validate_pixmap(char *string, char *name) { sprintf(string, "%s/Themes/%s/%s", THDIR, theme, name); if (access(string, R_OK) != 0) { sprintf(string, "%s/Default/%s", THDIR, name); if (access(string, R_OK) != 0) { fprintf(stderr, "\nascd: fatal error while loading theme '%s'\n", theme); fprintf(stderr, " Pixmap file '%s' was not found.\n\n", name); exit(1); } } } void fak_init_theme(int upgrade) { /* re-init all the buttons structure and globals */ int i; if (debug) fprintf(stderr, "** Init theme variables.\n Buttons...\n"); for (i = 1; i <= but_max ; i++) { thdata[i].type = 0; thdata[i].panel = 0; thdata[i].left = 0; thdata[i].mid = 0; thdata[i].right = 0; thdata[i].x = 0; thdata[i].y = 0; thdata[i].w = 0; thdata[i].h = 0; thdata[i].arg = 0; thdata[i].icon = FALSE; thdata[i].ox = 0; thdata[i].oy = 0; if (strcmp(thdata[i].xpm_file, "") != 0) { strcpy(thdata[i].xpm_file, ""); /*if (upgrade) XpmFree(&thdata[i].xpm);*/ } if (strcmp(thdata[i].altxpm_file, "") != 0) { strcpy(thdata[i].altxpm_file, ""); /*if (upgrade) XpmFree(&thdata[i].altxpm);*/ } } if (debug) fprintf(stderr, " Strings & globals...\n"); strcpy(th_name, ""); strcpy(th_author, ""); strcpy(th_release, ""); strcpy(th_email, ""); strcpy(th_url, ""); strcpy(th_comment, ""); strcpy(th_alpha1, ""); strcpy(th_alpha2, ""); strcpy(th_background, ""); strcpy(th_icon_window, ""); th_no_minus = FALSE; but_max = 0; but_counter = 0; but_msg = 0; but_tracknbr = 0; but_db = 0; but_current = 0; icon_counter = 0; icon_msg = 0; icon_tracknbr = 0; panels = 0; panel = 1; panel_stop = 0; panel_play = 0; /* if (upgrade) { XpmFree(&alphaXPM); XpmFree(&ralphaXPM); XpmFree(&backXPM); } */ if (debug) fprintf(stderr, "-> done.\n"); } int fak_load_theme(char *th, int upgrade) { char txt[256]; char key[256]; char arguments[256]; int button = FALSE; unsigned int i; XWindowAttributes Attributes; int Ret; FILE *in; #ifdef MIXER unsigned int j; struct { char name[MAX_LINE_NAME]; int dev; } mixernames[SOUND_MIXER_NRDEVICES] = { { "volume", SOUND_MIXER_VOLUME }, { "bass", SOUND_MIXER_BASS }, { "treble", SOUND_MIXER_TREBLE }, { "midi", SOUND_MIXER_SYNTH }, { "pcm", SOUND_MIXER_PCM }, { "speaker", SOUND_MIXER_SPEAKER }, { "line", SOUND_MIXER_LINE }, { "mic", SOUND_MIXER_MIC }, { "cd", SOUND_MIXER_CD }, { "imix", SOUND_MIXER_IMIX }, { "altpcm", SOUND_MIXER_ALTPCM }, { "reclev", SOUND_MIXER_RECLEV }, { "igain", SOUND_MIXER_IGAIN }, { "ogain", SOUND_MIXER_OGAIN }, { "line1", SOUND_MIXER_LINE1 }, { "line2", SOUND_MIXER_LINE2 }, { "line3", SOUND_MIXER_LINE3 } }; #endif /* check if theme directory if ok: */ sprintf(txt, "%s/Themes/%s", THDIR, th); if (debug) fprintf(stderr, "** Theme to load: %s\n", txt); if (access(txt, X_OK | R_OK) != 0) { sprintf(txt, "%s/Themes/default", THDIR); if (access(txt, X_OK | R_OK) != 0) { fprintf(stderr, "ascd: fatal error\n\n"); fprintf(stderr, "The '%s' and 'default' themes folders are not \navailable in %s.\n\n", th, THDIR); fprintf(stderr, "Please check the permissions and/or redo ascd installation.\n\n"); exit(1); } else { strcpy(th, "default"); } } sprintf(txt, "%s/Themes/%s/Theme", THDIR, th); /* parse and load the file */ if (in = fopen(txt, "r")) { /* we first clear everything... */ fak_init_theme(upgrade); /* that's ok, let's go! */ if (debug) fprintf(stderr, "-> Parsing Theme file...\n"); while (tes_xgets(txt, 255, in)) { if (fak_parse_line(txt, key, arguments)) { if (key[0] == '{') { button = TRUE; if (but_max < FAK_BMAX - 1) { but_max ++; strcpy(thdata[but_max].xpm_file, ""); strcpy(thdata[but_max].altxpm_file, ""); thdata[but_max].type = 0; } else { /* no more free buttons. We'll ignore the rest */ button = FALSE; } } else if (key[0] == '}') { button = FALSE; /* update the pointers to msg, counter and tracknbr: */ switch(thdata[but_max].type) { case FAK_COUNTER: if (thdata[but_max].icon) icon_counter = but_max; else but_counter = but_max; break; case FAK_MSG: if (thdata[but_max].icon) icon_msg = but_max; else but_msg = but_max; break; case FAK_DB: but_db = but_max; break; case FAK_TRACKNBR: if (thdata[but_max].icon) icon_tracknbr = but_max; else but_tracknbr = but_max; break; default: break; } if (debug > 1) { fprintf(stderr, " Button %02d type: %02d commands: %02d %02d %02d arg: %02d\n", but_max, thdata[but_max].type, thdata[but_max].left, thdata[but_max].mid, thdata[but_max].right, thdata[but_max].arg); fprintf(stderr, " Geometry: %02dx%02d on panel %02d\n", thdata[but_max].x, thdata[but_max].y, thdata[but_max].panel); fprintf(stderr, " Pixmaps: [%s] and [%s]\n", thdata[but_max].xpm_file, thdata[but_max].altxpm_file); } } if (!button) { if (strcmp(key, "name") == 0) strcpy(th_name, arguments); else if (strcmp(key, "release") == 0) strcpy(th_release, arguments); else if (strcmp(key, "author") == 0) strcpy(th_author, arguments); else if (strcmp(key, "email") == 0) strcpy(th_email, arguments); else if (strcmp(key, "url") == 0) strcpy(th_url, arguments); else if (strcmp(key, "comment") == 0) strcpy(th_comment, arguments); else if (strcmp(key, "alpha1") == 0) strcpy(th_alpha1, arguments); else if (strcmp(key, "alpha2") == 0) strcpy(th_alpha2, arguments); else if (strcmp(key, "background") == 0) strcpy(th_background, arguments); else if (strcmp(key, "icon_background") == 0) strcpy(th_icon_window, arguments); else if (strcmp(key, "panels") == 0) panels = atoi(arguments); else if (strcmp(key, "panel_stop") == 0) panel_stop = atoi(arguments); else if (strcmp(key, "panel_play") == 0) panel_play = atoi(arguments); else if (strcmp(key, "no_minus") == 0) th_no_minus = TRUE; } else { /* button definition: */ if (strcmp(key, "icon") == 0) thdata[but_max].icon = TRUE; if (strcmp(key, "type") == 0) { if (strcmp(arguments, "pixmap") == 0) thdata[but_max].type = FAK_PIXMAP; else if (strcmp(arguments, "counter") == 0) thdata[but_max].type = FAK_COUNTER; else if (strcmp(arguments, "tracknumber") == 0) thdata[but_max].type = FAK_TRACKNBR; else if (strcmp(arguments, "message") == 0) thdata[but_max].type = FAK_MSG; else if (strcmp(arguments, "database") == 0) thdata[but_max].type = FAK_DB; else if (strcmp(arguments, "progress_bar") == 0) thdata[but_max].type = FAK_CD_BAR; else if (strcmp(arguments, "vprogress_bar") == 0) thdata[but_max].type = FAK_VCD_BAR; else if (strcmp(arguments, "iprogress_bar") == 0) thdata[but_max].type = FAK_ICD_BAR; else if (strcmp(arguments, "pixmap_bar") == 0) thdata[but_max].type = FAK_CD_PIX; else if (strcmp(arguments, "vpixmap_bar") == 0) thdata[but_max].type = FAK_VCD_PIX; else if (strcmp(arguments, "volume_bar") == 0) thdata[but_max].type = FAK_VOL_BAR; else if (strcmp(arguments, "volume") == 0) thdata[but_max].type = FAK_VOL_BAR; else if (strcmp(arguments, "pixmap_volume") == 0) thdata[but_max].type = FAK_VOL_PIX; else if (strcmp(arguments, "vpixmap_volume") == 0) thdata[but_max].type = FAK_VVOL_PIX; else if (strcmp(arguments, "vvolume") == 0) thdata[but_max].type = FAK_VVOL_BAR; else if (strcmp(arguments, "vvolume_bar") == 0) thdata[but_max].type = FAK_VVOL_BAR; else if (strcmp(arguments, "ivolume") == 0) thdata[but_max].type = FAK_IVOL_BAR; else if (strcmp(arguments, "ivolume_bar") == 0) thdata[but_max].type = FAK_IVOL_BAR; else if (strcmp(arguments, "mixer_bar") == 0) thdata[but_max].type = FAK_MIXER_BAR; else if (strcmp(arguments, "mixer") == 0) thdata[but_max].type = FAK_MIXER_BAR; else if (strcmp(arguments, "vmixer_bar") == 0) thdata[but_max].type = FAK_VMIXER_BAR; else if (strcmp(arguments, "vmixer") == 0) thdata[but_max].type = FAK_VMIXER_BAR; else if (strcmp(arguments, "imixer_bar") == 0) thdata[but_max].type = FAK_IMIXER_BAR; else if (strcmp(arguments, "imixer") == 0) thdata[but_max].type = FAK_IMIXER_BAR; } i = 0; if ((strcmp(key, "left") == 0) || (strcmp(key, "middle") ==0) || (strcmp(key, "mid") ==0) || (strcmp(key, "right") == 0)) { /* --------------- available commands: ---------------- */ /* basic orders */ if (strcmp(arguments, "panel_switch") == 0) i = FAK_PANEL_SWITCH; else if (strcmp(arguments, "panel 1") == 0) i = FAK_PANEL1; else if (strcmp(arguments, "panel 2") == 0) i = FAK_PANEL2; else if (strcmp(arguments, "panel 3") == 0) i = FAK_PANEL3; else if (strcmp(arguments, "panel 4") == 0) i = FAK_PANEL4; else if (strcmp(arguments, "panel 5") == 0) i = FAK_PANEL5; else if (strcmp(arguments, "counter_mode") == 0) i = FAK_COUNTER_MODE; else if (strcmp(arguments, "quit") == 0) i = FAK_QUIT; else if (strcmp(arguments, "wings_window") == 0) i = FAK_WINGS; else if (strcmp(arguments, "theme_select") == 0) i = FAK_TSELECT; else if (strcmp(arguments, "theme_next") == 0) i = FAK_TNEXT; else if (strcmp(arguments, "theme_previous") == 0) i = FAK_TPREVIOUS; else if (strcmp(arguments, "ftrack_select") == 0) i = FAK_FTSELECT; else if (strcmp(arguments, "ftrack_next") == 0) i = FAK_FTNEXT; else if (strcmp(arguments, "ftrack_previous") == 0) i = FAK_FTPREVIOUS; else if (strcmp(arguments, "autoplay") == 0) i = FAK_TOG_AUTOPLAY; else if (strcmp(arguments, "autorepeat") == 0) i = FAK_TOG_AUTOREPEAT; else if (strcmp(arguments, "show_db") == 0) i = FAK_TOG_SHOWDB; else if (strcmp(arguments, "show_artist") == 0) i = FAK_TOG_SHOWARTIST; else if (strcmp(arguments, "uppercase") == 0) i = FAK_TOG_UPPER; else if (strcmp(arguments, "ignore_skips") == 0) i = FAK_TOG_ISKIPS; else if (strcmp(arguments, "save") == 0) i = FAK_SAVE; else if (strcmp(arguments, "load") == 0) i = FAK_LOAD; else if (strcmp(arguments, "quick_ref") == 0) i = FAK_QREF; /* CD player */ else if (strcmp(arguments, "play") == 0) i = FAK_CD_PLAY; else if (strcmp(arguments, "pause") == 0) i = FAK_CD_PAUSE; else if (strcmp(arguments, "stop") == 0) i = FAK_CD_STOP; else if (strcmp(arguments, "eject") == 0) i = FAK_CD_EJECT; else if (strcmp(arguments, "stop_eject") == 0) i = FAK_CD_STOPEJECT; else if (strcmp(arguments, "eject_quit") == 0) i = FAK_CD_EJECTQUIT; else if (strcmp(arguments, "rew") == 0) i = FAK_CD_REW; else if (strcmp(arguments, "first_track") == 0) i = FAK_CD_FIRST; else if (strcmp(arguments, "previous_track") == 0) i = FAK_CD_PREVIOUS; else if (strcmp(arguments, "fwd") == 0) i = FAK_CD_FWD; else if (strcmp(arguments, "last_track") == 0) i = FAK_CD_LAST; else if (strcmp(arguments, "next_track") == 0) i = FAK_CD_NEXT; else if (strcmp(arguments, "direct_access") == 0) i = FAK_CD_DIRECT; else if (strcmp(arguments, "loop") == 0) i = FAK_CD_LOOP; else if (strcmp(arguments, "loop_start") == 0) i = FAK_CD_LSTART; else if (strcmp(arguments, "loop_end") == 0) i = FAK_CD_LEND; else if (strcmp(arguments, "loop_go_start") == 0) i = FAK_CD_GOLSTART; else if (strcmp(arguments, "loop_go_end") == 0) i = FAK_CD_GOLEND; else if (strcmp(arguments, "loop_track") == 0) i = FAK_CD_LTRACK; else if (strcmp(arguments, "loop_to_track") == 0) i = FAK_CD_LTOTRACK; else if (strcmp(arguments, "loop_from_track") == 0) i = FAK_CD_LFROMTRACK; else if (strcmp(arguments, "loop_clear") == 0) i = FAK_CD_LCLEAR; else if (strcmp(arguments, "intro_scan") == 0) i = FAK_CD_INTRO; else if (strcmp(arguments, "fade") == 0) i = FAK_CD_FADE; else if (strcmp(arguments, "random_jump") == 0) i = FAK_CD_RANDOM; else if (strcmp(arguments, "random_mode") == 0) i = FAK_CD_RMODE; else if (strcmp(arguments, "mute") == 0) i = FAK_CD_MUTE; else if (strcmp(arguments, "volume") == 0) i = FAK_CD_VOLUME; /* mixer */ else if (strcmp(arguments, "set") == 0) i = FAK_MIXER_SET; else if (strcmp(arguments, "zero") == 0) i = FAK_MIXER_0; else if (strcmp(arguments, "0") == 0) i = FAK_MIXER_0; else if (strcmp(arguments, "50%") == 0) i = FAK_MIXER_50; else if (strcmp(arguments, "50") == 0) i = FAK_MIXER_50; else if (strcmp(arguments, "75%") == 0) i = FAK_MIXER_75; else if (strcmp(arguments, "75") == 0) i = FAK_MIXER_75; else if (strcmp(arguments, "100%") == 0) i = FAK_MIXER_100; else if (strcmp(arguments, "100") == 0) i = FAK_MIXER_100; /* ------------- which mouse button? --------------- */ if (strcmp(key, "left") == 0) thdata[but_max].left = i; else if (strcmp(key, "middle") == 0) thdata[but_max].mid = i; else if (strcmp(key, "mid") == 0) thdata[but_max].mid = i; else if (strcmp(key, "right") == 0) thdata[but_max].right = i; } else if (strcmp(key, "panel") == 0) thdata[but_max].panel = atoi(arguments); else if (strcmp(key, "x") == 0) thdata[but_max].x = atoi(arguments); else if (strcmp(key, "y") == 0) thdata[but_max].y = atoi(arguments); else if (strcmp(key, "w") == 0) thdata[but_max].w = atoi(arguments); else if (strcmp(key, "h") == 0) thdata[but_max].h = atoi(arguments); else if (strcmp(key, "arg") == 0) { thdata[but_max].arg = atoi(arguments); #ifdef MIXER for(j = 0; j < SOUND_MIXER_NRDEVICES; j++) { if(strcasecmp(mixernames[j].name, arguments) == 0) { thdata[but_max].arg = mixernames[j].dev; break; } } #endif } else if (strcmp(key, "pixmap") == 0) strcpy(thdata[but_max].xpm_file, arguments); else if (strcmp(key, "alt") == 0) strcpy(thdata[but_max].altxpm_file, arguments); } } } fclose(in); if (debug) { fprintf(stderr, "-> Theme summary for '%s':\n", th_name); fprintf(stderr, " Release: %s\n", th_release); fprintf(stderr, " Author: %s (%s)\n", th_author, th_email); fprintf(stderr, " URL: %s\n", th_url); fprintf(stderr, " Comment: %s\n", th_comment); fprintf(stderr, " Stats: %d panels, %d buttons\n", panels, but_max); fprintf(stderr, " Display: counter: %d / msg: %d (%d cars) / db: %d / track: %d\n", but_counter, but_msg, thdata[but_msg].w, but_db, but_tracknbr); if (th_no_icon_window) fprintf(stderr, " Using separate icon definition, background = %s\n", th_icon_window); fprintf(stderr, "-> Loading basic pixmap files... "); } XGetWindowAttributes(Disp, Root, &Attributes); /* the background pixmap: */ if (debug) fprintf(stderr, "background "); fak_validate_pixmap(txt, th_background); Ret = XpmReadFileToPixmap(Disp, Root, txt, &backXPM.pixmap, &backXPM.mask, &backXPM.attributes); if ((Ret != XpmSuccess) && (debug)) fprintf(stderr, "*!* "); /* the fonts: */ if (debug) fprintf(stderr, "alpha 1 "); fak_validate_pixmap(txt, th_alpha1); Ret = XpmReadFileToPixmap(Disp, Root, txt, &alphaXPM.pixmap, &alphaXPM.mask, &alphaXPM.attributes); if ((Ret != XpmSuccess) && (debug)) fprintf(stderr, "*!* "); if (debug) fprintf(stderr, "2 "); fak_validate_pixmap(txt, th_alpha2); Ret = XpmReadFileToPixmap(Disp, Root, txt, &ralphaXPM.pixmap, &ralphaXPM.mask, &ralphaXPM.attributes); if ((Ret != XpmSuccess) && (debug)) fprintf(stderr, "*!* "); if (debug) fprintf(stderr, "\n-> Loading buttons pixmaps... "); for (i = 1; i <= but_max; i++) { if (strlen(thdata[i].xpm_file) > 0) { if (debug > 1) fprintf(stderr, "%d ", i); fak_validate_pixmap(txt, thdata[i].xpm_file); thdata[i].xpm.attributes.valuemask |= (XpmReturnPixels | XpmReturnExtensions); Ret = XpmReadFileToPixmap(Disp, Root, txt, &thdata[i].xpm.pixmap, &thdata[i].xpm.mask, &thdata[i].xpm.attributes); if ((Ret != XpmSuccess) && (debug > 1)) fprintf(stderr, "*!* "); } if (strlen(thdata[i].altxpm_file) > 0) { if (debug > 1) fprintf(stderr, "a "); fak_validate_pixmap(txt, thdata[i].altxpm_file); thdata[i].xpm.attributes.valuemask |= (XpmReturnPixels | XpmReturnExtensions); Ret = XpmReadFileToPixmap(Disp, Root, txt, &thdata[i].altxpm.pixmap, &thdata[i].altxpm.mask, &thdata[i].altxpm.attributes); if ((Ret != XpmSuccess) && (debug > 1)) fprintf(stderr, "*!* "); } } /* the icon */ if (strlen(th_icon_window) > 0) { if (debug) fprintf(stderr, "\n-> Loading icon... "); fak_validate_pixmap(txt, th_icon_window); Ret = XpmReadFileToPixmap(Disp, Root, txt, &iconXPM.pixmap, &iconXPM.mask, &iconXPM.attributes); if ((Ret != XpmSuccess) && (debug)) fprintf(stderr, "*!* "); } if (debug) fprintf(stderr, "\n-> Theme loaded.\n"); return TRUE; } else { return FALSE; } } void fak_icon_text(char *string, unsigned int where, unsigned int col, unsigned int red) { unsigned int x = 0; unsigned int offset = 0; unsigned hoffset = 0; unsigned voffset = 0; unsigned char txt[128]; unsigned int j; unsigned int char_max; int out = FALSE; if (!th_no_icon_window) return; switch(where) { case COUNTER_PANEL: if (icon_counter == 0) out = TRUE; else { voffset = thdata[icon_counter].y; hoffset = thdata[icon_counter].x; } break; case MSG_PANEL: if (icon_msg == 0) out = TRUE; else { voffset = thdata[icon_msg].y; hoffset = thdata[icon_msg].x; } break; default: if (icon_tracknbr == 0) out = TRUE; else { voffset = thdata[icon_tracknbr].y; hoffset = thdata[icon_tracknbr].x; } break; } if (out) return; strcpy(txt, string); /* Deal with the string length: */ if ((strlen(txt) > thdata[icon_msg].w) && (where == MSG_PANEL)) { txt[thdata[icon_msg].w] = 0; } if ((strcmp(txt, "") == 0) && (where == MSG_PANEL)) { for (x = 1; x <= thdata[icon_msg].w; x++) { strcat(txt, " "); } } if (red) { char_max = alphaXPM.attributes.width / 6; } else { char_max = ralphaXPM.attributes.width / 6; } for(x = 0; x < strlen(txt); x++) { /* lookup in the accents table to remove them */ if (! force_upper) { if (char_max <= 116) { /* don't convert if 8bit font */ for (j = 0 ; j <= strlen(ACCTABLE) - 2 ; j = j + 2) { if ( txt[x] == (unsigned char)ACCTABLE[j] ) { txt[x] = ACCTABLE[j + 1]; break; } } } } else { /* force upper case */ for (j = 0 ; j <= strlen(UPACCTABLE) - 2 ; j = j + 2) { if ( txt[x] == (unsigned char)UPACCTABLE[j] ) { txt[x] = UPACCTABLE[j + 1]; break; } } txt[x] = toupper(txt[x]); } if ((txt[x] >= 32) && (txt[x] <= char_max + 32)) offset = txt[x] - 32; else offset = 31; if (red) { XCopyArea(Disp, ralphaXPM.pixmap, Iconwin, WinGC, 6 * offset, 0, 6, 9, hoffset + (col * 6) + (x * 6), voffset); } else { XCopyArea(Disp, alphaXPM.pixmap, Iconwin, WinGC, 6 * offset, 0, 6, 9, hoffset + (col * 6) + (x * 6), voffset); } } } void fak_text(char *string, unsigned int where, unsigned int col, unsigned int red) { /* different behaviour than the old draw_text() found in AScd <= 0.12.... The where parameter replaces the odl "row" one and should be: 0 = write to the counter zone 1 = write to the message zone 2 = write to the track number zone */ unsigned int x = 0; unsigned int offset = 0; unsigned hoffset = 0; unsigned voffset = 0; unsigned char txt[128]; unsigned int j; unsigned int char_max; int out = FALSE; int do_icon = TRUE; if (where == DB_PANEL) { do_icon = FALSE; if (but_db == 0) where = MSG_PANEL; } if (do_icon) fak_icon_text(string, where, col, red); switch(where) { case COUNTER_PANEL: if (but_counter == 0) out = TRUE; else { voffset = thdata[but_counter].y; hoffset = thdata[but_counter].x; } break; case MSG_PANEL: if (but_msg == 0) out = TRUE; else { voffset = thdata[but_msg].y; hoffset = thdata[but_msg].x; } break; case DB_PANEL: voffset = thdata[but_db].y; hoffset = thdata[but_db].x; break; default: if (but_tracknbr == 0) out = TRUE; else { voffset = thdata[but_tracknbr].y; hoffset = thdata[but_tracknbr].x; } break; } if (out) return; strcpy(txt, string); /* Deal with the string length: */ if ((strlen(txt) > thdata[but_msg].w) && (where == MSG_PANEL)) { txt[thdata[but_msg].w] = 0; } if ((strlen(txt) > thdata[but_db].w) && (where == DB_PANEL)) { txt[thdata[but_msg].w] = 0; } if ((strcmp(txt, "") == 0) && (where == MSG_PANEL)) { for (x = 1; x <= thdata[but_msg].w; x++) { strcat(txt, " "); } } if ((strcmp(txt, "") == 0) && (where == DB_PANEL)) { for (x = 1; x <= thdata[but_db].w; x++) { strcat(txt, " "); } } if (red) { char_max = alphaXPM.attributes.width / 6; } else { char_max = ralphaXPM.attributes.width / 6; } for(x = 0; x < strlen(txt); x++) { /* lookup in the accents table to remove them */ if (! force_upper) { if (char_max <= 116) { /* don't convert if 8bit font */ for (j = 0 ; j <= strlen(ACCTABLE) - 2 ; j = j + 2) { if ( txt[x] == (unsigned char)ACCTABLE[j] ) { txt[x] = ACCTABLE[j + 1]; break; } } } } else { /* force upper case */ for (j = 0 ; j <= strlen(UPACCTABLE) - 2 ; j = j + 2) { if ( txt[x] == (unsigned char)UPACCTABLE[j] ) { txt[x] = UPACCTABLE[j + 1]; break; } } txt[x] = toupper(txt[x]); } if ((txt[x] >= 32) && (txt[x] <= char_max + 32)) offset = txt[x] - 32; else offset = 31; if (red) { XCopyArea(Disp, ralphaXPM.pixmap, Win, WinGC, 6 * offset, 0, 6, 9, hoffset + (col * 6) + (x * 6), voffset); if (!th_no_icon_window) { XCopyArea(Disp, ralphaXPM.pixmap, Iconwin, WinGC, 6 * offset, 0, 6, 9, hoffset + (col * 6) + (x * 6), voffset); } } else { XCopyArea(Disp, alphaXPM.pixmap, Win, WinGC, 6 * offset, 0, 6, 9, hoffset + (col * 6) + (x * 6), voffset); if (!th_no_icon_window) { XCopyArea(Disp, alphaXPM.pixmap, Iconwin, WinGC, 6 * offset, 0, 6, 9, hoffset + (col * 6) + (x * 6), voffset); } } } } int fak_flush_expose(Window w) { XEvent dummy; int i=0; while (XCheckTypedWindowEvent (Disp, w, Expose, &dummy))i++; return i; } void fak_minus(void) { if (th_no_minus) return; if (time_mode == 1) { if (!th_no_icon_window) { if (but_counter == 0) return; XCopyArea(Disp, alphaXPM.pixmap, Win, WinGC, 6 * (45 - 32), 0, 6, 7, thdata[but_counter].x, thdata[but_counter].y); XCopyArea(Disp, alphaXPM.pixmap, Iconwin, WinGC, 6 * (45 - 32), 0, 6, 7, thdata[but_counter].x, thdata[but_counter].y); } else { if (but_counter > 0) { XCopyArea(Disp, alphaXPM.pixmap, Win, WinGC, 6 * (45 - 32), 0, 6, 7, thdata[but_counter].x, thdata[but_counter].y); } if (icon_counter > 0) { XCopyArea(Disp, alphaXPM.pixmap, Iconwin, WinGC, 6 * (45 - 32), 0, 6, 7, thdata[icon_counter].x, thdata[icon_counter].y); } } } else if (time_mode == 3) { if (!th_no_icon_window) { if (but_counter == 0) return; XCopyArea(Disp, alphaXPM.pixmap, Win, WinGC, 588, 0, 4, 7, thdata[but_counter].x, thdata[but_counter].y); XCopyArea(Disp, alphaXPM.pixmap, Iconwin, WinGC, 588, 0, 4, 7, thdata[but_counter].x, thdata[but_counter].y); } else { if (but_counter > 0) { XCopyArea(Disp, alphaXPM.pixmap, Win, WinGC, 588, 0, 4, 7, thdata[but_counter].x, thdata[but_counter].y); } if (icon_counter > 0) { XCopyArea(Disp, alphaXPM.pixmap, Iconwin, WinGC, 588, 0, 4, 7, thdata[icon_counter].x, thdata[icon_counter].y); } } } /* if displaying CD times, we display a little 'cd' */ if (time_mode >= 2) { if (!th_no_icon_window) { if (but_counter == 0) return; XCopyArea(Disp, ralphaXPM.pixmap, Win, WinGC, 582, 0, 4, 4, thdata[but_counter].x, thdata[but_counter].y); XCopyArea(Disp, ralphaXPM.pixmap, Iconwin, WinGC, 582, 0, 4, 4, thdata[but_counter].x, thdata[but_counter].y); } else { if (but_counter > 0) { XCopyArea(Disp, ralphaXPM.pixmap, Win, WinGC, 582, 0, 4, 4, thdata[but_counter].x, thdata[but_counter].y); } if (icon_counter > 0) { XCopyArea(Disp, ralphaXPM.pixmap, Iconwin, WinGC, 582, 0, 4, 4, thdata[icon_counter].x, thdata[icon_counter].y); } } } } void fak_singlemask(int i) { /* we first remove pixmap and alt from the mask */ if (strlen(thdata[i].xpm_file) > 0) { if (!th_no_icon_window) { XShapeCombineMask(Disp, Win, ShapeBounding, thdata[i].x, thdata[i].y, thdata[i].xpm.mask, ShapeSubtract); XShapeCombineMask(Disp, Iconwin, ShapeBounding, thdata[i].x, thdata[i].y, thdata[i].xpm.mask, ShapeSubtract); } else { if (thdata[i].icon) { XShapeCombineMask(Disp, Iconwin, ShapeBounding, thdata[i].x, thdata[i].y, thdata[i].xpm.mask, ShapeSubtract); } else { XShapeCombineMask(Disp, Win, ShapeBounding, thdata[i].x, thdata[i].y, thdata[i].xpm.mask, ShapeSubtract); } } } if (strlen(thdata[i].altxpm_file) > 0) { if (!th_no_icon_window) { XShapeCombineMask(Disp, Win, ShapeBounding, thdata[i].x, thdata[i].y, thdata[i].altxpm.mask, ShapeSubtract); XShapeCombineMask(Disp, Iconwin, ShapeBounding, thdata[i].x, thdata[i].y, thdata[i].altxpm.mask, ShapeSubtract); } else { if (thdata[i].icon) { XShapeCombineMask(Disp, Iconwin, ShapeBounding, thdata[i].x, thdata[i].y, thdata[i].altxpm.mask, ShapeSubtract); } else { XShapeCombineMask(Disp, Win, ShapeBounding, thdata[i].x, thdata[i].y, thdata[i].altxpm.mask, ShapeSubtract); } } } /* then we set of the two : */ if ((fak_use_alt(i)) && (strlen(thdata[i].altxpm_file) > 0)) { if (!th_no_icon_window) { XShapeCombineMask(Disp, Win, ShapeBounding, thdata[i].x, thdata[i].y, thdata[i].altxpm.mask, ShapeUnion); XShapeCombineMask(Disp, Iconwin, ShapeBounding, thdata[i].x, thdata[i].y, thdata[i].altxpm.mask, ShapeUnion); } else { if (thdata[i].icon) { XShapeCombineMask(Disp, Iconwin, ShapeBounding, thdata[i].x, thdata[i].y, thdata[i].altxpm.mask, ShapeUnion); } else { XShapeCombineMask(Disp, Win, ShapeBounding, thdata[i].x, thdata[i].y, thdata[i].altxpm.mask, ShapeUnion); } } } else { if (!th_no_icon_window) { XShapeCombineMask(Disp, Win, ShapeBounding, thdata[i].x, thdata[i].y, thdata[i].xpm.mask, ShapeUnion); XShapeCombineMask(Disp, Iconwin, ShapeBounding, thdata[i].x, thdata[i].y, thdata[i].xpm.mask, ShapeUnion); } else { if (thdata[i].icon) { XShapeCombineMask(Disp, Iconwin, ShapeBounding, thdata[i].x, thdata[i].y, thdata[i].xpm.mask, ShapeUnion); } else { XShapeCombineMask(Disp, Win, ShapeBounding, thdata[i].x, thdata[i].y, thdata[i].xpm.mask, ShapeUnion); } } } } void fak_maskset() { int i; if (debug) fprintf(stderr, "** Setting pixmaps mask\n"); if (debug) fprintf(stderr, "-> background\n"); XShapeCombineMask(Disp, Win, ShapeBounding, 0, 0, backXPM.mask, ShapeSet); if (!th_no_icon_window) { XShapeCombineMask(Disp, Iconwin, ShapeBounding, 0, 0, backXPM.mask, ShapeSet); } else { if (strlen(th_icon_window) > 0) { XShapeCombineMask(Disp, Iconwin, ShapeBounding, 0, 0, iconXPM.mask, ShapeSet); } } if (debug) fprintf(stderr, "-> buttons "); for (i=1; i <= but_max; i++) { if ((thdata[i].panel == panel) || (thdata[i].panel == 0)) { if (strlen(thdata[i].xpm_file) > 0) { if (debug) fprintf(stderr, "%d ", i); if ((fak_use_alt(i)) && (strlen(thdata[i].altxpm_file) > 0)) { if (!th_no_icon_window) { XShapeCombineMask(Disp, Win, ShapeBounding, thdata[i].x, thdata[i].y, thdata[i].altxpm.mask, ShapeUnion); XShapeCombineMask(Disp, Iconwin, ShapeBounding, thdata[i].x, thdata[i].y, thdata[i].altxpm.mask, ShapeUnion); } else { if (thdata[i].icon) { XShapeCombineMask(Disp, Iconwin, ShapeBounding, thdata[i].x, thdata[i].y, thdata[i].altxpm.mask, ShapeUnion); } else { XShapeCombineMask(Disp, Win, ShapeBounding, thdata[i].x, thdata[i].y, thdata[i].altxpm.mask, ShapeUnion); } } } else { if (!th_no_icon_window) { XShapeCombineMask(Disp, Win, ShapeBounding, thdata[i].x, thdata[i].y, thdata[i].xpm.mask, ShapeUnion); XShapeCombineMask(Disp, Iconwin, ShapeBounding, thdata[i].x, thdata[i].y, thdata[i].xpm.mask, ShapeUnion); } else { if (thdata[i].icon) { XShapeCombineMask(Disp, Iconwin, ShapeBounding, thdata[i].x, thdata[i].y, thdata[i].xpm.mask, ShapeUnion); } else { XShapeCombineMask(Disp, Win, ShapeBounding, thdata[i].x, thdata[i].y, thdata[i].xpm.mask, ShapeUnion); } } } } } } if (debug) fprintf(stderr, "\n-> done.\n"); } void fak_redraw() { char txt[256]; int i; long int dodo = 300000; char cdtime[6]; int disp_time; int use_alt = FALSE; int offset; DIR *dir_fd; struct dirent *dir_pt; unsigned int fx; unsigned int fy; unsigned int fw; unsigned int fh; /* ============================================================== */ /* ============================================================== */ /* ============================================================== */ /* First part: check different modes before doing the real redraw */ /* ============================================================== */ /* ============================================================== */ /* ============================================================== */ if (debug) fprintf(stderr, "** Entering redraw routine\n"); if (!blind_mode) { if ((cur_cdmode == WM_CDM_PLAYING) || (wanna_play)) wm_cd_status(); } /* the panel auto-switch mode: */ if (((cur_cdmode == WM_CDM_STOPPED) || (cur_cdmode == WM_CDM_EJECTED)) && (panel_stop > 0)) panel = panel_stop; if (((cur_cdmode == WM_CDM_PLAYING) || (cur_cdmode == WM_CDM_PAUSED)) && (panel_play > 0)) panel = panel_play; /* =================================================================== Auto-Repeat mode: at then end of the CD, play again the first track =================================================================== */ if ((cur_track >= cur_ntracks) && (cur_cdmode != WM_CDM_PAUSED) && (cur_cdmode != WM_CDM_PLAYING)) { /*if (wanna_play) {*/ if (autorepeat) { newtext("A.Repeat"); do_autorepeat = TRUE; cd_control(PLAY); } else { cd_control(STOPONLY); /* added in 0.13 */ if (debug) fprintf(stderr, "-> Stopping\n"); cur_cdmode = WM_CDM_STOPPED; wm_cd_status(); cur_track = 0; redraw = TRUE; fak_maskset(); } } /* ======================================================= */ /* the next track handling. We have to skip 'avoid' tracks */ /* ======================================================= */ if ((cur_cdmode != WM_CDM_EJECTED) && (! ignore_avoid)) { if (cur_ntracks > 1) { /* only if there are more than ONE track */ if (cur_track != old_track) { if (debug) fprintf(stderr, "-> Track change (current = %d, old = %d)\n", cur_track, old_track); redraw = TRUE; i = cur_track - 1; while ((i <= cur_ntracks) && (cd->trk[i].avoid == 1)) { i ++; } /* go to the next valid track, only if it is now the current track... */ if (i != cur_track - 1) { direct_track = i + 1; cd_control(DIRECTTRACK); } } } } /* ====================================================================== Do we *really* need to update the counter? If the cur time is the same as last time, we simply exit the redraw function ====================================================================== */ if ((cur_track == old_track) && (lasttime == cur_pos_rel) && (!redraw) && (text_start == 0) && (strlen(led_text) == 0)) return; lasttime = cur_pos_rel; /* ===================================== */ /* ===================================== */ /* ===================================== */ /* ===================================== */ /* Dealing with the __real__ redraw now: */ /* ===================================== */ /* ===================================== */ /* ===================================== */ /* ===================================== */ if (debug) fprintf(stderr, "-> Redrawing\n"); fak_flush_expose(Win); fak_flush_expose(Iconwin); /* ================================ */ /* draw the text if we have a query */ /* ================================ */ /* but but but... If we see a "redraw" query, we skip the text! It will be displayed next time the function is called... 0.13 */ if (!redraw) { if (strlen(led_text) > 0) { if (text_start == 0) { text_start = time(NULL); fak_text("", MSG_PANEL, 0, FALSE); fak_text(led_text, MSG_PANEL, 0, FALSE); } if (time(NULL) - text_start > text_timeout) { text_start = 0; redraw = TRUE; strcpy(led_text, ""); fak_text("", MSG_PANEL, 0, FALSE); } else { if (!fade_out) return; } } } /* ======================================= */ /* if WINGs support, update the track list */ /* ======================================= */ #ifdef WMK if (cur_track != old_track) { update_track(); old_track = cur_track; } #endif /* =============================================== We don't redraw everything if not required, so whe ckech fo each element if redraw variable is set =============================================== */ /* the background: */ if (redraw) { if (debug) fprintf(stderr, "-> ** GLOBAL REDRAW NEEDED **\n"); XCopyArea(Disp,backXPM.pixmap,Win,WinGC,0,0,backXPM.attributes.width, backXPM.attributes.height,0,0); if (!th_no_icon_window) { XCopyArea(Disp,backXPM.pixmap,Iconwin,WinGC,0,0,backXPM.attributes.width, backXPM.attributes.height,0,0); } else { if (strlen(th_icon_window) > 0) { XCopyArea(Disp,iconXPM.pixmap,Iconwin,WinGC,0,0,iconXPM.attributes.width, iconXPM.attributes.height,0,0); } } } /* the buttons: */ for (i = 1; i <= but_max; i++) { use_alt = FALSE; if ((thdata[i].panel == panel) || (thdata[i].panel == 0)) { if (thdata[i].type == FAK_VCD_BAR) { if ( (cur_cdmode != WM_CDM_STOPPED) && (cur_cdmode != WM_CDM_EJECTED) ) { if ((time_mode == 2) || (time_mode == 3)) { if (cur_cdlen > 0) { XCopyArea(Disp, thdata[i].xpm.pixmap, Win, WinGC, 0, 0, thdata[i].xpm.attributes.width, 0 + (int)((float)cur_pos_abs / (float)cur_cdlen * (float)thdata[i].xpm.attributes.height), thdata[i].x, thdata[i].y); if (!th_no_icon_window) { XCopyArea(Disp, thdata[i].xpm.pixmap, Iconwin, WinGC, 0, 0, thdata[i].xpm.attributes.width, 0 + (int)((float)cur_pos_abs / (float)cur_cdlen * (float)thdata[i].xpm.attributes.height), thdata[i].x, thdata[i].y); } } } else { if (cur_tracklen > 0) { XCopyArea(Disp, thdata[i].xpm.pixmap, Win, WinGC, 0, 0, thdata[i].xpm.attributes.width, 0 + (int)((float)cur_pos_rel / (float)cur_tracklen * (float)thdata[i].xpm.attributes.height), thdata[i].x, thdata[i].y); if (!th_no_icon_window) { XCopyArea(Disp, thdata[i].xpm.pixmap, Iconwin, WinGC, 0, 0, thdata[i].xpm.attributes.width, 0 + (int)((float)cur_pos_rel / (float)cur_tracklen * (float)thdata[i].xpm.attributes.height), thdata[i].x, thdata[i].y); } } } } } else if (thdata[i].type == FAK_ICD_BAR) { if ( (cur_cdmode != WM_CDM_STOPPED) && (cur_cdmode != WM_CDM_EJECTED) ) { if ((time_mode == 2) || (time_mode == 3)) { if (cur_cdlen > 0) { offset = (int)((float)cur_pos_abs / (float)cur_cdlen * (float)thdata[i].xpm.attributes.height); offset = thdata[i].xpm.attributes.height - offset; XCopyArea(Disp, thdata[i].xpm.pixmap, Win, WinGC, 0, 0, thdata[i].xpm.attributes.width, thdata[i].xpm.attributes.height - offset, thdata[i].x, thdata[i].y +offset); if (!th_no_icon_window) { XCopyArea(Disp, thdata[i].xpm.pixmap, Iconwin, WinGC, 0, 0, thdata[i].xpm.attributes.width, thdata[i].xpm.attributes.height - offset, thdata[i].x, thdata[i].y +offset); } } } else { if (cur_tracklen > 0) { offset = (int)((float)cur_pos_rel / (float)cur_tracklen * (float)thdata[i].xpm.attributes.height); offset = thdata[i].xpm.attributes.height - offset; XCopyArea(Disp, thdata[i].xpm.pixmap, Win, WinGC, 0, 0, thdata[i].xpm.attributes.width, thdata[i].xpm.attributes.height - offset, thdata[i].x, thdata[i].y +offset); if (!th_no_icon_window) { XCopyArea(Disp, thdata[i].xpm.pixmap, Iconwin, WinGC, 0, 0, thdata[i].xpm.attributes.width, thdata[i].xpm.attributes.height - offset, thdata[i].x, thdata[i].y +offset); } } } } } else if (thdata[i].type == FAK_CD_BAR) { if ( (cur_cdmode != WM_CDM_STOPPED) && (cur_cdmode != WM_CDM_EJECTED) ) { if ((time_mode == 2) || (time_mode == 3)) { if (cur_cdlen > 0) { XCopyArea(Disp, thdata[i].xpm.pixmap, Win, WinGC, 0, 0, 0 + (int)((float)cur_pos_abs / (float)cur_cdlen * (float)thdata[i].xpm.attributes.width), thdata[i].xpm.attributes.height, thdata[i].x, thdata[i].y); if (!th_no_icon_window) { XCopyArea(Disp, thdata[i].xpm.pixmap, Iconwin, WinGC, 0, 0, 0 + (int)((float)cur_pos_abs / (float)cur_cdlen * (float)thdata[i].xpm.attributes.width), thdata[i].xpm.attributes.height, thdata[i].x, thdata[i].y); } } } else { if (cur_tracklen > 0) { XCopyArea(Disp, thdata[i].xpm.pixmap, Win, WinGC, 0, 0, 0 + (int)((float)cur_pos_rel / (float)cur_tracklen * (float)thdata[i].xpm.attributes.width), thdata[i].xpm.attributes.height, thdata[i].x, thdata[i].y); if (!th_no_icon_window) { XCopyArea(Disp, thdata[i].xpm.pixmap, Iconwin, WinGC, 0, 0, 0 + (int)((float)cur_pos_rel / (float)cur_tracklen * (float)thdata[i].xpm.attributes.width), thdata[i].xpm.attributes.height, thdata[i].x, thdata[i].y); } } } } } else if (thdata[i].type == FAK_VCD_PIX) { /************** vertical pixmap slider *****************/ if ((cur_cdmode != WM_CDM_STOPPED) && (cur_cdmode != WM_CDM_EJECTED) && (cur_cdlen > 0)) { /* erase the old position : */ if (thdata[i].ox > 0) { XCopyArea(Disp, thdata[i].xpm.pixmap, Win, WinGC, 0, thdata[i].oy, thdata[i].altxpm.attributes.width, thdata[i].altxpm.attributes.height, thdata[i].x, thdata[i].oy + thdata[i].y); if (!th_no_icon_window) { XCopyArea(Disp, thdata[i].xpm.pixmap, Iconwin, WinGC, 0, thdata[i].oy, thdata[i].altxpm.attributes.width, thdata[i].altxpm.attributes.height, thdata[i].x, thdata[i].oy + thdata[i].y); } } /* compute the new geometry: */ if ((time_mode == 2) || (time_mode == 3)) fx = (int)((float)cur_pos_abs / (float)cur_cdlen * (float)(thdata[i].xpm.attributes.width - thdata[i].altxpm.attributes.width)); else fx = (int)((float)cur_pos_rel / (float)cur_tracklen * (float)(thdata[i].xpm.attributes.width - thdata[i].altxpm.attributes.width)); /* ugly, need to CHANGE THIS!!!!! */ if (fx < 1) fx = 1; /* and show it: */ XCopyArea(Disp, thdata[i].altxpm.pixmap, Win, WinGC, 0, 0, thdata[i].altxpm.attributes.width, thdata[i].altxpm.attributes.height, thdata[i].x, thdata[i].y + fx); if (!th_no_icon_window) { XCopyArea(Disp, thdata[i].altxpm.pixmap, Iconwin, WinGC, 0, 0, thdata[i].altxpm.attributes.width, thdata[i].altxpm.attributes.height, thdata[i].x, thdata[i].y + fx); } /* finaly, save it! */ thdata[i].oy = fx; } } else if (thdata[i].type == FAK_CD_PIX) { /**************** horizontal pixmap slider *****************/ if ((cur_cdmode != WM_CDM_STOPPED) && (cur_cdmode != WM_CDM_EJECTED) && (cur_cdlen > 0)) { /* erase the old position : */ if (thdata[i].ox > 0) { XCopyArea(Disp, thdata[i].xpm.pixmap, Win, WinGC, thdata[i].ox, 0, thdata[i].altxpm.attributes.width, thdata[i].altxpm.attributes.height, thdata[i].ox + thdata[i].x, thdata[i].y); if (!th_no_icon_window) { XCopyArea(Disp, thdata[i].xpm.pixmap, Iconwin, WinGC, thdata[i].ox, 0, thdata[i].altxpm.attributes.width, thdata[i].altxpm.attributes.height, thdata[i].ox + thdata[i].x, thdata[i].y); } } /* compute the new geometry: */ if ((time_mode == 2) || (time_mode == 3)) fx = (int)((float)cur_pos_abs / (float)cur_cdlen * (float)(thdata[i].xpm.attributes.height - thdata[i].altxpm.attributes.height)); else fx = (int)((float)cur_pos_rel / (float)cur_tracklen * (float)(thdata[i].xpm.attributes.height - thdata[i].altxpm.attributes.height)); /* ugly, need to CHANGE THIS!!!!! */ if (fx < 1) fx = 1; /* and show it: */ XCopyArea(Disp, thdata[i].altxpm.pixmap, Win, WinGC, 0, 0, thdata[i].altxpm.attributes.width, thdata[i].altxpm.attributes.height, thdata[i].x + fx, thdata[i].y); if (!th_no_icon_window) { XCopyArea(Disp, thdata[i].altxpm.pixmap, Iconwin, WinGC, 0, 0, thdata[i].altxpm.attributes.width, thdata[i].altxpm.attributes.height, thdata[i].x + fx, thdata[i].y); } /* finaly, save it! */ thdata[i].ox = fx; } } else if (thdata[i].type == FAK_VOL_BAR) { if ( (cur_cdmode != WM_CDM_STOPPED) && (cur_cdmode != WM_CDM_EJECTED) ) { XCopyArea(Disp, thdata[i].xpm.pixmap, Win, WinGC, 0, 0, 0 + (int)((float)volume / (float)max_volume * (float)thdata[i].xpm.attributes.width), thdata[i].xpm.attributes.height, thdata[i].x, thdata[i].y); if (!th_no_icon_window) { XCopyArea(Disp, thdata[i].xpm.pixmap, Iconwin, WinGC, 0, 0, 0 + (int)((float)volume / (float)max_volume * (float)thdata[i].xpm.attributes.width), thdata[i].xpm.attributes.height, thdata[i].x, thdata[i].y); } } } else if (thdata[i].type == FAK_VOL_PIX) { if ((cur_cdmode != WM_CDM_STOPPED) && (cur_cdmode != WM_CDM_EJECTED)) { /* first erase the old position : */ if (thdata[i].ox > 0) { XCopyArea(Disp, thdata[i].xpm.pixmap, Win, WinGC, thdata[i].ox, 0, thdata[i].altxpm.attributes.width, thdata[i].altxpm.attributes.height, thdata[i].ox + thdata[i].x, thdata[i].y); if (!th_no_icon_window) { XCopyArea(Disp, thdata[i].xpm.pixmap, Iconwin, WinGC, thdata[i].ox, 0, thdata[i].altxpm.attributes.width, thdata[i].altxpm.attributes.height, thdata[i].ox + thdata[i].x, thdata[i].y); } } /* compute the new geometry: */ fx = (int)((float)volume / (float)max_volume * (float)(thdata[i].xpm.attributes.width - thdata[i].altxpm.attributes.width)); /* ugly, need to CHANGE THIS!!!!! */ if (fx < 1) fx = 1; /* and show it: */ XCopyArea(Disp, thdata[i].altxpm.pixmap, Win, WinGC, 0, 0, thdata[i].altxpm.attributes.width, thdata[i].altxpm.attributes.height, thdata[i].x + fx, thdata[i].y); if (!th_no_icon_window) { XCopyArea(Disp, thdata[i].altxpm.pixmap, Iconwin, WinGC, 0, 0, thdata[i].altxpm.attributes.width, thdata[i].altxpm.attributes.height, thdata[i].x + fx, thdata[i].y); } /* finaly, save it! */ thdata[i].ox = fx; } } else if (thdata[i].type == FAK_VVOL_BAR) { if ( (cur_cdmode != WM_CDM_STOPPED) && (cur_cdmode != WM_CDM_EJECTED) ) { XCopyArea(Disp, thdata[i].xpm.pixmap, Win, WinGC, 0, 0, thdata[i].xpm.attributes.width, 0 + (int)((float)volume / (float)max_volume * (float)thdata[i].xpm.attributes.height), thdata[i].x, thdata[i].y); if (!th_no_icon_window) { XCopyArea(Disp, thdata[i].xpm.pixmap, Iconwin, WinGC, 0, 0, thdata[i].xpm.attributes.width, 0 + (int)((float)volume / (float)max_volume * (float)thdata[i].xpm.attributes.height), thdata[i].x, thdata[i].y); } } } else if (thdata[i].type == FAK_IVOL_BAR) { if ( (cur_cdmode != WM_CDM_STOPPED) && (cur_cdmode != WM_CDM_EJECTED) ) { offset = (int)((float)volume / (float)max_volume * (float)thdata[i].xpm.attributes.height); offset = thdata[i].xpm.attributes.height - offset; XCopyArea(Disp, thdata[i].xpm.pixmap, Win, WinGC, 0, offset, thdata[i].xpm.attributes.width, thdata[i].xpm.attributes.height - offset, thdata[i].x, thdata[i].y +offset); if (!th_no_icon_window) { XCopyArea(Disp, thdata[i].xpm.pixmap, Iconwin, WinGC, 0, offset, thdata[i].xpm.attributes.width, thdata[i].xpm.attributes.height - offset, thdata[i].x, thdata[i].y +offset); } } } else if (thdata[i].type == FAK_MIXER_BAR) { #ifdef MIXER XCopyArea(Disp, thdata[i].xpm.pixmap, Win, WinGC, 0, 0, 0 + (int)((float)getvol(thdata[i].arg) / 100.0 * (float)thdata[i].xpm.attributes.width), thdata[i].xpm.attributes.height, thdata[i].x, thdata[i].y); if (!th_no_icon_window) { XCopyArea(Disp, thdata[i].xpm.pixmap, Iconwin, WinGC, 0, 0, 0 + (int)((float)getvol(thdata[i].arg) / 100.0 * (float)thdata[i].xpm.attributes.width), thdata[i].xpm.attributes.height, thdata[i].x, thdata[i].y); } #endif } else if (thdata[i].type == FAK_VMIXER_BAR) { #ifdef MIXER XCopyArea(Disp, thdata[i].xpm.pixmap, Win, WinGC, 0, 0, thdata[i].xpm.attributes.width, 0 + (int)((float)getvol(thdata[i].arg) / 100.0 * (float)thdata[i].xpm.attributes.height), thdata[i].x, thdata[i].y); if (!th_no_icon_window) { XCopyArea(Disp, thdata[i].xpm.pixmap, Iconwin, WinGC, 0, 0, thdata[i].xpm.attributes.width, 0 + (int)((float)getvol(thdata[i].arg) / 100.0 * (float)thdata[i].xpm.attributes.height), thdata[i].x, thdata[i].y); } #endif } else if (thdata[i].type == FAK_IMIXER_BAR) { #ifdef MIXER offset = (int)((float)getvol(thdata[i].arg) / 100.0 * (float)thdata[i].xpm.attributes.height); offset = thdata[i].xpm.attributes.height - offset; XCopyArea(Disp, thdata[i].xpm.pixmap, Win, WinGC, 0, offset, thdata[i].xpm.attributes.width, thdata[i].xpm.attributes.height - offset, thdata[i].x, thdata[i].y + offset); if (!th_no_icon_window) { XCopyArea(Disp, thdata[i].xpm.pixmap, Iconwin, WinGC, 0, offset, thdata[i].xpm.attributes.width, thdata[i].xpm.attributes.height - offset, thdata[i].x, thdata[i].y + offset); } #endif } else { if (redraw) { if (strlen(thdata[i].xpm_file) > 0) { if (strlen(thdata[i].altxpm_file) == 0) use_alt = FALSE; else use_alt = fak_use_alt(i); if (use_alt) { if (!th_no_icon_window) { XCopyArea(Disp, thdata[i].altxpm.pixmap, Win, WinGC, 0, 0, thdata[i].xpm.attributes.width, thdata[i].altxpm.attributes.height, thdata[i].x, thdata[i].y); XCopyArea(Disp, thdata[i].altxpm.pixmap, Iconwin, WinGC, 0, 0, thdata[i].xpm.attributes.width, thdata[i].altxpm.attributes.height, thdata[i].x, thdata[i].y); } else { if (thdata[i].icon) { XCopyArea(Disp, thdata[i].altxpm.pixmap, Iconwin, WinGC, 0, 0, thdata[i].xpm.attributes.width, thdata[i].altxpm.attributes.height, thdata[i].x, thdata[i].y); } else { XCopyArea(Disp, thdata[i].altxpm.pixmap, Win, WinGC, 0, 0, thdata[i].xpm.attributes.width, thdata[i].altxpm.attributes.height, thdata[i].x, thdata[i].y); } } } else { if (!th_no_icon_window) { XCopyArea(Disp, thdata[i].xpm.pixmap, Win, WinGC, 0, 0, thdata[i].xpm.attributes.width, thdata[i].xpm.attributes.height, thdata[i].x, thdata[i].y); XCopyArea(Disp, thdata[i].xpm.pixmap, Iconwin, WinGC, 0, 0, thdata[i].xpm.attributes.width, thdata[i].xpm.attributes.height, thdata[i].x, thdata[i].y); } else { if (thdata[i].icon) { XCopyArea(Disp, thdata[i].xpm.pixmap, Iconwin, WinGC, 0, 0, thdata[i].xpm.attributes.width, thdata[i].xpm.attributes.height, thdata[i].x, thdata[i].y); } else { XCopyArea(Disp, thdata[i].xpm.pixmap, Win, WinGC, 0, 0, thdata[i].xpm.attributes.width, thdata[i].xpm.attributes.height, thdata[i].x, thdata[i].y); } } } } } } } } redraw = FALSE; if (debug) fprintf(stderr, "-> Display [last section]\n"); /* The Track number */ /* if ((cur_cdmode == WM_CDM_PLAYING) || (cur_cdmode == WM_CDM_PAUSED)) { */ if (!th_no_minus) fak_text(" ", COUNTER_PANEL, 0, FALSE); else fak_text(" ", COUNTER_PANEL, 0, FALSE); /* no CD? no counters! */ if (cur_cdmode == WM_CDM_EJECTED) { if (!th_no_minus) fak_text("AScd", COUNTER_PANEL, 1, FALSE); else fak_text("AScd", COUNTER_PANEL, 0, FALSE); fak_text("NO CD", MSG_PANEL, 1, TRUE); if (debug) fprintf(stderr, "-> No CD. Leaving redraw routine\n"); return; } if (debug) fprintf(stderr, "-> Dealing with theme/fast_track selectors\n"); /* ================== */ /* The theme selector */ /* ================== */ if (theme_select > 0) { /* 5 seconds timeout */ if (time(NULL) - selectors_timeout <= 5) { fak_text("THEME", COUNTER_PANEL, 0, TRUE); sprintf(cdtime, "%02d", theme_select); fak_text(cdtime, TRACK_PANEL, 0, FALSE); i = 0; sprintf(txt, "%s/Themes", THDIR); if ((dir_fd = opendir(txt)) != NULL) { i = 0; while((dir_pt = readdir(dir_fd)) != NULL) { if (dir_pt->d_name[0] != '.') { i++; if (i == theme_select) { strcpy(selected_theme, dir_pt->d_name); fak_text(dir_pt->d_name, MSG_PANEL, 0, FALSE); } } } closedir(dir_fd); } return; } else { theme_select = 0; redraw = TRUE; } } /* =================== */ /* Fast Track selector */ /* =================== */ if (fast_track == 0) { if (cur_track > 0) { /* 15 seconds timeout */ if (time_mode != 15) { sprintf(cdtime, "%02d", cur_track); } else { sprintf(cdtime, "%02d", cur_ntracks - cur_track); } } else { sprintf(cdtime, "%02d", cur_ntracks); } if ((thdata[but_tracknbr].panel == panel) || (thdata[but_tracknbr].panel == 0)) fak_text(cdtime, TRACK_PANEL, 0, TRUE); } else { if (time(NULL) - selectors_timeout <= 3) { sprintf(cdtime, "%02d", fast_track); fak_text("TRACK", COUNTER_PANEL, 0, TRUE); if ((thdata[but_tracknbr].panel == panel) || (thdata[but_tracknbr].panel == 0)) fak_text(cdtime, TRACK_PANEL, 0, FALSE); return; } else { selectors_timeout = 0; fast_track = 0; redraw = TRUE; } } if (debug) fprintf(stderr, "-> Counter\n"); /* the counter: */ switch(time_mode) { case 0: fak_minus(); disp_time = cur_pos_rel; break; case 1: fak_minus(); disp_time = cur_tracklen - cur_pos_rel ; break; case 2: fak_minus(); disp_time = cur_pos_abs; break; default: fak_minus(); disp_time = cur_cdlen - cur_pos_abs; break; } strcpy(cdtime, "00:00"); if ((cur_cdmode == WM_CDM_PLAYING) || (cur_cdmode == WM_CDM_PAUSED)) { cdtime[0] = 0 ; cdtime[1] = (disp_time / 60); if (cdtime[1] >= 10) { cdtime[0] = (cdtime[1] / 10); cdtime[1] = (cdtime[1] % 10); } cdtime[3] = ((disp_time % 60) / 10); cdtime[4] = (disp_time % 10); } else { cdtime[0] = 0; cdtime[1] = (cur_cdlen / 60); if (cdtime[1] >= 10) { cdtime[0] = (cdtime[1] / 10); cdtime[1] = (cdtime[1] % 10); } cdtime[3] = ((cur_cdlen % 60) / 10); cdtime[4] = (cur_cdlen % 10); } cdtime[0] = cdtime[0] + 48; cdtime[1] = cdtime[1] + 48; cdtime[3] = cdtime[3] + 48; cdtime[4] = cdtime[4] + 48; if (th_no_minus) fak_text(cdtime, 0, 0, FALSE); else fak_text(cdtime, 0, 1, FALSE); /* ================= */ /* The auto fade out */ /* ================= */ if ((cur_cdmode == WM_CDM_PLAYING) && (fade_out)) { if (!fade_ok) { fade_ok = 1; return; } else { unmuted_volume = volume ; while (volume > min_volume) { volume = volume - fade_step; cd_volume(volume, 10, max_volume); usleep(dodo); } fade_out = 0; fade_ok = 0; cd_control(PAUSE); old_track = 0; volume = unmuted_volume; cd_volume(volume, 10, max_volume); } } /* ================= */ /* The auto fade in: */ /* ================= */ if ((cur_cdmode == WM_CDM_PAUSED) && (fade_out)){ if (!fade_ok) { fade_ok = 1; return; } else { unmuted_volume = volume; volume = min_volume; cd_volume(volume, 10, max_volume); wm_cd_status(); usleep(dodo * 5); cd_control(PAUSE); usleep(dodo * 5); while (volume < max_volume) { volume = volume + fade_step; cd_volume(volume, 10, max_volume); usleep(dodo); } fade_out = 0; fade_ok = 0; volume = unmuted_volume; cd_volume(volume, 10, max_volume); } } /* end of redraw routine */ old_track = cur_track; if (debug) fprintf(stderr, "-> End of global redraw. Leaving redraw routine\n"); } ascd-0.13.2.orig/ascd/misc.c0100644000175000017500000003435606722276231015016 0ustar hallonhallon/* =========================================================================== * AScd: the AfterStep and WindowMaker CD player * misc.c: various stuff * =========================================================================== * Copyright (c) 1999 Denis Bourez and Rob Malda. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Denis Bourez & Rob Malda * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY DENIS BOUREZ AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL DENIS BOUREZ, ROB MALDA OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * =========================================================================== */ #include "ext.h" extern tes_xgets(); extern fak_parse_line(); extern cd_control_version(); /* The rc file functions, taken from xfascd*/ void load_rc_file(int mx) { FILE *in; struct passwd *pw; char st[256]; if (NULL == (pw = getpwuid(getuid()))) { return; } else { sprintf(st, "%s/.ascdrc", pw->pw_dir); if ((in = fopen(st, "r"))) { while ( fgets(st, 255, in) ) { if (strlen(st) > 0) st[strlen(st) - 1] = 0; if (!mx) { #ifndef NO_D_DEVICE if (strncmp(st, "CD_DEVICE=", 10) == 0) strcpy(cd_device, st + 10); else if (strncmp(st, "THEME=", 6) == 0) strcpy(theme, st + 6); else if (strncmp(st, "VISU=", 5) == 0) strcpy(xv, st + 5); else if (strncmp(st, "AUTOREPEAT=", 11) == 0) autorepeat = atoi(st + 11); #else if (strncmp(st, "AUTOREPEAT=", 11) == 0) autorepeat = atoi(st + 11); #endif else if (strncmp(st, "AUTOPLAY=", 9) == 0) autoplay = atoi(st + 9); else if (strncmp(st, "AUTOPROBE=", 10) == 0) autoprobe = atoi(st + 10); else if (strncmp(st, "CUE_TIME=", 9) == 0) cue_time = atoi(st + 9); else if (strncmp(st, "TI=", 3) == 0) text_timeout = atoi(st + 3); else if (strncmp(st, "MAX_VOL=", 8) == 0) max_volume = atoi(st + 8); else if (strncmp(st, "MIN_VOL=", 8) == 0) min_volume = atoi(st + 8); else if (strncmp(st, "MUT_VOL=", 8) == 0) muted_volume = atoi(st + 8); else if (strncmp(st, "VOLUME=", 7) == 0) volume = atoi(st + 7); else if (strncmp(st, "FADE_STEP=", 10) == 0) fade_step = atoi(st + 10); else if (strncmp(st, "TIMEMODE=", 9) == 0) time_mode = atoi(st + 9); else if (strcmp(st, "WITHDRAWN") == 0) withdrawn = TRUE; else if (strcmp(st, "SHOWDB") == 0) show_db = TRUE; else if (strcmp(st, "SHOWARTIST") == 0) show_artist = TRUE; else if (strcmp(st, "UPPERCASE") == 0) force_upper = TRUE; else if (strncmp(st, "IGNORE_AVOID=", 13) == 0) ignore_avoid = atoi(st + 13); } } fclose(in); return; } else { return; } } } void save_rc_file() { FILE *out; struct passwd *pw; char st[128]; if (NULL == (pw = getpwuid(getuid()))) { /* hum... big problem... */ return; } else { sprintf(st, "%s/.ascdrc", pw->pw_dir); if ((out = fopen(st, "w"))) { fprintf(out, "#### generated by AScd version %s ####\n", VERSION); #ifndef NO_D_DEVICE fprintf(out, "CD_DEVICE=%s\n", cd_device); #endif fprintf(out, "THEME=%s\n", theme); fprintf(out, "VISU=%s\n", xv); fprintf(out, "AUTOREPEAT=%d\n", autorepeat); fprintf(out, "AUTOPLAY=%d\n", autoplay); fprintf(out, "AUTOPROBE=%d\n", autoprobe); fprintf(out, "CUE_TIME=%d\n", cue_time); fprintf(out, "TI=%d\n", text_timeout); fprintf(out, "VOLUME=%d\n", volume); fprintf(out, "MAX_VOL=%d\n", max_volume); fprintf(out, "MIN_VOL=%d\n", min_volume); fprintf(out, "MUT_VOL=%d\n", muted_volume); fprintf(out, "FADE_STEP=%d\n", fade_step); fprintf(out, "TIMEMODE=%d\n", time_mode); fprintf(out, "IGNORE_AVOID=%d\n", ignore_avoid); if (withdrawn) { fprintf(out, "WITHDRAWN\n"); } if (show_db) { fprintf(out, "SHOWDB\n"); } if (show_artist) { fprintf(out, "SHOWARTIST\n"); } if (force_upper) { fprintf(out, "UPPERCASE\n"); } fclose(out); return; } else { return; } } } void command_line_help() { fprintf(stderr, "ascd %s ", VERSION); #ifdef WMK fprintf(stderr, "[WINGs] "); #endif #ifdef MIXER fprintf(stderr, "[mixer] "); #endif fprintf(stderr, "\n(c) 1999 Rob Malda and Denis Bourez\n"); fprintf(stderr, "Usage: ascd [-options ...] where the options are:\n\n"); fprintf(stderr, "-version Display the version numbers and exit\n"); fprintf(stderr, "-help Display this help screen and exit\n"); fprintf(stderr, "-themes Display available themes and exit\n\n"); fprintf(stderr, "+/-withdrawn Turn on/off withdrawn mode for WindowMaker\n"); fprintf(stderr, "-geometry geom Standard X Location\n"); fprintf(stderr, "-ti time Texts display timeout in seconds (default = 1)\n"); fprintf(stderr, "-cue time Cue Time in seconds (default = 10)\n"); fprintf(stderr, "+/-a Turn on/off Autoplay mode\n"); fprintf(stderr, "+/-p Turn on/off Autoprobe mode\n"); fprintf(stderr, "+/-t Turn on/off Autorepeat mode\n"); fprintf(stderr, "+/-B Turn on/off Blind mode (no counters updates)\n"); fprintf(stderr, "+/-ia Apply/Ignore 'avoid' tags in WorkMan database\n"), fprintf(stderr, "+/-up All messages in uppercase?\n"); fprintf(stderr, "-theme value Select the visual theme (in %s)\n", THDIR); fprintf(stderr, "-xf Launch XfAscd with middle click on counter\n"); fprintf(stderr, "-minvolume value Minimum volume\n"); fprintf(stderr, "-maxvolume value Maximum volume\n"); fprintf(stderr, "-volume value CD Drive volume, from 0 to maxvolume\n"); fprintf(stderr, "-mvolume value CD Drive volume in mute mode, from 0 to maxvolume\n"); fprintf(stderr, "-fadestep value Fade in/out timing offset\n"); fprintf(stderr, "-device device_driver CDROM drive device\n"); #ifdef MIXER fprintf(stderr, "-mixer device_driver Mixer device\n"); #endif fprintf(stderr, "-showtitle Turn on Song Title Scrolling\n"); fprintf(stderr, "-showartist Show artist name when scrolling song title\n"); fprintf(stderr, "-debug Enable debug (verbose) messages on stderr\n"); fprintf(stderr, "-save Save settings and exit. Should be *last* command.\n\n"); exit(0); } void command_line_err() { fprintf(stderr, "ascd: bad command line syntax.\n"); fprintf(stderr, "Type 'ascd -help' for a list of command line options.\n"); exit(-1); } void themes_help() { char txt[256]; char key[256]; char r[256]; char d[256]; char arguments[256]; DIR *dir_fd; struct dirent *dir_pt; FILE *in; fprintf(stderr, "List of AScd installed themes:\n\n"); fprintf(stderr, "Theme Release Description\n"); fprintf(stderr, "---------------- ------------ -------------------------------------\n"); sprintf(txt, "%s/Themes", THDIR); if ((dir_fd = opendir(txt)) != NULL) { while((dir_pt = readdir(dir_fd)) != NULL) { if (dir_pt->d_name[0] != '.') { fprintf(stderr, "%-16s ", dir_pt->d_name); sprintf(txt, "%s/Themes/%s/Theme", THDIR, dir_pt->d_name); if (access(txt, R_OK) == 0) { if (!(in = fopen(txt, "r"))) { fprintf(stderr, "cannot open Theme definition file"); } else { strcpy(d, ""); strcpy(r, ""); while (tes_xgets(txt, 256, in)) { fak_parse_line(txt, key, arguments); if (strcmp(key, "release") == 0) strcpy(r, arguments); if (strcmp(key, "name") == 0) strcpy(d, arguments); } fprintf(stderr, "%-12s %s", r, d); fclose(in); } } else { fprintf(stderr, "cannot find Theme definition file"); } fprintf(stderr, "\n"); } } closedir(dir_fd); } else { fprintf(stderr, "Can't read directory %s!\n", txt); } fprintf(stderr, "\n"); exit(0); } #define MAX_LINE_NAME 16 void command_line_parse(int argc, char *argv[]) { int i; char *Argument; int sw; for (i = 1 ; i < argc ; i++) { Argument = argv[i]; if ((Argument[0] == '-') || (Argument[0] == '+')) { if (Argument[0] == '-') { sw = FALSE; } else if (Argument[0] == '+') { sw = TRUE; } if ((strcmp(Argument + 1, "w") == 0) || (strcmp(Argument + 1, "withdrawn") == 0)) { if (sw) withdrawn = TRUE; else withdrawn = FALSE; } else if ((strcmp(Argument + 1, "g") == 0) || (strcmp(Argument + 1, "geometry") == 0)) { if(++i >= argc) command_line_err(); Geometry = argv[i]; } else if ((strcmp(Argument + 1, "d") == 0) || (strcmp(Argument + 1, "device") == 0)) { if(++i >= argc) command_line_err(); cd_device = malloc(strlen(argv[i]) + 1); strcpy(cd_device, argv[i]); } #ifdef MIXER else if (strcmp(Argument + 1, "mixer") == 0) { if(++i >= argc) command_line_err(); strcpy(mixer_device, argv[i]); } #endif else if (strcmp(Argument + 1, "theme") == 0) { if(++i >= argc) command_line_err(); strcpy(theme, argv[i]); } else if ((strcmp(Argument + 1, "c") == 0) || (strcmp(Argument + 1, "cue") == 0)) { if(++i >= argc) command_line_err(); cue_time = atoi(argv[i]); } else if ((strcmp(Argument + 1, "i") == 0) || (strcmp(Argument + 1, "ti") == 0)) { if(++i >= argc) command_line_err(); text_timeout = atoi(argv[i]); } else if ((strcmp(Argument + 1, "a") == 0) || (strcmp(Argument + 1, "autoplay") == 0)) { if (sw) autoplay = TRUE; else autoplay = FALSE; } else if ((strcmp(Argument + 1, "p") == 0) || (strcmp(Argument + 1, "autoprobe") == 0)) { if (sw) autoprobe = TRUE; else autoprobe = FALSE; } else if (strcmp(Argument + 1, "B") == 0) { if (sw) blind_mode = TRUE; else blind_mode = FALSE; } else if (strcmp(Argument + 1, "ia") == 0) { if (sw) ignore_avoid = TRUE; else ignore_avoid = FALSE; } else if (strcmp(Argument + 1, "up") == 0) { if (sw) force_upper = TRUE; else force_upper = FALSE; } else if ((strcmp(Argument + 1, "t") == 0) || (strcmp(Argument + 1, "autorepeat") == 0)) { if (sw) autorepeat = TRUE; else autorepeat = FALSE; } else if (strcmp(Argument + 1, "showtitle") == 0) { show_db = TRUE; } else if (strcmp(Argument + 1, "showartist") == 0) { show_artist = TRUE; } else if (strcmp(Argument + 1, "debug") == 0) { debug++; } else if (strcmp(Argument + 1, "mvolume") == 0) { if(++i >= argc) command_line_err(); muted_volume = atoi(argv[i]); } else if (strcmp(Argument + 1, "volume") == 0) { if(++i >= argc) command_line_err(); volume = atoi(argv[i]); } else if (strcmp(Argument + 1, "xf") == 0) { xflaunch = TRUE; } else if (strcmp(Argument + 1, "maxvolume") == 0) { if(++i >= argc) command_line_err(); max_volume = atoi(argv[i]); } else if (strcmp(Argument + 1, "minvolume") == 0) { if(++i >= argc) command_line_err(); min_volume = atoi(argv[i]); } else if (strcmp(Argument + 1, "fadestep") == 0) { if(++i >= argc) command_line_err(); fade_step = atoi(argv[i]); } else if (strcmp(Argument + 1, "save") == 0) { save_rc_file(); fprintf(stderr, "Settings file saved.\n"); exit(0); } else if ((strcmp(Argument + 1, "version") == 0) || (strcmp(Argument + 1, "v") == 0)) { fprintf(stderr, "%s %s (CDcontrol %s, %s) ", PACKAGE, VERSION, (char *)cd_control_version(), wm_libver_string()); #ifdef WMK fprintf(stderr, "[WINGs] "); #endif #ifdef MIXER fprintf(stderr, "[mixer] "); #endif fprintf(stderr, "\n"); exit(0); } else if (strcmp(Argument + 1, "themes") == 0) { themes_help(); } else if ((strcmp(Argument + 1, "h") == 0) || (strcmp(Argument + 1, "help") == 0)) { command_line_help(); } else { command_line_err(); } } else { command_line_err(); } } } void quick_reference(int nbr) { char txt[127]; char fic[40]; if (nbr == 0) strcpy(fic, "quick*"); else sprintf(fic, "quick%d.gif", nbr); sprintf(txt, "%s/Themes/%s/quick", THDIR, theme); if (access(txt, R_OK) == 0) { sprintf(txt, "%s %s/Themes/%s/quick/%s &", xv, THDIR, theme, fic); system(txt); } } /* ------------------------------------------------------------------------ dumb functions: do nothing, but they need to be present if we don't wanna change anything in the WorkMan code... ------------------------------------------------------------------------ */ void disable_save() { } int get_playnew() { return autoplay; } void set_abtimer(int a, int b) { } void about_set_drivetype(char *vendor, char *model, char *rev) { } ascd-0.13.2.orig/ascd/handlers.c0100644000175000017500000002741306734025205015653 0ustar hallonhallon/* =========================================================================== * AScd: handlers.c * mouse events <-> integrated commands * =========================================================================== * Copyright (c) 1999 Denis Bourez and Rob Malda. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Denis Bourez & Rob Malda * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY DENIS BOUREZ AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL DENIS BOUREZ, ROB MALDA OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * =========================================================================== */ #include "ext.h" #include "faktory_prot.h" void theme_select_init() { char txt[256]; DIR *dir_fd; struct dirent *dir_pt; int i; theme_select = 1; theme_select_nbr = 0; sprintf(txt, "%s/Themes", THDIR); if ((dir_fd = opendir(txt)) != NULL) { while((dir_pt = readdir(dir_fd)) != NULL) if (dir_pt->d_name[0] != '.') theme_select_nbr++; closedir(dir_fd); } sprintf(txt, "%s/Themes", THDIR); if ((dir_fd = opendir(txt)) != NULL) { i = 0; while((dir_pt = readdir(dir_fd)) != NULL) { if (dir_pt->d_name[0] != '.') { i++; if (strcmp(dir_pt->d_name, theme) == 0) theme_select = i; } } closedir(dir_fd); } } void fak_event_handle(int event, XEvent Event) { /* global commands handling: panel switches, quit, GUI additional modules */ switch (event) { case FAK_QUIT: exit(0); break; case FAK_PANEL_SWITCH: panel++; if (panel > panels) panel = 1; fak_redraw(); fak_maskset(); break; case FAK_PANEL1: panel = 1; fak_redraw(); fak_maskset(); break; case FAK_PANEL2: panel = 2; fak_redraw(); fak_maskset(); break; case FAK_PANEL3: panel = 3; fak_redraw(); fak_maskset(); break; case FAK_PANEL4: panel = 4; fak_redraw(); fak_maskset(); break; case FAK_PANEL5: panel = 5; fak_redraw(); fak_maskset(); break; case FAK_WINGS: /* must be compiled with WINGs support */ #ifdef WMK big_window(scr); #endif break; case FAK_COUNTER_MODE: time_mode++ ; if (time_mode > 3) time_mode = 0; break; case FAK_TOG_SHOWDB: if (show_db) show_db = FALSE; else show_db = TRUE; redraw = TRUE; break; case FAK_TOG_SHOWARTIST: if (show_artist) show_artist = FALSE; else show_artist = TRUE; redraw = TRUE; break; case FAK_TOG_UPPER: if (force_upper) force_upper = FALSE; else force_upper = TRUE; redraw = TRUE; break; case FAK_TOG_AUTOPLAY: if (autoplay) autoplay = FALSE; else autoplay = TRUE; redraw = TRUE; break; case FAK_TOG_AUTOREPEAT: if (autorepeat) autorepeat = FALSE; else autorepeat = TRUE; redraw = TRUE; break; case FAK_TOG_ISKIPS: if (ignore_avoid) ignore_avoid = FALSE; else ignore_avoid = TRUE; redraw = TRUE; break; case FAK_TSELECT: if (theme_select == 0) { selectors_timeout = time(NULL); theme_select_init(); } else { theme_select = 0; strcpy(theme, selected_theme); fak_load_theme(theme, TRUE); fak_maskset(); } break; case FAK_TNEXT: selectors_timeout = time(NULL); if (theme_select == 0) theme_select_init(); theme_select ++; if (theme_select > theme_select_nbr) theme_select = 1; break; case FAK_TPREVIOUS: selectors_timeout = time(NULL); if (theme_select == 0) theme_select_init(); theme_select --; if (theme_select == 0) theme_select = theme_select_nbr; break; case FAK_FTSELECT: show_db_pos = 0; if (fast_track == 0) { fast_track = cur_track; selectors_timeout = time(NULL); } else { if (fast_track != cur_track) { direct_track = fast_track; fast_track = 0; cd_control(DIRECTTRACK); } } break; case FAK_FTNEXT: selectors_timeout = time(NULL); show_db_pos = 0; if (fast_track == 0) { if (cur_track < cur_ntracks) fast_track = cur_track + 1; else fast_track = 1; } else { if (fast_track == cur_ntracks) fast_track = 1; else fast_track++; } break; case FAK_FTPREVIOUS: selectors_timeout = time(NULL); show_db_pos = 0; if (fast_track == 0) { if (cur_track > 1) fast_track = cur_track - 1; else fast_track = cur_ntracks; } else { if (fast_track == 1) fast_track = cur_ntracks; else fast_track--; } break; case FAK_SAVE: newtext("Saving"); save_rc_file(); break; case FAK_LOAD: newtext("Loading"); load_rc_file(); break; case FAK_QREF: quick_reference(thdata[but_current].arg); break; default: break; } redraw = TRUE; fak_singlemask(but_current); } void cd_event_handle(int event, XEvent Event) { /* All the AScd CD player commands, access to cd_control() */ switch (event) { case FAK_CD_PLAY: case FAK_CD_PAUSE: if (cur_cdmode == WM_CDM_PAUSED) { newtext("Playing"); wanna_play = TRUE; cd_control(PAUSE); } else if (cur_cdmode == WM_CDM_PLAYING) { if (fast_track != 0) { direct_track = fast_track; fast_track = 0; cd_control(DIRECTTRACK); } else { newtext("Paused"); cd_control(PAUSE); } } else if (cur_cdmode == WM_CDM_EJECTED) { /* the future?. Not yet working on my FreeBSD box... */ cd_control(CLOSETRAY); } else { newtext("Play"); wanna_play = TRUE; cd_control(PLAY); if (cd->volume > 0) { volume=cd->volume; cd_volume(volume, 10, max_volume); } } redraw = TRUE; fak_redraw(); break; case FAK_CD_STOP: fast_track = 0; if (cur_cdmode != WM_CDM_STOPPED) { newtext("Stop"); cd_control(STOPONLY); wm_cd_status(); cur_track = 0; redraw = TRUE; fak_redraw(); } break; case FAK_CD_STOPEJECT: fast_track = 0; if (cur_cdmode != WM_CDM_STOPPED) { newtext("Stop"); cd_control(STOPONLY); wm_cd_status(); cur_track = 0; redraw = TRUE; fak_redraw(); fak_maskset(); } else { newtext("Eject"); cd_control(EJECT); redraw = TRUE; fak_redraw(); } break; case FAK_CD_EJECT: fast_track = 0; newtext("Eject"); cd_control(EJECT); redraw = TRUE; fak_redraw(); break; case FAK_CD_EJECTQUIT: fast_track = 0; if ((cur_cdmode != WM_CDM_EJECTED) && (cur_cdmode != WM_CDM_STOPPED)) { newtext("Eject"); cd_control(EJECT); redraw = TRUE; fak_redraw(); } else { exit(0); } break; case FAK_CD_NEXT: cd_control(UPTRACK); break; case FAK_CD_PREVIOUS: cd_control(DNTRACK); break; case FAK_CD_FIRST: cd_control(FIRST); break; case FAK_CD_LAST: cd_control(LAST); break; case FAK_CD_REW: cd_control(REV); break; case FAK_CD_FWD: cd_control(CUE); break; case FAK_CD_DIRECT: /* Direct Access: we have to compute the offset to pass it to cd_control. We also have to check if we want to move inside the current track or in the whole CD */ if (cur_track < 1) cur_track = 1; if ((time_mode == 2) || (time_mode == 3)) { if ((thdata[but_current].type == FAK_CD_BAR) || (thdata[but_current].type == FAK_CD_PIX)) { direct_access = (int)((float)(Event.xbutton.x - thdata[but_current].x) / (float)thdata[but_current].xpm.attributes.width * (float)cur_cdlen); } else if (thdata[but_current].type == FAK_ICD_BAR) { direct_access = (int)((float)(Event.xbutton.y - thdata[but_current].y) / (float)thdata[but_current].xpm.attributes.height * (float)cur_cdlen); direct_access = cur_cdlen - direct_access; } else { direct_access = (int)((float)(Event.xbutton.y - thdata[but_current].y) / (float)thdata[but_current].xpm.attributes.height * (float)cur_cdlen); } cd_control(GLOBALACCESS); } else { if ((thdata[but_current].type == FAK_CD_BAR) || (thdata[but_current].type == FAK_CD_PIX)) { direct_access = (int)((float)(Event.xbutton.x - thdata[but_current].x) / (float)thdata[but_current].xpm.attributes.width * (float)cur_tracklen); } else if (thdata[but_current].type == FAK_ICD_BAR) { direct_access = (int)((float)(Event.xbutton.y - thdata[but_current].y) / (float)thdata[but_current].xpm.attributes.height * (float)cur_tracklen); direct_access = cur_tracklen - direct_access; } else { direct_access = (int)((float)(Event.xbutton.y - thdata[but_current].y) / (float)thdata[but_current].xpm.attributes.height * (float)cur_tracklen); } cd_control(DIRECTACCESS); } wm_cd_status(); redraw = TRUE; fak_redraw(); fak_maskset(); break; case FAK_CD_VOLUME: if ((cur_cdmode != WM_CDM_EJECTED) && (cur_cdmode != WM_CDM_STOPPED)) { if ((thdata[but_current].xpm.attributes.width > 0) && (max_volume > 0)) { if (thdata[but_current].type == FAK_VVOL_BAR) { volume = (int)((float)(Event.xbutton.y - thdata[but_current].y) / (float)thdata[but_current].xpm.attributes.height * (float)max_volume); } else if (thdata[but_current].type == FAK_IVOL_BAR) { volume = (int)((float)(Event.xbutton.y - thdata[but_current].y) / (float)thdata[but_current].xpm.attributes.height * (float)max_volume); volume = max_volume - volume; } else { volume = (int)((float)(Event.xbutton.x - thdata[but_current].x) / (float)thdata[but_current].xpm.attributes.width * (float)max_volume); } cd_volume(volume, 10, max_volume); wm_cd_status(); redraw = TRUE; fak_redraw(); } } break; case FAK_CD_LOOP: if (loop_mode) { loop_mode = 0; newtext("Loop Off"); } else { cd_control(LOOP); if (!anomalie) newtext("Loop On"); else newtext("ERROR!"); } redraw = TRUE; break; case FAK_CD_LSTART: loop_1 = cur_pos_rel; newtext("L. Start"); loop_start_track = cur_track; break; case FAK_CD_LEND: loop_2 = cur_pos_rel; loop_end_track = cur_track; newtext("L. End"); break; case FAK_CD_GOLSTART: direct_access = loop_1; cd_control(DIRECTACCESS); break; case FAK_CD_GOLEND: direct_access = loop_2; cd_control(DIRECTACCESS); break; case FAK_CD_LTRACK: loop_1 = 0; loop_2 = cur_tracklen; loop_start_track = cur_track; loop_end_track = cur_track; break; case FAK_CD_LCLEAR: loop_1 = 0; loop_2 = 0; loop_start_track = 1; loop_end_track = 1; newtext("L. Clear"); break; case FAK_CD_INTRO: cd_control(INTROSCAN); wm_cd_status(); newtext("Intro"); fak_maskset(); break; case FAK_CD_MUTE: if (muted) { muted = 0; newtext("Mute Off"); cd_volume(volume, 10, max_volume); } else { newtext("Mute On"); muted = 1; cd_volume(muted_volume, 10, max_volume); } break; case FAK_CD_FADE: fade_out = TRUE; newtext("Fade..."); /*fak_redraw();*/ break; default: break; } redraw = TRUE; fak_singlemask(but_current); } ascd-0.13.2.orig/ascd/ext.h0100644000175000017500000000677306740156262014673 0ustar hallonhallon#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "ascd.h" #include #ifdef WMK #include #endif extern open(); extern time(); /* added this for this lib: */ extern unsigned int info_modified; extern int wanted_track; extern unsigned int do_autorepeat; extern int anomalie; /* xfascd vars */ extern unsigned int wanna_play; #ifdef XFASCD extern unsigned int update_xpm; #endif extern unsigned int blind_mode; extern unsigned int loop_mode, intro_mode; extern unsigned int datatrack, cue_time; extern unsigned int loop_start_track, loop_end_track; extern unsigned int loop_1; extern unsigned int loop_2; extern unsigned int direct_access, direct_track; extern unsigned int ignore_avoid; extern int lasttime; extern Display *Disp; extern Window Root; extern Window Iconwin; extern Window Win; extern char *Geometry; extern char device[]; extern char xv[]; extern int withdrawn; extern GC WinGC; extern int CarrierOn; extern char led_text[]; extern unsigned int text_timeout; extern long text_start; extern int redraw; extern int mixer_changed; extern unsigned int autorepeat; extern unsigned int autoplay; extern unsigned int autoprobe; extern unsigned int time_mode; extern unsigned int global_mode; extern unsigned int volume; extern unsigned int muted_volume; extern unsigned int muted; extern unsigned int unmuted_volume; extern unsigned int fade_ok; extern unsigned int old_track; extern int selectors_timeout; /* The WorkMan stuff: */ extern char *cd_device; /* from/for WorkMan database code: */ extern int mark_a; extern int mark_b; extern int cur_stopmode; extern int cur_playnew; extern char theme[]; extern char selected_theme[]; extern unsigned int theme_select; extern unsigned int theme_select_nbr; extern int no_mask; extern unsigned int show_db; extern unsigned int show_artist; extern unsigned int show_db_pos; extern unsigned int show_icon_db_pos; extern unsigned int force_upper; extern unsigned int fast_track; extern unsigned int xflaunch; extern unsigned int fade_out; extern unsigned int fade_step; extern int min_volume,max_volume; /* from LibWorkMan */ extern int debug; extern unsigned int panel; /* current panel */ extern unsigned int panels; /* how many panels? */ extern unsigned int but_max; /* how many buttons? */ extern unsigned int but_msg; /* which one is the message zone? */ extern unsigned int but_counter; /* which one is the counter? */ extern unsigned int but_tracknbr; /* which one is the track number? */ extern unsigned int but_db; extern unsigned int icon_msg; extern unsigned int icon_counter; extern unsigned int icon_tracknbr; extern unsigned int but_current; extern unsigned int panel_stop; extern unsigned int panel_play; extern char th_name[]; extern char th_author[]; extern char th_release[]; extern char th_email[]; extern char th_url[]; extern char th_comment[]; extern char th_alpha1[]; extern char th_alpha2[]; extern char th_background[]; extern char th_icon_window[]; extern int th_no_minus; extern int th_no_icon_window; extern struct fak_button thdata[]; extern XpmIcon alphaXPM; extern XpmIcon ralphaXPM; extern XpmIcon backXPM; extern XpmIcon iconXPM; #ifdef WMK #include "wings_ext.h" #endif #ifdef MIXER #include "mixer_ext.h" #endif ascd-0.13.2.orig/ascd/README0100644000175000017500000001075506720103443014564 0ustar hallonhallon======================================================================== AScd 0.13 CD player for Afterstep and Window Maker ======================================================================== MAINTAINER: Denis Bourez: - email: denis@rsn.fdn.fr - AScd home page: http://worldserver.oleane.com/rsn/ AScd ORIGINAL AUTHOR: Rob Malda: - email: malda@slashdot.org - WWW: http://CmdrTaco.net/ ======================================================================== DESCRIPTION: AScd is a CD player that can be "docked" on the Afterstep Wharf or the Window Maker dock. It uses libworkman to access CD drivers. ======================================================================== HISTORY: AScd 0.1 -> 0.6 --------------- The original code was taken by Rob Malda from asclock (Afterstep wharf module, by Beat Christen ) and from workbone (CD driver). AScd 0.7 -> 0.9 --------------- I removed all the workbone code (Linux specific): ascd could then be compiled on several UN*X flavors. I took a big part or the WorkMan (see at the end of this text) src and merged it with the ascd 0.4 interface. The WorkMan code was compiled as a library. AScd >= 0.10 ------------ WorkMan has splitted in 2 parts: the ui and the lib, named libworkman. So, AScd uses this brand new lib, instead of the one which was included in the AScd's archive. WorkMan's maintainer is Dirk Foersterling (milliByte@DeathsDoor.com). AScd >= 0.12 ------------ AScd no longer includes the pixmaps in the source files. It is now possible to change the pixmaps theme at run time. AScd now needs a directory where to store the pixmaps. The default is /usr/local/share/AScd. AScd >= 0.13 ------------ The theme files are now fully customizable. All theme directories are installed by default in /usr/local/share/AScd/Themes. ======================================================================== HOW TO COMPILE???? ======================================================================== You need to download, compile and install the WorkMan library. Please use the 99/05/05 snapshot wish can be found on the AScd's home page or on the primary ftp site for WorkMan: ftp://ftp.midwinter.com/WorkMan/snapshots/ ======================================================================== CONFIGURATION ======================================================================== Run ./configure This script will ask you a few questions about compilation-time options, and generate a "config.h" file matching your choices. The script will then run xmkmf to generate the Makefile. ======================================================================== COMPILATION/INSTALLATION ======================================================================== IMPORTANT NOTE: if you're upgrading from AScd 0.12, please remove everything in the AScd default directory (/usr/local/share/AScd) as the theme files are *not* compatible. make - If you want to try the program, just type ./ascd (try './ascd -help' to see the commandline options) If everything is ok, you can install the program and the man page: make install make install.man * installation for AfterStep -------------------------- Add a line in your ~/.steprc file: *Wharf - - Swallow "ascd" /usr/local/bin/ascd -device /dev/wcd0a & (customized to your system settings of course!) * installation for Window Maker ----------------------------- Launch ascd with the "+w" option. Dock ascd by dragging it to the dock. ======================================================================== CREDITS ======================================================================== Denis Bourez (denis@rsn.fdn.fr) http://worldserver.oleane.com/rsn/ Rob Malda (malda@slashdot.org) http://CmdrTaco.net/ The 0.12 *digits.xpm were taken and modified from wmitime, an excellent clock applet for Window Maker. Wmitime was written by Dave Clark (clarkd@skynet.ca) More info at: http://www.neotokyo.org. I added the lower case letters. The new 0.13 default font is fully 8bit compatible! It has been drawn by Stefan Zeiger (szeiger@novocode.com). ======================================================================== Denis Bourez, 05/17/1999 ascd-0.13.2.orig/ascd/wings_global.c0100644000175000017500000000222506720011340016502 0ustar hallonhallon#include #include WMScreen *scr; /* the main window */ WMWindow *win; WMButton *b_title; WMPopUpButton *pop, *pop2, *pop3; WMButton *b_autoplay; WMButton *b_autorepeat; WMButton *b_ignoreavoid; WMTextField *b_device; WMSlider *b_volume; WMButton *b_scroll; WMButton *b_artist; WMButton *b_upper; WMTextField *b_cuetime; WMTextField *b_fadestep; WMTextField *b_minvol; WMTextField *b_maxvol; WMTextField *b_mutedvol; WMButton *b_mode1; WMButton *b_mode2; WMButton *b_mode3; WMButton *b_mode4; WMButton *b_save; WMButton *b_quit; WMButton *b_close; WMButton *b_about; WMButton *b_help; /* the database window */ WMWindow *dbwin; WMTextField *db_artist; WMTextField *db_title; WMTextField *db_track; WMButton *db_avoid; WMButton *db_playauto; WMSlider *db_volume; WMButton *db_close; WMButton *db_prev; WMButton *db_next; WMWidget *db_tlabel; /* the 'about' window */ WMWindow *aboutwin; WMWidget *about_th1; WMWidget *about_th2; WMWidget *about_th3; WMWidget *about_th4; WMWidget *about_th5; WMWidget *about_th6; /* misc */ int en_vue = FALSE; int db_en_vue = FALSE; int about_en_vue = FALSE; int pistes = 0; int db_curtrack = 1; ascd-0.13.2.orig/ascd/wings_ext.h0100644000175000017500000000263406720011357016063 0ustar hallonhallonextern WMScreen *scr; /* the main window */ extern WMWindow *win; extern WMButton *b_title; extern WMPopUpButton *pop, *pop2, *pop3; extern WMButton *b_autoplay; extern WMButton *b_autorepeat; extern WMButton *b_ignoreavoid; extern WMTextField *b_device; extern WMSlider *b_volume; extern WMButton *b_scroll; extern WMButton *b_artist; extern WMButton *b_upper; extern WMTextField *b_cuetime; extern WMTextField *b_fadestep; extern WMTextField *b_minvol; extern WMTextField *b_maxvol; extern WMTextField *b_mutedvol; extern WMButton *b_mode1; extern WMButton *b_mode2; extern WMButton *b_mode3; extern WMButton *b_mode4; extern WMButton *b_save; extern WMButton *b_quit; extern WMButton *b_close; extern WMButton *b_about; extern WMButton *b_help; /* the database window */ extern WMWindow *dbwin; extern WMTextField *db_artist; extern WMTextField *db_title; extern WMTextField *db_track; extern WMButton *db_avoid; extern WMButton *db_playauto; extern WMSlider *db_volume; extern WMButton *db_close; extern WMButton *db_prev; extern WMButton *db_next; extern WMWidget *db_tlabel; /* the 'about' window */ extern WMWindow *aboutwin; extern WMWidget *about_th1; extern WMWidget *about_th2; extern WMWidget *about_th3; extern WMWidget *about_th4; extern WMWidget *about_th5; extern WMWidget *about_th6; /* misc */ extern int en_vue; extern int db_en_vue; extern int about_en_vue; extern int pistes; int db_curtrack; ascd-0.13.2.orig/ascd/wings_main.c0100644000175000017500000007250506720532423016210 0ustar hallonhallon/* =========================================================================== * AScd: the AfterStep and WindowMaker CD player * gui_wings.c: window handling using WINGs toolkit * =========================================================================== * Copyright (c) 1999 Denis Bourez and Rob Malda. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Denis Bourez & Rob Malda * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY DENIS BOUREZ AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL DENIS BOUREZ, ROB MALDA OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * =========================================================================== */ #include #include #include "ext.h" /*int old_track = 0;*/ void close_win(WMWidget *self, void *data) { WMCloseWindow(win); en_vue = FALSE; muted_volume = atoi(WMGetTextFieldText(b_mutedvol)); min_volume = atoi(WMGetTextFieldText(b_minvol)); max_volume = atoi(WMGetTextFieldText(b_maxvol)); cue_time = atoi(WMGetTextFieldText(b_cuetime)); fade_step = atoi(WMGetTextFieldText(b_fadestep)); } void close_aboutwin(WMWidget *self, void *data) { WMCloseWindow(aboutwin); about_en_vue = FALSE; } void close_dbwin(WMWidget *self, void *data) { char txt[127]; char txt2 [127]; WMCloseWindow(dbwin); strcpy(cd->artist, WMGetTextFieldText(db_artist)); strcpy(cd->cdname, WMGetTextFieldText(db_title)); if (strlen(WMGetTextFieldText(db_track)) > 0) { cd->trk[db_curtrack - 1].songname = malloc(strlen(WMGetTextFieldText(db_track)) + 1); strcpy(cd->trk[db_curtrack - 1].songname, WMGetTextFieldText(db_track)); } save(); load(); if (cd->artist != NULL) { strcpy(txt, cd->artist); if (strcmp(txt, "") == 0) strcpy(txt, "unknown artist"); } else { strcpy(txt, "unknown artist"); } strcat(txt, "\n"); if (cd->cdname != NULL) { strcpy(txt2, cd->cdname); if (strcmp(txt2, "") == 0) strcpy(txt2, "unknown album"); } else { strcpy(txt2, "unknown album"); } strcat(txt, txt2); WMSetButtonText(b_title, txt); db_en_vue = FALSE; } void quit_ascd(WMWidget *self, void *data) { exit(0); } void save_cb(WMWidget *self, void *data) { muted_volume = atoi(WMGetTextFieldText(b_mutedvol)); min_volume = atoi(WMGetTextFieldText(b_minvol)); max_volume = atoi(WMGetTextFieldText(b_maxvol)); cue_time = atoi(WMGetTextFieldText(b_cuetime)); fade_step = atoi(WMGetTextFieldText(b_fadestep)); cd_device = WMGetTextFieldText(b_device); save_rc_file(); } void track_select(WMWidget *self, void *data) { show_db_pos = 0; direct_track = WMGetPopUpButtonSelectedItem(self) + 1; cd_control(DIRECTTRACK); old_track = 0; if (cur_cdmode == WM_CDM_STOPPED) cd_control(PLAY); } void theme_pick(WMWidget *self, void *data) { strcpy(theme, WMGetPopUpButtonItem(self, WMGetPopUpButtonSelectedItem(self))); fak_load_theme(theme, TRUE); fak_maskset(); } void help_cb(WMWidget *self, void *data) { quick_reference(0); } void mode1_cb(WMWidget *self, void *data) { if (WMGetButtonSelected(b_mode1)) { WMSetButtonSelected((b_mode2), FALSE); } else { WMSetButtonSelected((b_mode2), TRUE); } if (WMGetButtonSelected(b_mode1)) { if (WMGetButtonSelected(b_mode3)) time_mode = 0; else time_mode = 1; } else { if (WMGetButtonSelected(b_mode3)) time_mode = 2; else time_mode = 3; } } void mode2_cb(WMWidget *self, void *data) { if (WMGetButtonSelected(b_mode2)) { WMSetButtonSelected((b_mode1), FALSE); } else { WMSetButtonSelected((b_mode1), TRUE); } if (WMGetButtonSelected(b_mode1)) { if (WMGetButtonSelected(b_mode3)) time_mode = 0; else time_mode = 1; } else { if (WMGetButtonSelected(b_mode3)) time_mode = 2; else time_mode = 3; } } void mode3_cb(WMWidget *self, void *data) { if (WMGetButtonSelected(b_mode3)) { WMSetButtonSelected((b_mode4), FALSE); } else { WMSetButtonSelected((b_mode4), TRUE); } if (WMGetButtonSelected(b_mode1)) { if (WMGetButtonSelected(b_mode3)) time_mode = 0; else time_mode = 1; } else { if (WMGetButtonSelected(b_mode3)) time_mode = 2; else time_mode = 3; } } void mode4_cb(WMWidget *self, void *data) { if (WMGetButtonSelected(b_mode4)) { WMSetButtonSelected((b_mode3), FALSE); } else { WMSetButtonSelected((b_mode3), TRUE); } if (WMGetButtonSelected(b_mode1)) { if (WMGetButtonSelected(b_mode3)) time_mode = 0; else time_mode = 1; } else { if (WMGetButtonSelected(b_mode3)) time_mode = 2; else time_mode = 3; } } void autoplay_cb(WMWidget *self, void *data) { if (autoplay) autoplay = 0; else autoplay = 1; if (WMGetButtonSelected(b_mode1)) { if (WMGetButtonSelected(b_mode3)) time_mode = 0; else time_mode = 1; } else { if (WMGetButtonSelected(b_mode3)) time_mode = 2; else time_mode = 3; } } void autorepeat_cb(WMWidget *self, void *data) { if (autorepeat) autorepeat = 0; else autorepeat = 1; } void ignoreavoid_cb(WMWidget *self, void *data) { if (ignore_avoid) ignore_avoid = 0; else ignore_avoid = 1; } void upper_cb(WMWidget *self, void *data) { if (force_upper) force_upper = 0; else force_upper = 1; } void scroll_cb(WMWidget *self, void *data) { if (show_db) show_db = 0; else show_db = 1; } void artist_cb(WMWidget *self, void *data) { if (show_artist) show_artist = 0; else show_artist = 1; } void volume_cb(WMWidget *self, void *data) { if (cur_cdmode != WM_CDM_EJECTED) { volume = WMGetSliderValue(self); cd_volume(volume, 10, max_volume); redraw = TRUE; } } /* --------------------------------------------------- */ void create_about_window(WMScreen *scr) { char txt[256]; WMWidget *lb1, *lb2, *lb3, *lb4, *lb5, *lb6; WMFont *font; aboutwin = WMCreateWindow(scr, "AScd-about"); WMSetWindowCloseAction(aboutwin, close_aboutwin, NULL); WMSetWindowTitle(aboutwin, "AScd Info"); WMResizeWidget(aboutwin, 350, 170); lb1 = WMCreateLabel(aboutwin); WMResizeWidget(lb1, 35, 20); WMMoveWidget(lb1, 10, 10); font = WMBoldSystemFontOfSize(scr, 12); if (font) { WMSetLabelFont(lb1, font); WMReleaseFont(font); } WMSetLabelText(lb1, "AScd"); lb2 = WMCreateLabel(aboutwin); WMResizeWidget(lb2, 200, 20); WMMoveWidget(lb2, 50, 10); sprintf(txt, "release %s", VERSION); WMSetLabelText(lb2, txt); lb3 = WMCreateLabel(aboutwin); WMResizeWidget(lb3, 280, 40); WMMoveWidget(lb3, 50, 30); font = WMSystemFontOfSize(scr, 10); if (font) { WMSetLabelFont(lb3, font); WMReleaseFont(font); } sprintf(txt, "(c) 1996-1999 Denis Bourez and Rob Malda\nContact: denis@rsn.fdn.fr\nhttp://worldserver.oleane.com/rsn/ascd-en.html"); WMSetLabelText(lb3, txt); lb5 = WMCreateLabel(aboutwin); WMResizeWidget(lb5, 60, 20); WMMoveWidget(lb5, 10, 70); font = WMBoldSystemFontOfSize(scr, 10); if (font) { WMSetLabelFont(lb5, font); WMReleaseFont(font); } WMSetLabelText(lb5, "Ctrl:"); lb4 = WMCreateLabel(aboutwin); WMResizeWidget(lb4, 260, 20); WMMoveWidget(lb4, 50, 70); font = WMSystemFontOfSize(scr, 10); if (font) { WMSetLabelFont(lb4, font); WMReleaseFont(font); } sprintf(txt, "CD Control %s + %s", cd_control_version(), wm_libver_string()); WMSetLabelText(lb4, txt); lb6 = WMCreateLabel(aboutwin); WMResizeWidget(lb6, 60, 20); WMMoveWidget(lb6, 10, 85); font = WMBoldSystemFontOfSize(scr, 10); if (font) { WMSetLabelFont(lb6, font); WMReleaseFont(font); } WMSetLabelText(lb6, "Theme:"); about_th1 = WMCreateLabel(aboutwin); WMResizeWidget(about_th1, 280, 12); WMMoveWidget(about_th1, 50, 89); font = WMSystemFontOfSize(scr, 10); if (font) { WMSetLabelFont(about_th1, font); WMReleaseFont(font); } WMSetLabelText(about_th1, "A"); about_th2 = WMCreateLabel(aboutwin); WMResizeWidget(about_th2, 280, 12); WMMoveWidget(about_th2, 50, 101); font = WMSystemFontOfSize(scr, 10); if (font) { WMSetLabelFont(about_th2, font); WMReleaseFont(font); } WMSetLabelText(about_th2, "B"); about_th3 = WMCreateLabel(aboutwin); WMResizeWidget(about_th3, 280, 12); WMMoveWidget(about_th3, 50, 113); font = WMSystemFontOfSize(scr, 10); if (font) { WMSetLabelFont(about_th3, font); WMReleaseFont(font); } WMSetLabelText(about_th3, "C"); about_th4 = WMCreateLabel(aboutwin); WMResizeWidget(about_th4, 280, 12); WMMoveWidget(about_th4, 50, 125); font = WMSystemFontOfSize(scr, 10); if (font) { WMSetLabelFont(about_th4, font); WMReleaseFont(font); } WMSetLabelText(about_th4, "D"); about_th5 = WMCreateLabel(aboutwin); WMResizeWidget(about_th5, 280, 12); WMMoveWidget(about_th5, 50, 137); font = WMSystemFontOfSize(scr, 10); if (font) { WMSetLabelFont(about_th5, font); WMReleaseFont(font); } WMSetLabelText(about_th5, "E"); about_th6 = WMCreateLabel(aboutwin); WMResizeWidget(about_th6, 280, 12); WMMoveWidget(about_th6, 50, 149); font = WMSystemFontOfSize(scr, 10); if (font) { WMSetLabelFont(about_th6, font); WMReleaseFont(font); } WMSetLabelText(about_th6, "F"); WMRealizeWidget(aboutwin); } void about_window(WMScreen *scr) { char txt[256]; if (! about_en_vue) { sprintf(txt, "%s %s", th_name, th_release); WMSetLabelText(about_th1, txt); WMSetLabelText(about_th2, th_author); WMSetLabelText(about_th3, th_email); WMSetLabelText(about_th4, th_url); WMSetLabelText(about_th5, th_comment); sprintf(txt, "Faktory: %dx%d (panels: %d Buttons: %d)", backXPM.attributes.width, backXPM.attributes.height, panels, but_max); WMSetLabelText(about_th6, txt); WMRealizeWidget(aboutwin); WMMapSubwidgets(aboutwin); WMMapWidget(aboutwin); about_en_vue = TRUE; } else { WMCloseWindow(aboutwin); about_en_vue = FALSE; } } /* --------------------------------------------------- */ void db_prev_cb(WMWidget *self, void *data) { char txt[256]; if (cur_cdmode == WM_CDM_EJECTED) return; strcpy(cd->artist, WMGetTextFieldText(db_artist)); strcpy(cd->cdname, WMGetTextFieldText(db_title)); if (strlen(WMGetTextFieldText(db_track)) > 0) { cd->trk[db_curtrack - 1].songname = malloc(strlen(WMGetTextFieldText(db_track)) + 1); strcpy(cd->trk[db_curtrack - 1].songname, WMGetTextFieldText(db_track)); } save(); load(); if (db_curtrack == 1) db_curtrack = cur_ntracks; else db_curtrack--; sprintf(txt, "Tk %d:", db_curtrack); WMSetLabelText(db_tlabel, txt); if (cd->trk[db_curtrack - 1].songname != NULL) { sprintf(txt, cd->trk[db_curtrack - 1].songname); } else { strcpy(txt, ""); } WMSetTextFieldText(db_track, txt); if (cd->trk[db_curtrack - 1].avoid) { WMSetButtonSelected(db_avoid, TRUE); } else { WMSetButtonSelected(db_avoid, FALSE); } WMRealizeWidget(dbwin); } void db_next_cb(WMWidget *self, void *data) { char txt[256]; if (cur_cdmode == WM_CDM_EJECTED) return; strcpy(cd->artist, WMGetTextFieldText(db_artist)); strcpy(cd->cdname, WMGetTextFieldText(db_title)); if (strlen(WMGetTextFieldText(db_track)) > 0) { cd->trk[db_curtrack - 1].songname = malloc(strlen(WMGetTextFieldText(db_track)) + 1); strcpy(cd->trk[db_curtrack - 1].songname, WMGetTextFieldText(db_track)); } save(); load(); if (db_curtrack == cur_ntracks) db_curtrack = 1; else db_curtrack++; sprintf(txt, "Tk %d:", db_curtrack); WMSetLabelText(db_tlabel, txt); if (cd->trk[db_curtrack - 1].songname != NULL) { sprintf(txt, cd->trk[db_curtrack - 1].songname); } else { strcpy(txt, ""); } WMSetTextFieldText(db_track, txt); if (cd->trk[db_curtrack - 1].avoid) { WMSetButtonSelected(db_avoid, TRUE); } else { WMSetButtonSelected(db_avoid, FALSE); } WMRealizeWidget(dbwin); } void db_avoid_cb(WMWidget *self, void *data) { if (cur_cdmode == WM_CDM_EJECTED) return; if (cd->trk[db_curtrack - 1].avoid) { cd->trk[db_curtrack - 1].avoid = 0; } else { cd->trk[db_curtrack - 1].avoid = 1; } save(); load(); } void db_playauto_cb(WMWidget *self, void *data) { if (cur_cdmode == WM_CDM_EJECTED) return; if (cd->autoplay) { cd->autoplay = 0; } else { cd->autoplay = 1; } save(); load(); } void db_volume_cb(WMWidget *self, void *data) { if (cur_cdmode != WM_CDM_EJECTED) { cd->volume = WMGetSliderValue(self); save(); load(); volume = cd->volume; cd_volume(volume, 10, max_volume); redraw = TRUE; WMSetSliderMinValue(b_volume, min_volume); WMSetSliderMaxValue(b_volume, max_volume); WMSetSliderValue(b_volume, volume); } } void create_db_window(WMScreen *scr) { char txt[256]; WMWidget *fr, *fr2; WMWidget *lb1, *lb2, *lb3; dbwin = WMCreateWindow(scr, "AScd-db"); WMSetWindowCloseAction(dbwin, close_dbwin, NULL); WMSetWindowTitle(dbwin, "AScd database edition"); WMResizeWidget(dbwin, 350, 220); fr = WMCreateFrame(dbwin); WMMoveWidget(fr, 10, 05); WMResizeWidget(fr, 330, 105); WMSetFrameTitle(fr, "CD info:"); lb1 = WMCreateLabel(dbwin); WMResizeWidget(lb1, 40, 20); WMMoveWidget(lb1, 16, 20); WMSetLabelText(lb1, "Artist:"); db_artist = WMCreateTextField(dbwin); WMMoveWidget(db_artist, 70, 20); WMResizeWidget(db_artist, 255, 20); lb2 = WMCreateLabel(dbwin); WMResizeWidget(lb2, 40, 20); WMMoveWidget(lb2, 16, 40); WMSetLabelText(lb2, "Title:"); db_title = WMCreateTextField(dbwin); WMMoveWidget(db_title, 70, 40); WMResizeWidget(db_title, 255, 20); db_playauto = WMCreateButton(dbwin, WBTSwitch); WMMoveWidget(db_playauto, 70, 65); WMResizeWidget(db_playauto, 255, 20); WMSetButtonText(db_playauto, "play this CD automatically (WorkMan)"); WMSetButtonAction(db_playauto, db_playauto_cb, NULL); lb3 = WMCreateLabel(dbwin); WMResizeWidget(lb3, 54, 20); WMMoveWidget(lb3, 16, 85); WMSetLabelText(lb3, "Volume:"); db_volume = WMCreateSlider(dbwin); WMResizeWidget(db_volume, 255, 15); WMMoveWidget(db_volume, 70, 88); WMSetSliderKnobThickness(db_volume, 22); WMSetSliderAction(db_volume, db_volume_cb, NULL); /* --- */ fr2 = WMCreateFrame(dbwin); WMMoveWidget(fr2, 10, 115); WMResizeWidget(fr2, 330, 65); WMSetFrameTitle(fr2, "Track info:"); db_tlabel = WMCreateLabel(dbwin); WMResizeWidget(db_tlabel, 54, 20); WMMoveWidget(db_tlabel, 16, 130); sprintf(txt, "Track %d:", db_curtrack); WMSetLabelText(db_tlabel, txt); db_track = WMCreateTextField(dbwin); WMMoveWidget(db_track, 70, 130); WMResizeWidget(db_track, 255, 20); db_avoid = WMCreateButton(dbwin, WBTSwitch); WMMoveWidget(db_avoid, 70, 152); WMResizeWidget(db_avoid, 235, 20); WMSetButtonText(db_avoid, "don't play this track"); WMSetButtonAction(db_avoid, db_avoid_cb, NULL); /* --- */ db_prev = WMCreateButton(dbwin, 0); WMResizeWidget(db_prev, 110, 25); WMMoveWidget(db_prev, 10, 190); WMSetButtonText(db_prev, "Previous Track"); WMSetButtonAction(db_prev, db_prev_cb, NULL); db_next = WMCreateButton(dbwin, 0); WMResizeWidget(db_next, 110, 25); WMMoveWidget(db_next, 125, 190); WMSetButtonText(db_next, "Next Track"); WMSetButtonAction(db_next, db_next_cb, NULL); db_close = WMCreateButton(dbwin, 0); WMResizeWidget(db_close, 55, 25); WMMoveWidget(db_close, 285, 190); WMSetButtonText(db_close, "Close"); WMSetButtonAction(db_close, close_dbwin, NULL); WMRealizeWidget(dbwin); } void db_window(WMScreen *scr) { char txt[256]; if (! db_en_vue) { if (cur_cdmode == WM_CDM_EJECTED) return; /* 0.13 fix */ if (db_curtrack < 1) db_curtrack = 1; load(); if (cd->artist != NULL) strcpy(txt, cd->artist); else strcpy(txt, ""); WMSetTextFieldText(db_artist, txt); if (cd->cdname != NULL) strcpy(txt, cd->cdname); else strcpy(txt, ""); WMSetTextFieldText(db_title, txt); if (cd->autoplay) { WMSetButtonSelected(db_playauto, TRUE); } else { WMSetButtonSelected(db_playauto, TRUE); } if (cd->trk[db_curtrack - 1].songname != NULL) { sprintf(txt, cd->trk[db_curtrack - 1].songname); } else { strcpy(txt, ""); } WMSetTextFieldText(db_track, txt); if (cd->trk[db_curtrack - 1].avoid) { WMSetButtonSelected(db_avoid, TRUE); } else { WMSetButtonSelected(db_avoid, FALSE); } WMSetSliderMinValue(db_volume, min_volume); WMSetSliderMaxValue(db_volume, max_volume); if (cd->volume > 0) WMSetSliderValue(db_volume, cd->volume); else WMSetSliderValue(db_volume, max_volume); WMRealizeWidget(dbwin); WMMapSubwidgets(dbwin); WMMapWidget(dbwin); db_en_vue = TRUE; } else { WMCloseWindow(dbwin); db_en_vue = FALSE; } } void db_cb(WMWidget *self, void *data) { char txt[127]; sprintf(txt, "Tk %d:", db_curtrack); WMSetLabelText(db_tlabel, txt); /*WMRealizeWidget(dbwin);*/ db_window(scr); } void about_cb(WMWidget *self, void *data) { about_window(scr); } void create_big_window(WMScreen *scr) { WMWidget *fr, *fr3, *fr4, *fr5; WMWidget *lb1, *lb2, *lb3, *lb4, *lb6; win = WMCreateWindow(scr, "AScd"); WMSetWindowCloseAction(win, close_win, NULL); WMSetWindowTitle(win, "AScd"); WMResizeWidget(win, 320, 370); b_title = WMCreateButton(win, 0); WMResizeWidget(b_title, 300, 40); WMMoveWidget(b_title, 10, 5); WMSetButtonText(b_title, "1\n2"); WMSetButtonAction(b_title, db_cb, NULL); pop = WMCreatePopUpButton(win); WMResizeWidget(pop, 300, 20); WMMoveWidget(pop, 10, 50); WMSetPopUpButtonPullsDown(pop, True); WMSetPopUpButtonText(pop, "Tracks"); WMAddPopUpButtonItem(pop, "1"); WMSetPopUpButtonAction(pop, track_select, NULL); fr = WMCreateFrame(win); WMMoveWidget(fr, 10, 75); WMResizeWidget(fr, 110, 140); WMSetFrameTitle(fr, "Playback:"); b_autoplay = WMCreateButton(win, WBTSwitch); WMMoveWidget(b_autoplay, 20, 95); WMResizeWidget(b_autoplay, 90, 20); WMSetButtonText(b_autoplay, "autoplay"); WMSetButtonAction(b_autoplay, autoplay_cb, NULL); b_autorepeat = WMCreateButton(win, WBTSwitch); WMMoveWidget(b_autorepeat, 20, 115); WMResizeWidget(b_autorepeat, 90, 20); WMSetButtonText(b_autorepeat, "autorepeat"); WMSetButtonAction(b_autorepeat, autorepeat_cb, NULL); b_ignoreavoid = WMCreateButton(win, WBTSwitch); WMMoveWidget(b_ignoreavoid, 20, 135); WMResizeWidget(b_ignoreavoid, 90, 20); WMSetButtonText(b_ignoreavoid, "apply skips"); WMSetButtonAction(b_ignoreavoid, ignoreavoid_cb, NULL); lb6 = WMCreateLabel(win); WMResizeWidget(lb6, 80, 20); WMMoveWidget(lb6, 15, 165); WMSetLabelText(lb6, "CD Device:"); b_device = WMCreateTextField(win); WMResizeWidget(b_device, 85, 20); WMMoveWidget(b_device, 20, 185); fr3 = WMCreateFrame(win); WMMoveWidget(fr3, 130, 75); WMResizeWidget(fr3, 180, 140); WMSetFrameTitle(fr3, "Display:"); b_scroll = WMCreateButton(win, WBTSwitch); WMMoveWidget(b_scroll, 140, 95); WMResizeWidget(b_scroll, 130, 20); WMSetButtonText(b_scroll, "scroll song names"); WMSetButtonAction(b_scroll, scroll_cb, NULL); b_artist = WMCreateButton(win, WBTSwitch); WMMoveWidget(b_artist, 140, 115); WMResizeWidget(b_artist, 130, 20); WMSetButtonText(b_artist, "add artist name"); WMSetButtonAction(b_artist, artist_cb, NULL); b_upper = WMCreateButton(win, WBTSwitch); WMMoveWidget(b_upper, 140, 135); WMResizeWidget(b_upper, 130, 20); WMSetButtonText(b_upper, "force uppercase"); WMSetButtonAction(b_upper, upper_cb, NULL); lb4 = WMCreateLabel(win); WMResizeWidget(lb4, 80, 20); WMMoveWidget(lb4, 135, 165); WMSetLabelText(lb4, "Theme:"); pop2 = WMCreatePopUpButton(win); WMResizeWidget(pop2, 160, 20); WMMoveWidget(pop2, 140, 185); WMSetPopUpButtonText(pop2, theme); WMAddPopUpButtonItem(pop2, "1"); WMSetPopUpButtonAction(pop2, theme_pick, NULL); b_help = WMCreateButton(win, 0); WMResizeWidget(b_help, 80, 18); WMMoveWidget(b_help, 220, 165); WMSetButtonText(b_help, "Quick Ref."); WMSetButtonAction(b_help, help_cb, NULL); /* the volume */ fr4 = WMCreateFrame(win); WMMoveWidget(fr4, 10, 220); WMResizeWidget(fr4, 300, 80); WMSetFrameTitle(fr4, "Volume & Misc:"); b_minvol = WMCreateTextField(win); WMResizeWidget(b_minvol, 30, 20); WMMoveWidget(b_minvol, 20, 240); b_volume = WMCreateSlider(win); WMResizeWidget(b_volume, 220, 20); WMMoveWidget(b_volume, 50, 240); WMSetSliderKnobThickness(b_volume, 22); WMSetSliderAction(b_volume, volume_cb, NULL); b_maxvol = WMCreateTextField(win); WMResizeWidget(b_maxvol, 30, 20); WMMoveWidget(b_maxvol, 270, 240); lb1 = WMCreateLabel(win); WMResizeWidget(lb1, 40, 20); WMMoveWidget(lb1, 15, 270); WMSetLabelText(lb1, "Muted"); b_mutedvol = WMCreateTextField(win); WMResizeWidget(b_mutedvol, 30, 20); WMMoveWidget(b_mutedvol, 65, 270); lb2 = WMCreateLabel(win); WMResizeWidget(lb2, 70, 20); WMMoveWidget(lb2, 105, 270); WMSetLabelText(lb2, "Cue Time"); b_cuetime = WMCreateTextField(win); WMResizeWidget(b_cuetime, 25, 20); WMMoveWidget(b_cuetime, 180, 270); lb3 = WMCreateLabel(win); WMResizeWidget(lb3, 33, 20); WMMoveWidget(lb3, 225, 270); WMSetLabelText(lb3, "Fade"); b_fadestep = WMCreateTextField(win); WMResizeWidget(b_fadestep, 25, 20); WMMoveWidget(b_fadestep, 275, 270); /* the counter modes */ fr5 = WMCreateFrame(win); WMMoveWidget(fr5, 10, 305); WMResizeWidget(fr5, 190, 60); WMSetFrameTitle(fr5, "Counter Mode:"); b_mode1 = WMCreateButton(win, WBTRadio); WMMoveWidget(b_mode1, 20, 320); WMResizeWidget(b_mode1, 55, 20); WMSetButtonText(b_mode1, "Track"); WMSetButtonAction(b_mode1, mode1_cb, NULL); b_mode2 = WMCreateButton(win, WBTRadio); WMMoveWidget(b_mode2, 20, 340); WMResizeWidget(b_mode2, 55, 20); WMSetButtonText(b_mode2, "CD"); WMSetButtonAction(b_mode2, mode2_cb, NULL); b_mode3 = WMCreateButton(win, WBTRadio); WMMoveWidget(b_mode3, 90, 320); WMResizeWidget(b_mode3, 85, 20); WMSetButtonText(b_mode3, "Elapsed"); WMSetButtonAction(b_mode3, mode3_cb, NULL); b_mode4 = WMCreateButton(win, WBTRadio); WMMoveWidget(b_mode4, 90, 340); WMResizeWidget(b_mode4, 85, 20); WMSetButtonText(b_mode4, "Remaining"); WMSetButtonAction(b_mode4, mode4_cb, NULL); /* the global buttons */ b_save = WMCreateButton(win, 0); WMResizeWidget(b_save, 50, 25); WMMoveWidget(b_save, 205, 340); WMSetButtonText(b_save, "Save"); WMSetButtonAction(b_save, save_cb, NULL); b_about = WMCreateButton(win, 0); WMResizeWidget(b_about, 50, 25); WMMoveWidget(b_about, 205, 310); WMSetButtonText(b_about, "Info"); WMSetButtonAction(b_about, about_cb, NULL); b_save = WMCreateButton(win, 0); WMResizeWidget(b_save, 50, 25); WMMoveWidget(b_save, 260, 310); WMSetButtonText(b_save, "Quit"); WMSetButtonAction(b_save, quit_ascd, NULL); b_close = WMCreateButton(win, 0); WMResizeWidget(b_close, 50, 25); WMMoveWidget(b_close, 260, 340); WMSetButtonText(b_close, "Close"); WMSetButtonAction(b_close, close_win, NULL); /* finished, draw everything */ WMRealizeWidget(win); /* WMMapSubwidgets(win); WMMapWidget(win); */ } void update_track() { int i; char txt[127]; char txt2[127]; if (en_vue) { if (cur_cdmode != WM_CDM_EJECTED) { if (cd->artist != NULL) { strcpy(txt, cd->artist); if (strcmp(txt, "") == 0) strcpy(txt, "unknown artist"); } else { strcpy(txt, "unknown artist"); } strcat(txt, "\n"); if (cd->cdname != NULL) { strcpy(txt2, cd->cdname); if (strcmp(txt2, "") == 0) strcpy(txt2, "unknown album"); } else { strcpy(txt2, "unknown album"); } strcat(txt, txt2); WMSetButtonText(b_title, txt); for (i = WMGetPopUpButtonNumberOfItems(pop); i >= 0; i --) { WMRemovePopUpButtonItem(pop, i); } for (i = 0; i < cur_ntracks; i++) { sprintf(txt, "%2d ", i + 1); if (cd->trk[i].songname != NULL) strcat(txt, cd->trk[i].songname); WMAddPopUpButtonItem(pop, txt); } pistes = cur_ntracks; if (cur_track >= 1) { if (cd->trk[cur_track - 1].songname != NULL) { sprintf(txt, "%s", cd->trk[cur_track - 1].songname); if (strcmp(txt, "") == 0) sprintf(txt, "Track %d", cur_track); WMSetPopUpButtonText(pop, txt); } else { sprintf(txt, "Track %d", cur_track); WMSetPopUpButtonText(pop, txt); } } else { WMSetPopUpButtonText(pop, "Track 1"); } } else { WMSetButtonText(b_title, "No CD in drive\nor the tray is not loaded"); } } } void big_window(WMScreen *scr) { int i; char txt[256]; DIR *dir_fd; struct dirent *dir_pt; if (! en_vue) { /*if (cur_cdmode == WM_CDM_EJECTED) return;*/ en_vue = TRUE; sprintf(txt, "%d", cue_time); WMSetTextFieldText(b_cuetime, txt); sprintf(txt, "%d", fade_step); WMSetTextFieldText(b_fadestep, txt); sprintf(txt, "%d", min_volume); WMSetTextFieldText(b_minvol, txt); sprintf(txt, "%d", max_volume); WMSetTextFieldText(b_maxvol, txt); sprintf(txt, "%d", muted_volume); WMSetTextFieldText(b_mutedvol, txt); WMSetTextFieldText(b_device, cd_device); WMSetSliderMinValue(b_volume, min_volume); WMSetSliderMaxValue(b_volume, max_volume); WMSetSliderValue(b_volume, volume); /* remove everything in the two popups */ for (i = WMGetPopUpButtonNumberOfItems(pop); i >= 0; i --) { WMRemovePopUpButtonItem(pop, i); } for (i = WMGetPopUpButtonNumberOfItems(pop2); i >= 0; i --) { WMRemovePopUpButtonItem(pop2, i); } /* update the database stuff. AScd 0.13: I deleted all this stuff from this function as update_track() do the same! */ update_track(); /* make the theme select menu */ sprintf(txt, "%s/Themes", THDIR); if ((dir_fd = opendir(txt)) != NULL) { while((dir_pt = readdir(dir_fd)) != NULL) { if (dir_pt->d_name[0] != '.') { WMAddPopUpButtonItem(pop2, dir_pt->d_name); } } closedir(dir_fd); } WMSetPopUpButtonText(pop2, theme); /* several options toggles */ if (autoplay) { WMSetButtonSelected(b_autoplay, TRUE); } else { WMSetButtonSelected(b_autoplay, FALSE); } if (autorepeat) { WMSetButtonSelected(b_autorepeat, TRUE); } else { WMSetButtonSelected(b_autorepeat, FALSE); } if (show_db) { WMSetButtonSelected(b_scroll, TRUE); } else { WMSetButtonSelected(b_scroll, FALSE); } if (show_artist) { WMSetButtonSelected(b_artist, TRUE); } else { WMSetButtonSelected(b_artist, FALSE); } if (ignore_avoid) { WMSetButtonSelected(b_ignoreavoid, FALSE); } else { WMSetButtonSelected(b_ignoreavoid, TRUE); } if (force_upper) { WMSetButtonSelected(b_upper, TRUE); } else { WMSetButtonSelected(b_upper, FALSE); } /* finally, the counter mode radio buttons */ switch(time_mode) { case 0: WMSetButtonSelected((b_mode1), TRUE); WMSetButtonSelected((b_mode2), FALSE); WMSetButtonSelected((b_mode3), TRUE); WMSetButtonSelected((b_mode4), FALSE); break; case 1: WMSetButtonSelected((b_mode1), TRUE); WMSetButtonSelected((b_mode2), FALSE); WMSetButtonSelected((b_mode4), TRUE); WMSetButtonSelected((b_mode3), FALSE); break; case 2: WMSetButtonSelected((b_mode2), TRUE); WMSetButtonSelected((b_mode1), FALSE); WMSetButtonSelected((b_mode3), TRUE); WMSetButtonSelected((b_mode4), FALSE); break; default: WMSetButtonSelected((b_mode2), TRUE); WMSetButtonSelected((b_mode1), FALSE); WMSetButtonSelected((b_mode4), TRUE); WMSetButtonSelected((b_mode3), FALSE); break; } WMRealizeWidget(win); WMMapSubwidgets(win); WMMapWidget(win); } else { WMCloseWindow(win); muted_volume = atoi(WMGetTextFieldText(b_mutedvol)); min_volume = atoi(WMGetTextFieldText(b_minvol)); max_volume = atoi(WMGetTextFieldText(b_maxvol)); cue_time = atoi(WMGetTextFieldText(b_cuetime)); fade_step = atoi(WMGetTextFieldText(b_fadestep)); en_vue = FALSE; } } ascd-0.13.2.orig/ascd/mixer_handlers.c0100644000175000017500000001040406720003047017042 0ustar hallonhallon/* =========================================================================== * AScd: mixer_handlers.c * mouse events <-> integrated commands with mixer module * =========================================================================== * Copyright (c) 1999 Denis Bourez and Rob Malda. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Denis Bourez & Rob Malda * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY DENIS BOUREZ AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL DENIS BOUREZ, ROB MALDA OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * =========================================================================== */ #include "ext.h" #ifdef MIXER int check_mixer() { int fd; if ((fd = open(mixer_device,0))) { close(fd); } else { return FALSE; } return TRUE; } int getvol(int control) { int fd; int status = 0; if (mixer_ok) { if ((fd = open(mixer_device,0))) { ioctl(fd, MIXER_READ(control), &mixer_vol); mixer_vol = mixer_vol >> 8; close(fd); return mixer_vol; } } return 0; } void setvol(int control, int setto, int maximum) { int fd; if (setto > maximum) setto = maximum; if (setto < 0) setto = 0; if ((fd = open(mixer_device, 0))) { mixer_vol = ((float)setto / (float)maximum) * 100; mixer_old = mixer_vol << 8; mixer_vol = mixer_old | mixer_vol; ioctl(fd, MIXER_WRITE(control), &mixer_vol); close(fd); } } void mixer_event_handle(int event, XEvent Event) { int value; if (!mixer_ok) return; switch (event) { case FAK_MIXER_SET: if ((thdata[but_current].xpm.attributes.width > 0) && (max_volume > 0)) { if (thdata[but_current].type == FAK_MIXER_BAR) { value = (int)((float)(Event.xbutton.x - thdata[but_current].x) / (float)thdata[but_current].xpm.attributes.width * 100.0); } else if (thdata[but_current].type == FAK_VMIXER_BAR) { value = (int)((float)(Event.xbutton.y - thdata[but_current].y) / (float)thdata[but_current].xpm.attributes.height * 100.0); } else { value = (int)((float)(Event.xbutton.y - thdata[but_current].y) / (float)thdata[but_current].xpm.attributes.height * 100.0); value = 100 - value; } setvol(thdata[but_current].arg, value, 100); redraw = TRUE; fak_redraw(); } break; case FAK_MIXER_0: setvol(thdata[but_current].arg, 0, 100); redraw = TRUE; fak_redraw(); break; case FAK_MIXER_50: setvol(thdata[but_current].arg, 50, 100); redraw = TRUE; fak_redraw(); break; case FAK_MIXER_75: setvol(thdata[but_current].arg, 75, 100); redraw = TRUE; fak_redraw(); break; case FAK_MIXER_100: setvol(thdata[but_current].arg, 100, 100); redraw = TRUE; fak_redraw(); break; default: break; } redraw = TRUE; fak_singlemask(but_current); } #endif ascd-0.13.2.orig/ascd/mixer_global.c0100644000175000017500000000044406717656776016542 0ustar hallonhallon#if defined (__FreeBSD__) # include #else # include # include #endif #define DEFAULTMIXERDEVICE "/dev/mixer" char mixer_device[128]=DEFAULTMIXERDEVICE; int mixer_ok = 1; int mixer_control; int mixer_vol; int mixer_but; int mixer_old; ascd-0.13.2.orig/ascd/mixer_ext.h0100644000175000017500000000041306717647002016061 0ustar hallonhallon#if defined (__FreeBSD__) # include #else # include # include #endif extern char mixer_device[]; extern int mixer_ok; extern int mixer_control; extern int mixer_vol; extern int mixer_but; extern int mixer_old; ascd-0.13.2.orig/ascd/workman/0040744000175000017500000000000006764326154015371 5ustar hallonhallonascd-0.13.2.orig/ascd/workman/wm_cdda.h0100600000175000017500000000660406661516166017135 0ustar hallonhallon#ifndef WM_CDDA_H #define WM_CDDA_H /* * $Id: wm_cdda.h,v 1.2 1999/02/14 09:50:46 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /* * Information about a particular block of CDDA data. */ struct cdda_block { unsigned char status; /* see below */ unsigned char track; unsigned char index; unsigned char minute; unsigned char second; unsigned char frame; /* Average volume levels, for level meters */ unsigned char lev_chan0; unsigned char lev_chan1; /* Current volume setting (0-255) */ unsigned char volume; /* Current balance setting (0-255, 128 = balanced) */ unsigned char balance; }; /* * cdda_block status codes. */ #define WMCDDA_ERROR 0 /* Couldn't read CDDA from disc */ #define WMCDDA_OK 1 /* Read this block successfully (raw data) */ #define WMCDDA_PLAYED 2 /* Just played the block in question */ #define WMCDDA_STOPPED 3 /* Block data invalid; we've just stopped */ #define WMCDDA_ACK 4 /* Acknowledgement of command from parent */ #define WMCDDA_DONE 5 /* Chunk of data is done playing */ #define WMCDDA_EJECTED 6 /* Disc ejected or offline */ /* * Enable or disable CDDA building depending on platform capabilities, and * determine endianness based on architecture. (Gross!) * * For header-comfort, the macros LITTLE_ENDIAN and BIG_ENDIAN had to be * renamed. At least Linux does have bytesex.h and endian.h for easy * byte-order examination. */ #ifdef sun # ifdef SYSV # include # include # ifndef CDROMCDDA # undef BUILD_CDDA # endif # ifdef i386 # define WM_LITTLE_ENDIAN 1 # define WM_BIG_ENDIAN 0 # else # define WM_BIG_ENDIAN 1 # define WM_LITTLE_ENDIAN 0 # endif # else # undef BUILD_CDDA # endif #endif /* Linux only allows definition of endianness, because there's no * standard interface for CDROM CDDA functions that aren't available * if there is no support. */ #ifdef linux # include # include /* * XXX could this be a problem? The results are only 0 and 1 because * of the ! operator. How about other linux compilers than gcc ? */ # define WM_LITTLE_ENDIAN !(__BYTE_ORDER - __LITTLE_ENDIAN) # define WM_BIG_ENDIAN !(__BYTE_ORDER - __BIG_ENDIAN) #endif /* * The following code shouldn't take effect now. * In 1998, the WorkMan platforms don't support __PDP_ENDIAN * architectures. * */ #if !WM_LITTLE_ENDIAN # if !WM_BIG_ENDIAN # error yet unsupported architecture foo bar this is to stop the compiler. # endif #endif #endif /* WM_CDDA_H */ ascd-0.13.2.orig/ascd/workman/wm_config.h0100600000175000017500000003165006714071416017477 0ustar hallonhallon#ifndef WM_CONFIG_H #define WM_CONFIG_H /* * $Id: wm_config.h,v 1.5 1999/05/05 16:34:22 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ********************************************************************** * * This file consists of several parts. First, there's a generic, * platform independent part. Set needed options there. * The following parts are platform dependent. You may search for the * names listed below and then set your OS specific options there. * Don't be surprised, if there are no options for your OS. They aren't * needed in any case. * * The default values should produce a functional WorkMan on every * platform. * ********************* * Current platforms: ********************* * BSD386 * FreeBSD * HP-UX * Irix (SGI) * Linux * News (Sony NewsOS) * OpenBSD * OSF1 * Sun (SunOS/Solaris, Sparc or x86) * SVR4 * Ultrix * AIX * * The above order corresponds with the order of the platform specific * options below. */ /****************************************************************** * generic options ****************************************************************** ** ** *** **** ** **** ** * ** ** ** * ** * * * *** **** * * *** * ** ** *** * * * * * * ** * * *** **** ** *** ** ** ** * * ** * * ** * * * *** **** **** *** * ** ** *** * * * * *** ** * * * * ** **** * * ** ** **** ** * * *** ** ******************************************************************/ /* * This option is obvious. But please do not forget the original * WorkMan version string if you need support. */ #define WORKMAN_NAME "LibWorkMan" #define WORKMAN_VERSION "1.4.0" /* * If your CD-ROM drive closes its tray if the device is opened, then * the next define can make WorkMans "Eject" button an "open/close" * button. If it disturbs you, just comment it out. * * ### this is preliminary. It may have no effect for you ### */ #define CAN_CLOSE 1 /* * Define the following if you want the balance slider to * decrease one channel's volume while increasing the other's */ /* #define SYMETRIC_BALANCE 1 */ /* * Define this if you want CDDA support. Supported systems are: * * - Solaris (2.4 or newer) * --> Linux is on the way. Don't define it now. It would lead to errors only. */ /*#define BUILD_CDDA 1*/ /* * * This is for experimental cddb support. * This activates the UI component. */ #define CDDB_IN_UI 1 /****************************************************************** * BSD386 ****************************************************************** *** **** *** ******* ** **** **** ************ *** ** ** ****** * ***** ****** ** ** ** *************** *** ****** **** ** *** ***** ***** *** ************ *** ** ****** ** * *** ******** ** ** ** ** *********** *** **** *** *** ****** **** **** ************ ******************************************************************/ #ifdef __bsdi__ /* * This lets you use the SoundBlaster Mixer on BSD/386 */ #define SOUNDBLASTER 1 #endif /* __bsdi__ (BSD/386) */ /****************************************************************** * FreeBSD ****************************************************************** *** ** *** ** ** **** *** *********** *** ****** ** ** ****** ****** ** ** ****** * ********** *** **** *** **** **** ****** **** ** ********* *** ****** ** ** ****** ****** ** ****** ** * ********** *** ****** ** ** ** ** **** *** *********** ******************************************************************/ #if defined(__FreeBSD__) || defined(__NetBSD__) #define DEFAULT_CD_DEVICE "/dev/rmatcd0c" #endif /* freebsd */ /****************************************************************** * HP-UX ****************************************************************** *** ** ** ********* ** ** ** *************************** *** ** ** ** ******** ** *** **************************** *** ** *** ** ** **** ***************************** *** ** ** ************ ** *** **************************** *** ** ** ************* *** ** *************************** ******************************************************************/ #if defined(hpux) || defined (__hpux) #define DEFAULT_CD_DEVICE "/dev/rscsi" #endif /* hpux */ /****************************************************************** * Irix ****************************************************************** *** ** *** ** ** ********************************* ***** **** ** **** ***** ********************************** ***** **** ***** ****** *********************************** ***** **** ** **** ***** ********************************** *** ** ** ** ** ** ********************************* ******************************************************************/ #if defined(sgi) #define DEFAULT_CD_DEVICE "/dev/scsi/sc0d6l0" #endif /* sgi IRIX */ /****************************************************************** * Linux ****************************************************************** *** ****** ** *** ** ** ** ** *********************** *** ******** **** ** ** ** *** ************************ *** ******** **** * * ** ** **** ************************* *** ******** **** ** ** ** *** ************************ *** ** ** *** *** *** ** *********************** ******************************************************************/ #ifdef linux /* * Uncomment the following line to have WorkMan send SCSI commands * directly to the CD-ROM drive. If you have a SCSI drive you * probably want this, but it will cause WorkMan to not work on IDE * drives. */ #define LINUX_SCSI_PASSTHROUGH 1 /* * Which device should be opened by WorkMan at default? */ #define DEFAULT_CD_DEVICE "/dev/sbpcd" /* * Uncomment the following if you use the sbpcd or mcdx device driver. * It shouldn't hurt if you use it on other devices. It'll be nice to * hear from non-sbpcd (or mcdx) users if this is right. */ /*#define SBPCD_HACK 1*/ /* * Linux Soundcard support */ #define OSS_SUPPORT 1 /* * This has nothing to do with the above. */ /* #define CURVED_VOLUME */ /* * Uncomment the following if you want to try out a better responding * WorkMan, especially with IDE drives. This may work with non-IDE * drives as well. But it may be possible, that it doesn't work at all. * If your drive/driver combination cannot handle the faster access, * the driver will usually hang and you have to reboot your machine. */ /* #define FAST_IDE 1 */ /* * There are two alternative ways of checking a device containing a * mounted filesystem. Define BSD_MOUNTTEST for the test using * getmntent(). Undefine it for using the SVR4 ustat(). * I built in the choice, because it's not clear which method should * be used in Linux. The ustat manpage tells us since 1995, that * fstat() should be used, but I'm too dumb to do so. */ #define BSD_MOUNTTEST #endif /* linux */ /****************************************************************** * Sony NewsOS ****************************************************************** *** *** ** ** ***** *** ***************************** *** ** ** ****** ***** ** ******************************** *** * * ** **** ** ** **** ****************************** *** ** ** ****** * * ****** **************************** *** *** ** ** * *** ***************************** ******************************************************************/ #if defined(__sony_news) || defined(sony_news) #define DEFAULT_CD_DEVICE "/dev/rsd/b0i6u0p2\0" #endif /****************************************************************** * OpenBSD ****************************************************************** **** *** *** ** *** ** **** *** ********* *** ** ** ** ** ****** ** ** ** ** ****** * ******** *** ** ** *** **** * * ** ****** **** ** ******* *** ** ** ****** ****** ** ** ** ****** ** * ******** **** *** ****** ** *** ** **** *** ********* ******************************************************************/ #ifdef __OpenBSD__ #define DEFAULT_CD_DEVICE "/dev/rcdrom" #endif /****************************************************************** * OSF1 ****************************************************************** **** **** *** *** *** ******************************* *** ** ** ****** ****** ** ******************************* *** ** **** **** *** ***** ******************************* *** ** ****** ** **** ****** ******************************* **** **** *** *** ***** ***************************** ******************************************************************/ #if defined(__osf__) #define DEFAULT_CD_DEVICE "/dev/rcdrom/cd0" #endif /****************************************************************** * SunOS/Solaris ****************************************************************** **** *** ** ** *** *************************************** *** ****** ** ** ** *************************************** ***** **** ** ** * * *************************************** ******* ** ** ** ** *************************************** **** **** *** *** *************************************** ******************************************************************/ #if defined(sun) || defined(__sun__) /* * Define the following for Solaris 2.x * If you don't want WorkMan to try to activate the SPARCstation 5 * internal audio input so you get sound from the workstation, comment * out the CODEC define. */ #define SYSV 1 #define CODEC 1 /* * set the following to "SUNW,CS4231" for Sun and to "SUNW,sb16" * for PC (with SoundBlaster 16) running Solaris x86 * (only important if you define CODEC above) */ /*#define SUN_AUD_DEV "SUNW,CS4231"*/ #define SUN_AUD_DEV "SUNW,sbpro" #endif /****************************************************************** * SVR4 ****************************************************************** **** *** **** ** *** * ******************************** *** ****** **** ** ** ** * ******************************** ***** ***** ** *** *** ******************************* ******* *** ** *** ** ***** ******************************** **** ***** **** ** ***** ******************************** ******************************************************************/ #if defined(SVR4) && !defined(sun) && !defined(__sun__) #define DEFAULT_CD_DEVICE "/dev/rcdrom/cd0" #endif /****************************************************************** * Ultrix ****************************************************************** *** ** ** ***** ** *** ** ** ****************** *** ** ** ******* **** ** **** ***** ******************* *** ** ** ******* **** ***** ****** ******************** *** ** ** ******* **** ** **** ***** ******************* **** *** *** **** ** ** ** ** ****************** ******************************************************************/ #if defined(ultrix) || defined(__ultrix) #endif /****************************************************************** * IBM AIX ****************************************************************** **** *** ** ** ***************************************** *** ** **** ***** ****************************************** *** **** ****** ******************************************* *** ** **** ***** ****************************************** *** ** ** ** ** ***************************************** ******************************************************************/ #if defined(AIXV3) #define DEFAULT_CD_DEVICE "/dev/cd0" #endif /* IBM AIX */ /******************************************************************/ #endif /* WM_CONFIG_H */ ascd-0.13.2.orig/ascd/workman/wm_cdinfo.h0100644000175000017500000000547506723407436017517 0ustar hallonhallon#ifndef WM_CDINFO_H #define WM_CDINFO_H /* * $Id: wm_cdinfo.h,v 1.5 1999/05/28 03:35:58 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Prototypes from cdinfo.c * * This is just one more step to a more modular and understandable code. */ extern char *cur_trackname; /* Take a guess */ extern int cur_index; /* Current index mark */ extern int cur_frame; /* Current frame number */ extern struct wm_play *playlist; /* = NULL */ extern struct wm_cdinfo thiscd; extern struct wm_cdinfo *cd; extern int cur_track; /* Current track number, starting at 1 */ extern char *cur_artist; /* Name of current CD's artist */ extern char cur_avoid; /* Avoid flag */ extern char cur_contd; /* Continued flag */ extern char *cur_cdname; /* Album name */ extern int cur_nsections; /* Number of sections currently defined */ extern int exit_on_eject; extern int cur_track; extern int cur_pos_abs; extern int cur_pos_rel; extern int cur_tracklen; extern int cur_cdlen; extern enum wm_cd_modes cur_cdmode; extern int cur_ntracks; extern int cur_lasttrack; extern int cur_firsttrack; extern int cur_listno; extern int cur_stopmode; void wipe_cdinfo( void ); void play_next_entry( int forward ); void make_playlist( int playmode, int starttrack ); int get_autoplay( void ); int get_playmode( void ); void pl_find_track( int track ); void play_prev_track( int forward ); void play_next_track( int forward ); int tracklen( int num ); int get_default_volume( int track ); int split_trackinfo( int pos ); int remove_trackinfo( int num ); void freeup( char **x ); int get_runtime( void ); char *trackname( int num ); void stash_cdinfo( char *artist, char *cdname, int autoplay, int playmode ); void stash_trkinfo( int track, char *songname, int contd, int avoid ); int get_avoid( int num ); int get_contd( int num ); void default_volume( int track, int vol ); char *listentry( int num ); #endif /* WM_CDINFO_H */ ascd-0.13.2.orig/ascd/workman/wm_cdrom.h0100600000175000017500000000404206714066523017334 0ustar hallonhallon#ifndef WM_CDROM_H #define WM_CDROM_H /* * $Id: wm_cdrom.h,v 1.6 1999/05/05 16:09:55 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Prototypes from cdrom.c * * This is just one more step to a more modular and understandable code. */ #define WM_CDS_NO_DISC 0 #define WM_CDS_DISC_READY 1 #define WM_CDS_JUST_INSERTED 2 #define WM_STR_GENVENDOR "Generic" #define WM_STR_GENMODEL "drive" #define WM_STR_GENREV "type" extern int wm_cd_cur_balance; char * wm_drive_vendor( void ); char * wm_drive_model( void ); char * wm_drive_revision( void ); void wm_drive_settype( char *vendor, char *model, char *revision ); int wm_cd_status( void ); void wm_cd_play( int start, int pos, int end ); void wm_cd_play_chunk( int start, int end, int realstart ); void wm_cd_play_from_pos( int pos ); void wm_cd_pause( void ); void wm_cd_stop( void ); int wm_cd_eject( void ); int wm_cd_closetray( void ); int wm_cd_read_initial_volume( int max ); /* * Following are the missing to rename. */ int find_trkind( int track, int index, int start ); void cd_volume( int vol, int bal, int max ); #endif /* WM_CDROM_H */ ascd-0.13.2.orig/ascd/workman/wm_helpers.h0100600000175000017500000000656106670435234017702 0ustar hallonhallon#ifndef WM_HELPERS_H #define WM_HELPERS_H /* * $Id: wm_helpers.h,v 1.6 1999/03/07 08:36:44 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Here to be found: Prototypes. Including variable names to be easier * to read. * This is just one more step to a more modular and understandable code. * */ /* * LibWorkMan message levels. I'm not sure how to call them all and which * use they should fulfill. This is not very urgent now, because there * aren't many messages in LibWorkMan now. */ #define WM_MSG_LEVEL_NONE 0 #define WM_MSG_LEVEL_ERROR 1 #define WM_MSG_LEVEL_TWO 2 #define WM_MSG_LEVEL_THREE 3 #define WM_MSG_LEVEL_FOUR 4 #define WM_MSG_LEVEL_INFO 5 #define WM_MSG_LEVEL_SIX 6 #define WM_MSG_LEVEL_SEVEN 7 #define WM_MSG_LEVEL_EIGHT 8 #define WM_MSG_LEVEL_DEBUG 9 /* * Message classes. This is somehow a definition of * the message's source. */ #define WM_MSG_CLASS_PLATFORM 0x010 #define WM_MSG_CLASS_SCSI 0x020 #define WM_MSG_CLASS_CDROM 0x040 #define WM_MSG_CLASS_DB 0x080 #define WM_MSG_CLASS_MISC 0x100 #define WM_MSG_CLASS_ALL 0xff0 extern int wm_lib_verbosity; /* * I did not know any better place... */ #ifdef DEBUG #define CHECKPOINT(t) fprintf(stderr, "%s (%d): %s\n", __FILE__, __LINE__, t ); #else #define CHECKPOINT(t) #endif #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif #ifdef linux #include /* Linux doesn't have a SIGEMT */ #if !defined( SIGEMT ) # define SIGEMT SIGUNUSED #endif #endif /* linux */ void freeup( char **x ); void wm_strmcat( char **t, char *s); void wm_strmcpy( char **t, char *s ); char * wm_strdup( char *s ); /* Somebody's version query unsatisfied? */ int wm_libver_major( void ); /* return major internal version number */ int wm_libver_minor( void ); /* return minor internal version number */ int wm_libver_pl( void ); /* return internal patchlevel number */ char * wm_libver_name( void ); /* return internal name (LibWorkMan) */ char * wm_libver_number( void ); /* returns string: ".." */ char * wm_libver_string( void ); /* returns string: " " */ char * wm_libver_date( void ); /* returns string: date of compilation */ void wm_lib_set_verbosity( int level ); /* set verbosity level */ int wm_lib_get_verbosity( void ); /* get verbosity level */ void wm_lib_message( unsigned int level, char *format, ... ); /* put out a message on stderr */ int wm_susleep( int usec ); #endif /* WM_HELPERS_H */ ascd-0.13.2.orig/ascd/workman/wm_database.h0100600000175000017500000000272506661516167020007 0ustar hallonhallon#ifndef WM_DATABASE_H #define WM_DATABASE_H /* * $Id: wm_database.h,v 1.3 1999/02/14 09:50:47 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Prototypes for WorkMan database * * This is just one more step to a more modular and understandable code. */ #define WM_DB_SAVE_ERROR 1 #define WM_DB_SAVE_DISABLED 2 int wm_db_get_playnew( void ); void split_workmandb( void ); int save( void ); void load( void ); void load_settings( void ); extern int wm_db_save_disabled; extern int cur_playnew; #endif /* WM_DATABASE_H */ ascd-0.13.2.orig/ascd/workman/wm_struct.h0100644000175000017500000001336406723407436017575 0ustar hallonhallon#ifndef WM_STRUCT_H #define WM_STRUCT_H /* * $Id: wm_struct.h,v 1.7 1999/05/28 03:35:58 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /* * Structure for a single track. This is pretty much self-explanatory -- * one of these exists for each track on the current CD. */ struct wm_trackinfo { char *songname; /* Name of song, dynamically allocated */ char *otherdb; /* Unrecognized info for this track */ char *otherrc; int length; /* Length of track in seconds or Kbytes */ int start; /* Starting position (f+s*75+m*60*75) */ int volume; /* Per-track volume (1-32, 0 to disable) */ int track; /* Physical track number */ int section; /* Section number (0 if track not split) */ int contd; /* Flag: continuation of previous track */ int avoid; /* Flag: don't play this track. */ int data; /* Flag: data track */ }; /* * Structure for internal playlist management. The internal playlist is * simply the list of track ranges that are being played currently. This * is built whenever the CD starts playing; it's used in normal and shuffle * modes as well as playlist mode. * * The "starttime" element represents how much time has elapsed by the time * we get to this entry. For instance, if the list begins with a 5-minute * track and a 3-minute track, the third entry would have a starttime of 8 * minutes. This is used so that the elapsed play time can be displayed * even in shuffle or playlist modes. * * The last member of the list has a start track of 0, and its starttime is * the total playing time of the playlist (which will usually be overestimated, * since we don't play leadouts in some cases.) */ struct wm_play { int start; /* Start track, or 0 if end of list */ int end; /* last track plus 1 */ int starttime; /* Number of seconds elapsed previously */ }; /* * Structure for playlists (as seen by the user.) This is simply a name * followed by a zero-terminated list of track numbers to play. The list * is terminated by a NULL name. */ struct wm_playlist { char *name; /* Name of this playlist */ int *list; /* List of tracks */ }; struct wm_cdinfo { char artist[84]; /* Artist's name */ char cdname[84]; /* Disc's name */ int ntracks; /* Number of tracks on the disc */ int length; /* Total running time in seconds */ int autoplay; /* Start playing CD immediately */ int playmode; /* How to play the CD */ int volume; /* Default volume (1-32, 0 for none) */ struct wm_trackinfo *trk; /* struct wm_trackinfo[ntracks] */ struct wm_playlist *lists; /* User-specified playlists */ char *whichdb; /* Which database is this entry from? */ char *otherdb; /* Unrecognized lines from this entry */ char *otherrc; char *user; /* Name of originating user */ unsigned int cddbid; /* CDDB-ID of the current disc */ struct cdinfo *next; /* For browsers, etc. */ }; /* The global variable "cd" points to the struct for the CD that's playing. */ extern struct wm_cdinfo *cd; struct wm_playlist *new_list(); enum wm_cd_modes { WM_CDM_UNKNOWN = -1, WM_CDM_BACK = 0, WM_CDM_TRACK_DONE = 0, WM_CDM_PLAYING = 1, WM_CDM_FORWARD = 2, WM_CDM_PAUSED = 3, WM_CDM_STOPPED = 4, WM_CDM_EJECTED = 5 }; /* * Drive descriptor structure. Used for access to low-level routines. */ struct wm_drive { int fd; /* File descriptor, if used by platform */ char vendor[32]; /* Vendor name */ char model[32]; /* Drive model */ char revision[32]; /* Revision of the drive */ void *aux; /* Pointer to optional platform-specific info */ void *daux; /* Pointer to optional drive-specific info */ int (*init)(); int (*get_trackcount)(); int (*get_cdlen)(); int (*get_trackinfo)(); int (*get_drive_status)(); int (*get_volume)(); int (*set_volume)(); int (*pause)(); int (*resume)(); int (*stop)(); int (*play)(); int (*eject)(); int (*closetray)(); }; /* * Structure for information of the usage of cddb. */ struct wm_cddb { int protocol; /* 0-off, 1-cddbp, 2-http, 3-htproxy */ char cddb_server[84]; /* host.domain.name:port */ char mail_adress[84]; /* user@domain.name */ char path_to_cgi[84]; /* (/)path/to/cddb.cgi */ char proxy_server[84]; /* host.domain.name:port */ }; extern struct wm_cddb cddb; /* * Each platform has to define generic functions, so may as well declare * them all here to save space. * These functions should never be seen outside libworkman. So I don't care * about the wm_ naming convention here. */ int gen_init(), gen_get_trackcount(), gen_get_cdlen(), gen_get_trackinfo(), gen_get_drive_status(), gen_get_volume(), gen_set_volume(), gen_pause(), gen_resume(), gen_stop(), gen_play(), gen_eject(), gen_closetray(); struct wm_drive *find_drive_struct(); #endif /* WM_STRUCT_H */ ascd-0.13.2.orig/ascd/workman/wm_index.h0100600000175000017500000000270306661516167017346 0ustar hallonhallon#ifndef WM_INDEX_H #define WM_INDEX_H /* * $Id: wm_index.h,v 1.2 1999/02/14 09:50:47 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Prototypes for wm_index.c * * This is just one more step to a more modular and understandable code. */ int idx_find_entry( char *file, int ntracks, int *tracks, int len, int fuzz, unsigned long *pos ); int idx_delete_entry(char *file, int track, int fuzz, unsigned long pos ); int idx_write_entry( char *file, int track, unsigned long pos ); #endif /* WM_INDEX_H */ ascd-0.13.2.orig/ascd/workman/wm_platform.h0100600000175000017500000000323106661516167020060 0ustar hallonhallon#ifndef WM_PLATFORM_H #define WM_PLATFORM_H /* * $Id: wm_platform.h,v 1.3 1999/02/14 09:50:47 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * The platform interface * * This is just one more step to a more modular and understandable code. */ #include "wm_struct.h" int wmcd_open( struct wm_drive *d ); int wmcd_reopen( struct wm_drive *d ); /* * void keep_cd_open( void ); */ int wm_scsi( struct wm_drive *d, unsigned char *cdb, int cdblen, void *retbuf, int retbuflen, int getreply ); /**************************************** * * The drive prototypes. * */ extern struct wm_drive generic_proto; extern struct wm_drive sony_proto; extern struct wm_drive toshiba_proto; #endif /* WM_PLATFORM_H */ ascd-0.13.2.orig/ascd/workman/wm_scsi.h0100600000175000017500000000340506661516167017200 0ustar hallonhallon#ifndef WM_SCSI_H #define WM_SCSI_H /* * $Id: wm_scsi.h,v 1.3 1999/02/14 09:50:47 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * SCSI prototypes (scsi.c) * * This is just one more step to a more modular and understandable code. */ #include "wm_struct.h" #define WM_ERR_SCSI_INQUIRY_FAILED -1 int wm_scsi_mode_sense( struct wm_drive *d, unsigned char page, unsigned char *buf ); int sendscsi( struct wm_drive *d, void *buf, unsigned int len, int dir, unsigned char a0, unsigned char a1, unsigned char a2, unsigned char a3, unsigned char a4, unsigned char a5, unsigned char a6, unsigned char a7, unsigned char a8, unsigned char a9, unsigned char a10, unsigned char a11 ); int wm_scsi_get_drive_type( struct wm_drive *d, char *vendor, char *model, char *rev ); #endif /* WM_SCSI_H */ ascd-0.13.2.orig/ascd/workman/workman.h0100600000175000017500000000277206714071416017210 0ustar hallonhallon#ifndef WORKMAN_H #define WORKMAN_H /* * $Id: workman.h,v 1.5 1999/05/05 16:34:22 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * all-in-one libworkman include file. * */ /* * wm_config should always be included first */ #include "wm_config.h" #include "workman_defs.h" #ifdef BUILD_CDDA #include "wm_cdda.h" #endif #include "wm_cddb.h" #include "wm_cdinfo.h" #include "wm_cdrom.h" #include "wm_database.h" #include "wm_helpers.h" #include "wm_index.h" #include "wm_platform.h" #include "wm_scsi.h" #include "wm_struct.h" #endif /* WORKMAN_H */ ascd-0.13.2.orig/ascd/workman/wm_cddb.h0100600000175000017500000000264706702051640017124 0ustar hallonhallon#ifndef WM_CDDB_H #define WM_CDDB_H /* * $Id: wm_cddb.h,v 1.2 1999/02/14 09:50:46 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ extern struct wm_cddb cddb; extern int cur_cddb_protocol; extern char *cur_cddb_server, *cur_cddb_mail_adress, *cur_cddb_path_to_cgi, *cur_cddb_proxy_server; unsigned int cddb_discid(); void cddb_struct2cur(); void cddb_cur2struct(); void cddb_select(); void connect_cddb(); void update_cddbserver(); void cddb_request(); #endif /* WM_CDDB_H */ ascd-0.13.2.orig/ascd/workman/workman_defs.h0100600000175000017500000000176506661516167020222 0ustar hallonhallon#ifndef WORKMAN_DEFS_H #define WORKMAN_DEFS_H /* * $Id: workman_defs.h,v 1.4 1999/02/14 09:50:47 dirk Exp $ * * This file is part of WorkMan, the civilized CD player program * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * #defined CONSTANTS * * Too bad this file seems to be so empty... * */ #include "wm_version.h" #endif /* WORKMAN_DEFS_H */ ascd-0.13.2.orig/ascd/workman/wm_version.h0100644000175000017500000000237006723407436017731 0ustar hallonhallon#ifndef WM_VERSION_H #define WM_VERSION_H /* * $Id: wm_version.h,v 1.2 1999/05/28 03:35:58 dirk Exp $ * * This file is part of WorkMan, the civilized CD player library * (c) 1991-1997 by Steven Grimm (original author) * (c) by Dirk Försterling (current 'author' = maintainer) * The maintainer can be contacted by his e-mail address: * milliByte@DeathsDoor.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Version information * */ #define WM_LIBVER_MAJOR 1 #define WM_LIBVER_MINOR 4 #define WM_LIBVER_PL 2 #define WM_LIBVER_NAME "LibWorkMan" #endif /* WM_VERSION_H */ ascd-0.13.2.orig/ascd/workman/include0120777000175000017500000000000006764460510022656 2../libworkman/includeustar hallonhallonascd-0.13.2.orig/ascd/Imakefile0100644000175000017500000000251406764325047015525 0ustar hallonhallon#include "config.h" #include "dirs.h" NAME = ascd BINDIR = CBINDIR MANDIR = CMANDIR THEMESDIR = CTHDIR MOREFLAGS = -I/usr/local/include -I/usr/X11R6/include -I. CCOPTIONS = $(MOREFLAGS) SYS_LIBRARIES = $(XLIB) -lXpm LOCAL_LIBRARIES = -L../libworkman -lworkman -L/usr/local/lib SRCS_OPT1 = SRCS_OPT2 = SRCS_OPT3 = OBJS_OPT1 = OBJS_OPT2 = OBJS_OPT3 = #ifdef WMK SRCS_OPT1 = wings_main.c OBJS_OPT1 = wings_main.o #endif #ifdef MIXER SRCS_OPT2 = mixer_handlers.c OBJS_OPT2 = mixer_handlers.o #endif SRCS = cdcontrol.c misc.c faktory.c handlers.c \ $(SRCS_OPT1) \ $(SRCS_OPT2) \ $(SRCS_OPT3) \ ascd.c OBJS = cdcontrol.o misc.o faktory.o handlers.o \ $(OBJS_OPT1) \ $(OBJS_OPT2) \ $(OBJS_OPT3) \ ascd.o #ifdef WMK WM_LIB = -lm -lz -lpng -ljpeg -ltiff -lgif -lPropList -lwraster -lWINGs #else WM_LIB = #endif AllTarget($(NAME)) NormalProgramTarget($(NAME),$(OBJS),NullParameter,$(SYS_LIBRARIES) $(LOCAL_LIBRARIES) $(WM_LIB),NullParameter) InstallProgram($(NAME),$(BINDIR)) InstallManPage($(NAME),$(MANDIR)) InstallMultiple(themes/themes-manual.ps.gz,$(THEMESDIR)) install:: @echo "Installing themes..." @cp themes/themes.tar $(THEMESDIR) @cp themes/default.tar $(THEMESDIR) @cd $(THEMESDIR) ; tar xf themes.tar @cd $(THEMESDIR) ; tar xf default.tar @cd $(THEMESDIR) ; rm themes.tar @cd $(THEMESDIR) ; rm default.tar @echo "Done." ascd-0.13.2.orig/ascd/faktory_prot.h0100644000175000017500000000112506725564012016577 0ustar hallonhallonextern void tes_sncpy(char *, char *, int); extern char *tes_xgets(char *, int , FILE *); extern int fak_parse_line(char *, char *, char *); extern int fak_use_alt(int); extern void fak_validate_pixmap(char *, char *); extern void fak_init_theme(int); extern int fak_load_theme(char *, int); extern void fak_icon_text(char *, unsigned int, unsigned int, unsigned int); extern void fak_text(char *, unsigned int, unsigned int, unsigned int); extern int fak_flush_expose(Window); extern void fak_minus(void); extern void fak_singlemask(int); extern void fak_maskset(); extern void fak_redraw(); ascd-0.13.2.orig/ascd/config.h0100644000175000017500000000027506764326154015334 0ustar hallonhallon#define PACKAGE "ascd" #define DEFAULT_COLOR "#2FAFAF" #define DEFAULT_BGCOLOR "#000000" #define DEFAULTDEVICE "/dev/cdrom" #define THDIR "/usr/local/share/AScd" #define VERSION "0.13.2" ascd-0.13.2.orig/ascd/ascd.man0100644000175000017500000001206306717663135015324 0ustar hallonhallon.TH ascd 1 "17 may 1999" ascd .UC .SH NAME \fBascd\fP \- An AfterStep and WindowMaker CD player .SH SYNOPSIS .B ascd [ .BI \-help ] .br .B ascd [ .BI \-version ] .br .B ascd [ .BI \-themes ] .br .br .B ascd [ .BI \-geometry " geometry" ] [ .BI \+/-withdrawn ] [ .BI \-device " device" ] [ .BI \-mixer " device" ] [ .BI \+/-a ] [ .BI \+/-p ] [ .BI \+/-t ] [ .BI \+/-B ] [ .BI \-cue " time" ] [ .BI \-ti " time" ] [ .BI \-volume " volume" ] [ .BI \-mvolume " volume" ] [ .BI \-maxvolume " volume" ] [ .BI \-minvolume " volume" ] [ .BI \-fadestep " value" ] [ .BI \-theme " theme directory" ] [ .BI \+/-ia ] [ .BI \+/-up ] [ .BI \-showtitle ] [ .BI \-showartist ] [ .BI \-debug ] [ .BI \-save ] .SH DESCRIPTION \fBascd\fP is CD player written to play audio CD's integrated in afterstep's Wharf module or WindowMaker's dock. \fBascd\fP handles mounted volumes, and opens and closes the tray. .SH CONFIGURATION OPTIONS .B -help, -h print a list of commandline options and exit. .B -version print the version number and exit. .B -themes print the list of installed themes and exit. .B -geometry specifies the geometry of \fBascd\fP. The Geometry works like the standard X-Window geometry option. .B +/-withdrawn, +/-w Turn on and off withdrawn mode. Use this option if you use ascd with WindowMaker. .B -device specifies the CDROM device which should be used by ascd. If "-DNO_DEFAULT_DEVICE" was set at compilation time this option will have no effect. .B -mixer specifies the mixer device. Works only if mixer support was enabled at compilation. .B -cue specifies the time -in seconds- for \fBintro scan\fP and \fBcue\fP modes. .B -ti specifies the timeout for the help texts. The default is 1 second. .B +/-autoplay, +/-a Turn on or off \fBautoplay mode\fP. When this is turned on, ascd always wait for a CD, and play it automatically when inserted. .B +/-autoprobe, +/-p Turn on or off \fBautoprobe mode\fP. This mode checks for inserted CD. Default is on. .B +/-autorepeat, +/-t autorepeat mode: when ascd reaches the end of the last track, the CD is not stopped and first track is played. .B +/-B This option is no longer supported. .B -maxvolume Set the CD driver max volume. .B -minvolume Set the CD driver min volume. .B -volume Set the CD driver volume, between 0 and maxvolume. Note that the -volume option in independant from the mixer. It controls the drive, not the sound card. .B -mvolume Set the CD driver volume for the mute mode. .B -fadestep Set the fade in/out speed. Default is 5. Greater values accelerate the fade. .B -theme Specify the visual theme to use. .B +/-ia When this option is enabled, AScd ignore the skip orders found in WorkMan database and read all the tracks of the CD. .B +/-up When enabled, all the message (and the track title display) are forced in uppercase. .B -showtitle Show the track title if found in WorkMan database. If the message panel is not large enough, AScd scrolls the title. .B -showartist Add the artist name to the track title (-showtitle option needed) .B -debug AScd verbose mode .B -save Save all the settings and exit. Usefull to 'make' a new configuration file: set all the stuff you want to set and put -save as last commandline option. Example: ascd +w +a -device /dev/cd0c -save Then, you just call ascd without arguments, it will use the settings you just saved. .SH FILES \fBascd\fP stores its settings in ~/.ascdrc. The theme files are usually stored in /usr/local/share/AScd. .SH INVOCATION \fBascd\fP can be called from one of many ways. The most common invocation is the command line: .nf % ascd -device /dev/wcd0a +w +a & .fi With Afterstep, another way to call \fBascd\fP is from the window manager: .nf *Wharf - - Swallow "ascd" ascd& .fi This line, when placed in the \fI.steprc\fP file in the users home directory will cause \fBascd\fP to use the shape extensions so that it will be a button on the \fBWharf (1)\fP button bar under the \fBafterstep (1)\fP window manager. .SH COPYRIGHTS Copyright 1999, Rob Malda and Denis Bourez. No guarantees or warranties or anything are provided or implied in any way whatsoever. Use this program at your own risk. Permission to use this program for any purpose is given, as long as the copyright is kept intact. .SH AUTHORS Denis Bourez application since 0.7 .br Rob Malda application until 0.6 .br Dirk Foersterling WorkMan maintainer .br Steven Grimm WorkMan maintainer until 1.3 .br Erik O'Shaughnessy AIX platform device driver .br Michael Kurz changes and man page until 0.6 .SH MORE INFORMATION .br ascd-0.13.2.orig/ascd/cdcontrol.c0100644000175000017500000002262306726077660016055 0ustar hallonhallon/* =========================================================================== * AScd: cdcontrol.c * This is cd_control() function: accept orders from the ui player and send * the appropriate commands to libworkman. * * Please do *not* modify this function as it is used without changes by * several programs! * =========================================================================== * Copyright (c) 1999 Denis Bourez and Rob Malda. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Denis Bourez & Rob Malda * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY DENIS BOUREZ AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL DENIS BOUREZ, ROB MALDA OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * =========================================================================== */ #define CD_C_VERSION "1.4" #include "ext.h" void cd_control(int order) { static int pos_changed = FALSE; int currenttrack; anomalie = 0; wanna_play = FALSE; #ifdef XFASCD update_xpm = TRUE; #endif if (cur_cdmode != WM_CDM_EJECTED) { if (cd->trk[cur_track - 1].data) datatrack = 1; else datatrack = 0; } if ((cur_ntracks == 1) && (cd->trk[cur_track - 1].data)) { /* only one track, and it's a data track. We ignore all commands to avoid some funny things. Only the EJECT commands are allowed */ if ((order != STOP) && (order != EJECT)) { anomalie = 1; return; } } switch(order) { case PLAY: loop_mode = 0; intro_mode = 0; if (! pos_changed) { wm_cd_status(); } else { pos_changed = FALSE; } if (cur_track < 1) cur_track = 1; /* don't play data tracks: */ if (! cd->trk[cur_track - 1].data) { if (cur_cdmode != WM_CDM_EJECTED) { if (cur_cdmode != WM_CDM_PAUSED) { if (do_autorepeat) { cur_track = 1; do_autorepeat = FALSE; } /* skip data and avoid tracks */ while (((cd->trk[cur_track - 1].data) || ((cd->trk[cur_track - 1].avoid == 1) && (!ignore_avoid)) ) && (cur_track <= cur_ntracks)) cur_track++; if (cur_track > cur_ntracks) cur_track--; if (!(cd->trk[cur_track - 1].data)) { wanna_play = TRUE; wm_cd_play(cur_track, 0, cur_ntracks + 1); } } } } break; case PAUSE: loop_mode = 0; intro_mode = 0; if (pos_changed) { cur_track = wanted_track; wanna_play = TRUE; wm_cd_play(cur_track, 0, cur_ntracks + 1); cur_cdmode = WM_CDM_PLAYING; } else { wm_cd_pause(); } if (cur_cdmode == WM_CDM_PLAYING) { pos_changed = FALSE; } break; case STOP: /* Civilized handler: STOP and EJECT combined */ loop_mode = 0; intro_mode = 0; if ((cur_cdmode == WM_CDM_PLAYING) || (cur_cdmode == WM_CDM_PAUSED)) { cur_cdmode = WM_CDM_PAUSED; wm_cd_stop(); cur_cdmode = WM_CDM_STOPPED; } else { if (cur_cdmode != WM_CDM_EJECTED) { currenttrack = 0; wm_cd_eject(); } } pos_changed = FALSE; break; case STOPONLY: /* STOP, no more. Doesn't eject if CD is already stopped */ loop_mode = 0; intro_mode = 0; if ((cur_cdmode == WM_CDM_PLAYING) || (cur_cdmode == WM_CDM_PAUSED)) { cur_cdmode = WM_CDM_PAUSED; wm_cd_stop(); cur_cdmode = WM_CDM_STOPPED; } pos_changed = FALSE; break; case EJECT: /* Troll handler: don't try to guess the current mode, just eject */ if (cur_cdmode != WM_CDM_EJECTED) { loop_mode = 0; intro_mode = 0; currenttrack = 0; wm_cd_eject(); } break; case CLOSETRAY: /* let's try this */ if (cur_cdmode == WM_CDM_EJECTED) { /* commented, as current libworkman crashes when it receive this order */ /*wm_cd_closetray();*/ } break; case UPTRACK: /* next track */ loop_mode = 0; intro_mode = 0; if (pos_changed) cur_track = wanted_track; if (cur_track + 1 > cur_ntracks ) { cur_track = 1; } else { cur_track ++; } if (cur_cdmode == WM_CDM_PAUSED) { pos_changed = TRUE; wanted_track = cur_track; } if (cur_cdmode == WM_CDM_PLAYING) { wanna_play = TRUE; wm_cd_play(cur_track, 0, cur_ntracks + 1); } break; case DNTRACK: /* previous track */ loop_mode = 0; intro_mode = 0; if (pos_changed) cur_track = wanted_track; if (cur_cdmode == WM_CDM_PAUSED) { if (cur_pos_rel < 2 || pos_changed) cur_track--; cur_pos_rel = 0; pos_changed = TRUE; } else if (cur_cdmode == WM_CDM_PLAYING) { if (cur_pos_rel < 2) cur_track--; cur_pos_rel = 0; } else { cur_track--; } if (cur_track < 1) cur_track = cur_ntracks; if (cur_cdmode == WM_CDM_PAUSED) { pos_changed = TRUE; wanted_track = cur_track; } if (cur_cdmode == WM_CDM_PLAYING) { wanna_play = TRUE; wm_cd_play(cur_track, 0, cur_ntracks + 1); } break; case DIRECTTRACK: /* direct access to a random track */ loop_mode = 0; intro_mode = 0; if (direct_track < 1) direct_track = 1; if (cur_cdmode == WM_CDM_PAUSED) pos_changed = TRUE; cur_track = direct_track; if (cur_track >= cur_ntracks + 1) cur_track = 1; /* if it's a data track, skip it */ while ((cd->trk[cur_track - 1].data) && (cur_track <= cur_ntracks)) cur_track++; if (cur_cdmode == WM_CDM_PLAYING) { wanna_play = TRUE; wm_cd_play(cur_track, 0, cur_ntracks + 1); } break; case CUE: loop_mode = 0; intro_mode = 0; if (cur_cdmode == WM_CDM_PLAYING) { wanna_play = TRUE; wm_cd_play(cur_track, cur_pos_rel + cue_time, cur_ntracks + 1); } break; case REV: loop_mode = 0; intro_mode = 0; if ( (cur_cdmode == WM_CDM_PLAYING) && ( (cur_pos_rel - cue_time) >= 0 ) ) { wanna_play = TRUE; wm_cd_play(cur_track, cur_pos_rel - cue_time, cur_ntracks + 1); } break; case FIRST: loop_mode = 0; intro_mode = 0; cur_track = 1; if (cur_cdmode == WM_CDM_PLAYING) { wanna_play = TRUE; wm_cd_play(cur_track, 0, cur_ntracks + 1); } else if (cur_cdmode == WM_CDM_PAUSED) { pos_changed = TRUE; wanted_track = cur_track; } break; case LAST: loop_mode = 0; intro_mode = 0; cur_track = cur_ntracks; if (cur_cdmode == WM_CDM_PLAYING) { wanna_play = TRUE; wm_cd_play(cur_track, 0, cur_ntracks + 1); } else if (cur_cdmode == WM_CDM_PAUSED) { pos_changed = TRUE; wanted_track = cur_track; } break; case LOOP: if ( (loop_2 > loop_1) || (loop_end_track > loop_start_track) ) { if (loop_start_track == 0) loop_start_track = 1; intro_mode = 0; if ( ( loop_2 > loop_1 ) || ( loop_start_track != loop_end_track ) ) currenttrack = loop_start_track; else { loop_end_track = cur_ntracks; currenttrack = loop_start_track = 1; loop_1 = 0; loop_2 = thiscd.trk[ loop_end_track - 1 ].length - 1; } wm_cd_play(loop_start_track, loop_1, cur_ntracks + 1); wanna_play = TRUE; loop_mode = 1; } else { anomalie = 1; } break; case DIRECTACCESS: /* direct access to a random position of the current track */ if (direct_access < 0) direct_access = 0; loop_mode = 0; intro_mode = 0; wm_cd_status(); wm_cd_play(cur_track, direct_access, cur_ntracks + 1); wanna_play = TRUE; break; case GLOBALACCESS: if (direct_access < 0) direct_access = 0; loop_mode = 0; intro_mode = 0; wm_cd_status(); wm_cd_play(1, direct_access, cur_ntracks + 1); wanna_play = TRUE; break; case INTROSCAN: if (! intro_mode) { intro_mode = 1; wm_cd_play(cur_track, 0, cur_ntracks + 1); } else { intro_mode = 0; } break; case INTRONEXT: wm_cd_pause(); currenttrack = cur_track; currenttrack++; if (cur_track +1 > cur_ntracks ) currenttrack = 1; else currenttrack = cur_track + 1; cur_pos_rel = 0; wm_cd_play(currenttrack, 0, cur_ntracks + 1); break; case LOCACCESS: if ( (loop_1 > 0) && (loop_start_track > 0) ) { intro_mode = 0; loop_mode = 0; currenttrack = loop_start_track; wm_cd_stop(); wm_cd_play(loop_start_track, loop_1, cur_ntracks + 1); wanna_play = TRUE; } else { anomalie = 1; } break; } } char *cd_control_version(void) { char *s = NULL; wm_strmcat(&s, CD_C_VERSION); return s; } ascd-0.13.2.orig/ascd/configure0100755000175000017500000001211606717645120015615 0ustar hallonhallon#!/bin/sh LS=/bin/ls rm -f config.h rm -f dirs.h echo "/* auto-generated config.h for AScd. */" > config.h echo "/* do not edit. Run ./configure! */" >> config.h echo "" >> config.h echo "/* internal defines, do not change! */" >> config.h echo "#define PACKAGE \"ascd\"" >> config.h cat version.h >> config.h echo "" >> config.h echo "/* user choices */" >> config.h echo "#define DEFAULT_COLOR \"#2FAFAF\"" >> config.h echo "#define DEFAULT_BGCOLOR \"#000000\"" >> config.h clear ################################################################# echo "Welcome to the ascd configuration script. Please answer the" echo "following questions before compilation." echo echo "--------------------" echo "1. Default CD device" echo "--------------------" echo echo "Please select a default CD device. This can be overriden at run" echo "time with the -d option. Default is /dev/cdrom. You can also type" echo "'NO' if you don't want to specify a default device (in case you're" echo "using Volume Manager for example." echo printf "Default device or NO (or return to accept the default): " read CDD echo case $CDD in "") echo "#define DEFAULTDEVICE \"/dev/cdrom\"" >> config.h echo "** the default device will be /dev/cdrom" ;; NO) echo "#define DEFAULTDEVICE \"/dev/cdrom\"" >> config.h echo "#define NO_D_DEVICE" >> config.h echo "** no device option enabled" ;; *) echo "#define DEFAULTDEVICE \"$CDD\"" >> config.h echo "** the default device will be $CDD" ;; esac ################################################################# echo echo "------------------" echo "2. Binary location" echo "------------------" echo echo "Where shall I install ascd program? Press return to accept the" echo "default value (/usr/local/bin)." echo printf "Bin directory? " read BINDIR echo case $BINDIR in "") echo "#define CBINDIR /usr/local/bin" > dirs.h echo "** Ascd will be /usr/local/bin/ascd" ;; *) echo "#define CBINDIR $BINDIR" >> dirs.h echo "** Ascd will be $BINDIR/ascd" ;; esac ################################################################# echo echo "---------------" echo "3. Man location" echo "---------------" echo echo "Where shall I install the man page? Press return to accept the" echo "default value (/usr/local/man/man1)." echo printf "Man directory? " read MANDIR echo case $MANDIR in "") echo "#define CMANDIR /usr/local/man/man1" >> dirs.h echo "** Man page will be installed in /usr/local/man/man1." ;; *) echo "#define CMANDIR $MANDIR" >> dirs.h echo "** Man page will be installed in $MANDIR." ;; esac ################################################################# echo echo "------------------" echo "4. themes location" echo "------------------" echo echo "Where shall I install the ascd themes files? Press return" echo "to accept default value (/usr/local/share/AScd)." echo printf "Themes pixmaps directory? " read THDIR echo case $THDIR in "") echo "#define THDIR \"/usr/local/share/AScd\"" >> config.h echo "#define CTHDIR /usr/local/share/AScd" >> dirs.h echo "** Theme dir: /usr/local/share/AScd." ;; *) echo "#define THDIR \"$THDIR\"" >> config.h echo "#define CTHDIR $THDIR" >> dirs.h echo "** Theme dir: $THDIR." ;; esac ################################################################# echo echo "-------------------------" echo "5. optional WINGs support" echo "-------------------------" echo echo "If you're using Window Maker window manager, AScd can be compiled" echo "with a configuration window using WINGs toolkit. Please note that" echo "it's work in progress and you may have to change a few things in" echo "ascd/Imakefile." echo echo "1) compile with WINGs support" echo "2) no WINGs support (DEFAULT)" echo printf "Type 1 or 2: " read WINGS echo case $WINGS in 1) echo "#define WMK" >> config.h echo "** Compiling with WINGs support." ;; *) echo "** No WINGs support." ;; esac ################################################################# echo echo "-------------------------" echo "6. optional mixer support" echo "-------------------------" echo echo "This optional module adds mixing capabilities to AScd's themes." echo "It is not supported on a lot of platforms, and you may have to" echo "make some changes in the sources." echo echo "1) compile with mixer support" echo "2) no mixer support (DEFAULT)" echo printf "Type 1 or 2: " read WINGS echo case $WINGS in 1) echo "#define MIXER" >> config.h echo "** Compiling with mixer support." ;; *) echo "** No mixer support." ;; esac ################################################################# echo echo "-----------------------------" echo "Automatic Makefile generation" echo "-----------------------------" echo echo "Configuration is done. This script is now running xmkmf to" echo "generate the Makefiles." echo xmkmf -a echo echo "---------" echo "Finished!" echo "---------" echo echo "You are now ready to compile AScd. type:" echo echo "make ... to compile the software" echo "make install ... to install it" echo "make install.man ... to install the man page" echo echo ascd-0.13.2.orig/ascd/version.h0100644000175000017500000000003306726075410015536 0ustar hallonhallon#define VERSION "0.13.2" ascd-0.13.2.orig/ascd/dirs.h0100644000175000017500000000015006764326154015020 0ustar hallonhallon#define CBINDIR /usr/local/bin #define CMANDIR /usr/local/man/man1 #define CTHDIR /usr/local/share/AScd ascd-0.13.2.orig/configure0100755000175000017500000000014106706165615014702 0ustar hallonhallon#!/bin/sh cd ascd rm -f workman ln -s ../libworkman/include workman ./configure cd .. xmkmf -a ascd-0.13.2.orig/README0100644000175000017500000000247506764326055013670 0ustar hallonhallonThis archive includes the original ascd 0.13.2 archive and the latest LibWorkMan snapshot (990620). To compile the software: - run ./configure (*) - make - make install - make install.man (*) configure will ask you a few question about ascd options. If you want to use the default settings, run ./default instead of ./configure. Important note: --------------- I changed two things in libworkman: 1) I added #under OSS_SUPPORT in plat_linux.c in order to definitly prevent libworkman to use the mixer. 2) I added wm_cddb.h in installed files as it was missing in the original tarball. Upgrading from ascd <= 0.12.X ----------------------------- Ascd 0.13 uses the last libworkman snapshot and is *not* compatible with the previous ones. Do not forget to compile and install the snapsnot included in this archive before trying to compile ascd 0.13. More infos: ----------- I strongly suggest to read the following texts: - in libworkman/ dir, read the README file and edit Config file. - in ascd/ dir, read the README file. AScd: ----- * maintained by Denis Bourez * homepage: http://worldserver.oleane.com/rsn/ascd-en.html LibWorkMan: ----------- * maintained by Dirk Försterling * homepage: http://www.DeathsDoor.com/milliByte/WorkMan/ Denis Bourez, 99/9/5 ascd-0.13.2.orig/default0100755000175000017500000000014406706165623014347 0ustar hallonhallon#!/bin/sh cd ascd rm -f workman ln -s ../libworkman/include workman ./misc/default cd .. xmkmf -a ascd-0.13.2.orig/Imakefile0100644000175000017500000000017306706165657014617 0ustar hallonhallon#define IHaveSubdirs #define PassCDebugFlags SUBDIRS = libworkman ascd MakeSubdirs($(SUBDIRS)) DependSubdirs($(SUBDIRS)) ascd-0.13.2.orig/version.h0100644000175000017500000000003306726075410014624 0ustar hallonhallon#define VERSION "0.13.2"