Example #1
0
def playlist_requests_new(playlist, pattern, me, request):
    """ handle play requests for playlist
        given the html GET request
        caller should catch MyException which is used for all
        errors in kodi playback
    """

    if 'kodi_local' == pattern:
        try:
            clientip = request.META['REMOTE_ADDR']
        except KeyError:
            message = str('ERROR could not get client ip from request')
            utils.log(message)
            raise rutils.MyException(message)
        time.sleep(5)
        play_to_kodi(playlist, clientip, me)
        return True
    elif 'kodi_lf' == pattern:
        play_to_kodi(playlist, settings.HOST_LF, me)
        return True
    elif 'kodi_bf' == pattern:
        time.sleep(5)
        play_to_kodi(playlist, settings.HOST_BF, me)
        return True
    return False
Example #2
0
def get_json_rpc(host):
    """ given the host construct the json rpc """
    jsonrpc = "jsonrpc"
    if not host.endswith("/"):
        jsonrpc = "/" + jsonrpc
    utils.log("JSON rpc %s" % host + jsonrpc)
    return host + jsonrpc
Example #3
0
 def clean_filePath(self):
     self.drive = -1
     new_path=self.cleaned_data['filePath']
     for i,drive in enumerate(settings.DRIVES,1):
         toCheck = os.path.join(settings.MY_MEDIA_FILES_ROOT,drive,new_path)
         utility.log("checking drive %d name %s path %s" % (i,drive,new_path))
         utility.log("to check %s" % toCheck)
         if os.path.exists(toCheck):
             self.drive=i
             utility.log("OK selecting drive %d" % i)
             break
         else: 
             utility.log("not found on drive %d" % i)
     if self.drive > 0:
         a,b,last = new_path.rpartition('/')
         #print('last a %s b %s last %s' % (a,b,last))
         #print('new_path unchanged %s' % new_path)
         if len(last):
             final = str(new_path)
         else:
             final = str(new_path[:-1])
         if final[0]=='/':
             return final[1:]
         return final
         
     utility.log("DOES NOT EXIST")
     raise ValidationError(u'Path does not exist '+new_path,code=u'invalid')
Example #4
0
def init_xbmc(ip):
    """ given an ip address, setup the kodi connection """
    utils.log("init_xmbc with ip %s" % ip)
    host = str('http://%s' % ip)
    user = settings.XBMC_USER
    password = settings.XBMC_PASSWD
    xbmc_i = XBMC(get_json_rpc(host), user, password)
    return xbmc_i
Example #5
0
def look_at_res(msg, res):
    """ takes the result from a kodi json command """

    if res is not None:
        success = False
        if "result" in res and (res["result"] == "OK"
                                or res["result"] == True):
            success = True
            # Application.SetVolume returns an integer
        # JSONRPC.Ping() returns the string 'pong'
        elif "result" in res and res["result"] == "pong":
            utils.log("OK ping returned pong")
            success = True
        elif "error" in res and "message" in res["error"]:
            message = (res["error"]["message"])
            amsg = ('msg %s %s' % (msg, message))
            utils.log(amsg)
            raise rutils.MyException(amsg)
        else:
            message = ("Kodi Unknown error : '%s'" % (res))
            amsg = ('msg %s %s' % (msg, message))
            utils.log(amsg)
            raise rutils.MyException(amsg)
        if success:
            utils.log("Success")
            print("Success.")
    return success
Example #6
0
def playlist_select(playlist, playback, request):
    """ handle play requests for playlist
        given playback from choices.songplay
        caller should catch MyException which is used for all
        errors in kodi playback
    """
    try:
        me = models.User.objects.get(username=request.user)
    except models.User.DoesNotExist:
        me = None

    if playback == choices.KODI_LOCAL:
        utils.log('local')
        try:
            clientip = request.META['REMOTE_ADDR']
        except KeyError:
            message = str('ERROR could not get client ip from request')
            utils.log(message)
            raise rutils.MyException(message)
        time.sleep(5)
        play_to_kodi(playlist, clientip, me)
        return True
    elif playback == choices.KODI_LF:
        utils.log('lf')
        play_to_kodi(playlist, settings.HOST_LF, me)
        return True
    elif playback == choices.KODI_BF:
        utils.log('bf')
        time.sleep(5)
        play_to_kodi(playlist, settings.HOST_BF, me)
        return True
    return False
Example #7
0
def add_movie(mTitle, mFileName, mSlug, mCollection, fKind=choices.MOVIE):
    try:
        dbobj = bmodels.Movie.objects.get(slug__iexact=mSlug)
    except bmodels.Movie.DoesNotExist:
        utility.log("---> ADD Movie slug %s: " % (mSlug))
        mCollection.save()
        title = unicode(mTitle)
        fileName = unicode(mFileName)
        dbobj = bmodels.Movie(title=title,
                              slug=mSlug,
                              fileName=fileName,
                              collection=mCollection)
        dbobj.save()
    setFileKind(dbobj, fKind)
    dbobj.save()
    return dbobj
Example #8
0
def add_picture(mTitle, mFileName, mSlug, mCollection):
    try:
        dbobj = bmodels.Picture.objects.get(slug__iexact=mSlug)
    except bmodels.Picture.DoesNotExist:
        utility.log("---> ADD Picture %s: " % (mSlug))
        mCollection.save()
        title = unicode(mTitle)
        fileName = unicode(mFileName)
        dbobj = bmodels.Picture(title=title,
                                slug=mSlug,
                                fileName=fileName,
                                collection=mCollection)
        dbobj.save()
    dbobj.fileKind = choices.PICTURE
    dbobj.save()
    return dbobj
Example #9
0
def add_song(sTitle, sFileName, sSlug, sCollection):

    try:
        dbobj = bmodels.Song.objects.get(slug__iexact=sSlug)
    except bmodels.Song.DoesNotExist:
        utility.log("---> ADD Song slug %s: " % (sSlug))
        sCollection.save()
        title = unicode(sTitle)
        fileName = unicode(sFileName)
        dbobj = bmodels.Song(title=title,
                             slug=sSlug,
                             fileName=fileName,
                             collection=sCollection)
        dbobj.save()
    dbobj.fileKind = choices.SONG
    dbobj.save()
    return dbobj
Example #10
0
def add_musician(aName, aSlug):
    if aSlug == 'unknown-mus':
        raise rutils.MyException('No Way - no unknown musicians')
    if aSlug == 'unknown-artist-mus':
        raise rutils.MyException('No Way - no unknown-artist musicians')

    try:
        dbobj = bmodels.Musician.objects.get(slug__iexact=aSlug)
    except bmodels.Musician.DoesNotExist:
        utility.log("---> ADD Musician %s, slug %s" % (aName, aSlug))
        for b in bmodels.Musician.objects.all():
            if utility.slugCompare(aSlug, b.slug):
                return b
        name = unicode(aName)
        dbobj = bmodels.Musician(fullName=name, slug=aSlug)
        dbobj.save()
    return dbobj
Example #11
0
def stream_to_vlc(movie, request):
    """ instruct vlc to stream the movie using host/client from
        html request
        note, no correct interface at this time, uses command line
    """
    utils.log("User pressed StreamMovie")
    try:
        clientip = request.META['REMOTE_ADDR']
    except KeyError:
        clientip = 'unknown'
    hostip = request.get_host()

    #playit = "/home/catherine/FHL/FriendlyHomeLibrary/static/mediafiles/" + movie.collection.filePath + '/' + movie.fileName
    playit = utils.object_path_with_static(movie)
    sstr = (
        "vlc -vvv %s --sout \'#rtp{dst=%s,port=1234,sdp=rtsp://%s:8080/test.sdp}\'"
        % (playit, clientip, hostip[:-5]))
    utils.log(sstr)
    os.system(sstr)
Example #12
0
def add_collection(cAlbum, cSlug, cPath, cDrive, saveIt=True):

    try:
        dbobj = bmodels.Collection.objects.get(slug__iexact=cSlug)
        if dbobj.filePath != cPath:
            # create a new slug by adding -1
            fslug = slugify(unicode('%s-%d' % (cSlug, 1)))
            return add_collection(cAlbum, fslug, cPath, cDrive, saveIt)
    except bmodels.Collection.DoesNotExist:
        utility.log("---> ADD Collection %s slug %s path %s" %
                    (cAlbum, cSlug, cPath))
        path = unicode(cPath)
        album = unicode(cAlbum)
        dbobj = bmodels.Collection(filePath=path,
                                   title=album,
                                   slug=cSlug,
                                   drive=cDrive)
        if saveIt:
            dbobj.save()
    return dbobj
Example #13
0
def to_kodi(thefile, host, xbmc_i):
    """ ping kodi and if successful open the player with the file
        thefile should be the full samba or local path, not the django
        static file path used for html
        Control of the playback is passed to kodi on the selected host
        xbmc_i should be the initialized kodi connection
        host is unused except in the message for an exception
    """
    ping_result = xbmc_i.JSONRPC.Ping()
    look_at_res('ping', ping_result)
    if ping_result:
        utils.log('File to kodi %s' % thefile)
        context = {'item': {'file': thefile}}
        #guess at what a close might look like, not working
        #cresult = xbmc_i.Player.Close()
        #look_at_res(cresult)
        result = xbmc_i.Player.Open(context)
        look_at_res('Player.Open', result)
    else:
        message = str('Error unable to ping kodi at host %s' % host)
        raise rutils.MyException(message)
Example #14
0
    def add_members(self, path, drive, kind, tag, knownCollection=None):
        """
        walk the specified directory to populate the database
        handles (or should handle) all file type errors
        this is the main connection to the file system
        """
        #print("ADD_MEMBERS path %s" % (path))

        sDrive = utility.get_drive(drive)
        album = None
        artist = None
        setPath = os.path.join(settings.MY_MEDIA_FILES_ROOT, sDrive)
        scanPath = os.path.join(setPath, path)
        goodPath = os.path.exists(scanPath)

        if not goodPath:
            message = ('ERROR path does not exist check drive setup %s' %
                       scanPath)
            utility.log(message)
            raise rutils.MyException(message)
        for root, _, files in os.walk(scanPath):
            try:
                myroot = unicode(root[len(setPath):])
                if knownCollection is None:
                    album = self.handle_collection(myroot, drive)
                else:
                    album = knownCollection
                for obj in files:
                    try:
                        artist = add_file(unicode(root), unicode(obj), myroot,
                                          album, kind, tag)
                    except UnicodeDecodeError:
                        print("UnicodeDecodeError file in collection %s" %
                              (album.title))
                    except IOError:
                        print("IOError file in collection %s file %s" %
                              (album.title, obj))
            except UnicodeDecodeError:
                print("UnicodeDecodeError collection")
        return album, artist
Example #15
0
def verify_list(alist):
    blist = []
    utility.log('--- Starting Diagnostics ---')
    for current in alist:
        if current.collection is None:
            msg = (u'DELETING no collection %s' % current.title)
            utility.log(msg)
            blist.append(msg)
            #current.delete()
        elif os.path.exists(settings.DRIVES[0]):
            lpath = utility.object_path_local(current)
            file_exists = os.path.exists(lpath)
            if not file_exists:
                msg = (u'DELETING file does not exist %s %s' %
                       (current.collection.filePath, current.title))
                utility.log(msg)
                blist.append(msg)
                #current.delete()
        else:
            msg = (u'ERROR diagnostic abandonded missing path %s' %
                   settings.DRIVES[0])
            blist.append(msg)
            utility.log(msg)
    return blist
Example #16
0
def slideshow_kodi(playlist, host, xbmc_i, me):
    """ kodi playlist is from a directory, so this annotates the 
        pictures in the playlist and copies them to /tmp/slides-username
        Still to do: clean up pictures from previous slide shows
    """

    utils.log("picturelist to kodi")
    try:
        rutils.cleanup_my_private_directory(me, 'slides')
        file_path, _ = rutils.my_private_directory(me, 'slides')
        # put all the pictures in the directory
        for picture in playlist:
            _, _ = rutils.annotate(picture, me)

        ping_result = xbmc_i.JSONRPC.Ping()
        look_at_res('ping', ping_result)
        if ping_result:
            utils.log('after ping with file_path %s' % file_path)
            path_context = {'directory': file_path}
            open_context = {'item': path_context}

            # play it
            result = xbmc_i.Player.Open(open_context)
            look_at_res('playlist open', result)
        else:
            message = str('Error unable to ping kodi at host %s' % host)
            raise rutils.MyException(message)

    except Exception as ex:
        # in this case I want to see what the exception is
        # but there's no way to handle it, just give back message
        message = str('Cannot create/link kodi directory %s' %
                      (type(ex).__name__))
        utils.log(message)
        utils.log(playlist)
        raise rutils.MyException(message)
Example #17
0
def play_to_kodi(playlist, ip, me):
    """ send the playlist to kodi for playback
        where ip is the ip address
        of kodi where playback is requested
    """
    host = ip + settings.KODI_PORT
    utils.log('play_to_kodi host %s' % host)
    try:
        xbmc_i = init_xbmc(host)
        if playlist[0] and playlist[0].fileKind == choices.PICTURE:
            slideshow_kodi(playlist, host, xbmc_i, me)
            utils.log('after calling slideshow_kodi')
        else:
            play_kodi(playlist, host, xbmc_i)
    except Exception as ex:
        # in this case I want to see what the exception is
        # but there's no way to handle it, just give back message
        message = str('Cannot init_xbmc host %s exception %s' %
                      (host, type(ex).__name__))
        utils.log(message)
        raise rutils.MyException(message)
Example #18
0
def send_to_kodi(ob, ip, local=False):
    """ send an object (song, movie) to kodi for playback
        where ob is the object, ip is the ip address
        of kodi where playback is requested
    """
    host = ip + settings.KODI_PORT
    if local:
        # use files from the local symbols links, no longer required
        # only need when running from 127.0.0.1
        thefile = utils.object_path_local(ob)
    else:
        thefile = utils.object_path_samba(ob)
    try:
        utils.log("Host %s" % host)
        utils.log("ip %s" % ip)
        xbmc_i = init_xbmc(host)
        to_kodi(thefile, host, xbmc_i)
    except Exception as ex:
        # in this case I want to see what the exception is
        # but there's no way to handle it, just pass it back for display
        message = str('Cannot init_xbmc host %s exception %s' %
                      (host, type(ex).__name__))
        utils.log(message)
        raise rutils.MyException(message)
Example #19
0
def add_file(root, myfile, path, newCollection, formKind, formTag):
    """
    passed the root, file, path from an os walk
    newCollection was created to hold the new database object
    formKind, formTag are from the create collections form
    returns musician (null unless it was found for a song) to allow redirect if appropriate
    """

    musician = None

    theFile = unicode(os.path.join(root, myfile))
    try:
        statinfo = os.stat(theFile)
    except Exception as ex:
        # in this case I want to see what the exception is, but the file is ok and
        # will not be ignored
        utility.log("SKIP (os.stat) %s unhandled exception %s" %
                    (theFile, type(ex).__name__))
        return musician
    if not statinfo.st_size:
        utility.log("SKIP file with 0 size %s" % theFile)
        return musician
    base = unicode(os.path.basename(theFile))
    mTitle, extension = os.path.splitext(base)
    mTitle = unicode(mTitle)
    extension = unicode(extension)
    adate = time.gmtime(os.path.getmtime(theFile))
    fdate = time.strftime('%Y-%m-%d', adate)

    if mp3.isMp3File(theFile):
        nc = newCollection
        sSlug = slugify(unicode('%s%s-sg' % (nc.slug, mTitle)))
        song = add_song(mTitle, base, sSlug, nc)
        song.date_added = fdate

        if len(formTag):
            xSlug = slugify(unicode('%s' % (formTag)))
            xTag = add_tag(formTag, xSlug)
            song.tags.add(xTag)

        # fill in extra details from the id3 tag on file if possible
        musician = fix_song(song, theFile, nc)
        song.save()

    else:
        # This section is for the info on mkv files
        # currently not being used, but may be in future
        # in this section new movies will be added to the passed collection
        ## try:
        ##    with open(theFile,'rb') as f:
        ##        mkv = enzyme.MKV(f)
        ##        print (mkv)
        ##        print (type(mkv))
        ##    f.close()
        ##except enzyme.MalformedMKVError:
        ##    print("BOGUS MKV skip")

        nc = newCollection
        if as_movie(extension):
            mSlug = slugify(unicode('%s%s-mv' % (nc.slug, mTitle)))
            movie = add_movie(mTitle, base, mSlug, nc, formKind)
            movie.date_added = fdate

            if len(formTag):
                xSlug = slugify(unicode('%s' % (formTag)))
                xTag = add_tag(formTag, xSlug)
                movie.tags.add(xTag)

            movie.save()
        elif as_picture(extension):
            mSlug = slugify(unicode('%s%s-pict' % (nc.slug, mTitle)))
            picture = add_picture(mTitle, base, mSlug, nc)
            picture.date_added = fdate
            picture.save()

            # supposed to be faster with details=False
            #itags = exifread.process_file(theFile, details=False)
            fname = unicode(theFile)
            try:
                #print("before open file open file %s" % fname)
                with open(fname, 'r') as f:
                    #print("file open ok now get info")
                    itags = exifread.process_file(f, details=False)
                    #print("got info %s " % fname)
                    #print (itags)
                    #print tag['Image DateTime']
                    for tag in itags:
                        if tag in 'Image DateTime':
                            value = itags[tag]
                            picture.data1 = value
                            try:
                                picture.year = int(value[:4])
                            except ValueError:
                                # if its not a number just
                                # don't set the year
                                pass
                        if tag in 'EXIF DateTimeOriginal':
                            value = itags[tag]
                            picture.data2 = value
                            #print("2 %s" % value)
                        if tag in 'EXIF DateTimeDigitized':
                            value = itags[tag]
                            #print("3 %s" % value)
                            picture.data3 = value
                    picture.save()
            except NameError:
                #print("ERROR (opening for info) NameError file %s" % fname)
                # this is ok, file is OK just ignore the info
                pass
            except Exception as ex:
                # in this case I want to see what the exception is, but the file is ok and
                # will not be ignored
                utility.log(
                    "ERROR (opening for info) %s unhandled exception %s" %
                    (fname, type(ex).__name__))

            if len(formTag):
                xSlug = slugify(unicode('%s' % (formTag)))
                xTag = add_tag(formTag, xSlug)
                picture.tags.add(xTag)

            picture.save()
        else:
            utility.log("SKIPPING - unhandled extension %s/%s" % (path, base))
    return musician
Example #20
0
def fix_song(song, theFile, collection):
    """
    Given a song, file and collection, attempt to get
    album,title,artist,genre information from the id3 tag
    to populate the database
    """
    tag = None
    try:
        tag = id3.Tag()
        tag.parse(theFile)
    except IOError:
        # id3 library has an issue with ? so just give up
        return None
    except Exception as ex:
        utility.log("ERROR (idetag) %s unhandled exception %s" %
                    (theFile, type(ex).__name__))
        return None

    if tag is None:
        # pick some reasonable defaults
        myArtist = pick_artist(collection.filePath)
        title = song.title
    else:
        myArtist = unicode(tag.artist)
        if myArtist is None:
            #myArtist = u'various'
            myArtist = pick_artist(collection.filePath)
        elif myArtist == 'unknown':
            myArtist = pick_artist(collection.filePath)
        elif myArtist == 'Unknown':
            myArtist = pick_artist(collection.filePath)
        elif myArtist == 'Unknown Artist':
            myArtist = pick_artist(collection.filePath)

        title = unicode(tag.title)
        if title is None:
            title = song.title
        elif title == 'None':
            title = song.title

        album = tag.album
        if album is None:
            pass
        elif album == 'None':
            pass
        else:
            collection.title = album

    t1, _ = tag.track_num
    if t1 is None:
        t1 = 0
    song.track = t1

    # musician has name, slug
    artistSlug = slugify(unicode('%s%s' % (myArtist, '-mus')))

    musician = add_musician(aName=myArtist, aSlug=artistSlug)
    musician.albums.add(collection)
    musician.songs.add(song)
    musician.save()

    #print('musician %s collection %s' % (musician.fullName,collection.title))

    genre = tag.genre
    if genre is None:
        pass
    elif genre.name == 'None':
        pass
    elif genre.name == 'Unknown':
        pass
    elif genre.name == 'unknown':
        pass
    elif genre.name == '<not-set>':
        pass
    else:
        genreSlug = slugify(unicode('%s' % (genre.name)))
        gen = add_tag(unicode(genre.name), genreSlug)
        song.tags.add(gen)

    return musician
def generic_collection_view(request, **kwargs):
    """
    Keep view details and playback requests in a single place
    so all collections view look the same and have the same options
    """

    if 'stopshow' in request.GET:
        slideshow = False
        return redirect(reverse('user_page'))

    template_name = 'FHLBuilder/collection_detail.html'
    slideshow = False

    # respond to playlist
    if 'playlist' in request.GET:
        asPlayList = True
    else:
        asPlayList = False

    # arguments and defaults
    songs = kwargs.get('songs', [])
    movies = kwargs.get('movies', [])
    pictures = kwargs.get('pictures', [])
    artists = kwargs.get('artists', [])
    title = kwargs.get('title', 'Collection View')
    allowChoice = kwargs.get('allowChoice', False)
    kind = kwargs.get('kind', choices.UNKNOWN)
    update = kwargs.get('update', None)
    sorder = kwargs.get('myorder', choices.NAME)

    allow_tag = True

    if kind == choices.SONG and not len(songs):
        # no tagging everything please
        allow_tag = False
        if sorder == choices.NEWEST:
            songs = models.Song.newest_objects.all()
        elif sorder == choices.OLDEST:
            songs = models.Song.oldest_objects.all()
        else:
            songs = models.Song.objects.all()

        title = ('All Songs %d' % songs.count())

    if sorder == choices.NEWEST:
        ob = '-date_added'
    elif sorder == choices.OLDEST:
        ob = 'date_added'
    else:
        ob = 'title'

    if kind in choices.videos and not len(movies):
        allow_tag = False
        # all movies view, can there be a faster option?
        olist, title = movies_bykind(kind)
        movies = olist.order_by(ob)

    # respond to slide show
    current_picture = 1
    picture = None
    filename = None

    picture_count = len(pictures)

    use_all = False
    if not picture_count and kind == choices.PICTURE:
        # all pictures view
        picture_count = models.Picture.slide_objects.all().count()
        use_all = True

    try:
        me = models.User.objects.get(username=request.user)
    except models.User.DoesNotExist:
        # anonymous user
        me = None
    except Exception as ex:
        utility.log("ERROR unhandled exception %s" % (type(ex).__name__))

    message = ''

    ccasts = []

    #print(request.GET)
    if 'options' in request.GET and not slideshow:
        ccasts = chromecast.find_chrome_casts()
        val = request.GET.get('options')
        if val == 'slideshow':
            slideshow = True
        elif val[:4] == 't___':
            dev = val[4:]
            chromecast.cast_slides(dev, pictures, me, True)
        elif val[:4] == 'cst_':
            dev = val[4:]
            chromecast.cast_slides(dev, pictures, me, False)
        elif val == 'CastAll-title':
            chromecast.cast_slides_all(pictures, me, True)
        elif val == 'CastAll':
            chromecast.cast_slides_all(pictures, me, False)
        else:
            # kodi playlist options
            try:
                res = kodi.playlist_requests_new(pictures, val, me, request)
                if res:
                    message = u'success - pictures sent'
            except rutils.MyException as ex:
                message = ex.message
                #print('Caught %s' % ex.message)

    if 'sNext' in request.GET and request.GET.get('sNext'):
        current_picture = int(request.GET.get('sNext'))
        slideshow = True
        current_picture = current_picture + 1
        if current_picture > picture_count:
            current_picture = 1
    if 'cNext' in request.GET and request.GET.get('cNext'):
        current_picture = int(request.GET.get('cNext'))
        current_picture = current_picture + 1
        if current_picture > picture_count:
            current_picture = 1
    elif 'cPrev' in request.GET and request.GET.get('cPrev'):
        current_picture = int(request.GET.get('cPrev'))
        if current_picture == 1:
            current_picture = picture_count
        else:
            current_picture = current_picture - 1

    if picture_count and not slideshow:
        ccasts = chromecast.find_chrome_casts()

    if use_all:
        # all pictures view
        allow_tag = False
        picture = models.Picture.slide_objects.all().order_by(
            ob)[current_picture]
        title = ('All Pictures %d' % picture_count)
        filename = utility.object_path(picture)
    elif picture_count:
        allow_tag = False
        picture = pictures[current_picture - 1]
        filename = utility.object_path(picture)

    # tags all objects
    if 'tq' in request.GET and request.GET['tq']:
        tq = request.GET['tq']
        tqSlug = slugify(str(tq))
        new_tag = collection.add_tag(tq, tqSlug)

        for obj in songs:
            obj.tags.add(new_tag)
        for obj in pictures:
            obj.tags.add(new_tag)
        for obj in movies:
            obj.tags.add(new_tag)

    # kodi playlist options
    try:
        if movies and kodi.playlist_requests(movies, request):
            message = u'success - movies sent'
        elif songs and kodi.playlist_requests(songs, request):
            message = u'success - songs sent'
        elif pictures and kodi.playlist_requests(pictures, request):
            message = u'success - pictures sent'

    except rutils.MyException as ex:
        message = ex.message
        print('Caught %s' % ex.message)

    context = {
        'title': title,
        'songlist': songs,
        'picture': picture,
        'pictureCount': picture_count,
        'filename': filename,
        'index': current_picture,
        'asPlayList': asPlayList,
        'movielist': movies,
        'update': update,
        'choices': choices.LIVE_CHOICES,
        'listkind': kind,
        'allowChoice': allowChoice,
        'artists': artists,
        'message': message,
        'allow_tag': allow_tag,
        'slideshow': slideshow,
        'ccasts': ccasts,
        'use_all': use_all
    }
    return render(request, template_name, context)