mod_musicindex  1.4.1
playlist-vorbis.c
Go to the documentation of this file.
1 /*
2  * playlist-ogg.c
3  * mod_musicindex
4  *
5  * $Id: playlist-vorbis.c 1010 2012-08-07 13:38:34Z varenet $
6  *
7  * Created by Regis BOUDIN on Thu Jan 22 2004.
8  * Copyright (c) 2003-2004 Regis BOUDIN
9  * Copyright (c) 2003-2005,2007 Thibaut VARENE
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 2.1,
13  * as published by the Free Software Foundation.
14  *
15  */
16 
31 #include "playlist.h"
32 #include "playlist-vorbis.h"
33 
34 #include <vorbis/codec.h>
35 #include <vorbis/vorbisfile.h>
36 
37 #ifdef HAVE_SYS_STAT_H
38 #include <sys/stat.h>
39 #endif
40 
48 static inline short ogg_ext_check(const char *const filename)
49 {
50  const char *const ext = strrchr(filename, '.');
51  if (ext && (!strncasecmp(ext, ".ogg", 4) || /* official extention */
52  !strncasecmp(ext, ".oga", 4)) ) /* audio in ogg */
53  return TRUE;
54  return FALSE;
55 }
56 
70 mu_ent *make_ogg_entry(request_rec *r, apr_pool_t *pool, FILE *const in,
71  const char *const filename)
72 {
73  const mu_config *const conf = (mu_config *)ap_get_module_config(r->per_dir_config, &musicindex_module);
74  mu_ent *p = NULL;
75  OggVorbis_File vf;
76  const char *t;
77  struct stat filestat;
78 
79  if (!ogg_ext_check(filename) || (ov_test(in, &vf, NULL, 0) != 0))
80  return NULL;
81 
82  p = NEW_ENT(pool);
83  if (p == NULL) {
84  ov_clear(&vf);
85  return NULL;
86  }
87 
88  p->filetype = FT_OGG;
89  p->flags &= ~EF_VBR;
90 
91  fstat(fileno(in), &filestat);
92  p->size = filestat.st_size;
93  p->mtime = filestat.st_mtime;
94 
95  if (ov_test_open(&vf) == 0) {
96 
97  vorbis_comment *comment = ov_comment(&vf, -1);
98  if (comment != NULL) {
99  if ((t = vorbis_comment_query(comment, "ALBUM", 0)))
100  p->album = apr_pstrdup(pool, t);
101  if ((t = vorbis_comment_query(comment, "ARTIST", 0)))
102  p->artist = apr_pstrdup(pool, t);
103  if ((t = vorbis_comment_query(comment, "TITLE", 0)))
104  p->title = apr_pstrdup(pool, t);
105  if ((t = vorbis_comment_query(comment, "TRACKNUMBER", 0)))
106  p->track = atoi(t);
107  if ((t = vorbis_comment_query(comment, "DATE", 0)))
108  p->date = atoi(t);
109  if ((t = vorbis_comment_query(comment, "DISCNUMBER", 0))) /* http://reactor-core.org/ogg-tagging.html */
110  p->posn = atoi(t);
111  if ((t = vorbis_comment_query(comment, "GENRE", 0)))
112  p->genre = apr_pstrdup(pool, t);
113  }
114 
115  if (conf->options & MI_QUICKPL) {
116  p->bitrate = p->length = p->freq = 0;
117  }
118  else {
119  vorbis_info *info = ov_info(&vf, -1);
120  p->freq = info->rate;
121 
122 #ifndef NO_BR_NOMINAL
123  if (info->bitrate_nominal)
124  p->bitrate = info->bitrate_nominal; /* when available this is what players show */
125  else
126 #endif
127  p->bitrate = (long)ov_bitrate(&vf, -1);
128  if ((info->bitrate_upper > 0) && (info->bitrate_upper == info->bitrate_lower));
129  else /* we have a VBR file */
130  p->flags |= EF_VBR;
131  p->length = (long)ov_time_total(&vf, -1);
132  }
133 
134  }
135  ov_clear(&vf);
136  return p;
137 }