home *** CD-ROM | disk | FTP | other *** search
- /* files.c */
-
- /* songs management, mainly some iterators
- */
-
- /*
- * $Author: Espie $
- * $Date: 91/05/16 15:05:01 $
- * $Revision: 1.8 $
- * $Log: files.c,v $
- * Revision 1.8 91/05/16 15:05:01 Espie
- * *** empty log message ***
- *
- * Revision 1.7 91/05/12 19:53:05 Espie
- * Corrected the non-freed icons problem.
- *
- * Revision 1.6 91/05/12 15:56:53 Espie
- * Bugs mostly corrected.
- *
- * Revision 1.5 91/05/11 14:58:02 Espie
- * Corrected an auto-cleanup problem.
- *
- * Revision 1.4 91/05/10 00:04:19 Espie
- * Added albums support. Directories missing, not sure
- * I will add it...
- *
- * Revision 1.3 91/05/09 17:35:17 Espie
- * Support for appwindow, mk_wbarg optimization.
- *
- * Revision 1.2 91/05/08 18:33:46 Espie
- * Added check_abort() for loooong runs.
- * Added support for arp pattern-matching... need checking that arp is around.
- * Does enter subdirectories too !
- *
- * Revision 1.1 91/05/08 15:50:32 Espie
- * Initial revision
- *
- *
- */
-
- #include <exec/types.h>
- #include <dos/dos.h>
- #include <exec/memory.h>
- #include <workbench/startup.h>
- #include <workbench/workbench.h>
- #include <string.h>
- #include <stddef.h>
- #include <custom/cleanup.h>
- #include <proto/exec.h>
- #include <proto/dos.h>
- #include <proto/icon.h>
- #include <stdio.h>
-
- #include <libraries/arpbase.h>
- #include <proto/arp.h>
-
- #include "song.h"
- #include "public_play.h"
-
- void *malloc();
-
- #include "proto.h"
-
- LOCAL struct WBStartup *msg;
- LOCAL char **tools;
-
- /***
- *
- * Tooltypes management
- *
- ***/
-
- /* get_arg(tools, tooltype, def): reads the tooltype in the tools array,
- * as a numerical argument, with def as a default value.
- */
-
- int get_arg(char **tools, char *tooltype, int def)
- {
- int val;
- char *string = NULL;
- if (tools)
- string = FindToolType(tools, tooltype);
- if (string && sscanf(string, "%d", &val) == 1)
- return val;
- else
- return def;
- }
-
- /* same thing with default tools */
-
- int do_get_arg(char *tooltype, int def)
- {
- return get_arg(tools, tooltype, def);
- }
-
-
- /* map_arg: gives a numerical argument from a limited set
- * of strings values
- */
- int map_arg(char **tools, char *tooltype, char **names, int def)
- {
- int val;
- char *string = NULL;
- if (tools)
- string = FindToolType(tools, tooltype);
- if (string)
- {
- for (val = 0; names; val++, names++)
- if (MatchToolValue(string, *names))
- return val;
- }
- return def;
- }
-
- int do_map_arg(char *tooltype, char **names, int def)
- {
- return map_arg(tools, tooltype, names, def);
- }
-
- /* exist_tooltype(tools, tooltype): checks if tooltype exists among tools
- */
- BOOL exist_tooltype(char **tools, char *tooltype)
- {
- if (!tools)
- return NULL;
- return (FindToolType(tools, tooltype) != NULL);
- }
-
-
-
- /***
- *
- * Iterators.
- * Every argument is managed as an iterator
- * you can resume later. This makes a nice
- * framework for multiple arguments, pattern-matching,
- * albums, directory traversal...
- *
- ***/
-
-
-
-
- enum it_tag {CLI_list, Match_list, Dir_list, WB_list, Album, Empty};
-
- struct CLI_it
- {
- int number;
- int index;
- char **names;
- };
-
- struct WB_it
- {
- int number;
- int index;
- struct WBArg *args;
- };
-
-
- #define MAX_LENGTH 400
-
- struct Album_it
- {
- FILE *f;
- char *pbuf;
- char buffer[MAX_LENGTH];
- };
-
- struct Match_it
- {
- struct AnchorPath anchor;
- BYTE suppl_buffer[MAX_LENGTH];
- };
-
-
- /*
-
- struct Dir_List
- {
- struct FileInfoBlock examiner;
- };
-
- */
-
- /* be careful of the fields you use, the FileInfoBlock/AnchorPath
- * must be longword aligned !
- */
-
- struct iterator
- {
- enum it_tag tag;
- struct iterator *next;
- CLEAN auto_clean;
- BPTR save_lock;
- struct DiskObject *currenticon;
- BOOL cd;
- BOOL ownlock;
- union
- {
- struct CLI_it CLI;
- struct WB_it WB;
- struct Album_it Album;
- struct Match_it Match;
- } u;
- };
-
-
-
- /***
- *
- * Support functions
- *
- ***/
-
-
- LOCAL void free_last_icon(struct iterator *it)
- {
- if (it->currenticon)
- FreeDiskObject(it->currenticon);
- it->currenticon = NULL;
- }
-
- /* where do we get the tooltypes from anyway
- */
- char **grab_tooltypes(struct iterator *it, char *arg)
- {
- struct DiskObject *icon;
- if (icon_around())
- {
- icon = GetDiskObject(arg);
- if (icon)
- {
- if (it)
- {
- free_last_icon(it);
- it->currenticon = icon;
- }
- else
- ToClean(FreeDiskObject, icon);
- return icon->do_ToolTypes;
- }
- }
- return NULL;
- }
- /* we need doFreeAnchorChain 'cause FreeAnchorChain exists only as a pragma
- */
-
- LOCAL void doFreeAnchorChain(struct AnchorPath *ap)
- {
- FreeAnchorChain(ap);
- }
-
-
- /* getline(buffer, bufsize, f): read a line from file f into buffer,
- * upto bufsize characters. Puts a \0 at the end of line in place of
- * the \n. The last line may end without a \n.
- * If the line is too long, remaining characters are skipped.
- * returns the strlen of buffer, or -1 if the line is too long.
- * A NULL f is allowed, in that case, the call will never succeed.
- *
- * It is the responsibility of the client to close that file.
- */
-
- LOCAL int getline(char *buffer, int bufsize, FILE *f)
- {
- int i, c;
- if (!f)
- return 0;
- for (i = 0; i < bufsize; i++)
- {
- c = fgetc(f);
- if (c == EOF)
- {
- buffer[i] = '\0';
- return i;
- }
- if (c == '\n')
- {
- buffer[i] = '\0';
- return i;
- }
- buffer[i] = c;
- }
- while((c=fgetc(f)) != '\n' && c != EOF);
- return (-1);
- }
-
- /* The iterators need to change dir in an effective way.
- */
- LOCAL void un_dir(struct iterator *it)
- {
- if (it->cd)
- {
- if (it->ownlock)
- UnLock(CurrentDir(it->save_lock));
- else
- CurrentDir(it->save_lock);
- }
- it->cd = FALSE;
- it->ownlock = FALSE;
- }
-
- LOCAL void change_dir(struct iterator *it, BPTR new_dir)
- {
- un_dir(it);
- it->save_lock = CurrentDir(new_dir);
- it->cd = TRUE;
- }
-
- /* iterator creation. An iterator is always the son of another,
- * except the root, of course. new_iterator() initializes all
- * relevant fields to reasonable values.
- */
-
- LOCAL struct iterator *new_iterator(struct iterator *father)
- {
- struct iterator *new;
- /* this is an aligned structure */
- new = AllocMem(sizeof(struct iterator), MEMF_ANY);
- if (!new)
- return NULL;
- new->auto_clean = AllocClean(NIL);
- ToClean2L(new->auto_clean, FreeMem, new, sizeof(struct iterator));
- new->ownlock = FALSE;
- new->cd = FALSE;
- new->next = father;
- new->currenticon = NULL;
- ToCleanL(new->auto_clean, un_dir, new);
- ToCleanL(new->auto_clean, free_last_icon, new);
- return new;
- }
-
- /* insert_iterator(it): returns a new iterator inserted as a son
- * of it, so executed before we resume it. Note that the address of
- * it is necessary.
- */
-
- LOCAL struct iterator *insert_iterator(struct iterator **head)
- {
- struct iterator *base;
- base = new_iterator(*head);
- *head = base;
- return base;
- }
-
- /* creation of common iterator types
- */
- LOCAL struct iterator *mk_CLI_iterator(struct iterator **head,
- int argc, char **argv)
- {
- struct iterator *new;
- new = insert_iterator(head);
- new->tag = CLI_list;
- new->u.CLI.names = argv;
- new->u.CLI.number = argc;
- new->u.CLI.index = 0;
- return new;
- }
-
- LOCAL struct iterator *mk_WB_iterator(struct iterator **head,
- int argn, struct WBArg *argarray)
- {
- struct iterator *new;
- new = insert_iterator(head);
- new->tag = WB_list;
- new->u.WB.args = argarray;
- new->u.WB.number = argn;
- new->u.WB.index = 0;
- return new;
- }
-
- /* the arp pattern matcher... */
- LOCAL char *match_next(struct AnchorPath *ap)
- {
- int res;
- forever
- {
- res = FindNext(ap);
- if (res)
- return NULL;
- if (ap->ap_Info.fib_DirEntryType < 0)
- return ap->ap_Buf;
- if (!ap->ap_Flags & APF_DidDir)
- ap->ap_Flags |= APF_DoDir;
- }
- }
-
- /* ...and the start of it */
- LOCAL char *match_CLI(struct iterator **head)
- {
- struct iterator *first, *new;
- first = *head;
- forever
- {
- if (first->u.CLI.index >= first->u.CLI.number)
- return NULL;
- if (requester_type() != ARP)
- return first->u.CLI.names[first->u.CLI.index++];
- else
- {
- struct AnchorPath *ap;
- int res;
- new = insert_iterator(head);
- new->tag = Match_list;
- ap = &new->u.Match.anchor;
- ap->ap_BreakBits = 0;
- ap->ap_Flags = APF_DoWild;
- ap->ap_StrLen = MAX_LENGTH;
- ToCleanL(new->auto_clean, doFreeAnchorChain, ap);
- res = FindFirst(first->u.CLI.names[first->u.CLI.index++], ap);
- if (!res)
- {
- if (ap->ap_Info.fib_DirEntryType < 0)
- return ap->ap_Buf;
- else
- {
- ap->ap_Flags |= APF_DoDir;
- return match_next(ap);
- }
- }
- }
- }
- }
-
- /* how to restart an existing iterator */
-
- LOCAL char *resume_iterator(struct iterator **head)
- {
- struct iterator *new, *first;
- struct WBArg *temp;
- first = *head;
- switch(first->tag)
- {
- case CLI_list:
- return match_CLI(head);
- case WB_list:
- if (first->u.WB.index >= first->u.WB.number)
- return NULL;
- temp = first->u.WB.args + first->u.WB.index++;
- if (temp->wa_Lock)
- change_dir(first, temp->wa_Lock);
- return temp->wa_Name;
- case Match_list:
- return match_next(&first->u.Match.anchor);
- case Album:
- if (!getline(first->u.Album.pbuf, MAX_LENGTH, first->u.Album.f))
- {
- /* temporary kludge */
- if (first->u.Album.f)
- {
- fclose(first->u.Album.f);
- first->u.Album.f = NULL;
- }
- return NULL;
- }
- else
- {
- new = mk_CLI_iterator(head, 1, &(first->u.Album.pbuf));
- return match_CLI(head);
- }
- }
- }
-
- LOCAL void delete_first(struct iterator **head)
- {
- struct iterator *next;
- next = (*head)->next;
- CleanUp((*head)->auto_clean);
- *head = next;
- }
-
- /* basic stuff about iterators. Still needs a special test
- * about albums.
- */
- LOCAL char *do_next_song(struct iterator **head)
- {
- char *temp;
- forever
- {
- check_abort();
- if (!*head)
- return NULL;
- if (temp = resume_iterator(head))
- return temp;
- else
- delete_first(head);
- }
- }
-
- /* basic code to deal with albums. Once we've detected an album,
- * we can insert it.
- */
- LOCAL void insert_album(struct iterator **head, char *arg)
- {
- struct iterator *base;
- base = insert_iterator(head);
- base->tag = Album;
- base->u.Album.pbuf = base->u.Album.buffer;
- base->u.Album.f = fopen(arg, "r");
- /* I can't autoclean this stuff: conflict with Lattice
- ToCleanL(base->auto_clean, fclose, base->u.Album.f);
- */
- }
-
-
- char *next_song(struct iterator **head, BOOL req)
- {
- char *test;
- struct iterator *new;
- static struct WBArg holder;
- forever
- {
- test = do_next_song(head);
- if (test)
- {
- if (exist_tooltype(grab_tooltypes(*head, test), "ALBUM"))
- {
- insert_album(head, test);
- }
- else
- return test;
- }
- else
- {
- if (req && query_name("Module to play", &holder))
- {
- new = mk_WB_iterator(head, 1, &holder);
- new->ownlock = TRUE;
- }
- else
- return NULL;
- }
- }
- }
-
-
- /* init_iterator(): builds an initial iterator from the arguments
- * supplied by the user.
- */
- LOCAL struct iterator *zero;
-
- LOCAL struct iterator *init_iterator(int argc, char **argv)
- {
- struct iterator *base;
- zero = NULL;
- if (argc)
- {
- msg = NULL;
- base = mk_CLI_iterator(&zero, argc, argv);
- }
- else
- {
- msg = (struct WBStartup *)argv;
- base = mk_WB_iterator(&zero, msg->sm_NumArgs, msg->sm_ArgList);
- }
- return base;
- }
-
- /* insert_args: adds new songs given to the appwindow.
- */
- void insert_args(struct iterator **head, struct AppMessage *msg)
- {
- struct iterator *new;
- new = mk_WB_iterator(head, msg->am_NumArgs, msg->am_ArgList);
- ToCleanL(new->auto_clean, ReplyMsg, msg);
- }
-
-
- /* setup_arguments: initial setup for everything
- */
- struct iterator *setup_arguments(int argc, char **argv)
- {
- struct iterator *result;
- result = init_iterator(argc, argv);
- if (argc)
- tools = argv; /* grab_tooltypes(NIL, next_song(&result, FALSE)); */
- else
- tools = grab_tooltypes(NIL, next_song(&result, FALSE));
- return result;
- }
-
-