Пример #1
0
def generate_waveform(song, mp3_file, filename_appendix=""):
    suffix = '.png'
    png_tmp_handle = tempfile.NamedTemporaryFile(mode='r+b', suffix=suffix)

    p = subprocess.Popen([
        'waveform',
        '--width',
        str(design.waveform_size[0]),
        '--height',
        str(design.waveform_size[1]),
        '--color-bg',
        '00000000',
        '--color-center',
        design.waveform_center_color,
        '--color-outer',
        design.waveform_outer_color,
        mp3_file,
        png_tmp_handle.name,
    ])
    p.communicate()
    # move to storage
    song.waveform_img = os.path.join(
        obfuscated_url(song.band),
        clean_filename(song.displayString()) + filename_appendix + suffix)
    import storage
    storage.engine.store(png_tmp_handle.name,
                         song.waveform_img,
                         reducedRedundancy=True)
    # clean up
    png_tmp_handle.close()
Пример #2
0
def handle_mp3_upload(file_mp3_handle, song, max_song_len=None, filename_appendix=""):
    data = {'success': False}

    # upload mp3 file to temp folder
    mp3_tmp_handle = tempfile.NamedTemporaryFile(suffix='.mp3', delete=False)
    upload_file_h(file_mp3_handle, mp3_tmp_handle)
    mp3_tmp_handle.close()

    # read the length tag
    try:
        audio = MP3(mp3_tmp_handle.name, ID3=EasyID3)
        song.length = audio.info.length
    except:
        data['reason'] = design.invalid_mp3_file
        return data

    # reject if invalid
    if audio.info.sketchy:
        data['reason'] = design.sketchy_mp3_file
        return data

    # reject if too long
    if max_song_len != None:
        if audio.info.length > max_song_len:
            data['reason'] = design.song_too_long
            return data

    # enforce ID3 tags
    try:
        audio.add_tags(ID3=EasyID3)
    except MutagenID3Error:
        pass

    audio['artist'] = song.band.title
    if song.title != None:
        audio['title'] = song.title
    if song.album != None:
        audio['album'] = song.album

    try:
        audio.save()
    except:
        data['reason'] = design.unable_to_save_id3_tags
        return data

    # pick a path for the mp3 file. obscure the URL so that people can't steal songs
    song.mp3_file = os.path.join(obfuscated_url(song.band), clean_filename(song.displayString() + filename_appendix + '.mp3'))

    generate_waveform(song, mp3_tmp_handle.name, filename_appendix)

    # count mp3 against the band's size quota
    song.band.used_space += os.path.getsize(mp3_tmp_handle.name)

    # move mp3 file to storage
    move_to_storage(mp3_tmp_handle.name, song.mp3_file)

    song.band.save()
    data = {'success': True}
    return data
Пример #3
0
def download_zip(request):
    song = get_object_or_404(Song, pk=get_val(request.GET, 'song', 0))

    if not song.permission_to_view_source(request.user):
        raise Http403

    wanted_samples = request.GET.getlist('s')
    if len(wanted_samples) == 0:
        want_project = True
        deps = SampleDependency.objects.filter(song=song).exclude(uploaded_sample=None)
    else:
        want_project = False

        wanted_sample_ids = []
        
        for wanted_sample in wanted_samples:
            if wanted_sample == 'project':
                want_project = True
                continue
            try:
                wanted_sample_id = int(wanted_sample)
            except ValueError:
                continue

            wanted_sample_ids.append(wanted_sample_id)

        deps = SampleDependency.objects.filter(pk__in=wanted_sample_ids, song=song).exclude(uploaded_sample=None)

    zip_file_h = make_timed_temp_file()
    z = zipfile.ZipFile(zip_file_h, mode='w', compression=zipfile.ZIP_DEFLATED, allowZip64=True)

    import storage

    def store_file_id(file_id, title):
        tmp = tempfile.NamedTemporaryFile(mode='r+b')
        storage.engine.retrieve(file_id, tmp.name)
        z.write(tmp.name, title)
        tmp.close()
        
    if want_project:
        _path, title = os.path.split(song.source_file)
        store_file_id(song.source_file, title)

    for dep in deps:
        file_id = dep.uploaded_sample.sample_file.path
        store_file_id(file_id, dep.title)

    z.close()

    response = HttpResponse(FileWrapper(zip_file_h), mimetype='application/zip')
    response['Content-Disposition'] = 'attachment; filename="%s"' % clean_filename(song.displayString() + '.zip')
    response['Content-Length'] = zip_file_h.tell()

    zip_file_h.seek(0)
    return response
Пример #4
0
def generate_waveform(song, mp3_file, filename_appendix=""):
    suffix = '.png'
    png_tmp_handle = tempfile.NamedTemporaryFile(mode='r+b', suffix=suffix)

    p = subprocess.Popen(['waveform',
        '--width', str(design.waveform_size[0]),
        '--height', str(design.waveform_size[1]),
        '--color-bg', '00000000',
        '--color-center', design.waveform_center_color,
        '--color-outer', design.waveform_outer_color,
        mp3_file,
        png_tmp_handle.name,
    ])
    p.communicate()
    # move to storage
    song.waveform_img = os.path.join(obfuscated_url(song.band), clean_filename(song.displayString()) + filename_appendix + suffix)
    import storage
    storage.engine.store(png_tmp_handle.name, song.waveform_img, reducedRedundancy=True)
    # clean up
    png_tmp_handle.close()
Пример #5
0
def handle_project_file(filename, user, song, filename_appendix=""):
    """
    creates the database entries necessary for filename as the project for song.
    moves filename to storage or deletes it if there is a problem.
    increments the band's used space. be sure to save song and song.band after calling.
    """
    _prefix, ext = os.path.splitext(filename)
    profile = user.get_profile()

    # handle zip files
    if ext.lower() == '.zip':
        studioExts = studio_extensions()
        song.studio = None
        def zipCallback(extracted_filename):
            _path, title = os.path.split(extracted_filename)
            _prefix, ext = os.path.splitext(extracted_filename)
            if ext[1:].lower() in studioExts:
                if song.studio is None:
                    handle_project_file(extracted_filename, user, song, filename_appendix=filename_appendix)
            else:
                handle_sample_file(extracted_filename, title, user, song.band)

        zip_walk(filename, zipCallback)
        os.remove(filename)
        return

    # read the project file with the daw
    source_file_title = song.displayString()
    profile_save_required = False
    try:
        dawProject = daw.load(filename)
        dawExt = dawProject.extension() 

        # assign the correct studio
        try:
            song.studio = Studio.objects.get(identifier=dawProject.identifier)

            # assume the user owns the studio
            profile.studios.add(song.studio)
            profile_save_required = True
        except Studio.DoesNotExist:
            pass

        stuff = (
            (dawProject.generators(), PluginDepenency.GENERATOR),
            (dawProject.effects(), PluginDepenency.EFFECT),
        )
        for plugins, plugin_type in stuff:
            for plugin in plugins:
                # if it's an invalid name, ignore
                if plugin.strip() == '':
                    continue

                if plugin in IGNORED_PLUGINS:
                    continue

                # see if it already exists
                deps = PluginDepenency.objects.filter(title=plugin)
                if deps.count() == 0:
                    # create it
                    dep = PluginDepenency()
                    dep.title = plugin
                    dep.plugin_type = plugin_type
                    dep.save()
                else:
                    dep = deps[0]

                # add it as a dependency
                song.plugins.add(dep)

                # assume that the user owns this dependency
                if profile.assume_uploaded_plugins_owned:
                    profile.plugins.add(dep)
                    profile_save_required = True

        samples = dawProject.samples()
        for sample in samples:
            # if it's an invalid name, ignore
            if sample.strip() == '':
                continue

            _path, title = os.path.split(sample)

            # create the dependency
            dep = SampleDependency()
            dep.title = title
            dep.song = song
                
            # if the title matches anthing the user or band has already uploaded,
            # establish a link.
            existing_samples = UploadedSample.objects.filter(title=title).filter(Q(user=user)|Q(band=song.band))

            if existing_samples.count() > 0:
                # TODO: handle title ambiguity
                # copy the dependency to this song
                existing_sample = existing_samples[0]
                dep.uploaded_sample = existing_sample

            dep.save()

        if dawExt:
            source_file_title += filename_appendix + "." + dawExt

        usingDaw = True
    except daw.exceptions.LoadError:
        usingDaw = False
        # ok forget about processing it with the daw
        # add the extension from before
        source_file_title += filename_appendix + ext
    finally:
        if profile_save_required:
            profile.save()

    song.source_file = os.path.join(obfuscated_url(song.band), clean_filename(source_file_title))

    if usingDaw:
        out_handle = tempfile.NamedTemporaryFile(mode='r+b')
        dawProject.save(out_handle.name)

        # count it against the band's size quota
        song.band.used_space += os.path.getsize(out_handle.name)

        # move to storage
        import storage
        storage.engine.store(out_handle.name, song.source_file)
        out_handle.close()

        os.remove(filename)
    else:
        # count it against the band's size quota
        song.band.used_space += os.path.getsize(filename)
        # move to storage
        move_to_storage(filename, song.source_file)

    song.save()
Пример #6
0
def download_zip(request):
    song = get_object_or_404(Song, pk=get_val(request.GET, 'song', 0))

    if not song.permission_to_view_source(request.user):
        raise Http403

    wanted_samples = request.GET.getlist('s')
    if len(wanted_samples) == 0:
        want_project = True
        deps = SampleDependency.objects.filter(song=song).exclude(
            uploaded_sample=None)
    else:
        want_project = False

        wanted_sample_ids = []

        for wanted_sample in wanted_samples:
            if wanted_sample == 'project':
                want_project = True
                continue
            try:
                wanted_sample_id = int(wanted_sample)
            except ValueError:
                continue

            wanted_sample_ids.append(wanted_sample_id)

        deps = SampleDependency.objects.filter(
            pk__in=wanted_sample_ids, song=song).exclude(uploaded_sample=None)

    zip_file_h = make_timed_temp_file()
    z = zipfile.ZipFile(zip_file_h,
                        mode='w',
                        compression=zipfile.ZIP_DEFLATED,
                        allowZip64=True)

    import storage

    def store_file_id(file_id, title):
        tmp = tempfile.NamedTemporaryFile(mode='r+b')
        storage.engine.retrieve(file_id, tmp.name)
        z.write(tmp.name, title)
        tmp.close()

    if want_project:
        _path, title = os.path.split(song.source_file)
        store_file_id(song.source_file, title)

    for dep in deps:
        file_id = dep.uploaded_sample.sample_file.path
        store_file_id(file_id, dep.title)

    z.close()

    response = HttpResponse(FileWrapper(zip_file_h),
                            mimetype='application/zip')
    response[
        'Content-Disposition'] = 'attachment; filename="%s"' % clean_filename(
            song.displayString() + '.zip')
    response['Content-Length'] = zip_file_h.tell()

    zip_file_h.seek(0)
    return response
Пример #7
0
def handle_mp3_upload(file_mp3_handle,
                      song,
                      max_song_len=None,
                      filename_appendix=""):
    data = {'success': False}

    # upload mp3 file to temp folder
    mp3_tmp_handle = tempfile.NamedTemporaryFile(suffix='.mp3', delete=False)
    upload_file_h(file_mp3_handle, mp3_tmp_handle)
    mp3_tmp_handle.close()

    # read the length tag
    try:
        audio = MP3(mp3_tmp_handle.name, ID3=EasyID3)
        song.length = audio.info.length
    except:
        data['reason'] = design.invalid_mp3_file
        return data

    # reject if invalid
    if audio.info.sketchy:
        data['reason'] = design.sketchy_mp3_file
        return data

    # reject if too long
    if max_song_len != None:
        if audio.info.length > max_song_len:
            data['reason'] = design.song_too_long
            return data

    # enforce ID3 tags
    try:
        audio.add_tags(ID3=EasyID3)
    except MutagenID3Error:
        pass

    audio['artist'] = song.band.title
    if song.title != None:
        audio['title'] = song.title
    if song.album != None:
        audio['album'] = song.album

    try:
        audio.save()
    except:
        data['reason'] = design.unable_to_save_id3_tags
        return data

    # pick a path for the mp3 file. obscure the URL so that people can't steal songs
    song.mp3_file = os.path.join(
        obfuscated_url(song.band),
        clean_filename(song.displayString() + filename_appendix + '.mp3'))

    generate_waveform(song, mp3_tmp_handle.name, filename_appendix)

    # count mp3 against the band's size quota
    song.band.used_space += os.path.getsize(mp3_tmp_handle.name)

    # move mp3 file to storage
    move_to_storage(mp3_tmp_handle.name, song.mp3_file)

    song.band.save()
    data = {'success': True}
    return data
Пример #8
0
def handle_project_file(filename, user, song, filename_appendix=""):
    """
    creates the database entries necessary for filename as the project for song.
    moves filename to storage or deletes it if there is a problem.
    increments the band's used space. be sure to save song and song.band after calling.
    """
    _prefix, ext = os.path.splitext(filename)
    profile = user.get_profile()

    # handle zip files
    if ext.lower() == '.zip':
        studioExts = studio_extensions()
        song.studio = None

        def zipCallback(extracted_filename):
            _path, title = os.path.split(extracted_filename)
            _prefix, ext = os.path.splitext(extracted_filename)
            if ext[1:].lower() in studioExts:
                if song.studio is None:
                    handle_project_file(extracted_filename,
                                        user,
                                        song,
                                        filename_appendix=filename_appendix)
            else:
                handle_sample_file(extracted_filename, title, user, song.band)

        zip_walk(filename, zipCallback)
        os.remove(filename)
        return

    # read the project file with the daw
    source_file_title = song.displayString()
    profile_save_required = False
    try:
        dawProject = daw.load(filename)
        dawExt = dawProject.extension()

        # assign the correct studio
        try:
            song.studio = Studio.objects.get(identifier=dawProject.identifier)

            # assume the user owns the studio
            profile.studios.add(song.studio)
            profile_save_required = True
        except Studio.DoesNotExist:
            pass

        stuff = (
            (dawProject.generators(), PluginDepenency.GENERATOR),
            (dawProject.effects(), PluginDepenency.EFFECT),
        )
        for plugins, plugin_type in stuff:
            for plugin in plugins:
                # if it's an invalid name, ignore
                if plugin.strip() == '':
                    continue

                if plugin in IGNORED_PLUGINS:
                    continue

                # see if it already exists
                deps = PluginDepenency.objects.filter(title=plugin)
                if deps.count() == 0:
                    # create it
                    dep = PluginDepenency()
                    dep.title = plugin
                    dep.plugin_type = plugin_type
                    dep.save()
                else:
                    dep = deps[0]

                # add it as a dependency
                song.plugins.add(dep)

                # assume that the user owns this dependency
                if profile.assume_uploaded_plugins_owned:
                    profile.plugins.add(dep)
                    profile_save_required = True

        samples = dawProject.samples()
        for sample in samples:
            # if it's an invalid name, ignore
            if sample.strip() == '':
                continue

            _path, title = os.path.split(sample)

            # create the dependency
            dep = SampleDependency()
            dep.title = title
            dep.song = song

            # if the title matches anthing the user or band has already uploaded,
            # establish a link.
            existing_samples = UploadedSample.objects.filter(
                title=title).filter(Q(user=user) | Q(band=song.band))

            if existing_samples.count() > 0:
                # TODO: handle title ambiguity
                # copy the dependency to this song
                existing_sample = existing_samples[0]
                dep.uploaded_sample = existing_sample

            dep.save()

        if dawExt:
            source_file_title += filename_appendix + "." + dawExt

        usingDaw = True
    except daw.exceptions.LoadError:
        usingDaw = False
        # ok forget about processing it with the daw
        # add the extension from before
        source_file_title += filename_appendix + ext
    finally:
        if profile_save_required:
            profile.save()

    song.source_file = os.path.join(obfuscated_url(song.band),
                                    clean_filename(source_file_title))

    if usingDaw:
        out_handle = tempfile.NamedTemporaryFile(mode='r+b')
        dawProject.save(out_handle.name)

        # count it against the band's size quota
        song.band.used_space += os.path.getsize(out_handle.name)

        # move to storage
        import storage
        storage.engine.store(out_handle.name, song.source_file)
        out_handle.close()

        os.remove(filename)
    else:
        # count it against the band's size quota
        song.band.used_space += os.path.getsize(filename)
        # move to storage
        move_to_storage(filename, song.source_file)

    song.save()