diff --git a/api/media.py b/api/media.py index b782a5b..a8ddfba 100755 --- a/api/media.py +++ b/api/media.py @@ -10,7 +10,7 @@ from xml.etree import ElementTree import config, scanner from web import app -from db import Track, Album, Artist, Folder, User, now, session +from db import Track, Album, Artist, Folder, User, ClientPrefs, now, session from api import get_entity from sqlalchemy import func @@ -29,33 +29,40 @@ def stream_media(): if not status: return res - maxBitRate, format, timeOffset, size, estimateContentLength = map(request.args.get, [ 'maxBitRate', 'format', 'timeOffset', 'size', 'estimateContentLength' ]) + maxBitRate, format, timeOffset, size, estimateContentLength, client = map(request.args.get, [ 'maxBitRate', 'format', 'timeOffset', 'size', 'estimateContentLength', 'c' ]) if format: format = format.lower() - do_transcoding = False src_suffix = res.suffix() dst_suffix = res.suffix() dst_bitrate = res.bitrate dst_mimetype = res.content_type - if format != 'raw': # That's from API 1.9.0 but whatever - if maxBitRate: - try: - maxBitRate = int(maxBitRate) - except: - return request.error_formatter(0, 'Invalid bitrate value') + if client: + prefs = ClientPrefs.query.get((request.user.id, client)) + if not prefs: + prefs = ClientPrefs(user_id = request.user.id, client_name = client) + session.add(prefs) - if dst_bitrate > maxBitRate and maxBitRate != 0: - do_transcoding = True - dst_bitrate = maxBitRate + if prefs.format: + dst_suffix = prefs.format + if prefs.bitrate and prefs.bitrate < dst_bitrate: + dst_bitrate = prefs.bitrate - if format and format != src_suffix: - do_transcoding = True - dst_suffix = format - dst_mimetype = scanner.get_mime(dst_suffix) + if maxBitRate: + try: + maxBitRate = int(maxBitRate) + except: + return request.error_formatter(0, 'Invalid bitrate value') - if do_transcoding: + if dst_bitrate > maxBitRate and maxBitRate != 0: + dst_bitrate = maxBitRate + + if format and format != 'raw' and format != src_suffix: + dst_suffix = format + dst_mimetype = scanner.get_mime(dst_suffix) + + if format != 'raw' and (dst_suffix != src_suffix or dst_bitrate != res.bitrate): transcoder = config.get('transcoding', 'transcoder_{}_{}'.format(src_suffix, dst_suffix)) decoder = config.get('transcoding', 'decoder_' + src_suffix) or config.get('transcoding', 'decoder') encoder = config.get('transcoding', 'encoder_' + dst_suffix) or config.get('transcoding', 'encoder') @@ -83,6 +90,7 @@ def stream_media(): proc.terminate() proc.wait() + app.logger.info('Transcoding track {0.id} for user {1.id}. Source: {2} at {0.bitrate}kbps. Dest: {3} at {4}kbps'.format(res, request.user, src_suffix, dst_suffix, dst_bitrate)) response = Response(transcode(), mimetype = dst_mimetype) else: response = send_file(res.path, mimetype = dst_mimetype) diff --git a/db.py b/db.py index 4c932e3..13bd479 100755 --- a/db.py +++ b/db.py @@ -97,6 +97,14 @@ class User(Base): 'shareRole': False } +class ClientPrefs(Base): + __tablename__ = 'client_prefs' + + user_id = Column(UUID, ForeignKey('user.id'), primary_key = True) + client_name = Column(String(32), nullable = False, primary_key = True) + format = Column(String(8), nullable = True) + bitrate = Column(Integer, nullable = True) + class Folder(Base): __tablename__ = 'folder' diff --git a/templates/profile.html b/templates/profile.html index ba2281f..9477138 100755 --- a/templates/profile.html +++ b/templates/profile.html @@ -18,5 +18,34 @@
  • Change password
  • + +{% if clients.count() %} +

    Clients

    +

    Here's a list of clients you used to stream music. If you want to use transcoding or downsampling with one of them (for instance using a low bitrate on + mobile connections to reduce used bandwidth), but the client doesn't provide options to do so, you can set default values here. They'll only be used if no + transcoding/downsampling is requested by the client.

    +
    + + + {% for client in clients %} + + + + + + + {% endfor %} +
    ClientFormatMax bitrateForget
    {{ client.client_name }}
    + +
    +{% endif %} {% endblock %} diff --git a/user.py b/user.py index 15634f3..4edbcb5 100755 --- a/user.py +++ b/user.py @@ -4,7 +4,7 @@ from flask import request, session, flash, render_template, redirect, url_for, m from web import app from managers.user import UserManager -from db import User, session as db_sess +from db import User, ClientPrefs, session as db_sess import uuid, csv import config from lastfm import LastFm @@ -23,7 +23,28 @@ def user_index(): @app.route('/user/me') def user_profile(): - return render_template('profile.html', user = UserManager.get(session.get('userid'))[1], api_key = config.get('lastfm', 'api_key')) + prefs = ClientPrefs.query.filter(ClientPrefs.user_id == uuid.UUID(session.get('userid'))) + return render_template('profile.html', user = UserManager.get(session.get('userid'))[1], api_key = config.get('lastfm', 'api_key'), clients = prefs) + +@app.route('/user/me', methods = [ 'POST' ]) +def update_clients(): + clients_opts = {} + for client in set(map(lambda k: k.rsplit('_', 1)[0],request.form.keys())): + clients_opts[client] = { k.rsplit('_', 1)[1]: v for k, v in filter(lambda (k, v): k.startswith(client), request.form.iteritems()) } + app.logger.debug(clients_opts) + + for client, opts in clients_opts.iteritems(): + prefs = ClientPrefs.query.get((uuid.UUID(session.get('userid')), client)) + if 'delete' in opts and opts['delete'] in [ 'on', 'true', 'checked', 'selected', '1' ]: + db_sess.delete(prefs) + continue + + prefs.format = opts['format'] if 'format' in opts and opts['format'] else None + prefs.bitrate = int(opts['bitrate']) if 'bitrate' in opts and opts['bitrate'] else None + + db_sess.commit() + flash('Clients preferences updated.') + return user_profile() @app.route('/user/changemail', methods = [ 'GET', 'POST' ]) def change_mail():