1 /*
2  * Copyright (c) 2010, 2011 Ryan Flannery <ryan.flannery@gmail.com>
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #ifndef META_INFO_H
18 #define META_INFO_H
19 
20 #include <ctype.h>
21 #include <limits.h>
22 #include <err.h>
23 #include <errno.h>
24 #include <stdbool.h>
25 #include <stdint.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <strings.h>
30 #include <time.h>
31 
32 /* non-baes includes (just TagLib) */
33 #include <tag_c.h>
34 
35 #include "debug.h"
36 #include "enums.h"
37 
38 #include "compat.h"
39 
40 /* the character-info fields.  used for all meta-info that's shown */
41 #define MI_NUM_CINFO     8
42 #define MI_CINFO_ARTIST  0
43 #define MI_CINFO_ALBUM   1
44 #define MI_CINFO_TITLE   2
45 #define MI_CINFO_TRACK   3
46 #define MI_CINFO_YEAR    4
47 #define MI_CINFO_GENRE   5
48 #define MI_CINFO_LENGTH  6
49 #define MI_CINFO_COMMENT 7
50 
51 /* struct used to represent all meta information from a given file */
52 typedef struct {
53    char       *filename;               /* filename of file itself */
54    char       *cinfo[MI_NUM_CINFO];    /* character meta info array */
55    int         length;                 /* play length in seconds */
56    time_t      last_updated;           /* last time info was extracted */
57    bool        is_url;                 /* if this is a url */
58 } meta_info;
59 
60 /*
61  * XXX Note in the above that the playlength is stored both numerically
62  * in the member 'length' and as a character string in the cinfo array
63  * in the form "hh:mm:ss"
64  */
65 
66 /* array of human-readable names of each CINFO member */
67 extern const char *MI_CINFO_NAMES[MI_NUM_CINFO];
68 
69 /* create/destroy meta_info structs */
70 meta_info *mi_new(void);
71 void mi_free(meta_info *info);
72 
73 /* read/write meta_info structs to a file */
74 void mi_fwrite(meta_info *mi, FILE *fout);
75 void mi_fread(meta_info *mi,  FILE *fin);
76 
77 /* used to extract meta info from a media file */
78 meta_info* mi_extract(const char *filename);
79 
80 
81 /*****************************************************************************
82  * XXX Important Note XXX These functions are used to replace any
83  * non-printable characters in a string -or- any of the cinfo fields of a
84  * meta-info struct.  This must be done as some files (sadly, some Aphex Twin)
85  * contain such characters in their meta info, and these characters correspond
86  * to ncurses control sequences, thus mucking-up the display when painted to
87  * the screen.  See "vitunes -e help check" for details.
88  * This is NOT called explicitly during mi_extract, and MUST be done
89  * eleswhere (medialib_db_update, medialib_db_scan_dirs, ecmd_addurl, etc.)
90  * This is so that one may use the "check" e-command to see which files have
91  * such characters, and then tag them correctly.
92  ****************************************************************************/
93 
94 void str_sanitize(char *s);
95 void mi_sanitize(meta_info *mi);
96 
97 
98 /*****************************************************************************
99  * Functions used to query meta_info's (i.e. to match them against a given
100  * search/filter).  It works by setting-up a global query description which
101  * contains a list of tokens in the search and whether or not each token
102  * should be matched positively/negatively.
103  *
104  * After the global query has been set, mi_match() can be used to compare a
105  * given meta_info against this global query description.
106  ****************************************************************************/
107 
108 /* structure used to describe what to match meta_info's against */
109 #define MI_MAX_QUERY_TOKENS   255
110 typedef struct {
111    char *tokens[MI_MAX_QUERY_TOKENS];
112    char  match[MI_MAX_QUERY_TOKENS];
113    int   ntokens;
114    char *raw;  /* a copy of the original, un-tokenized query */
115 } mi_query_description;
116 
117 /* flag to indicate if we should include filename when matching */
118 extern bool mi_query_match_filename;
119 
120 /* initialize, set, and clear global query description */
121 void mi_query_init();
122 bool mi_query_isset();
123 void mi_query_clear();
124 void mi_query_add_token(const char *token);
125 
126 void mi_query_setraw(const char *query);
127 const char *mi_query_getraw();
128 
129 /* match a given meta_info/string against the global query description */
130 bool mi_match(const meta_info *mi);
131 bool str_match_query(const char *s);
132 
133 
134 /*****************************************************************************
135  * Functions used to sort meta_info's.  These work by setting-up a global
136  * sort description that includes the ordering of the CINFO items to sort and
137  * which, if any, to sort descending.
138  *
139  * Once the global sort description has been setup, mi_compare() can be used
140  * to compare two meta_info's in a way that works with qsort(3), heapsort(3),
141  * or mergesort(3).
142  ****************************************************************************/
143 
144 /* structure used to describe how to sort meta_info structs */
145 typedef struct {
146    int   order[MI_NUM_CINFO];
147    bool  descending[MI_NUM_CINFO];
148    int   nfields;
149 } mi_sort_description;
150 
151 /* initialize, set, and clear global sort description */
152 void mi_sort_init();
153 void mi_sort_clear();
154 int  mi_sort_set(const char *str, const char **errmsg);
155 
156 /* compare two meta_info's using the global sort description */
157 int  mi_compare(const void *a, const void *b);
158 
159 
160 /*****************************************************************************
161  * Functions to control how to display meta_info's to the screen.  These
162  * setup a global description of the display format, which includes an ordered
163  * list of the fields and the width of each field.
164  ****************************************************************************/
165 
166 /* structure used to describe how to display meta_info structs */
167 typedef struct {
168    int       nfields;
169    int       order[MI_NUM_CINFO];
170    int       widths[MI_NUM_CINFO];
171    Direction align[MI_NUM_CINFO];
172 } mi_display_description;
173 extern mi_display_description mi_display;
174 
175 /* initialize and set the global display description */
176 void  mi_display_init();
177 int   mi_display_set(const char *str, const char **errmsg);
178 void  mi_display_reset();
179 
180 /* convert current display to a string */
181 char *mi_display_tostr();
182 
183 /* get total width of display */
184 int   mi_display_getwidth();
185 
186 #endif
187