upnpsoap: Add forced alphasort capability
Add the ability to force title modification for clients that do their own alphanumeric sorting. Adding a '!' to the beginning of the force_sort_criteria value will enable this behavior. It is implemented by prepending all titles with a zero-padded number, and possibly season and episode (or disc and track) numbers if they aren't already in the title.
This commit is contained in:
parent
c0e66e9997
commit
3e9ca13fa3
@ -740,6 +740,11 @@ init(int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
case FORCE_SORT_CRITERIA:
|
case FORCE_SORT_CRITERIA:
|
||||||
force_sort_criteria = ary_options[i].value;
|
force_sort_criteria = ary_options[i].value;
|
||||||
|
if (force_sort_criteria[0] == '!')
|
||||||
|
{
|
||||||
|
SETFLAG(FORCE_ALPHASORT_MASK);
|
||||||
|
force_sort_criteria++;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case MAX_CONNECTIONS:
|
case MAX_CONNECTIONS:
|
||||||
runtime_vars.max_connections = atoi(ary_options[i].value);
|
runtime_vars.max_connections = atoi(ary_options[i].value);
|
||||||
|
@ -80,6 +80,9 @@ model_number=1
|
|||||||
#root_container=.
|
#root_container=.
|
||||||
|
|
||||||
# always force SortCriteria to this value, regardless of the SortCriteria passed by the client
|
# always force SortCriteria to this value, regardless of the SortCriteria passed by the client
|
||||||
|
# note: you can prepend the sort criteria with "!" to alter the titles of the objects so that they
|
||||||
|
# will be alphanumerically sorted in the order you specify here, to work around clients that do their
|
||||||
|
# own alphanumeric sorting.
|
||||||
#force_sort_criteria=+upnp:class,+upnp:originalTrackNumber,+dc:title
|
#force_sort_criteria=+upnp:class,+upnp:originalTrackNumber,+dc:title
|
||||||
|
|
||||||
# maximum number of simultaneous connections
|
# maximum number of simultaneous connections
|
||||||
|
@ -161,6 +161,10 @@ The possible values are:
|
|||||||
.IP "\fBforce_sort_criteria\fP"
|
.IP "\fBforce_sort_criteria\fP"
|
||||||
Always force SortCriteria to this value, regardless of the SortCriteria passed by the client.
|
Always force SortCriteria to this value, regardless of the SortCriteria passed by the client.
|
||||||
.nf
|
.nf
|
||||||
|
You may prepend the sort criteria with "!" to alter the titles of the objects so that they
|
||||||
|
will be alphanumerically sorted in the order you specify here, to work around clients that do
|
||||||
|
their own alphanumeric sorting.
|
||||||
|
.nf
|
||||||
|
|
||||||
Example
|
Example
|
||||||
force_sort_criteria=+upnp:class,+upnp:originalTrackNumber,+dc:title
|
force_sort_criteria=+upnp:class,+upnp:originalTrackNumber,+dc:title
|
||||||
|
@ -196,6 +196,7 @@ extern uint32_t runtime_flags;
|
|||||||
#define SCANNING_MASK 0x0100
|
#define SCANNING_MASK 0x0100
|
||||||
#define RESCAN_MASK 0x0200
|
#define RESCAN_MASK 0x0200
|
||||||
#define SUBTITLES_MASK 0x0400
|
#define SUBTITLES_MASK 0x0400
|
||||||
|
#define FORCE_ALPHASORT_MASK 0x0800
|
||||||
|
|
||||||
#define SETFLAG(mask) runtime_flags |= mask
|
#define SETFLAG(mask) runtime_flags |= mask
|
||||||
#define GETFLAG(mask) (runtime_flags & mask)
|
#define GETFLAG(mask) (runtime_flags & mask)
|
||||||
|
39
upnpsoap.c
39
upnpsoap.c
@ -77,6 +77,8 @@
|
|||||||
#else
|
#else
|
||||||
# define __SORT_LIMIT
|
# define __SORT_LIMIT
|
||||||
#endif
|
#endif
|
||||||
|
#define NON_ZERO(x) (x && atoi(x))
|
||||||
|
#define IS_ZERO(x) (!x || !atoi(x))
|
||||||
|
|
||||||
/* Standard Errors:
|
/* Standard Errors:
|
||||||
*
|
*
|
||||||
@ -691,6 +693,35 @@ parse_sort_criteria(char *sortCriteria, int *error)
|
|||||||
return order;
|
return order;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_alphasort_alt_title(char **title, char **alt_title, int requested, int returned, const char *disc, const char *track)
|
||||||
|
{
|
||||||
|
char *old_title = *alt_title ?: NULL;
|
||||||
|
char buf[8];
|
||||||
|
int pad;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
snprintf(buf, sizeof(buf), "%d", requested);
|
||||||
|
pad = strlen(buf);
|
||||||
|
|
||||||
|
if (NON_ZERO(track) && !strstr(*title, track)) {
|
||||||
|
if (NON_ZERO(disc))
|
||||||
|
ret = asprintf(alt_title, "%0*d %s.%s %s",
|
||||||
|
pad, returned, disc, track, *title);
|
||||||
|
else
|
||||||
|
ret = asprintf(alt_title, "%0*d %s %s",
|
||||||
|
pad, returned, track, *title);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret = asprintf(alt_title, "%0*d %s", pad, returned, *title);
|
||||||
|
|
||||||
|
if (ret > 0)
|
||||||
|
*title = *alt_title;
|
||||||
|
else
|
||||||
|
*alt_title = NULL;
|
||||||
|
free(old_title);
|
||||||
|
}
|
||||||
|
|
||||||
inline static void
|
inline static void
|
||||||
add_resized_res(int srcw, int srch, int reqw, int reqh, char *dlna_pn,
|
add_resized_res(int srcw, int srch, int reqw, int reqh, char *dlna_pn,
|
||||||
char *detailID, struct Response *args)
|
char *detailID, struct Response *args)
|
||||||
@ -796,9 +827,6 @@ object_exists(const char *object)
|
|||||||
" d.THUMBNAIL, d.CREATOR, d.DLNA_PN, d.MIME, d.ALBUM_ART, d.ROTATION, d.DISC "
|
" d.THUMBNAIL, d.CREATOR, d.DLNA_PN, d.MIME, d.ALBUM_ART, d.ROTATION, d.DISC "
|
||||||
#define SELECT_COLUMNS "SELECT o.OBJECT_ID, o.PARENT_ID, o.REF_ID, " COLUMNS
|
#define SELECT_COLUMNS "SELECT o.OBJECT_ID, o.PARENT_ID, o.REF_ID, " COLUMNS
|
||||||
|
|
||||||
#define NON_ZERO(x) (x && atoi(x))
|
|
||||||
#define IS_ZERO(x) (!x || !atoi(x))
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
callback(void *args, int argc, char **argv, char **azColName)
|
callback(void *args, int argc, char **argv, char **azColName)
|
||||||
{
|
{
|
||||||
@ -947,6 +975,9 @@ callback(void *args, int argc, char **argv, char **azColName)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
dlna_flags |= DLNA_FLAG_TM_I;
|
dlna_flags |= DLNA_FLAG_TM_I;
|
||||||
|
/* Force an alphabetical sort, for clients that like to do their own sorting */
|
||||||
|
if( GETFLAG(FORCE_ALPHASORT_MASK) )
|
||||||
|
_alphasort_alt_title(&title, &alt_title, passed_args->requested, passed_args->returned, disc, track);
|
||||||
|
|
||||||
if( passed_args->flags & FLAG_SKIP_DLNA_PN )
|
if( passed_args->flags & FLAG_SKIP_DLNA_PN )
|
||||||
dlna_pn = NULL;
|
dlna_pn = NULL;
|
||||||
@ -1022,7 +1053,7 @@ callback(void *args, int argc, char **argv, char **azColName)
|
|||||||
if( *mime == 'a' && (passed_args->filter & FILTER_UPNP_ORIGINALTRACKNUMBER) ) {
|
if( *mime == 'a' && (passed_args->filter & FILTER_UPNP_ORIGINALTRACKNUMBER) ) {
|
||||||
ret = strcatf(str, "<upnp:originalTrackNumber>%s</upnp:originalTrackNumber>", track);
|
ret = strcatf(str, "<upnp:originalTrackNumber>%s</upnp:originalTrackNumber>", track);
|
||||||
} else if( *mime == 'v' ) {
|
} else if( *mime == 'v' ) {
|
||||||
if( passed_args->filter & FILTER_UPNP_EPISODESEASON )
|
if( NON_ZERO(disc) && (passed_args->filter & FILTER_UPNP_EPISODESEASON) )
|
||||||
ret = strcatf(str, "<upnp:episodeSeason>%s</upnp:episodeSeason>", disc);
|
ret = strcatf(str, "<upnp:episodeSeason>%s</upnp:episodeSeason>", disc);
|
||||||
if( passed_args->filter & FILTER_UPNP_EPISODENUMBER )
|
if( passed_args->filter & FILTER_UPNP_EPISODENUMBER )
|
||||||
ret = strcatf(str, "<upnp:episodeNumber>%s</upnp:episodeNumber>", track);
|
ret = strcatf(str, "<upnp:episodeNumber>%s</upnp:episodeNumber>", track);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user