Search code examples
pythonhtmlflaskgnuradio

play audio file saved in local drive via Python Flask webserver


When I navigate to my local disk and pick the audio .wav (or any other audio type) file and hit submit I don't get the audio output.

I was thinking of writing an "if statement" that tells my program when the chosen file is assigned to the variable "filename" then reload program with the assigned file/link.

I did some attempts to such if statement but failed due to lack of coding skills.

P.S. I mentioned the "if statement" workaround because I assumed that's the solution to my problem, otherwise I realize that I could be 200% wrong.

Please, help me if you can. Thanks.

My code:

from __future__ import print_function
from gnuradio import analog
from gnuradio import audio
from gnuradio import blocks
from gnuradio import eng_notation
from gnuradio import gr
from gnuradio.eng_option import eng_option
from gnuradio.filter import firdes
from optparse import OptionParser


class TopBlock22(gr.top_block): 


    def getfile(self, filename):

        gr.top_block.__init__(self, "Top Block 22")

        print('[TopBlock22] getfile: filename:', filename)

        filename = filename.encode('utf-8') 

        self.blocks_file_source_0 = blocks.file_source(gr.sizeof_float*1, filename, True)
        self.audio_sink = audio.sink(32000, '', True)

        ##################################################
        # Connections
        ##################################################
        self.connect((self.blocks_file_source_0, 0), (self.audio_sink, 0))


# -----------------------------------------------------------------------------

from flask import Flask, flash, request, redirect, jsonify, render_template_string


app = Flask(__name__)


tb = TopBlock22()
tb.start()


@app.route("/")
def index():
    args_filename = request.args.get('filename', '')


    return render_template_string('''<!DOCTYPE html>
<html>


<body>

<!-- Previous filename: {{ filename }} -->
<form action="getfile" method="POST" enctype="multipart/form-data">
    Project file path: <input type="file" name="file"><br>
    <input type="submit" value="Submit">
</form>



</body>
</html>''', filename=args_filename)


@app.route('/getfile', methods=['GET','POST'])
def getfile():


    result = request.files.get('file')
    print('[/getfile] result:', result.filename)

    if result:

        result.save(result.filename) 

        tb.getfile(result.filename)



    return redirect('/')



if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=True)

Traceback output (No error:

 * Serving Flask app "app" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: on
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 138-727-058
127.0.0.1 - - [23/Aug/2019 13:36:47] "GET / HTTP/1.1" 200 -
[/getfile] result: song.wav
[TopBlock22] getfile: filename: song.wav
gr::log :INFO: audio source - Audio sink arch: alsa
127.0.0.1 - - [23/Aug/2019 13:36:52] "POST /getfile HTTP/1.1" 302 -
127.0.0.1 - - [23/Aug/2019 13:36:52] "GET / HTTP/1.1" 200 -

Solution

  • All examples don't use Flask to easier test problem.


    To hear sound from file I have to run getfile() before start()

    from __future__ import print_function
    from gnuradio import gr
    from gnuradio import audio
    from gnuradio import blocks
    
    
    class TopBlock22(gr.top_block): 
    
        #def __init__(self):
        #    gr.top_block.__init__(self, "Top Block 22")
    
        def getfile(self, filename):
            print('[TopBlock22] getfile: filename:', filename)
    
            filename = filename.encode('utf-8') 
    
            self.blocks_file_source_0 = blocks.file_source(gr.sizeof_float*1, filename, True)
            self.audio_sink = audio.sink(32000, '', True)
    
            self.connect((self.blocks_file_source_0, 0), (self.audio_sink, 0))
    
    # -----------------------------------------------------------------------------
    
    tb = TopBlock22()
    
    tb.getfile('song.wav')
    tb.start()
    
    tb.wait()
    

    To use getfile() after start() and hear sound it has to stop() and start() it again.

    from __future__ import print_function
    from gnuradio import gr
    from gnuradio import audio
    from gnuradio import blocks
    
    
    class TopBlock22(gr.top_block): 
    
        #def __init__(self):
        #    gr.top_block.__init__(self, "Top Block 22")
    
        def getfile(self, filename):
            print('[TopBlock22] getfile: filename:', filename)
    
            filename = filename.encode('utf-8') 
    
            self.blocks_file_source_0 = blocks.file_source(gr.sizeof_float*1, filename, True)
            self.audio_sink = audio.sink(32000, '', True)
    
            self.connect((self.blocks_file_source_0, 0), (self.audio_sink, 0))
    
            self.stop()
            self.start()
    
    # -----------------------------------------------------------------------------
    
    tb = TopBlock22()
    
    tb.start()
    
    tb.getfile('song.wav')
    
    tb.wait()
    

    Or it has to use lock(), unlock()

    from __future__ import print_function
    from gnuradio import gr
    from gnuradio import audio
    from gnuradio import blocks
    
    
    class TopBlock22(gr.top_block): 
    
        #def __init__(self):
        #    gr.top_block.__init__(self, "Top Block 22")
    
        def getfile(self, filename):
            print('[TopBlock22] getfile: filename:', filename)
    
            filename = filename.encode('utf-8') 
    
            self.blocks_file_source_0 = blocks.file_source(gr.sizeof_float*1, filename, True)
            self.audio_sink = audio.sink(32000, '', True)
    
            self.lock()
            self.connect((self.blocks_file_source_0, 0), (self.audio_sink, 0))
            self.unlock()
    
    # -----------------------------------------------------------------------------
    
    tb = TopBlock22()
    
    tb.start()
    
    tb.getfile('song.wav')
    
    tb.wait()
    

    But this will not disconnect previous sound when you load new file. It would have to remeber if other file was loaded and use disconnect() to stop previous sound.

    from __future__ import print_function
    from gnuradio import gr
    from gnuradio import audio
    from gnuradio import blocks
    
    
    class TopBlock22(gr.top_block): 
    
        def __init__(self):
            gr.top_block.__init__(self, "Top Block 22")
    
            # at star file is not loaded and not connected
            self.file_source_connected = False
    
        def getfile(self, filename):
            print('[TopBlock22] getfile: filename:', filename)
    
            filename = filename.encode('utf-8') 
    
            ##################################################
            # Connections
            ##################################################
    
            self.lock()
    
            # disconnect previous file
            if self.file_source_connected:
                self.disconnect((self.blocks_file_source_0, 0), (self.audio_sink, 0))
    
            # use new file
            self.blocks_file_source_0 = blocks.file_source(gr.sizeof_float*1, filename, True)
            self.audio_sink = audio.sink(32000, '', True)
    
            self.connect((self.blocks_file_source_0, 0), (self.audio_sink, 0))
    
            self.unlock()
    
            # remember that file is connected
            self.file_source_connected = True
    
    
    # -----------------------------------------------------------------------------
    import time
    
    tb = TopBlock22()
    tb.start()
    
    tb.getfile('song.wav') # use one file 
    time.sleep(3)
    tb.getfile('another_song.wav') # use another file later
    
    tb.wait()