Top | ![]() |
![]() |
![]() |
![]() |
void
glyr_init (void
);
Init the library, this has to be called before any other calls from this library are made.
You should call glyr_cleanup()
once for every call of glyr_init()
This function is not threadsafe.
void
glyr_cleanup (void
);
Cleanup all parts of the library, you can use
:atexit()
1 2 |
glyr_init(); atexit(glyr_destroy); |
This function is not threadsafe.
GlyrMemCache * glyr_get (GlyrQuery *settings
,GLYR_ERROR *error
,int *length
);
settings
is pointer to a GlyrQuery struct filled to your needs via the glyr_opt_* methods,
Once an item is found the callback (set via glyr_opt_dlcallback()
) is called anytime a item is ready
settings |
The setting struct controlling glyr. (See the glyr_opt_* methods) |
|
error |
An optional pointer to an int, which gets filled with an error message, or GLYRE_OK on success, or |
|
length |
length An optional pointer storing the length of the returned list, or |
: a doubly linked list of GlyrMemCache, which should be freed by passing any element of the to glyr_free_list()
void
glyr_query_init (GlyrQuery *query
);
This functions may allocate dynamic memory. It should be freed with glyr_query_init()
after use.
void
glyr_query_destroy (GlyrQuery *query
);
Deletes all modifications and frees dynamic memory. It can be reused, as fresh from glyr_query_init()
void
glyr_signal_exit (GlyrQuery *query
);
Try to stop libglyr as soon as possible. This is supposed to be called on another thread. Calling this function twice on the same query will do nothing.
This function is threadsafe - but use with care anyway, since it causes libglyr to do really a hard stop. The returned data is NOT guaranteed to yield best results.
void
glyr_free_list (GlyrMemCache *head
);
Deletes all dynamic memory by calling glyr_cache_free()
on each cache.
GlyrMemCache *
glyr_cache_new (void
);
Initializes a new memcache.
Normally you never need to do this.
Don't forget to free the cache with glyr_cache_free()
GlyrMemCache *
glyr_cache_copy (GlyrMemCache *cache
);
Allocate a new cache and
copy all contents (= deep copy) from the original cache
,
The pointers next and prev are set to NULL.
void glyr_cache_set_dsrc (GlyrMemCache *cache
,const char *download_source
);
Copies download_source to the dsrc field, clearing all previously allocated content safely.
void glyr_cache_set_prov (GlyrMemCache *cache
,const char *provider
);
Copies provider to the prov field, clearing all previously allocated content safely.
void glyr_cache_set_img_format (GlyrMemCache *cache
,const char *img_format
);
Copies img_format to the img_format field, clearing all previously allocated content safely.
void glyr_cache_set_data (GlyrMemCache *cache
,const char *data
,int len
);
Safely sets the data of the cache. It frees the old data first, updates
the checksum and adjusts the size fields accordingly to len.
If len is a negative number strlen()
is used to determine the size.
Attention: data
is set directly! It get's freed once you free the cache. Be sure it's safe to be free'd.
int glyr_cache_write (GlyrMemCache *cache
,const char *path
);
Write cache
to the path specified by path
.
There are three special files:
"stdout" -> Outputs file to stdout
"stderr" -> Outputs file to stderr
"null" -> Outputs item nowhere
void
glyr_cache_update_md5sum (GlyrMemCache *cache
);
Updates the md5sum field of cache
.
void
glyr_cache_print (GlyrMemCache *cache
);
A debug method to print all fields of cache
.
GLYR_ERROR glyr_opt_dlcallback (GlyrQuery *settings
,DL_callback dl_cb
,void *userp
);
The callback should have the following form:
1 |
GLYR_ERROR my_callback(GlyrMemCache * dl, struct GlyrQuery * s); |
Note that you can return certaing members of GLYR_ERROR
in the callback:
GLYRE_SKIP
: To not add this item to the results.
GLYRE_OK
: To add this item to the results and continue happily.
GLYRE_STOP_POST
: To stop right now and return the results. The current element will be added.
GLYRE_STOP_PRE
: To stop right now and return the results. The current element will NOT be added.
GLYR_ERROR glyr_opt_type (GlyrQuery *s
,GLYR_GET_TYPE type
);
Example: GLYR_GET_COVERART
GLYR_ERROR glyr_opt_artist (GlyrQuery *s
,const char *artist
);
This is needed for all types of metadata. Libglyr keeps a copy of this string internally.
libglyr applies some basic normalization, like " artistX feat. artistY" -> "artistX"
GLYR_ERROR glyr_opt_album (GlyrQuery *s
,const char *album
);
This field is required for the following types:
Optional for the following types:
Libglyr keeps a copy of this string internally.
libglyr applies some basic normalization, like " CoOl_album CD01 (20.7)" -> "cool_album"
GLYR_ERROR glyr_opt_title (GlyrQuery *s
,const char *title
);
This field is required for the following types:
Optional for the following types:
Libglyr keeps a copy of this string internally.
libglyr applies some basic normalization, like "Songtitle (blahblah remix)" -> "Songtitle"
GLYR_ERROR glyr_opt_img_minsize (GlyrQuery *s
,int size
);
This is only taken as a hint, returned images are not necessarily higher than this size, but should be around it.
GLYR_ERROR glyr_opt_img_maxsize (GlyrQuery *s
,int size
);
This is only taken as a hint, returned images are not necessarily below this size, but should be around it.
GLYR_ERROR glyr_opt_parallel (GlyrQuery *s
,unsigned long parallel_jobs
);
A value of 0 lets libglyr chooses this value itself. This is the default.
GLYR_ERROR glyr_opt_timeout (GlyrQuery *s
,unsigned long timeout
);
Default is 20 seconds
GLYR_ERROR glyr_opt_redirects (GlyrQuery *s
,unsigned long redirects
);
A value of 0 is allowed but may break some plugins.
GLYR_ERROR glyr_opt_useragent (GlyrQuery *s
,const char *useragent
);
Some providers require an valid useragent, an empty string might break these therefore.
GLYR_ERROR glyr_opt_lang (GlyrQuery *s
,const char *langcode
);
Some providers offer localized content, or content only being available in certain countries. Examples are: last.fm, amazon and google. The language is given in ISO 639-1 codes like 'de' or 'en'. Alternatively you can set it to 'auto', which will cause libglyr to guess your language by your locale. "auto" is the default behavior.
GLYR_ERROR glyr_opt_lang_aware_only (GlyrQuery *s
,bool lang_aware_only
);
Note: Not for all types of metadata there may be localized content, and only fetchers, that provide text items are affected by this setting. The special provider 'local' is an exception here, it is queried, but delievers only language specific content too.
GLYR_ERROR glyr_opt_number (GlyrQuery *s
,unsigned int num
);
The maximum number of items to get in a glyr_get()
, resulting number of items may be below num
but not higher.
A value of 0 causes libglyr to search till infinity.
Default is 1.
GLYR_ERROR glyr_opt_verbosity (GlyrQuery *s
,unsigned int level
);
The verbosity level that is used by libglyr:
0: No output, but fatal errors.
1: Basic warnings.
2: Normal informal output
3: Basic debug output
4: Full debug output
GLYR_ERROR glyr_opt_from (GlyrQuery *s
,const char *from
);
Tell libglyr where you want your metadata want from.
You can get a full list of providers for each getter by running glyrc
@-L
The string you can pass here looks like this example for _cover_:
1 |
"lastfm;google" |
This would query to everybody's surprise"lastfm" and "google" Alternatively you may use the string "all" in it:
1 |
"all;-lastfm;" |
All providers except "lastfm" (therefore the '-') are used, a '+' is also allowed, which does plain nothing.
By default all built-in providers are used.
You can access the providernames by calling glyr_info_get()
GLYR_ERROR glyr_opt_plugmax (GlyrQuery *s
,int plugmax
);
Restricts providers to retrieve at max. plugmax
items, you might use this to get results
over several providers when glyr_opt_number()
is set to something higher than 1.
May be removed in future releases.
GLYR_ERROR glyr_opt_allowed_formats (GlyrQuery *s
,const char *formats
);
Restricts providers to retrieve at max. plugmax
items, you might use this to get results
over several providers when glyr_opt_number()
is set to something higher than 1.
For the getters GLYR_GET_COVERART
and GLYR_GET_ARTIST_PHOTOS
only.
The allowed formats for images, in a comma separated list.
Examples:
"png;jpeg"
"png;jpeg;tiff;jpg;" (default)
'jpeg' *and* 'jpg' because some websites return strange mimetypes (should be 'jpeg' only)
GLYR_ERROR glyr_opt_download (GlyrQuery *s
,bool download
);
Imageproviders only return URLs, by default libglyr downloads these and
gives you the cache. By settings glyr_opt_download()
to FALSE you tell
libglyr that you want only the URLs (in a searchengine like fashion)
An check for valid images is done however.
GLYR_ERROR glyr_opt_fuzzyness (GlyrQuery *s
,int fuzz
);
libglyr features fuzzy matching to enhance search results. Look at the string "Equilibrium" and the accidentally mistyped version "Aquillibriu": Those strings will be compares using the "Levenshtein distance" (http://en.wikipedia.org/wiki/Levenshtein_distance) which basically counts the number of insert, substitute and delete operations to transform Equilibrium"" into "Aquillibriu". The distance in this case is 3 since three edit-operations are needed (one insert, substitute and deletion)
The fuzziness parameter is the maximum distance two strings may have to match. A high distance (like about 10) matches even badly mistyped strings, but also introduces bad results. Low settings however will omit some good results.
The default values is currently 4. To be more secure some correction is applied:
Examples:
artist:Adele - album:19
artist:Adele - album:21
lv-distance = 2 which is <= 4
But since the lv-distance is the same as the length "21" it won't match.
The easiest way to prevent this though, is to properly tag your music. (http://musicbrainz.org/doc/MusicBrainz_Picard).
GLYR_ERROR glyr_opt_qsratio (GlyrQuery *s
,float ratio
);
0.00 means highest speed, querying fast providers first. 1.00 Takes possibly longer, but should deliver best results. 0.85 is the current default value.
All other values, smaller 0.0, greater 1.0 are clamped to [0.0..1.0]
GLYR_ERROR glyr_opt_proxy (GlyrQuery *s
,const char *proxystring
);
The proxy to use, if any. It is passed in the form: protocol://yourproxy.domain[:port] Example:
Proxy.fh-hof.de:3128
http://hman:rootroot @ godserve.com:666
The environment variables http_proxy, ftp_proxy, all_proxy are respected, but are overwritten by this.
GLYR_ERROR glyr_opt_force_utf8 (GlyrQuery *s
,bool force_utf8
);
For textitems only. Some providers (like metrolyrics) might return text with strange encodings, that can not be converted to regular UTF8, but might return a subset of UTF8. This options forces libglyr to prohibit those.
GLYR_ERROR glyr_opt_lookup_db (GlyrQuery *s
,GlyrDatabase *db
);
Bind the previosly created db
to the query s
.
By doing this you add a new 'local' provider,
that is queried before everything else and may speed up
things heavily.
You can either query it exclusively or disable it completely:
Enable exclusiv:
glyr_opt_from(s,"local");Disable:
1 |
glyr_opt_from(s,"all;-local"); |
GLYR_ERROR glyr_opt_db_autowrite (GlyrQuery *s
,bool write_to_db
);
If a database is specified via glyr_opt_lookup_db you can choose to automatically save newly found items to the database. They will be looked up from there if you search for it again.
GLYR_ERROR glyr_opt_db_autoread (GlyrQuery *s
,bool read_from_db
);
If set to true libglyr will lookup the database previously given by glyr_opt_lookup_db()
during searching in the web. If there's item that already seems to be in the DB it gets not
mixed into the results.
This does not influence the usage of the DB as local provider!
Use glyr_opt_from()
with "all;-local" to disable it.
GLYR_ERROR glyr_opt_musictree_path (GlyrQuery *s
,const char *musictree_path
);
Set the path to a specific mediafile and glyr will try to fetch covers from directories around this, since many people place things like 'folder.jpg' there. Instead of the actual file you can also pass the containing directory (see the 'dirname' utility) - the path can be either absolute or relative.
From there on it works by cascading upwards - i.e. checking all files in the dir (not recursing), go up, repeat. This will be repeated $(recurse_depth) times or till it cannot go upwards. How the file is checked depends on the metadata type to search, see below.
For reference the actual C code is given (${artist} gets expanded):
Example 1. Used regexes and recurse_depth
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
case GLYR_GET_COVERART: search_regex = "^(folder|front|cover|.*${album}.*)\\.(jpg|png|jpeg|gif)"; recurse_depth = 2; break; case GLYR_GET_ARTIST_PHOTOS: search_regex = "^(${artist}|artist)\\.(jpg|png|jpeg|gif)$"; recurse_depth = 3; break; case GLYR_GET_ALBUM_REVIEW: search_regex = "^(${album})\\.(info|txt)$"; recurse_depth = 2; break; case GLYR_GET_ARTIST_BIO: search_regex = "^BIOGRAPHY(\\.txt)?$"; recurse_depth = 2; break; default: search_regex = NULL; recurse_depth = 0; break; |
GLYR_ERROR glyr_opt_normalize (GlyrQuery *s
,GLYR_NORMALIZATION norm
);
Defines how much artist/album/title is normalized.
GLYR_NORMALIZE_NONE: Do no normalization, except strdown and utf-8-normalization.
GLYR_NORMALIZE_MODERATE: Remove stuff like feat., featuring. Track 01 etc.
GLYR_NORMALIZE_AGGRESSIVE: Also remove everything between()
, [] and <>. Slightly destructive!
Even for None, utf-8 normalization and strdown()
is done.
The default is GLYR_NORMALIZE_AGGRESSIVE | GLYR_NORMALIZE_ALL
GlyrMemCache * glyr_download (const char *url
,GlyrQuery *s
);
Downloads the data pointed to by url
and caches in it a GlyrMemCache, which is returned to you.
Use glyr_cache_free()
to free it after use.
const char *
glyr_strerror (GLYR_ERROR ID
);
Gets a descriptive message from an error ID.
GlyrFetcherInfo *
glyr_info_get (void
);
get information about existing Fetcher and Source A Doubly linked list of Fetcher is returned, each having a field 'head', being a pointer to a doubly linked list of GlyrSourceInfos
It is best understood by an example:
Example 2. Using GlyrFetcherInfo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
static void visualize_from_options(void) { GlyrFetcherInfo * info = glyr_info_get(); if(info != NULL) { for(GlyrFetcherInfo * elem0 = info; elem0; elem0 = elem0->next) { printf("%s\n",elem0->name); for(GlyrSourceInfo * elem1 = elem0->head; elem1; elem1 = elem1->next) { printf(" [%c] %s\n",elem1->key,elem1->name); } printf("\n"); } } glyr_info_free(info); } |
void
glyr_info_free (GlyrFetcherInfo *info
);
Free the return value of glyr_info_get()
pointed to by info
const char *
glyr_data_type_to_string (GLYR_DATA_TYPE type
);
Converts a type to a string.
const char *
glyr_get_type_to_string (GLYR_GET_TYPE type
);
Converts a get type to a string (GLYR_GET_COVERART => "cover") You must not modify the string or daemons will come to you at night!
char *
glyr_md5sum_to_string (unsigned char *md5sum
);
Convert a md5sum (raw data) to a human readable representation. String consists only of [0-9] and [a-f].
void glyr_string_to_md5sum (const char *string
,unsigned char *md5sum
);
Convert a string to a raw-data md5sum. Must be a 32 char long string only containing [0-9] and [a-f] The new checksum is written to m5sum, which must be a buffer with a size >= 16 bytes.
GLYR_FIELD_REQUIREMENT
glyr_get_requirements (GLYR_GET_TYPE type
);
Different getters need different fields set. You can use this to check if the artist, album and title field of a specific getter is required or optional.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
GLYR_FIELD_REQUIREMENT reqs = glyr_get_requirements(GLYR_GET_COVERART); if(reqs & GLYR_REQUIRES_ALBUM) { // do something when artist is required } else if(reqs & GLYR_OPTIONAL_TITLE) { // Title is optional } else { // None of both } |