* Add image rotation support during resize. (mostly useful for TiVo)
This commit is contained in:
parent
6820d05143
commit
c5bb5c84b3
1
NEWS
1
NEWS
@ -17,6 +17,7 @@
|
|||||||
- Add support for the av:mediaClass tag, so some Sony devices can filter items by media type.
|
- Add support for the av:mediaClass tag, so some Sony devices can filter items by media type.
|
||||||
- Fix inotify detection issues on first-level folders.
|
- Fix inotify detection issues on first-level folders.
|
||||||
- Work around LifeTab's broken DLNA support.
|
- Work around LifeTab's broken DLNA support.
|
||||||
|
- Add image rotation support during resize. (mostly useful for TiVo)
|
||||||
|
|
||||||
1.0.22 - Released 24-Aug-2011
|
1.0.22 - Released 24-Aug-2011
|
||||||
--------------------------------
|
--------------------------------
|
||||||
|
@ -218,7 +218,7 @@ check_embedded_art(const char *path, const char *image_data, int image_size)
|
|||||||
}
|
}
|
||||||
last_hash = hash;
|
last_hash = hash;
|
||||||
|
|
||||||
imsrc = image_new_from_jpeg(NULL, 0, image_data, image_size, 1);
|
imsrc = image_new_from_jpeg(NULL, 0, image_data, image_size, 1, ROTATE_NONE);
|
||||||
if( !imsrc )
|
if( !imsrc )
|
||||||
{
|
{
|
||||||
last_success = 0;
|
last_success = 0;
|
||||||
@ -302,7 +302,7 @@ check_for_album_file(const char *path)
|
|||||||
if( art_cache_exists(file, &art_file) )
|
if( art_cache_exists(file, &art_file) )
|
||||||
goto existing_file;
|
goto existing_file;
|
||||||
free(art_file);
|
free(art_file);
|
||||||
imsrc = image_new_from_jpeg(file, 1, NULL, 0, 1);
|
imsrc = image_new_from_jpeg(file, 1, NULL, 0, 1, ROTATE_NONE);
|
||||||
if( imsrc )
|
if( imsrc )
|
||||||
goto found_file;
|
goto found_file;
|
||||||
}
|
}
|
||||||
@ -315,7 +315,7 @@ check_for_album_file(const char *path)
|
|||||||
if( art_cache_exists(file, &art_file) )
|
if( art_cache_exists(file, &art_file) )
|
||||||
goto existing_file;
|
goto existing_file;
|
||||||
free(art_file);
|
free(art_file);
|
||||||
imsrc = image_new_from_jpeg(file, 1, NULL, 0, 1);
|
imsrc = image_new_from_jpeg(file, 1, NULL, 0, 1, ROTATE_NONE);
|
||||||
if( imsrc )
|
if( imsrc )
|
||||||
goto found_file;
|
goto found_file;
|
||||||
}
|
}
|
||||||
@ -332,7 +332,7 @@ existing_file:
|
|||||||
return art_file;
|
return art_file;
|
||||||
}
|
}
|
||||||
free(art_file);
|
free(art_file);
|
||||||
imsrc = image_new_from_jpeg(file, 1, NULL, 0, 1);
|
imsrc = image_new_from_jpeg(file, 1, NULL, 0, 1, ROTATE_NONE);
|
||||||
if( !imsrc )
|
if( !imsrc )
|
||||||
continue;
|
continue;
|
||||||
found_file:
|
found_file:
|
||||||
|
@ -31,7 +31,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/types.h>
|
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
#include <jpeglib.h>
|
#include <jpeglib.h>
|
||||||
#ifdef HAVE_MACHINE_ENDIAN_H
|
#ifdef HAVE_MACHINE_ENDIAN_H
|
||||||
@ -240,7 +239,7 @@ image_get_jpeg_resolution(const char * path, int * width, int * height)
|
|||||||
{
|
{
|
||||||
FILE *img;
|
FILE *img;
|
||||||
unsigned char buf[8];
|
unsigned char buf[8];
|
||||||
u_int16_t offset, h, w;
|
uint16_t offset, h, w;
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
size_t nread;
|
size_t nread;
|
||||||
long size;
|
long size;
|
||||||
@ -306,7 +305,7 @@ image_get_jpeg_date_xmp(const char * path, char ** date)
|
|||||||
FILE *img;
|
FILE *img;
|
||||||
unsigned char buf[8];
|
unsigned char buf[8];
|
||||||
char *data = NULL, *newdata;
|
char *data = NULL, *newdata;
|
||||||
u_int16_t offset;
|
uint16_t offset;
|
||||||
struct NameValueParserData xml;
|
struct NameValueParserData xml;
|
||||||
char * exif;
|
char * exif;
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
@ -425,7 +424,7 @@ image_new(int32_t width, int32_t height)
|
|||||||
}
|
}
|
||||||
|
|
||||||
image_s *
|
image_s *
|
||||||
image_new_from_jpeg(const char * path, int is_file, const char * buf, int size, int scale)
|
image_new_from_jpeg(const char * path, int is_file, const char * buf, int size, int scale, int rotate)
|
||||||
{
|
{
|
||||||
image_s *vimage;
|
image_s *vimage;
|
||||||
FILE *file = NULL;
|
FILE *file = NULL;
|
||||||
@ -435,7 +434,6 @@ image_new_from_jpeg(const char * path, int is_file, const char * buf, int size,
|
|||||||
int maxbuf;
|
int maxbuf;
|
||||||
struct jpeg_error_mgr pub;
|
struct jpeg_error_mgr pub;
|
||||||
|
|
||||||
|
|
||||||
cinfo.err = jpeg_std_error(&pub);
|
cinfo.err = jpeg_std_error(&pub);
|
||||||
pub.error_exit = libjpeg_error_handler;
|
pub.error_exit = libjpeg_error_handler;
|
||||||
jpeg_create_decompress(&cinfo);
|
jpeg_create_decompress(&cinfo);
|
||||||
@ -465,7 +463,7 @@ image_new_from_jpeg(const char * path, int is_file, const char * buf, int size,
|
|||||||
jpeg_start_decompress(&cinfo);
|
jpeg_start_decompress(&cinfo);
|
||||||
w = cinfo.output_width;
|
w = cinfo.output_width;
|
||||||
h = cinfo.output_height;
|
h = cinfo.output_height;
|
||||||
vimage = image_new(w, h);
|
vimage = (rotate & (ROTATE_90|ROTATE_270)) ? image_new(h, w) : image_new(w, h);
|
||||||
if(!vimage)
|
if(!vimage)
|
||||||
{
|
{
|
||||||
jpeg_destroy_decompress(&cinfo);
|
jpeg_destroy_decompress(&cinfo);
|
||||||
@ -498,8 +496,9 @@ image_new_from_jpeg(const char * path, int is_file, const char * buf, int size,
|
|||||||
maxbuf = vimage->width * vimage->height;
|
maxbuf = vimage->width * vimage->height;
|
||||||
if(cinfo.output_components == 3)
|
if(cinfo.output_components == 3)
|
||||||
{
|
{
|
||||||
|
int rx, ry;
|
||||||
ofs = 0;
|
ofs = 0;
|
||||||
if((ptr = (unsigned char *)malloc(w * 3 * cinfo.rec_outbuf_height + 16)) == NULL)
|
if((ptr = malloc(w * 3 * cinfo.rec_outbuf_height + 16)) == NULL)
|
||||||
{
|
{
|
||||||
DPRINTF(E_WARN, L_METADATA, "malloc failed\n");
|
DPRINTF(E_WARN, L_METADATA, "malloc failed\n");
|
||||||
image_free(vimage);
|
image_free(vimage);
|
||||||
@ -510,6 +509,7 @@ image_new_from_jpeg(const char * path, int is_file, const char * buf, int size,
|
|||||||
|
|
||||||
for(y = 0; y < h; y += cinfo.rec_outbuf_height)
|
for(y = 0; y < h; y += cinfo.rec_outbuf_height)
|
||||||
{
|
{
|
||||||
|
ry = (rotate & (ROTATE_90|ROTATE_180)) ? (y - h + 1) * -1 : y;
|
||||||
for(i = 0; i < cinfo.rec_outbuf_height; i++)
|
for(i = 0; i < cinfo.rec_outbuf_height; i++)
|
||||||
{
|
{
|
||||||
line[i] = ptr + (w * 3 * i);
|
line[i] = ptr + (w * 3 * i);
|
||||||
@ -517,11 +517,10 @@ image_new_from_jpeg(const char * path, int is_file, const char * buf, int size,
|
|||||||
jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height);
|
jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height);
|
||||||
for(x = 0; x < w * cinfo.rec_outbuf_height; x++)
|
for(x = 0; x < w * cinfo.rec_outbuf_height; x++)
|
||||||
{
|
{
|
||||||
|
rx = (rotate & (ROTATE_180|ROTATE_270)) ? (x - w + 1) * -1 : x;
|
||||||
|
ofs = (rotate & (ROTATE_90|ROTATE_270)) ? ry + (rx * h) : rx + (ry * w);
|
||||||
if( ofs < maxbuf )
|
if( ofs < maxbuf )
|
||||||
{
|
|
||||||
vimage->buf[ofs] = COL(ptr[x + x + x], ptr[x + x + x + 1], ptr[x + x + x + 2]);
|
vimage->buf[ofs] = COL(ptr[x + x + x], ptr[x + x + x + 1], ptr[x + x + x + 2]);
|
||||||
ofs++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(ptr);
|
free(ptr);
|
||||||
@ -531,7 +530,7 @@ image_new_from_jpeg(const char * path, int is_file, const char * buf, int size,
|
|||||||
ofs = 0;
|
ofs = 0;
|
||||||
for(i = 0; i < cinfo.rec_outbuf_height; i++)
|
for(i = 0; i < cinfo.rec_outbuf_height; i++)
|
||||||
{
|
{
|
||||||
if((line[i] = (unsigned char *)malloc(w)) == NULL)
|
if((line[i] = malloc(w)) == NULL)
|
||||||
{
|
{
|
||||||
int t = 0;
|
int t = 0;
|
||||||
|
|
||||||
@ -607,19 +606,19 @@ image_upsize(image_s * pdest, image_s * psrc, int32_t width, int32_t height)
|
|||||||
|
|
||||||
x_dist = rx - ((float)((int32_t)rx));
|
x_dist = rx - ((float)((int32_t)rx));
|
||||||
y_dist = ry - ((float)((int32_t)ry));
|
y_dist = ry - ((float)((int32_t)ry));
|
||||||
vcol = COL_FULL( (u_int8_t)((COL_RED(vcol1)*(1.0-x_dist)
|
vcol = COL_FULL( (uint8_t)((COL_RED(vcol1)*(1.0-x_dist)
|
||||||
+ COL_RED(vcol2)*(x_dist))*(1.0-y_dist)
|
+ COL_RED(vcol2)*(x_dist))*(1.0-y_dist)
|
||||||
+ (COL_RED(vcol3)*(1.0-x_dist)
|
+ (COL_RED(vcol3)*(1.0-x_dist)
|
||||||
+ COL_RED(vcol4)*(x_dist))*(y_dist)),
|
+ COL_RED(vcol4)*(x_dist))*(y_dist)),
|
||||||
(u_int8_t)((COL_GREEN(vcol1)*(1.0-x_dist)
|
(uint8_t)((COL_GREEN(vcol1)*(1.0-x_dist)
|
||||||
+ COL_GREEN(vcol2)*(x_dist))*(1.0-y_dist)
|
+ COL_GREEN(vcol2)*(x_dist))*(1.0-y_dist)
|
||||||
+ (COL_GREEN(vcol3)*(1.0-x_dist)
|
+ (COL_GREEN(vcol3)*(1.0-x_dist)
|
||||||
+ COL_GREEN(vcol4)*(x_dist))*(y_dist)),
|
+ COL_GREEN(vcol4)*(x_dist))*(y_dist)),
|
||||||
(u_int8_t)((COL_BLUE(vcol1)*(1.0-x_dist)
|
(uint8_t)((COL_BLUE(vcol1)*(1.0-x_dist)
|
||||||
+ COL_BLUE(vcol2)*(x_dist))*(1.0-y_dist)
|
+ COL_BLUE(vcol2)*(x_dist))*(1.0-y_dist)
|
||||||
+ (COL_BLUE(vcol3)*(1.0-x_dist)
|
+ (COL_BLUE(vcol3)*(1.0-x_dist)
|
||||||
+ COL_BLUE(vcol4)*(x_dist))*(y_dist)),
|
+ COL_BLUE(vcol4)*(x_dist))*(y_dist)),
|
||||||
(u_int8_t)((COL_ALPHA(vcol1)*(1.0-x_dist)
|
(uint8_t)((COL_ALPHA(vcol1)*(1.0-x_dist)
|
||||||
+ COL_ALPHA(vcol2)*(x_dist))*(1.0-y_dist)
|
+ COL_ALPHA(vcol2)*(x_dist))*(1.0-y_dist)
|
||||||
+ (COL_ALPHA(vcol3)*(1.0-x_dist)
|
+ (COL_ALPHA(vcol3)*(1.0-x_dist)
|
||||||
+ COL_ALPHA(vcol4)*(x_dist))*(y_dist))
|
+ COL_ALPHA(vcol4)*(x_dist))*(y_dist))
|
||||||
@ -769,7 +768,7 @@ image_downsize(image_s * pdest, image_s * psrc, int32_t width, int32_t height)
|
|||||||
alpha = (alpha > 255.0)? 255.0 : ((alpha < 0.0)? 0.0:alpha);
|
alpha = (alpha > 255.0)? 255.0 : ((alpha < 0.0)? 0.0:alpha);
|
||||||
#endif
|
#endif
|
||||||
put_pix_alpha_replace(pdest, vx, vy,
|
put_pix_alpha_replace(pdest, vx, vy,
|
||||||
COL_FULL((u_int8_t)red, (u_int8_t)green, (u_int8_t)blue, (u_int8_t)alpha));
|
COL_FULL((uint8_t)red, (uint8_t)green, (uint8_t)blue, (uint8_t)alpha));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -823,9 +822,9 @@ image_save_to_jpeg_buf(image_s * pimage, int * size)
|
|||||||
{
|
{
|
||||||
for(x = 0; x < pimage->width; x++)
|
for(x = 0; x < pimage->width; x++)
|
||||||
{
|
{
|
||||||
data[x + x + x] = COL_RED(pimage->buf[i]);
|
data[x * 3] = COL_RED(pimage->buf[i]);
|
||||||
data[x + x + x + 1] = COL_GREEN(pimage->buf[i]);
|
data[x * 3 + 1] = COL_GREEN(pimage->buf[i]);
|
||||||
data[x + x + x + 2] = COL_BLUE(pimage->buf[i]);
|
data[x * 3 + 2] = COL_BLUE(pimage->buf[i]);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
row_pointer[0] = (unsigned char *)data;
|
row_pointer[0] = (unsigned char *)data;
|
||||||
|
@ -21,9 +21,14 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with MiniDLNA. If not, see <http://www.gnu.org/licenses/>.
|
* along with MiniDLNA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
#include <sys/types.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
typedef u_int32_t pix;
|
#define ROTATE_NONE 0x0
|
||||||
|
#define ROTATE_90 0x1
|
||||||
|
#define ROTATE_180 0x2
|
||||||
|
#define ROTATE_270 0x4
|
||||||
|
|
||||||
|
typedef uint32_t pix;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int32_t width;
|
int32_t width;
|
||||||
@ -41,7 +46,7 @@ int
|
|||||||
image_get_jpeg_resolution(const char * path, int * width, int * height);
|
image_get_jpeg_resolution(const char * path, int * width, int * height);
|
||||||
|
|
||||||
image_s *
|
image_s *
|
||||||
image_new_from_jpeg(const char * path, int is_file, const char * ptr, int size, int scale);
|
image_new_from_jpeg(const char * path, int is_file, const char * ptr, int size, int scale, int resize);
|
||||||
|
|
||||||
image_s *
|
image_s *
|
||||||
image_resize(image_s * src_image, int32_t width, int32_t height);
|
image_resize(image_s * src_image, int32_t width, int32_t height);
|
||||||
|
78
metadata.c
78
metadata.c
@ -114,6 +114,7 @@
|
|||||||
#define FLAG_FREQUENCY 0x00001000
|
#define FLAG_FREQUENCY 0x00001000
|
||||||
#define FLAG_BPS 0x00002000
|
#define FLAG_BPS 0x00002000
|
||||||
#define FLAG_CHANNELS 0x00004000
|
#define FLAG_CHANNELS 0x00004000
|
||||||
|
#define FLAG_ROTATION 0x00008000
|
||||||
|
|
||||||
/* Audio profile flags */
|
/* Audio profile flags */
|
||||||
enum audio_profiles {
|
enum audio_profiles {
|
||||||
@ -281,36 +282,38 @@ parse_nfo(const char * path, metadata_t * m)
|
|||||||
void
|
void
|
||||||
free_metadata(metadata_t * m, uint32_t flags)
|
free_metadata(metadata_t * m, uint32_t flags)
|
||||||
{
|
{
|
||||||
if( m->title && (flags & FLAG_TITLE) )
|
if( flags & FLAG_TITLE )
|
||||||
free(m->title);
|
free(m->title);
|
||||||
if( m->artist && (flags & FLAG_ARTIST) )
|
if( flags & FLAG_ARTIST )
|
||||||
free(m->artist);
|
free(m->artist);
|
||||||
if( m->album && (flags & FLAG_ALBUM) )
|
if( flags & FLAG_ALBUM )
|
||||||
free(m->album);
|
free(m->album);
|
||||||
if( m->genre && (flags & FLAG_GENRE) )
|
if( flags & FLAG_GENRE )
|
||||||
free(m->genre);
|
free(m->genre);
|
||||||
if( m->creator && (flags & FLAG_CREATOR) )
|
if( flags & FLAG_CREATOR )
|
||||||
free(m->creator);
|
free(m->creator);
|
||||||
if( m->date && (flags & FLAG_DATE) )
|
if( flags & FLAG_DATE )
|
||||||
free(m->date);
|
free(m->date);
|
||||||
if( m->comment && (flags & FLAG_COMMENT) )
|
if( flags & FLAG_COMMENT )
|
||||||
free(m->comment);
|
free(m->comment);
|
||||||
if( m->dlna_pn && (flags & FLAG_DLNA_PN) )
|
if( flags & FLAG_DLNA_PN )
|
||||||
free(m->dlna_pn);
|
free(m->dlna_pn);
|
||||||
if( m->mime && (flags & FLAG_MIME) )
|
if( flags & FLAG_MIME )
|
||||||
free(m->mime);
|
free(m->mime);
|
||||||
if( m->duration && (flags & FLAG_DURATION) )
|
if( flags & FLAG_DURATION )
|
||||||
free(m->duration);
|
free(m->duration);
|
||||||
if( m->resolution && (flags & FLAG_RESOLUTION) )
|
if( flags & FLAG_RESOLUTION )
|
||||||
free(m->resolution);
|
free(m->resolution);
|
||||||
if( m->bitrate && (flags & FLAG_BITRATE) )
|
if( flags & FLAG_BITRATE )
|
||||||
free(m->bitrate);
|
free(m->bitrate);
|
||||||
if( m->frequency && (flags & FLAG_FREQUENCY) )
|
if( flags & FLAG_FREQUENCY )
|
||||||
free(m->frequency);
|
free(m->frequency);
|
||||||
if( m->bps && (flags & FLAG_BPS) )
|
if( flags & FLAG_BPS )
|
||||||
free(m->bps);
|
free(m->bps);
|
||||||
if( m->channels && (flags & FLAG_CHANNELS) )
|
if( flags & FLAG_CHANNELS )
|
||||||
free(m->channels);
|
free(m->channels);
|
||||||
|
if( flags & FLAG_ROTATION )
|
||||||
|
free(m->rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlite_int64
|
sqlite_int64
|
||||||
@ -562,7 +565,7 @@ GetImageMetadata(const char * path, char * name)
|
|||||||
//DEBUG DPRINTF(E_DEBUG, L_METADATA, " * size: %jd\n", file.st_size);
|
//DEBUG DPRINTF(E_DEBUG, L_METADATA, " * size: %jd\n", file.st_size);
|
||||||
|
|
||||||
/* MIME hard-coded to JPEG for now, until we add PNG support */
|
/* MIME hard-coded to JPEG for now, until we add PNG support */
|
||||||
asprintf(&m.mime, "image/jpeg");
|
m.mime = strdup("image/jpeg");
|
||||||
|
|
||||||
l = exif_loader_new();
|
l = exif_loader_new();
|
||||||
exif_loader_write_file(l, path);
|
exif_loader_write_file(l, path);
|
||||||
@ -572,7 +575,8 @@ GetImageMetadata(const char * path, char * name)
|
|||||||
goto no_exifdata;
|
goto no_exifdata;
|
||||||
|
|
||||||
e = exif_content_get_entry (ed->ifd[EXIF_IFD_EXIF], EXIF_TAG_DATE_TIME_ORIGINAL);
|
e = exif_content_get_entry (ed->ifd[EXIF_IFD_EXIF], EXIF_TAG_DATE_TIME_ORIGINAL);
|
||||||
if( e || (e = exif_content_get_entry(ed->ifd[EXIF_IFD_EXIF], EXIF_TAG_DATE_TIME_DIGITIZED)) ) {
|
if( e || (e = exif_content_get_entry(ed->ifd[EXIF_IFD_EXIF], EXIF_TAG_DATE_TIME_DIGITIZED)) )
|
||||||
|
{
|
||||||
m.date = strdup(exif_entry_get_value(e, b, sizeof(b)));
|
m.date = strdup(exif_entry_get_value(e, b, sizeof(b)));
|
||||||
if( strlen(m.date) > 10 )
|
if( strlen(m.date) > 10 )
|
||||||
{
|
{
|
||||||
@ -591,11 +595,11 @@ GetImageMetadata(const char * path, char * name)
|
|||||||
}
|
}
|
||||||
//DEBUG DPRINTF(E_DEBUG, L_METADATA, " * date: %s\n", m.date);
|
//DEBUG DPRINTF(E_DEBUG, L_METADATA, " * date: %s\n", m.date);
|
||||||
|
|
||||||
e = exif_content_get_entry (ed->ifd[EXIF_IFD_0], EXIF_TAG_MAKE);
|
e = exif_content_get_entry(ed->ifd[EXIF_IFD_0], EXIF_TAG_MAKE);
|
||||||
if( e )
|
if( e )
|
||||||
{
|
{
|
||||||
strncpyt(make, exif_entry_get_value(e, b, sizeof(b)), sizeof(make));
|
strncpyt(make, exif_entry_get_value(e, b, sizeof(b)), sizeof(make));
|
||||||
e = exif_content_get_entry (ed->ifd[EXIF_IFD_0], EXIF_TAG_MODEL);
|
e = exif_content_get_entry(ed->ifd[EXIF_IFD_0], EXIF_TAG_MODEL);
|
||||||
if( e )
|
if( e )
|
||||||
{
|
{
|
||||||
strncpyt(model, exif_entry_get_value(e, b, sizeof(b)), sizeof(model));
|
strncpyt(model, exif_entry_get_value(e, b, sizeof(b)), sizeof(model));
|
||||||
@ -606,12 +610,38 @@ GetImageMetadata(const char * path, char * name)
|
|||||||
}
|
}
|
||||||
//DEBUG DPRINTF(E_DEBUG, L_METADATA, " * model: %s\n", model);
|
//DEBUG DPRINTF(E_DEBUG, L_METADATA, " * model: %s\n", model);
|
||||||
|
|
||||||
|
e = exif_content_get_entry(ed->ifd[EXIF_IFD_0], EXIF_TAG_ORIENTATION);
|
||||||
|
if( e )
|
||||||
|
{
|
||||||
|
int rotate;
|
||||||
|
switch( exif_get_short(e->data, exif_data_get_byte_order(ed)) )
|
||||||
|
{
|
||||||
|
case 3:
|
||||||
|
rotate = 180;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
rotate = 270;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
rotate = 90;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rotate = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if( rotate )
|
||||||
|
{
|
||||||
|
if( asprintf(&m.rotation, "%d", rotate) < 0 )
|
||||||
|
m.rotation = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if( ed->size )
|
if( ed->size )
|
||||||
{
|
{
|
||||||
/* We might need to verify that the thumbnail is 160x160 or smaller */
|
/* We might need to verify that the thumbnail is 160x160 or smaller */
|
||||||
if( ed->size > 12000 )
|
if( ed->size > 12000 )
|
||||||
{
|
{
|
||||||
imsrc = image_new_from_jpeg(NULL, 0, (char *)ed->data, ed->size, 1);
|
imsrc = image_new_from_jpeg(NULL, 0, (char *)ed->data, ed->size, 1, ROTATE_NONE);
|
||||||
if( imsrc )
|
if( imsrc )
|
||||||
{
|
{
|
||||||
if( (imsrc->width <= 160) && (imsrc->height <= 160) )
|
if( (imsrc->width <= 160) && (imsrc->height <= 160) )
|
||||||
@ -664,10 +694,12 @@ no_exifdata:
|
|||||||
asprintf(&m.resolution, "%dx%d", width, height);
|
asprintf(&m.resolution, "%dx%d", width, height);
|
||||||
|
|
||||||
ret = sql_exec(db, "INSERT into DETAILS"
|
ret = sql_exec(db, "INSERT into DETAILS"
|
||||||
" (PATH, TITLE, SIZE, TIMESTAMP, DATE, RESOLUTION, THUMBNAIL, CREATOR, DLNA_PN, MIME) "
|
" (PATH, TITLE, SIZE, TIMESTAMP, DATE, RESOLUTION,"
|
||||||
|
" ROTATION, THUMBNAIL, CREATOR, DLNA_PN, MIME) "
|
||||||
"VALUES"
|
"VALUES"
|
||||||
" (%Q, '%q', %lld, %ld, %Q, %Q, %d, %Q, %Q, %Q);",
|
" (%Q, '%q', %lld, %ld, %Q, %Q, %Q, %d, %Q, %Q, %Q);",
|
||||||
path, name, file.st_size, file.st_mtime, m.date, m.resolution, thumb, m.creator, m.dlna_pn, m.mime);
|
path, name, file.st_size, file.st_mtime, m.date, m.resolution,
|
||||||
|
m.rotation, thumb, m.creator, m.dlna_pn, m.mime);
|
||||||
if( ret != SQLITE_OK )
|
if( ret != SQLITE_OK )
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error inserting details for '%s'!\n", path);
|
fprintf(stderr, "Error inserting details for '%s'!\n", path);
|
||||||
|
@ -36,6 +36,7 @@ typedef struct metadata_s {
|
|||||||
char *frequency;
|
char *frequency;
|
||||||
char *bps;
|
char *bps;
|
||||||
char *resolution;
|
char *resolution;
|
||||||
|
char *rotation;
|
||||||
char *duration;
|
char *duration;
|
||||||
char *date;
|
char *date;
|
||||||
char *mime;
|
char *mime;
|
||||||
|
11
scanner.c
11
scanner.c
@ -577,25 +577,26 @@ CreateDatabase(void)
|
|||||||
"ID INTEGER PRIMARY KEY AUTOINCREMENT, "
|
"ID INTEGER PRIMARY KEY AUTOINCREMENT, "
|
||||||
"PATH TEXT DEFAULT NULL, "
|
"PATH TEXT DEFAULT NULL, "
|
||||||
"SIZE INTEGER, "
|
"SIZE INTEGER, "
|
||||||
|
"TIMESTAMP INTEGER, "
|
||||||
"TITLE TEXT COLLATE NOCASE, "
|
"TITLE TEXT COLLATE NOCASE, "
|
||||||
"DURATION TEXT, "
|
"DURATION TEXT, "
|
||||||
"BITRATE INTEGER, "
|
"BITRATE INTEGER, "
|
||||||
"SAMPLERATE INTEGER, "
|
"SAMPLERATE INTEGER, "
|
||||||
|
"CREATOR TEXT COLLATE NOCASE, "
|
||||||
"ARTIST TEXT COLLATE NOCASE, "
|
"ARTIST TEXT COLLATE NOCASE, "
|
||||||
"ALBUM TEXT COLLATE NOCASE, "
|
"ALBUM TEXT COLLATE NOCASE, "
|
||||||
"GENRE TEXT COLLATE NOCASE, "
|
"GENRE TEXT COLLATE NOCASE, "
|
||||||
"COMMENT TEXT, "
|
"COMMENT TEXT, "
|
||||||
"CHANNELS INTEGER, "
|
"CHANNELS INTEGER, "
|
||||||
|
"DISC INTEGER, "
|
||||||
"TRACK INTEGER, "
|
"TRACK INTEGER, "
|
||||||
"DATE DATE, "
|
"DATE DATE, "
|
||||||
"RESOLUTION TEXT, "
|
"RESOLUTION TEXT, "
|
||||||
"THUMBNAIL BOOL DEFAULT 0, "
|
"THUMBNAIL BOOL DEFAULT 0, "
|
||||||
"CREATOR TEXT COLLATE NOCASE, "
|
|
||||||
"DLNA_PN TEXT, "
|
|
||||||
"MIME TEXT, "
|
|
||||||
"ALBUM_ART INTEGER DEFAULT 0, "
|
"ALBUM_ART INTEGER DEFAULT 0, "
|
||||||
"DISC INTEGER, "
|
"ROTATION INTEGER, "
|
||||||
"TIMESTAMP INTEGER"
|
"DLNA_PN TEXT, "
|
||||||
|
"MIME TEXT"
|
||||||
")");
|
")");
|
||||||
if( ret != SQLITE_OK )
|
if( ret != SQLITE_OK )
|
||||||
goto sql_failed;
|
goto sql_failed;
|
||||||
|
8
sql.c
8
sql.c
@ -216,13 +216,19 @@ db_upgrade(sqlite3 *db)
|
|||||||
return 5;
|
return 5;
|
||||||
if (db_vers < 6)
|
if (db_vers < 6)
|
||||||
{
|
{
|
||||||
DPRINTF(E_WARN, L_DB_SQL, "Updating DB version to v%d.\n", DB_VERSION);
|
|
||||||
ret = sql_exec(db, "CREATE TABLE BOOKMARKS ("
|
ret = sql_exec(db, "CREATE TABLE BOOKMARKS ("
|
||||||
"ID INTEGER PRIMARY KEY, "
|
"ID INTEGER PRIMARY KEY, "
|
||||||
"SEC INTEGER)");
|
"SEC INTEGER)");
|
||||||
if( ret != SQLITE_OK )
|
if( ret != SQLITE_OK )
|
||||||
return 6;
|
return 6;
|
||||||
}
|
}
|
||||||
|
if (db_vers < 7)
|
||||||
|
{
|
||||||
|
DPRINTF(E_WARN, L_DB_SQL, "Updating DB version to v%d.\n", DB_VERSION);
|
||||||
|
ret = sql_exec(db, "ALTER TABLE DETAILS ADD rotation INTEGER");
|
||||||
|
if( ret != SQLITE_OK )
|
||||||
|
return 7;
|
||||||
|
}
|
||||||
sql_exec(db, "PRAGMA user_version = %d", DB_VERSION);
|
sql_exec(db, "PRAGMA user_version = %d", DB_VERSION);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -56,7 +56,7 @@
|
|||||||
|
|
||||||
#include <sqlite3.h>
|
#include <sqlite3.h>
|
||||||
|
|
||||||
#define MINIDLNA_VERSION "1.0.22"
|
#define MINIDLNA_VERSION "1.1.0-cvs"
|
||||||
|
|
||||||
#ifdef NETGEAR
|
#ifdef NETGEAR
|
||||||
# define SERVER_NAME "ReadyDLNA"
|
# define SERVER_NAME "ReadyDLNA"
|
||||||
@ -66,7 +66,7 @@
|
|||||||
|
|
||||||
#define CLIENT_CACHE_SLOTS 20
|
#define CLIENT_CACHE_SLOTS 20
|
||||||
#define USE_FORK 1
|
#define USE_FORK 1
|
||||||
#define DB_VERSION 6
|
#define DB_VERSION 7
|
||||||
|
|
||||||
#ifdef ENABLE_NLS
|
#ifdef ENABLE_NLS
|
||||||
#define _(string) gettext(string)
|
#define _(string) gettext(string)
|
||||||
|
122
upnphttp.c
122
upnphttp.c
@ -900,7 +900,7 @@ ProcessHttpQuery_upnphttp(struct upnphttp * h)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* 7.3.33.4 */
|
/* 7.3.33.4 */
|
||||||
else if( ((h->reqflags & FLAG_TIMESEEK) || (h->reqflags & FLAG_PLAYSPEED)) &&
|
else if( (h->reqflags & (FLAG_TIMESEEK|FLAG_PLAYSPEED)) &&
|
||||||
!(h->reqflags & FLAG_RANGE) )
|
!(h->reqflags & FLAG_RANGE) )
|
||||||
{
|
{
|
||||||
DPRINTF(E_WARN, L_HTTP, "DLNA %s requested, responding ERROR 406\n",
|
DPRINTF(E_WARN, L_HTTP, "DLNA %s requested, responding ERROR 406\n",
|
||||||
@ -1366,7 +1366,7 @@ SendResp_albumArt(struct upnphttp * h, char * object)
|
|||||||
int fd;
|
int fd;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if( h->reqflags & FLAG_XFERSTREAMING || h->reqflags & FLAG_RANGE )
|
if( h->reqflags & (FLAG_XFERSTREAMING|FLAG_RANGE) )
|
||||||
{
|
{
|
||||||
DPRINTF(E_WARN, L_HTTP, "Client tried to specify transferMode as Streaming with an image!\n");
|
DPRINTF(E_WARN, L_HTTP, "Client tried to specify transferMode as Streaming with an image!\n");
|
||||||
Send406(h);
|
Send406(h);
|
||||||
@ -1481,7 +1481,7 @@ SendResp_thumbnail(struct upnphttp * h, char * object)
|
|||||||
ExifData *ed;
|
ExifData *ed;
|
||||||
ExifLoader *l;
|
ExifLoader *l;
|
||||||
|
|
||||||
if( h->reqflags & FLAG_XFERSTREAMING || h->reqflags & FLAG_RANGE )
|
if( h->reqflags & (FLAG_XFERSTREAMING|FLAG_RANGE) )
|
||||||
{
|
{
|
||||||
DPRINTF(E_WARN, L_HTTP, "Client tried to specify transferMode as Streaming with an image!\n");
|
DPRINTF(E_WARN, L_HTTP, "Client tried to specify transferMode as Streaming with an image!\n");
|
||||||
Send406(h);
|
Send406(h);
|
||||||
@ -1545,7 +1545,7 @@ void
|
|||||||
SendResp_resizedimg(struct upnphttp * h, char * object)
|
SendResp_resizedimg(struct upnphttp * h, char * object)
|
||||||
{
|
{
|
||||||
char header[512];
|
char header[512];
|
||||||
char str_buf[256];
|
char buf[128];
|
||||||
struct string_s str;
|
struct string_s str;
|
||||||
char **result;
|
char **result;
|
||||||
char date[30];
|
char date[30];
|
||||||
@ -1557,50 +1557,39 @@ SendResp_resizedimg(struct upnphttp * h, char * object)
|
|||||||
char *path, *file_path;
|
char *path, *file_path;
|
||||||
char *resolution;
|
char *resolution;
|
||||||
char *key, *val;
|
char *key, *val;
|
||||||
char *saveptr=NULL, *item=NULL;
|
char *saveptr, *item=NULL;
|
||||||
|
int rotate;
|
||||||
/* Not implemented yet *
|
/* Not implemented yet *
|
||||||
char *pixelshape=NULL;
|
char *pixelshape=NULL; */
|
||||||
int rotation; */
|
|
||||||
sqlite_int64 id;
|
sqlite_int64 id;
|
||||||
int rows=0, chunked, ret;
|
int rows=0, chunked, ret;
|
||||||
image_s *imsrc = NULL, *imdst = NULL;
|
image_s *imsrc = NULL, *imdst = NULL;
|
||||||
int scale = 1;
|
int scale = 1;
|
||||||
|
|
||||||
id = strtoll(object, NULL, 10);
|
id = strtoll(object, &saveptr, 10);
|
||||||
sprintf(str_buf, "SELECT PATH, RESOLUTION from DETAILS where ID = '%lld'", id);
|
snprintf(buf, sizeof(buf), "SELECT PATH, RESOLUTION, ROTATION from DETAILS where ID = '%lld'", id);
|
||||||
ret = sql_get_table(db, str_buf, &result, &rows, NULL);
|
ret = sql_get_table(db, buf, &result, &rows, NULL);
|
||||||
if( (ret != SQLITE_OK) )
|
if( (ret != SQLITE_OK) )
|
||||||
{
|
{
|
||||||
DPRINTF(E_ERROR, L_HTTP, "Didn't find valid file for %lld!\n", id);
|
DPRINTF(E_ERROR, L_HTTP, "Didn't find valid file for %lld!\n", id);
|
||||||
Send500(h);
|
Send500(h);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if( !rows || (access(result[2], F_OK) != 0) )
|
file_path = result[3];
|
||||||
|
resolution = result[4];
|
||||||
|
rotate = result[5] ? atoi(result[5]) : 0;
|
||||||
|
if( !rows || !file_path || !resolution || (access(file_path, F_OK) != 0) )
|
||||||
{
|
{
|
||||||
DPRINTF(E_WARN, L_HTTP, "%s not found, responding ERROR 404\n", object);
|
DPRINTF(E_WARN, L_HTTP, "%s not found, responding ERROR 404\n", object);
|
||||||
sqlite3_free_table(result);
|
sqlite3_free_table(result);
|
||||||
Send404(h);
|
Send404(h);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#if USE_FORK
|
|
||||||
pid_t newpid = 0;
|
|
||||||
newpid = fork();
|
|
||||||
if( newpid )
|
|
||||||
{
|
|
||||||
CloseSocket_upnphttp(h);
|
|
||||||
goto resized_error;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
file_path = result[2];
|
|
||||||
resolution = result[3];
|
|
||||||
srcw = strtol(resolution, &saveptr, 10);
|
|
||||||
srch = strtol(saveptr+1, NULL, 10);
|
|
||||||
|
|
||||||
path = strdup(object);
|
if( saveptr )
|
||||||
if( strtok_r(path, "?", &saveptr) )
|
saveptr = strchr(saveptr, '?');
|
||||||
{
|
path = saveptr ? saveptr + 1 : object;
|
||||||
item = strtok_r(NULL, "&,", &saveptr);
|
item = strtok_r(path, "&,", &saveptr);
|
||||||
}
|
|
||||||
while( item != NULL )
|
while( item != NULL )
|
||||||
{
|
{
|
||||||
#ifdef TIVO_SUPPORT
|
#ifdef TIVO_SUPPORT
|
||||||
@ -1617,29 +1606,39 @@ SendResp_resizedimg(struct upnphttp * h, char * object)
|
|||||||
{
|
{
|
||||||
height = atoi(val);
|
height = atoi(val);
|
||||||
}
|
}
|
||||||
/* Not implemented yet *
|
|
||||||
else if( strcasecmp(key, "rotation") == 0 )
|
else if( strcasecmp(key, "rotation") == 0 )
|
||||||
{
|
{
|
||||||
rotation = atoi(val);
|
rotate = (rotate + atoi(val)) % 360;
|
||||||
|
sql_exec(db, "UPDATE DETAILS set ROTATION = %d where ID = %lld", rotate, id);
|
||||||
}
|
}
|
||||||
|
/* Not implemented yet *
|
||||||
else if( strcasecmp(key, "pixelshape") == 0 )
|
else if( strcasecmp(key, "pixelshape") == 0 )
|
||||||
{
|
{
|
||||||
pixelshape = val;
|
pixelshape = val;
|
||||||
} */
|
} */
|
||||||
item = strtok_r(NULL, "&,", &saveptr);
|
item = strtok_r(NULL, "&,", &saveptr);
|
||||||
}
|
}
|
||||||
free(path);
|
|
||||||
|
|
||||||
if( h->reqflags & FLAG_XFERSTREAMING || h->reqflags & FLAG_RANGE )
|
#if USE_FORK
|
||||||
|
pid_t newpid = 0;
|
||||||
|
newpid = fork();
|
||||||
|
if( newpid )
|
||||||
{
|
{
|
||||||
DPRINTF(E_WARN, L_HTTP, "Client tried to specify transferMode as Streaming with a resized image!\n");
|
CloseSocket_upnphttp(h);
|
||||||
|
goto resized_error;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if( h->reqflags & (FLAG_XFERSTREAMING|FLAG_RANGE) )
|
||||||
|
{
|
||||||
|
DPRINTF(E_WARN, L_HTTP, "Client tried to specify transferMode as Streaming with an image!\n");
|
||||||
Send406(h);
|
Send406(h);
|
||||||
goto resized_error;
|
goto resized_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINTF(E_INFO, L_HTTP, "Serving resized image for ObjectId: %lld [%s]\n", id, file_path);
|
DPRINTF(E_INFO, L_HTTP, "Serving resized image for ObjectId: %lld [%s]\n", id, file_path);
|
||||||
|
|
||||||
/* Figure out the best destination resolution we can use */
|
/* Figure out the best destination resolution we can use */
|
||||||
|
srcw = strtol(resolution, &saveptr, 10);
|
||||||
|
srch = strtol(saveptr+1, NULL, 10);
|
||||||
dstw = width;
|
dstw = width;
|
||||||
dsth = ((((width<<10)/srcw)*srch)>>10);
|
dsth = ((((width<<10)/srcw)*srch)>>10);
|
||||||
if( dsth > height )
|
if( dsth > height )
|
||||||
@ -1647,6 +1646,27 @@ SendResp_resizedimg(struct upnphttp * h, char * object)
|
|||||||
dsth = height;
|
dsth = height;
|
||||||
dstw = (((height<<10)/srch) * srcw>>10);
|
dstw = (((height<<10)/srch) * srcw>>10);
|
||||||
}
|
}
|
||||||
|
switch( rotate )
|
||||||
|
{
|
||||||
|
case 90:
|
||||||
|
rotate = dsth;
|
||||||
|
dsth = dstw;
|
||||||
|
dstw = rotate;
|
||||||
|
rotate = ROTATE_90;
|
||||||
|
break;
|
||||||
|
case 270:
|
||||||
|
rotate = dsth;
|
||||||
|
dsth = dstw;
|
||||||
|
dstw = rotate;
|
||||||
|
rotate = ROTATE_270;
|
||||||
|
break;
|
||||||
|
case 180:
|
||||||
|
rotate = ROTATE_180;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rotate = ROTATE_NONE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if( dstw <= 640 && dsth <= 480 )
|
if( dstw <= 640 && dsth <= 480 )
|
||||||
strcpy(dlna_pn, "SM");
|
strcpy(dlna_pn, "SM");
|
||||||
@ -1655,11 +1675,11 @@ SendResp_resizedimg(struct upnphttp * h, char * object)
|
|||||||
else
|
else
|
||||||
strcpy(dlna_pn, "LRG");
|
strcpy(dlna_pn, "LRG");
|
||||||
|
|
||||||
if( srcw>>3 >= dstw && srch>>3 >= dsth)
|
if( srcw>>4 >= dstw && srch>>4 >= dsth)
|
||||||
scale = 8;
|
scale = 8;
|
||||||
else if( srcw>>2 >= dstw && srch>>2 >= dsth )
|
else if( srcw>>3 >= dstw && srch>>3 >= dsth )
|
||||||
scale = 4;
|
scale = 4;
|
||||||
else if( srcw>>1 >= dstw && srch>>1 >= dsth )
|
else if( srcw>>2 >= dstw && srch>>2 >= dsth )
|
||||||
scale = 2;
|
scale = 2;
|
||||||
|
|
||||||
str.data = header;
|
str.data = header;
|
||||||
@ -1688,7 +1708,7 @@ SendResp_resizedimg(struct upnphttp * h, char * object)
|
|||||||
if( strcmp(h->HttpVer, "HTTP/1.0") == 0 )
|
if( strcmp(h->HttpVer, "HTTP/1.0") == 0 )
|
||||||
{
|
{
|
||||||
chunked = 0;
|
chunked = 0;
|
||||||
imsrc = image_new_from_jpeg(file_path, 1, NULL, 0, scale);
|
imsrc = image_new_from_jpeg(file_path, 1, NULL, 0, scale, rotate);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1715,7 +1735,7 @@ SendResp_resizedimg(struct upnphttp * h, char * object)
|
|||||||
{
|
{
|
||||||
if( chunked )
|
if( chunked )
|
||||||
{
|
{
|
||||||
imsrc = image_new_from_jpeg(file_path, 1, NULL, 0, scale);
|
imsrc = image_new_from_jpeg(file_path, 1, NULL, 0, scale, rotate);
|
||||||
if( !imsrc )
|
if( !imsrc )
|
||||||
{
|
{
|
||||||
DPRINTF(E_WARN, L_HTTP, "Unable to open image %s!\n", file_path);
|
DPRINTF(E_WARN, L_HTTP, "Unable to open image %s!\n", file_path);
|
||||||
@ -1725,8 +1745,8 @@ SendResp_resizedimg(struct upnphttp * h, char * object)
|
|||||||
imdst = image_resize(imsrc, dstw, dsth);
|
imdst = image_resize(imsrc, dstw, dsth);
|
||||||
data = image_save_to_jpeg_buf(imdst, &size);
|
data = image_save_to_jpeg_buf(imdst, &size);
|
||||||
|
|
||||||
ret = sprintf(str_buf, "%x\r\n", size);
|
ret = sprintf(buf, "%x\r\n", size);
|
||||||
send_data(h, str_buf, ret, MSG_MORE);
|
send_data(h, buf, ret, MSG_MORE);
|
||||||
send_data(h, (char *)data, size, MSG_MORE);
|
send_data(h, (char *)data, size, MSG_MORE);
|
||||||
send_data(h, "\r\n0\r\n\r\n", 7, 0);
|
send_data(h, "\r\n0\r\n\r\n", 7, 0);
|
||||||
}
|
}
|
||||||
@ -1754,7 +1774,7 @@ SendResp_dlnafile(struct upnphttp * h, char * object)
|
|||||||
{
|
{
|
||||||
char header[1024];
|
char header[1024];
|
||||||
struct string_s str;
|
struct string_s str;
|
||||||
char sql_buf[256];
|
char buf[128];
|
||||||
char **result;
|
char **result;
|
||||||
int rows, ret;
|
int rows, ret;
|
||||||
char date[30];
|
char date[30];
|
||||||
@ -1775,15 +1795,15 @@ SendResp_dlnafile(struct upnphttp * h, char * object)
|
|||||||
id = strtoll(object, NULL, 10);
|
id = strtoll(object, NULL, 10);
|
||||||
if( id != last_file.id || h->req_client != last_file.client )
|
if( id != last_file.id || h->req_client != last_file.client )
|
||||||
{
|
{
|
||||||
sprintf(sql_buf, "SELECT PATH, MIME, DLNA_PN from DETAILS where ID = '%lld'", id);
|
snprintf(buf, sizeof(buf), "SELECT PATH, MIME, DLNA_PN from DETAILS where ID = '%lld'", id);
|
||||||
ret = sql_get_table(db, sql_buf, &result, &rows, NULL);
|
ret = sql_get_table(db, buf, &result, &rows, NULL);
|
||||||
if( (ret != SQLITE_OK) )
|
if( (ret != SQLITE_OK) )
|
||||||
{
|
{
|
||||||
DPRINTF(E_ERROR, L_HTTP, "Didn't find valid file for %lld!\n", id);
|
DPRINTF(E_ERROR, L_HTTP, "Didn't find valid file for %lld!\n", id);
|
||||||
Send500(h);
|
Send500(h);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if( !rows || !result[3] )
|
if( !rows || !result[3] || !result[4] )
|
||||||
{
|
{
|
||||||
DPRINTF(E_WARN, L_HTTP, "%s not found, responding ERROR 404\n", object);
|
DPRINTF(E_WARN, L_HTTP, "%s not found, responding ERROR 404\n", object);
|
||||||
sqlite3_free_table(result);
|
sqlite3_free_table(result);
|
||||||
@ -1817,10 +1837,6 @@ SendResp_dlnafile(struct upnphttp * h, char * object)
|
|||||||
strcpy(last_file.mime+6, "divx");
|
strcpy(last_file.mime+6, "divx");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
last_file.mime[0] = '\0';
|
|
||||||
}
|
|
||||||
if( result[5] )
|
if( result[5] )
|
||||||
snprintf(last_file.dlna, sizeof(last_file.dlna), "DLNA.ORG_PN=%s", result[5]);
|
snprintf(last_file.dlna, sizeof(last_file.dlna), "DLNA.ORG_PN=%s", result[5]);
|
||||||
else if( h->reqflags & FLAG_DLNA )
|
else if( h->reqflags & FLAG_DLNA )
|
||||||
@ -1935,23 +1951,17 @@ SendResp_dlnafile(struct upnphttp * h, char * object)
|
|||||||
{
|
{
|
||||||
if( (strncmp(last_file.mime, "video", 5) == 0) ||
|
if( (strncmp(last_file.mime, "video", 5) == 0) ||
|
||||||
(strncmp(last_file.mime, "audio", 5) == 0) )
|
(strncmp(last_file.mime, "audio", 5) == 0) )
|
||||||
{
|
|
||||||
strcatf(&str, "transferMode.dlna.org: Streaming\r\n");
|
strcatf(&str, "transferMode.dlna.org: Streaming\r\n");
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
strcatf(&str, "transferMode.dlna.org: Interactive\r\n");
|
strcatf(&str, "transferMode.dlna.org: Interactive\r\n");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if( h->reqflags & FLAG_CAPTION )
|
if( h->reqflags & FLAG_CAPTION )
|
||||||
{
|
{
|
||||||
if( sql_get_int_field(db, "SELECT ID from CAPTIONS where ID = '%lld'", id) > 0 )
|
if( sql_get_int_field(db, "SELECT ID from CAPTIONS where ID = '%lld'", id) > 0 )
|
||||||
{
|
|
||||||
strcatf(&str, "CaptionInfo.sec: http://%s:%d/Captions/%lld.srt\r\n",
|
strcatf(&str, "CaptionInfo.sec: http://%s:%d/Captions/%lld.srt\r\n",
|
||||||
lan_addr[h->iface].str, runtime_vars.port, id);
|
lan_addr[h->iface].str, runtime_vars.port, id);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
strftime(date, 30,"%a, %d %b %Y %H:%M:%S GMT" , gmtime(&curtime));
|
strftime(date, 30,"%a, %d %b %Y %H:%M:%S GMT" , gmtime(&curtime));
|
||||||
strcatf(&str, "Accept-Ranges: bytes\r\n"
|
strcatf(&str, "Accept-Ranges: bytes\r\n"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user