/**********************************************
 *  imp3sh.h                                                          
 *                                            
 *  Copyright 2001 Eric Kratzer.               
 *  Includes Xaudio software Copyright (C)
 *           1996-2000 Xaudio Corporation
 *           All Rights Reserved.
 *
 *  This file is part of imp3sh.
 *                                            
 *  imp3sh is free software; you can distribute
 *  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.
 *
 *  imp3sh 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.
 *
 *  You should have recieved a copy of the GNU
 *  General Public License along with imp3sh; if
 *  not, write to the Free Software Foundation,
 *  Inc., 59 Temple Place, Suite 330, Boston MA
 *  02111-1307 USA
 *
 *                                            
 **********************************************/

#ifndef IMP3SH_H
#define IMP3SH_H

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <ctype.h>
#include <string.h>
#include <dirent.h>
#include <signal.h>
#include <curses.h>
#include <term.h>
#include <errno.h>
#include <stdarg.h>

/* xaudio stuff */
#include "xaudio.h"
#include "decoder.h"
#include "player.h"
#include "control_pipe.h"

/* Ogg/Vorbis stuff */
#ifdef OGG_MODULE
#include "vorbis_codec.h"
#include "vcedit.h"
#endif

#define NAME            "imp3sh"
#define VERSION         "0.2.2"
#define DATE            "2001"

#define NOTIFY_MASK     (XA_NOTIFY_MASK_ERROR |\
			 XA_NOTIFY_MASK_DEBUG |\
			 XA_NOTIFY_MASK_PLAYER_STATE |\
			 XA_NOTIFY_MASK_INPUT_STATE |\
			 XA_NOTIFY_MASK_STREAM_DURATION |\
			 XA_NOTIFY_MASK_INPUT_TIMECODE |\
			 XA_NOTIFY_MASK_STREAM_PARAMETERS |\
                         XA_NOTIFY_MASK_OUTPUT_VOLUME |\
                         XA_NOTIFY_MASK_OUTPUT_BALANCE |\
                         XA_NOTIFY_MASK_OUTPUT_PCM_LEVEL |\
                         XA_NOTIFY_MASK_OUTPUT_MASTER_LEVEL |\
                         XA_NOTIFY_MASK_INPUT_POSITION |\
                         XA_NOTIFY_MASK_OUTPUT_STATE)

#define JOBB_SIZE       8192	/* max job buffer size        */
#define LIST_SIZE       2048	/* default list size          */
#define COMM_SIZE       1024	/* command-buffer size        */
#define CONB_SIZE       1024	/* max console buffer size    */
#define HIST_SIZE       1024	/* max history size           */
#define CHIST_SIZ       1024	/* comm history length        */
#define INFO_SIZE        256	/* max misc. length           */
#define DLOG_SIZE        256	/* max xaudio log size        */
#define HEAD_SIZE          8	/* max header length          */

#define VOLUME_JUMP        4	/* volume up/down             */
#define OFFSET_JUMP        3	/* fast-forward/rewind jump   */
#define BALANCE_JUMP       2	/* balance left/right         */

#define END_COMM        '\n'	/* user command delimiter     */
#define SEP_COMM        ';'	/* user command seperator     */
#define PARENTHESIS     '\"'	/* paranthesis char def       */
#define SPACE           ' '	/* space char def             */
#define TAB             '\t'	/* tab char def               */
#define AMPERSAND       '&'	/* ampersand char def         */
#define PERIOD          '.'	/* period char def            */
#define PIPE            '|'	/* pipe char def              */
#define EXCLAMATION     '!'	/* excl char def              */
#define ZCHAR           '\0'	/* NULL character             */
#define COLON           ':'
#define COMMA           ','
#define TILDE           '~'
#define ALIAS_SEPERATOR '='	/* alias seperator            */

#define SELECT_TIMEOUT 500000	/* microseconds               */

#define CURR_STATE         "IMP3_STATE"
#define CURR_STREAM        "IMP3_STREAM"
#define CURR_INFO          "IMP3_INFO"

#define CURR_ACTIVE_SOURCE "IMP3_ACTIVE_SOURCE"
#define CURR_ACTIVE_LEN    "IMP3_ACTIVE_LEN"
#define CURR_ACTIVE_INDEX  "IMP3_ACTIVE_INDEX"
#define CURR_ACTIVE_MODE   "IMP3_ACTIVE_MODE"
#define CURR_ACTIVE_VIEW   "IMP3_ACTIVE_VIEW"

#define CURR_EDIT_SOURCE   "IMP3_EDIT_SOURCE"
#define CURR_EDIT_LEN      "IMP3_EDIT_LEN"
#define CURR_EDIT_MODE     "IMP3_EDIT_MODE"
#define CURR_EDIT_VIEW     "IMP3_EDIT_VIEW"

#define NUM_COMM           86	/* user command count         */

/* user commands */
#define PRINT_INFO          0
#define PRINT_GPL           1
#define PRINT_HELP          2
#define EXIT_DECODER        3

#define PLAY_FILE           4
#define STOP_FILE           5
#define PAUSE_FILE          6
#define RESUME_FILE         7
#define NEXT_FILE           8
#define PREVIOUS_FILE       9
#define SEEK_FILE           10
#define SET_MIXER           11
#define MUTE_OUTPUT         12
#define UNMUTE_OUTPUT       13
#define REPORT_STATE        14

#define ADD_LIST            15
#define REMOVE_LIST         16
#define RESET_LIST          17
#define RENAME_LIST         18
#define USE_LIST            19
#define USE_NEXT_LIST       20
#define EDIT_LIST           21

#define PRINT_LIST          22
#define PRINT_LIST_STATUS   23

#define ADD_TO_LIST         24
#define ADD_FILE_TO_LIST    25
#define ADD_DIR_NORM        26
#define ADD_DIR_RECURSE     27
#define TOGGLE_READ_TAGS    28

#define PLAY_LIST_INDEX     29
#define MOVE_LIST_INDEX     30
#define DELETE_LIST_INDEX   31
#define SORT_LIST           32
#define SAVE_LIST           33
#define LOAD_LIST           34

#define SAVE_ALL_LISTS      35
#define LOAD_ALL_LISTS      36

#define PRINT_QUEUE         37
#define QUEUE_INDEX         38
#define QUEUE_FILE          39
#define CLEAR_QUEUE         40
#define RESIZE_QUEUE        41

#define SET_MODE_ONCE       42
#define SET_MODE_REPEAT     43
#define SET_MODE_TRANDOM    44
#define SET_MODE_SRANDOM    45

#define SET_MODE_LEARN      46
#define SET_LEARN_WEIGHTS   47

#define SET_PREF_TF         48
#define SET_PREF_TPF        49
#define SET_PREF_PF         50
#define SET_PREF_F          51

#define AUTO_REPORT         52
#define DJ_MODE             53

#define SET_STAMP_OFF       54
#define SET_STAMP_TIMP      55
#define SET_STAMP_TIML      56

#define SHOW_TAG            57
#define ADD_TAG             58
#define PRINT_STYLES        59
#define PRINT_PLAYERS       60
#define ADD_PLAYER          61

#define SHOW_EQ_BANDS       62
#define SET_EQ_BAND         63
#define ENABLE_EQ           64
#define DISABLE_EQ          65

#define PRINT_EVENTS        66
#define ADD_EVENT           67
#define REMOVE_EVENT        68

#define SOURCE_FILE         69
#define SHOW_CHIST          70
#define ADD_ALIAS           71
#define REMOVE_ALIAS        72
#define PRINT_JOBS          73
#define FLUSH_JOB_BUFF      74
#define SEND_JOB_2FG        75
#define SEND_JOB_2BG        76
#define SHOW_ENVIRON        77
#define SET_ENVIRON         78
#define CHANGE_DIR          79

#define MULTIPLE_AUDIO      80
#define AUTO_RECOVER        81
#define START_DECODER       82
#define SET_XAUDIO_OUTPUT   83
#define PRINT_DLOG          84
#define CLEAR_DLOG          85

/* this must not be included in user
   command count                       */
#define NO_BUILTIN_COMM     86

/* message headers     */
#define STATUS_MSG      ":->"
#define ERROR_MSG       ":-<"
#define DEBUG_MSG       ":-|"
#define LIST_MSG        "|||"
#define PNTR_MSG        ">>>"
#define DEL_ENTRY_MSG   "<--"
#define MISC_MSG        "-->"
#define REPORT_MSG      "__>"

/* char location defs  */
#define AMP_NONE          0
#define AMP_END           1
#define AMP_ALL           2
#define AMP_FRONT         3
#define AMP_MID           4

/* timestamp defs */
#define TIME_OFF          0
#define TIME_NORM         1
#define TIME_LEFT         2

/* job states */
#define J_FGRUN           0
#define J_BGRUN           1
#define J_STOPPED         2
#define J_DECINT          3
#define J_DECEXT          4

/* explosion search defs */
#define ANY_FILE          0
#define EXEC_FILE_ONLY    1
#define EXEC_AND_DIRS     2

/* playmode defs */
#define ONCE_MODE         0
#define REPEAT_MODE       1
#define TRANDOM_MODE      2
#define SRANDOM_MODE      3
#define LEARN_MODE        4
#define QUEUE_MODE        5

/* search preference defs */
#define TAG_FILE_PREF     0
#define TAG_PATH_PREF     1
#define PATH_FILE_PREF    2
#define FILE_ONLY_PREF    3

/* id3/file stuff      */
#define ID3_SEPERATOR     '-'
#define TAG_HEADER        "#EXT_INFO"
#define TAG_HEADER_LEN    8
#define TAG_CODE          "#$%^&"
#define TAG_CODE_LEN      5
#define STR_FILE          0
#define STR_TAG           1
#define LIST_INFO_TAG     "#LIST_INFO"

/* process defs        */
#define CHILD_EXEC_FAILED   211
#define DECODER_EXEC_FAILED 212

/* misc defs           */
#define TRUE              1
#define FALSE             0

/* signal handler type */
typedef void ((*sighandler_t) (int));

/* var types */
#define flag_t unsigned char

/* state data type     */
typedef enum {
    INIT,
    IDLE,
    PLAY,
    PAUSED,
    EXTERNAL
} ProcessState;

/* event stuff */

#define TIME_EVENT     1
#define LIST_EVENT     2
#define QUEUE_EVENT    4
#define ESTREAM_EVENT  8
#define SSTREAM_EVENT  16
#define EXIT_EVENT     32

typedef struct EventData_s {
    flag_t persist;
    flag_t quiet;
    int id;
    unsigned int type;
    time_t start;
    time_t period;
    char *info;
    char *command;
    struct EventData_s *next;
} EventData;

/* external player list node */
#define OUTP_NORM     0
#define OUTP_QUIET    1
#define OUTP_BUFFERED 2
#define OUTP_NONE     3

#define SIGNAL_TERM   0
#define SIGNAL_KILL   1
#define SIGNAL_NONE   2

typedef struct PlayerDef_s {
    char *name;
    char *command;
    char *sup_types;
    int output;
    int signal;
    struct PlayerDef_s *next;
} PlayerDef;

/* ID location node */
typedef struct FileInfoDef_s {
    char *type;
    int offset;
    int len;
} FileInfoDef;

/* buffer data */
#define DCHAR_NORM        0
#define DCHAR_SHIFT       1
#define DCHAR_GROW        2

typedef struct DCBNode_s {
    char *str;
    char info;
    short len;
} DCBNode;

typedef struct DCharBuf_s {
    char *name;
    unsigned int bytec;
    int var1;
    int size;
    int len;
    int pos;
    int mode;
    DCBNode *buf;
} DCharBuf;

/* List definition */
typedef struct ListDef_s {
    int playmode;
    int listview;
    int global_weight;
    int play_weight;
    int skip_weight;
    DCharBuf *dcb;
    struct ListDef_s *next;
} ListDef;

/* command node */
typedef struct CommandDef_s {
    void (*func) ();
    char *name;
    char *help;
} CommandDef;

/* process list node  */
typedef struct ProcessEntry_s {
    pid_t pid;
    int redir;
    int mode;
    int pipestdout[2];
    int pipestderr[2];
    char name[32];
    struct termios tty;
    struct DCharBuf_s *buff;
    struct ProcessEntry_s *next;
} ProcessEntry;

/* id3 tag definition */
typedef struct id3tag_s {
    char magic[3];
    char songname[30];
    char artist[30];
    char album[30];
    char year[4];
    char note[30];
    unsigned char style;
} id3tag_t;

/* id3 style definition */
struct style_s {
    unsigned char styleid;
    char *name;
};

/* equalizer stuff */
#define MAX_EQ_BANDS      10
#define EQ_BAND_VAL_LOW  -128
#define EQ_BAND_VAL_HIGH  127

typedef struct EQBandDef_s {
    int low;
    int high;
} EQBandDef;

/* dj mode stuff */
#define MAX_DJ_KEYS         6
#define DEFAULT_GRANULARITY 100
#define DJ_GRANULARITY      5

typedef struct DJKeyDef_s {
    flag_t set;
    unsigned long offset;
    unsigned long range;
    void (*override) ();
} DJKeyDef;

/* terminal control strings */
#define NUM_TERM_CTRL     32
#define NUM_TERM_USER     4

#define TC_CLR            0
#define TC_CLR_TOBOT      1
#define TC_CLR_TOEOL      2
#define TC_ND             3
#define TC_UP             4
#define TC_CR             5

#define UP_ARROW          6
#define DOWN_ARROW        7
#define RIGHT_ARROW       8
#define LEFT_ARROW        9
#define HOME_KEY          10
#define END_KEY           11
#define INSERT_KEY        12
#define DELETE_KEY        13
#define PAGEUP_KEY        14
#define PAGEDOWN_KEY      15
#define F1_KEY            16
#define F2_KEY            17
#define F3_KEY            18
#define F4_KEY            19
#define F5_KEY            20
#define F6_KEY            21
#define F7_KEY            22
#define F8_KEY            23
#define F9_KEY            24
#define F10_KEY           25
#define F11_KEY           26
#define F12_KEY           27

#define UP_ARROW_2        28
#define DOWN_ARROW_2      29
#define RIGHT_ARROW_2     30
#define LEFT_ARROW_2      31

typedef struct TermCtrl_s {
    char *name;
    char *string;
} TermCtrl;

/************************************
 *        Forward References        *
 ************************************/

/* module globals.c */
void deallocate_vars();
void allocate_vars();
void resize_queue();		/* user */
void report_memuse();
void clear_time();
void report_name(char *);
void clear_duration();
void clear_info();
void set_state(ProcessState);
void print_status();		/* user */
void toggle_multiple_audio_procs();	/* user */
void toggle_auto_recover();	/* user */
void toggle_dj_mode();		/* user */
void toggle_auto_rprt();	/* user */
void toggle_read_tags();	/* user */
void set_stamp_mode();		/* user */
void set_play_mode();		/* user */
void set_search_mode();		/* user */
void set_learn_weights();	/* user */

/* module buff.c */
unsigned g_dbuf_bytec(DCharBuf *);
void sp_dbuf(DCharBuf *, int, int);
void verify_dbuf(DCharBuf *);
int resize_dbuf(DCharBuf *, int);
void f_dbuf(DCharBuf *);
DCharBuf *i_dbuf(char *, int, int);
void c_dbuf(DCharBuf *);
int s_dbuf(DCharBuf *, int, int);
int r_dbuf(DCharBuf *, int);
char g_dbuf_info(DCharBuf *, int);
char *g_dbuf(DCharBuf *, int);
int a_dbuf(DCharBuf *, char *);
void sort_dbuf(DCharBuf *);
int outb_empty();
void clear_outbuffer();
void sort_outbuffer();
void add_outbuffer(const char *, ...);
void flush_outbuffer();
int check_outbuffer(char);
void flush_console_buf();
void add_console(const char *, ...);
void show_user(const char *, ...);
void show_user_n(char *);
void add_dlog(char *);
void show_dlog();		/* user */
void clear_dlog();		/* user */

/* module command.c */
void mybeep();
int find_comm_match(char *);
int test_background_mode(int *);
void setup_child_process(int);
void try_to_exec();		/* user (indirect) */
int check_for_homedir(char *);
int check_for_envvars(char *);
int add_arg(char *);
void make_arg_list(char *);
void insert_chistory(int, char *, char *);
int check_for_bang(char *);
void handle_user_message(char *);
void clear_comm();
void print_ctrl_str(int, int);
void backup_cursor(int);
void restore_edit_cursor(int, int);
void prompt(int);
void update_prompt(int);
void backspace_char();
void delete_char();
void insert_char(char);
void append_char(char);
void clear_scr();
int monitor_char_input();

/* module decoder.c */
void play_internal(char *);
void stop_internal();
void pause_internal();
void resume_internal();
void seek_internal(int, int);
void mixer_internal(int, int, int);
void close_internal_input();
int close_internal_output();
void set_internal_output();	/* user */
void close_decoder();
void open_decoder();		/* user */
void mute_output();		/* user */
void unmute_output();		/* user */
void show_eq_bands();		/* user */
void set_eq_band_comm();	/* user */
void disable_equalizer();	/* user */
void set_equalizer();		/* user */
void set_mixer();		/* user */
void handle_decoder_state_change(unsigned int);
void handle_decoder_message();
void monitor_decoder();

/* module info.c */
void print_gpl();		/* user */
void print_info();		/* user */
void print_key_help();
void print_help();		/* user */
void print_cmnd_help(int);

/* module keys.c */
void do_up_arrow();
void do_down_arrow();
void do_right_arrow();
void do_left_arrow();
void fastf_key();
void rewind_key();
void inc_masvol_key();
void dec_masvol_key();
void inc_pcmvol_key();
void dec_pcmvol_key();
void bal_right_key();
void bal_left_key();
void handle_special_char();
int check_tilde(char);
int check_special_chars(char *);

/* module main.c */
void outstr(char *);
void outstrnl(char *);
void outflush();
int piped_io();
int have_tty();
void int_sig_handler();
void alarm_sig_handler();
void winch_sig_handler();
void clear_child_sigs();
void count_child_sigs();
void handle_child_sigs();
void source_file(char *);
void source_comm();		/* user */
void shut_down();
void exit_imp3sh();		/* user */

/* module listlogic.c */
PlayerDef *check_format(char *);
int play_file(char *);
void play_lindex(ListDef *, int);
void play_comm();		/* user */
void resume_file();		/* user */
void stop_file();		/* user */
void pause_file();		/* user */
void seek_file();		/* user */
float calc_random_index();
int get_smart_random();
void determine_next_stream();
void next_file();		/* user */
void previous_file();		/* user */
int get_list_weight(ListDef *);

/* module player.c */
unsigned int g_player_bytec();
void pause_external();
void resume_external();
void stop_external();
void handle_external_death(pid_t);
void play_external(PlayerDef *, char *);
void print_players();		/* user */
void add_player();		/* user */
void clear_players();

/* module playlist.c */
unsigned int g_playlist_bytec();
void update_list_env();
void update_active_env(ListDef *);
ListDef *g_list_base();
ListDef *g_list(char *);
int a_list(char *);
int r_list(char *);
void clear_all_lists();
void verify_lists();
void rename_list();		/* user */
void reset_list();		/* user */
void use_list();		/* user */
void use_next_list();		/* user */
void edit_list_comm();		/* user */
void add_list();		/* user */
void remove_list();		/* user */

/* module stream.c */
void clear_played(ListDef *);
void clear_all_played();
void clear_good_played(ListDef *, int);
void add_stream_weight(ListDef *);
void remove_stream_weight(ListDef *);
int d_chck(mode_t);
void add_dir(int, DCharBuf *, DCharBuf *);
void add_dir_comm();		/* user */
char *get_stream(DCharBuf *, int, int);
int add_stream(char *, DCharBuf *, int, int);
void get_sort_id(char *, char *);
void get_stream_id(ListDef *, int, char *);

/* module queue.c */
int in_queue();
void clear_queue();		/* user */
void add_queue();
void print_queue();		/* user */
void queue_directory(char *);
void queue_files_comm();	/* user */
void queue_list_index();	/* user */

/* module listfile.c */
void save_all_lists();		/* user */
void load_all_lists();		/* user */
void save_list_comm();		/* user */
void save_list(char *, DCharBuf *);
void load_list_comm();		/* user */
void load_list(char *, DCharBuf *);

/* module listmanip.c */
int compare_list(const void *, const void *);
void sort_list();		/* user */
void print_list_comm();		/* user */
void add_file_to_list();	/* user */
void play_list_index();		/* user */
void print_list_status();	/* user */
void move_list_index();		/* user */
void delete_list_index_comm();	/* user */
void delete_list_index(ListDef *, char *);
void add_to_list();		/* user */

/* module shell.c */
void show_chist();		/* user */
void read_chist();
void write_chist();
void add_chist();
int check_alias(char *);
void get_aliasname(char *);
char *get_alias(int);
void remove_alias();		/* user */
void add_alias();		/* user */
void set_environ();		/* user */
void show_environ();		/* user */
void list_dir();		/* user */
void print_dir();		/* user */
void change_dir();		/* user */
DIR *my_open_dir(char *);
void beep_expl(char *);
void spack_expl(char *, char *);
int find_good_length(char *, char *);
int check_file_type(int, mode_t);
void find_file_match(int, char *, char *, int, int *, mode_t *, char *);
void explode_file(char *, int);
void explode_comm(char *);
void explode_fileORcomm();

/* module util.c */
void make_printable(char *);
int is_all_space(char *);
int is_any_space(char *);
int is_upper_c(char);
int is_all_digits(char *);
int is_digit_range(char *);
void get_digit_range(char *, int *, int *, int, int);
void remove_end_space(char *);
int get_strlen(char *);
void remove_newline(char *);
char *skip_space(char *);
char *grep_str(char *, char *);
int grep_against_args(int, char *);
char *tokenize(char *, char **, char);
char *tokenize_kparen(char *, char **, char);
int get_cpos(char, char *);
int get_cloc(char, char *);
char *safe_strcpy(char *, char *, int);
char *file_from_path(char *);
void get_fline(FILE *, char *, int);
void build_string(va_list, const char *, char *);
void build_time_string(time_t, char *);
FILE *myfopen(char *, const char *);
void mysetenv(char *, char *);
int is_url(char *);

/* module tags.c */
int id3_readtag(FILE *, id3tag_t *);
int id3_appendtag(FILE *, id3tag_t *);
int id3_replacetag(FILE *, id3tag_t *);
void id3_cleartag(id3tag_t *);
char *id3_findstyle(int);
void make_tag_line(char *, id3tag_t *);
int read_id3tag(char *, char *);
char *determine_fname(char *);
void print_id3tag(id3tag_t *);
void print_id3_styles();	/* user */
unsigned char find_style_match(char *);
void print_addtag_help();
void add_tag();			/* user */
void show_id3tag();		/* user */
int get_stream_info(char *, char *);

/* module event.c */
unsigned int g_event_bytec();
void clear_events();		/* user */
void print_events();		/* user */
void add_event_comm();		/* user */
void remove_event_comm();	/* user */
void check_events();
void post_event(unsigned int);

/* module jobs.c */
unsigned int g_jobs_bytec();
void clear_proclist();
void protect_procs();
void unprotect_procs();
ProcessEntry *get_process(pid_t, ProcessEntry **);
int stop_fg_process(ProcessEntry *);
void set_proc_term(ProcessEntry *);
int clean_process(ProcessEntry *, ProcessEntry *);
void add_proclist(pid_t, int, int, int[2], int[2], char *);
void set_proc_xg(ProcessEntry *, int);
void send_job_2xg(int mode);
void send_job_2fg();		/* user */
void send_job_2bg();		/* user */
void print_jobs();		/* user */
void check_procpipes(fd_set *);
void clean_procpipes(ProcessEntry *);
void set_procpipes(fd_set *, int *);
void add_procpipes(ProcessEntry *, int[2], int[2]);
void flush_job_buff();		/* user */

#endif
