new audioplayer

geo
Alexander Roidl 2 years ago
parent 31de55429d
commit 60ac20d90d

Binary file not shown.

@ -1,9 +1,12 @@
*{
font-family: "Helvetica"
font-family: "Helvetica";
box-sizing: border-box;
}
body{
background-color: #f1f1f1;
font-size: clamp(12px, 1.2vw, 25px);
box-sizing: border-box;
}
p{
@ -12,12 +15,27 @@ p{
a{
text-decoration: underline;
color: black;
color: inherit;
}
a:hover{
text-decoration: underline;
color: #0000FF;
text-decoration: inherit;
color: inherit;
}
audio{
width: 100%;
}
.navigation ul{
list-style-type: none;
padding: 0;
display: flex;
justify-content: right;
}
.navigation ul li{
padding: 0.5em;
}
#map {
@ -27,5 +45,162 @@ a:hover{
height: 100vh;
width: 100vw;
z-index: -1;
}
.locations_list{
width: 100%;
}
.locations_list .row{
display: flex;
justify-content: space-between;
border-bottom: 1px solid black;
}
.locations_list .row div:first-of-type {
width: 5%;
}
.locations_list .row div:last-of-type{
width: 10%;
min-width: 3rem;
}
.locations_list .row div{
width: 20%;
padding: 1em;
white-space: wrap;
overflow: hidden;
text-overflow: ellipsis;
}
.locations_list .row div audio{
width: 100%;
}
.locations_list .row .delete_btn{
text-decoration: none;
background-color: black;
color: white;
padding: 0.5em;
border-radius: 1em;
}
/* FROM */
.form-control{
width: 100%;
height: 20vh;
box-sizing: border-box;
}
#audio{
margin: 4em 0;
}
.record_controls{
display: flex;
justify-content: space-between;
}
.audio_btn{
font-size: 2em;
padding: 0.5em;
text-decoration: none;
background-color: black;
border-radius: 2em;
color: white;
margin: 2em 0;
display: block;
box-sizing: border-box;
min-width: 25%;
}
.audio_btn:hover{
color: white;
}
.stop_btn{
display: none;
flex-grow:1;
}
.record_btn .icon{
display: inline-block;
background-color: white;
width: 0.5em;
height: 0.5em;
border-radius: 100%;
margin-right: 0.5em;
}
.stop_btn .icon{
display: inline-block;
background-color: white;
width: 0.5em;
height: 0.5em;
margin-right: 0.5em;
}
.record_btn{
background-color: red;
flex-grow:1;
}
.play_btn{
display: none;
flex-grow: 1;
position: relative;
overflow: hidden;
}
.play_btn .icon_p{
display: inline-block;
position: relative;
top: 0px;
left: 3px;
border-style: solid;
border-width: 0.3em 0 0.3em 0.6em;
border-color: transparent transparent transparent white;
margin-right: 0.5em;
z-index: 99;
}
.play_btn .icon_b{
box-sizing: border-box;
position: relative;
display: inline-block;
/* transform: scale(var(--ggs,1)); */
width: 0.5em;
height: 0.5em;
border-left: 0.15em solid;
border-right: 0.15em solid;
margin-right: 0.5em;
z-index: 99;
}
.play_btn .text{
display: inline-block;
position: relative;
z-index: 99;
}
.play_btn .progress_bar{
display: block;
background-color: rgb(115, 115, 115);
position: absolute;
top: 0em;
left: 0em;
border-radius: 2em 2em 2em 2em;
height: 100%;
border-right: 1px solid white;
z-index: 0;
}
.redo_btn{
display: none;
}

@ -3,26 +3,7 @@
{% block main %}
<h1 class="page-header">About</h1>
<div style="width: 900px;">
<p class='about'>
XPPL is a project aimed at people who are studying the field of media culture, or as we like to call them: knowledge comrades.
<br>
<br>
This digital library gathers all the books and articles floating around on the shelves of the Piet Zwart Institute, and our hard drives and memory sticks, so that they can be shared, annotated and grouped together into stacks... Its web interface hosts a curated catalogue of books and articles, and its distributed architecture provides instances for uploading and downloading.
<br>
<br>
It starts at XPUB, but can go anywhere we want it to.
<br>
<br>
Are you interested in how this library works? Have a look at the source code in <a href= 'https://git.xpub.nl/xpub-lib/log.html'> our git. </a>
</p>
<h2> What's the deal with the stacks? </h2>
<p class='about'>
A stack is a number of books that are read at a certain point in time, alternating between them. They usually have a topic in common, or follow a certain study path that can bring you to a point of knowledge. Rather than a bookshelf, where books are lined up and often forgotten, the stack on your table/nightstand/toilet consists of books prone to be opened and reopened at any time.
</p>
<h2>Who's behind this?</h2>
<p class='about'>
We're Angeliki, Alex, Alice, Joca, Natasha and Zalán, helped and supported by Femke, Aymeric, Michael, Steve, Andre, Leslie and many more. XPUB is a study path within the Piet Zwart Institute masters program.
</p>
<p>About</p>
</div>
{% endblock %}

@ -3,7 +3,7 @@
{% block main %}
{% from "_formhelpers.html" import render_field %}
<h1 class="page-header">Add Message</h1>
<h1 class="page-header">Add Audio</h1>
{% with messages = get_flashed_messages() %}
{% if messages %}
<div class="alert alert-danger">
@ -20,18 +20,24 @@
{{ form.csrf_token }}
<input type="hidden" name="longitude" value="{{ longitude }}" />
<input type="hidden" name="latitude" value="{{ latitude }}" />
<div style="width: 40%;">
message: {{ form.message(cols="45", rows="10", class="form-control") }}
</div>
<div id="audio">
<a onclick="record_audio()" href="#">record</a>
<a onclick="stop_audio()" href="#">stop</a>
<span id="seconds_rec"></span><span> seconds</span>
<div class="record_controls">
<a class="record_btn audio_btn" id="record_btn" onclick="record_audio()" href="#"><span class="icon"></span>record</a>
<a class="stop_btn audio_btn" id="stop_btn" onclick="stop_audio()" href="#"><span class="icon"></span>stop</a>
<a class="play_btn audio_btn" id="play_btn" onclick="play_audio()" href="#"><span class="progress_bar"></span><span class="icon_p"></span>play</a>
<a class="redo_btn audio_btn" id="redo_btn" onclick="redo_audio()" href="#"></span>redo</a>
</div>
<div id="audio-player-container"></div>
</div>
<input type="file" name="file" id="uploadedFile" accept="audio/*"><br>
<input hidden="true" type="file" name="file" id="uploadedFile" accept="audio/*"><br>
<div style="width: 100%;">
message: <br>{{ form.message(class="form-control") }}
</div>
<button type="submit">Submit</button>
@ -48,26 +54,32 @@
var mediaRecorder;
var seconds_rec = 0;
var seconds_int;
var audio;
var state = "empty";
function record_audio(){
seconds_int = setInterval(
function () {
document.getElementById("seconds_rec").innerHTML = seconds_rec;
seconds_rec += 1;
}, 1000);
if(state == "empty"){
navigator.mediaDevices.getUserMedia({ audio: true })
.then(stream => {
mediaRecorder = new MediaRecorder(stream);
mediaRecorder.start();
state = "recording";
document.getElementById('stop_btn').style.display = 'block'
seconds_int = setInterval(
function () {
document.getElementById("record_btn").innerHTML = seconds_rec + " s";
seconds_rec += 1;
}, 1000);
const audioChunks = [];
mediaRecorder.addEventListener("dataavailable", event => {
audioChunks.push(event.data);
});
mediaRecorder.addEventListener("stop", () => {
const audioBlob = new Blob(audioChunks);
const audioBlob = new Blob(audioChunks, {type: 'audio/mpeg'});
const audioUrl = URL.createObjectURL(audioBlob);
var sound = document.createElement('audio');
sound.id = 'audio-player';
@ -75,32 +87,68 @@ navigator.mediaDevices.getUserMedia({ audio: true })
sound.src = audioUrl;
console.log(audioUrl)
sound.type = 'audio/mpeg';
document.getElementById("audio-player-container").innerHTML = sound.outerHTML;
// document.getElementById("audio-player-container").innerHTML = sound.outerHTML;
audio = new Audio(audioUrl);
audio.addEventListener("ended", function(){
audio.currentTime = 0;
document.getElementById("play_btn").innerHTML = '<span class="icon_p"></span>play'
});
audio.addEventListener("timeupdate", function() {
var currentTime = audio.currentTime;
var duration = audio.duration;
$('.progress_bar').stop(true,true).animate({'width':(currentTime +.25)/duration*100+'%'},0,'linear');
});
document.getElementById('play_btn').style.display = 'block'
document.getElementById('redo_btn').style.display = 'block'
document.getElementById('stop_btn').style.display = 'none'
document.getElementById("record_btn").innerHTML = "recording…";
document.getElementById('record_btn').style.display = 'none'
const audio = new Audio(audioUrl);
//audio.play();
let file = new File([audioBlob], "audio.mp3",{type:"audio/mpeg"});
let container = new DataTransfer();
container.items.add(file);
document.getElementById("uploadedFile").files = container.files;
//const audio = new Audio(audioUrl);
//audio.play();
});
setTimeout(() => {
stop_audio()
}, 1000 * 60);
});
}
}
function stop_audio(){
clearInterval(seconds_int);
mediaRecorder.stop();
}
function redo_audio(){
state = "empty";
seconds_rec = 0;
document.getElementById('play_btn').style.display = 'none'
document.getElementById('redo_btn').style.display = 'none'
document.getElementById('stop_btn').style.display = 'block'
document.getElementById('record_btn').style.display = 'block'
record_audio()
}
function play_audio(){
if(audio.paused){
audio.play();
document.getElementById("play_btn").innerHTML = '</span><span class="icon_b"></span><span class="text">pause</span><span class="progress_bar">'
}
else{
audio.pause();
document.getElementById("play_btn").innerHTML = '</span><span class="icon_p"></span><span class="text">play</span><span class="progress_bar">'
}
}
</script>

@ -1,8 +1,8 @@
<nav class="navigation">
<ul>
<li><a href="{{ url_for('home') }}">Home</a></li>
<li><a href="{{ url_for('list_locations') }}">List</a></li>
<li><a href="{{ url_for('about') }}">About</a></li>
</ul>
<div class="clearfix"></div>
</nav>

@ -7,22 +7,11 @@
<button id="store_location" onclick="store_location()">store my position</button>
<button id="add_text" onclick="add_text()">add message</button>
<button id="add_audio" onclick="add_audio()">add audio</button>
<br><br><br>
{% for location in locations %}
<div >{{location.id}}: {{location.longitude}}, {{location.latitude}} {{location.message if location.loc_type == "message"}}
{% if location.loc_type == "audio" %}
<audio id="audio-player" controls="" src="uploads/{{location.audio}}"></audio>
{% endif %}
<a href="location/{{location.id}}/delete">delete</a></div>
{% endfor %}
</div>
<!-- HEADING DIRECTION https://stackoverflow.com/questions/46033649/heading-javascript-geolocation -->
<!-- COMPAS CROSS DEVICE https://stackoverflow.com/questions/16048514/can-i-use-javascript-to-get-the-compass-heading-for-ios-and-android-->
{% endblock main %}
{% block js %}
@ -41,21 +30,16 @@
attributionControl:false,
scrollWheelZoom: false,
zoom: 2000
}).setView([48.505, 1.09], 10);
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
zoom:2,
attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
}).addTo(map);
}).setView([48.505, 1.09], 16);
// L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
// maxZoom: 19,
// zoom:2,
// attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
// }).addTo(map);
locations.forEach(function (item, index) {
try {
var circle = L.circle([item.latitude, item.longitude], {
color: 'red',

@ -0,0 +1,33 @@
{% extends "base.html" %}
{% block main %}
<div id="home_content">
<h2 class="header">Index</h2>
<div class="locations_list">
{% for location in locations %}
<div class="row">
<div>{{location.id}}</div>
<div>{{location.longitude}}, {{location.latitude}}</div>
<div>{{location.message if location.loc_type == "message"}}</div>
<div>
{% if location.loc_type == "audio" %}
<audio id="audio-player" controls="" src="uploads/{{location.audio}}"></audio>
{% endif %}
</div>
<div>
<a class="delete_btn" href="location/{{location.id}}/delete">delete</a>
</div>
</div>
{% endfor %}
</div>
</div>
{% endblock main %}
{% block js %}
<script>
</script>
{% endblock js %}

@ -52,20 +52,20 @@ def uploaded_file(filename):
@app.route('/', methods= ['POST','GET'])
def home():
username = 'librarian'
server = request.host
if request.environ.get('HTTP_X_FORWARDED_FOR') is None:
client =request.environ['REMOTE_ADDR']
else:
client = request.environ['HTTP_X_FORWARDED_FOR']
locations = db.session.query(Location).all()
serialized = [location_schema.dump(location) for location in locations]
return render_template('home.html',domain=DOMAIN, server=server, locations = locations, data_locations = serialized)
@app.route('/listlocations', methods= ['POST','GET'])
def list_locations():
locations = db.session.query(Location).all()
serialized = [location_schema.dump(location) for location in locations]
print(locations)
return render_template('list.html',domain=DOMAIN, locations = locations, data_locations = serialized)
return render_template('home.html',domain=DOMAIN, server=server, locations = locations, data_locations = serialized)
@app.route('/hello/<name>')
def hello(name):
@ -138,7 +138,10 @@ def addaudio():
return render_template('addaudio.html', form=upload_form, longitude=longitude, latitude=latitude)
@app.route('/about/')
def about():
"""Render the website's about page."""
return render_template('about.html')
@app.route('/location/<int:id>/delete', methods=['POST', 'GET'])
def delete_location(id):

@ -1,3 +1,3 @@
#! /usr/bin/env python
from app import app, socketio
socketio.run(app,host="0.0.0.0", port=8080)
socketio.run(app,host="0.0.0.0", port=8080, ssl_context='adhoc')

Loading…
Cancel
Save