Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions music_player/__manifest__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
{
'name': "musicPlayer",
'name': "MusicPlayer",

'summary': """
Short (1 phrase/line) summary of the module's purpose, used as
Expand Down Expand Up @@ -32,6 +32,6 @@
'demo': [
'demo/demo.xml',
],
'installable': True,
'application': True,
'application':True,
'installable':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.
32 changes: 13 additions & 19 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"])
@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')

# A controller to play song from the audio
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
Expand Up @@ -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.
9 changes: 5 additions & 4 deletions music_player/models/player.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ class music_player(models.Model):
_name = 'music_player.music_player'
_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

name = fields.Char(string='Song Name')
filename = fields.Char(string='File Name')
url = fields.Char(compute='_compute_url')

# @api.depends('')
def _compute_url(self):
for record in self:
record.url = record.get_base_url() + '/music/' + str(record.id)
181 changes: 97 additions & 84 deletions music_player/static/app.js
Original file line number Diff line number Diff line change
@@ -1,129 +1,142 @@
/** @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) {
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 {
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) {
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) {

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

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 };
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>
<MusicList 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 = {MusicList};
}

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