Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Completed Music Player using owl
Browse files Browse the repository at this point in the history
arpa-odoo committed Mar 17, 2023
1 parent 15f15a8 commit 20cec9e
Showing 20 changed files with 492 additions and 426 deletions.
16 changes: 10 additions & 6 deletions music_player/__manifest__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
# -*- coding: utf-8 -*-
{
'name': "musicPlayer",
'name': "MusicPlayer",

'summary': """
Short (1 phrase/line) summary of the module's purpose, used as
subtitle on modules listing or apps.openerp.com""",
'summary': " ",
'License':'LGPL-3',

'description': """
Long description of module's purpose
@@ -28,10 +27,15 @@
'views/views.xml',
'views/templates.xml',
],
'assets':{
'web.assets_backend':[
'music_player/static/app.js'
],
},
# only loaded in demonstration mode
'demo': [
'demo/demo.xml',
],
'installable': True,
'application': True,
'installable':True,
'application':True,
}
Binary file removed music_player/__pycache__/__init__.cpython-310.pyc
Binary file not shown.
Binary file added music_player/__pycache__/__init__.cpython-38.pyc
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
40 changes: 17 additions & 23 deletions music_player/controllers/controllers.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,23 @@
# -*- coding: utf-8 -*-
import json
#-- coding: utf-8 --
from odoo import http
from odoo.http import Response
from odoo.modules.module import get_module_resource
import json

class MusicPlayer(http.Controller):
@http.route('/music', auth='public')
def index(self, **kw):
return http.request.render('music_player.music_template')

@http.route('/music/search', auth='public', type="http", methods=["GET"])
def search(self, **kw):
# Retrieve the song name from the search query
song_name = kw.get('song_name')
# you will be facing you are not allowed to acces this model ---> add to manifest the csv file. remove group for now
musics = http.request.env['music_player.music_player'].search_read([('name', 'ilike', song_name)],fields={"name", "url"})
if not musics:
musics = "Song not Found"

return Response(json.dumps({'result': musics}), content_type='application/json')
@http.route('/music', auth='public')
def index(self, **kw):
return http.request.render('music_player.music_template')

# A controller to play song from the audio
@http.route('/music/search', auth='public',type="http",methods=['GET'])
def search(self, **kw):
song_name = kw.get('song_name')
songs = http.request.env['music_player.music_player'].search_read([('name','ilike',song_name)],fields=["name","url"])
if not songs:
songs = "Song not found."
return http.Response(json.dumps({'result':songs}),content_type='application/json')

@http.route('/music/<model("music_player.music_player"):music>', type='http', auth="public", methods=["GET"])
def load(self, music, **kw):
music_file_path = get_module_resource('music_player', 'static/songs', music.filename)
file = open(music_file_path, 'rb').read()
return file
@http.route('/music/<model("music_player.music_player"):music>',type="http",auth="public",methods=['GET'])
def load(self,music,**kw):
music_file_path = get_module_resource('music_player','static/songs',music.filename)
file = open(music_file_path,'rb').read()
return file
2 changes: 1 addition & 1 deletion music_player/demo/demo.xml
Original file line number Diff line number Diff line change
@@ -33,4 +33,4 @@
<field name="name">Temp-song-3</field>
<field name="filename">Temp-song-3.mp3</field>
</record>
</odoo>
</odoo>
Binary file not shown.
Binary file not shown.
Binary file removed music_player/models/__pycache__/models.cpython-310.pyc
Binary file not shown.
Binary file not shown.
Binary file removed music_player/models/__pycache__/player.cpython-310.pyc
Binary file not shown.
Binary file not shown.
8 changes: 4 additions & 4 deletions music_player/models/player.py
Original file line number Diff line number Diff line change
@@ -8,9 +8,9 @@ class music_player(models.Model):
_description = 'music_player.music_player'

name = fields.Char('Song Name')
filename = fields.Char("File name")
url = fields.Char(compute="_compute_url") # for a computed url
filename = fields.Char('File Name')
url = fields.Char( compute ="_compute_url")

def _compute_url(self):
for record in self:
record.url = record.get_base_url() + '/music/' + str(record.id)
record.url = record.get_base_url() + '/music/' + str(record.id)
189 changes: 105 additions & 84 deletions music_player/static/app.js
Original file line number Diff line number Diff line change
@@ -1,129 +1,150 @@
/** @odoo-module**/

const { Component, xml, mount, setup, useState } = owl;
const { Component,xml,mount,useState,onWillStart } = owl;

let audio = '';
let audio='';
class Player extends Component {
static template = xml`
<div style="position:absolute;bottom:0px">
<h2 id="song-title">Song Title</h2>
<div>
<button id="pause-button" t-on-click="pauseThisSong">Pause</button>
<button id="play_btn" t-on-click="playThisSong">Play</button>
<button id="play-button" t-on-click="playThisSong">Play</button>
<button id="stop-button" t-on-click="stopThisSong">Stop</button>
</div>
</div>`;

playThisSong() {
if (!audio) {
return;
}
audio.play();
}
pauseThisSong() {
if (!audio) {
return;
}
audio.pause();
}
stopThisSong() {
if (!audio) {
return;
}
audio.pause();
audio.currentTime = 0;
</div>
`;
playThisSong(){
if(!audio){
return;
}
audio.play();
}
pauseThisSong(){
if(!audio){
return;
}
audio.pause();
}
stopThisSong(){
if(!audio){
return;
}
audio.pause();
audio.currentTime=0;
}
}

// class PlayList extends Component {
// static template = xml`
// <div style="float:right">
class PlayList extends Component {
static template = xml`
<div id="PlayList" style="float:right">
<h2>Playlist</h2>
<t t-if="props.playData[0]">
<t t-foreach="props.playData" t-as="song" t-key="song.id">
<p><t t-out="song.name"/></p>
<button t-att-value="song.url" t-on-click="removeSongFromPlayList">Remove from playlist</button>
<button t-att-value="song.url" t-on-click="playSong">Play Song</button>
</t>
</t>
</div>
`;

// </div>
// `;
removeSongFromPlayList(ev) {
const selectedSongUrl = ev.target.getAttribute('value');
const selectedSong = this.props.playData.findIndex(song => song.url===selectedSongUrl);
this.props.playData.splice(selectedSong,1);
}

// }
playSong(ev) {
if (audio) {
audio.pause();
audio.currentTime=0;
}
const selectedSongUrl = ev.target.getAttribute('value');
const selectedSong = this.props.playData.find(song => song.url===selectedSongUrl);
document.getElementById("song-title").textContent = selectedSong.name;
audio = new Audio(selectedSongUrl);
audio.play();
}
}

class MusicList extends Component {
class List extends Component {
static template = xml`
<div id="MusicList" style="float:left">
<t t-if="props.searchData[0] and props.searchData[0] !== 'Song not Found'">
<h2>List of Songs</h2>
<t t-foreach="props.searchData[0]" t-as="song" t-key="song.id">
<p><t t-out="song.name"/></p>
<button t-att-value="song.url" t-on-click="addSongToPlaylist">Add to playlist</button>
<button t-att-value="song.url" t-on-click="playSong">Play song</button>
</t>
</t>
<Player/>
<t t-if="props.searchData[0] and props.searchData[0] !== 'Song not found.'">
<h2>List of Songs</h2>
<t t-foreach="props.searchData[0]" t-as="song" t-key="song.id">
<p><t t-out="song.name"/></p>
<button t-att-value="song.url" t-on-click="addSongToPlaylist">Add to playlist</button>
<button t-att-value="song.url" t-on-click="playSong">Play Song</button>
</t>
</t>
<Player/>
</div>
`;
`;

addSongToPlaylist () {
//TAsk:
// add Playlist component as the child of root component and when addSongToPlaylist method is called update the
//PlayList component template with the song thats added.
// hint use callback method as which update the props u are passing to PlayList component.
playSong(ev) {
if (audio) {
audio.pause();
audio.currentTime=0;
}
const selectedSongUrl = ev.target.getAttribute('value');
const selectedSong = this.props.searchData[0].find(song => song.url===selectedSongUrl);
document.getElementById("song-title").textContent = selectedSong.name;
audio = new Audio(selectedSongUrl);
audio.play();
}

addSongToPlaylist(ev) {

playSong(ev) {
// in case a audio is already playing stop it to play another.
if (audio) {
audio.pause();
audio.currentTime = 0;
}
const selectedSongUrl = ev.target.getAttribute('value');
const selectedSong = this.props.searchData[0].find(song => song.url === selectedSongUrl);
document.getElementById('song-title').textContent = selectedSong.name;
audio = new Audio(selectedSongUrl);
audio.play();
}
static props = ['searchData'];

static components = { Player };
const selectedSongUrl = ev.target.getAttribute('value');
const selectedSong = this.props.searchData[0].find(song => song.url===selectedSongUrl);
this.props.addToPlayList(selectedSong);
}

static components = {Player};
}

class Search extends Component {
static template = xml `
<div style="text-align:center">
<input type="text" id="searchSong" placeholder="Search a music" value="Akon"/>
static template = xml`
<div style="text-align:center">
<input type="text" id="searchSong" placeholder="Search Music" value="Akon"/>
<button t-on-click="getMusic" id="SearchButton">Search</button>
<MusicList searchData="searchData"/>
</div>
<List searchData="searchData" addToPlayList="props.addToPlayList" playData="props.playData"/>
</div>
`;

setup() {
this.searchData = useState([]);
}

async getMusic() {
const findSong = document.getElementById('searchSong').value;
const findSong = document.getElementById("searchSong").value;
const response = await fetch(`/music/search?song_name=${findSong}`);
const {result : newData}= await response.json();
this.searchData.pop(); // add pop to remove previously searched data.
const {result: newData} = await response.json();
this.searchData.push(newData);
}

static components = { MusicList }
static components = {List};
}

class Root extends Component { // import from owl
// import from owl
static template = xml `
<style>
body {
margin: 0;
padding: 0;
height: 100vh;
}
</style>
<div id="Container" style="position:relative;height:100%">
<Search/>
class Root extends Component {
static template = xml`
<div>
<Search addToPlayList="this.addToPlayList" playData="playData"/>
<PlayList playData="playData"/>
</div>
`;

static components = { Search };
setup() {
this.playData = useState([]);
}

addToPlayList(song) {
this.playData.push(song);
}
static components = {Search,PlayList};
}

window.onload = function() {
mount(Root, document.body);
mount(Root,document.body);
};
Loading

0 comments on commit 20cec9e

Please sign in to comment.