- Abstraction work within the Music module.
This commit is contained in:
parent
086704cb5e
commit
9f8995cd25
|
@ -0,0 +1,87 @@
|
|||
import time
|
||||
from modules.music_player.music_objects.song import song
|
||||
from modules.music_player.music_objects.artist import artist
|
||||
from modules.music_player.music_objects.album import album
|
||||
|
||||
#############################################################
|
||||
# This is the backend for the regular MythMusic backend.
|
||||
# Information is pulled from the 'mythconverg' mysql db
|
||||
#############################################################
|
||||
class Backend:
|
||||
|
||||
def __init__(self, music_player):
|
||||
self.music_player = music_player
|
||||
self.dbMgr = music_player.dbMgr
|
||||
|
||||
#Returns a list of artist objects
|
||||
def get_artists(self):
|
||||
#Generate some SQL to retrieve videos that were in the final_file_list
|
||||
#Load the videos into the cover viewer
|
||||
sql = "SELECT * FROM music_artists"
|
||||
if self.music_player.glossMgr.debug: print "Music Artist SQL: " + sql
|
||||
|
||||
results = self.dbMgr.run_sql(sql)
|
||||
|
||||
#Check for null return
|
||||
if results == None:
|
||||
print "MusicPlayer: No connection to DB or no artists found in DB"
|
||||
return None
|
||||
|
||||
pixbuf = None
|
||||
artists = []
|
||||
#Else add the entries in
|
||||
for record in results:
|
||||
tempArtist = artist(self.music_player)
|
||||
tempArtist.import_from_mythObject(record)
|
||||
artists.append(tempArtist)
|
||||
#self.artistImageRow.add_object(tempArtist)
|
||||
time.sleep(0.01) #Arbitary sleep time to avoid CPU bound status
|
||||
|
||||
return artists
|
||||
|
||||
#Given an artistID, returns a list of albums for them
|
||||
def get_albums_by_artistID(self, id):
|
||||
#Generate some SQL
|
||||
sql = "SELECT * FROM music_albums where artist_id='%s'" % (str(id))
|
||||
if self.music_player.glossMgr.debug: print "Music Album SQL: " + sql
|
||||
|
||||
results = self.dbMgr.run_sql(sql)
|
||||
|
||||
#Check for null return
|
||||
if results == None:
|
||||
print "MusicPlayer: No connection to DB or no albums found with ID %s" % (str(id))
|
||||
return None
|
||||
|
||||
pixbuf = None
|
||||
artists = []
|
||||
#Else add the entries in
|
||||
for record in results:
|
||||
tempAlbum = album(self.music_player)
|
||||
tempAlbum.import_from_mythObject(record)
|
||||
artists.append(tempAlbum)
|
||||
#self.artistImageRow.add_object(tempArtist)
|
||||
return artists
|
||||
|
||||
#Given an albumID, returns a list of songs on the album
|
||||
def get_songs_by_albumID(self, id):
|
||||
#Generate some SQL
|
||||
sql = "SELECT * FROM music_songs where album_id='%s'" % (str(id))
|
||||
if self.music_player.glossMgr.debug: print "Music Song SQL: " + sql
|
||||
|
||||
results = self.dbMgr.run_sql(sql)
|
||||
|
||||
#Check for null return
|
||||
if results == None:
|
||||
print "MusicPlayer: No connection to DB or no songs found with ID %s" % (str(id))
|
||||
return None
|
||||
|
||||
pixbuf = None
|
||||
songs = []
|
||||
#Else add the entries in
|
||||
for record in results:
|
||||
tempSong = song(self.music_player)
|
||||
tempSong.import_from_mythObject(record)
|
||||
songs.append(tempSong)
|
||||
#self.artistImageRow.add_object(tempArtist)
|
||||
return songs
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
import time
|
||||
import thread
|
||||
import clutter
|
||||
from ui_elements.image_row import ImageRow
|
||||
from ui_elements.image_frame import ImageFrame
|
||||
|
||||
class MusicObjectRow(ImageRow):
|
||||
|
||||
def __init__(self, glossMgr, width, height, columns, music_player):
|
||||
ImageRow.__init__(self, glossMgr, width, height, columns)
|
||||
self.music_player = music_player
|
||||
|
||||
self.objectLibrary = []
|
||||
|
||||
def add_object(self, object):
|
||||
self.objectLibrary.append(object)
|
||||
|
||||
|
||||
def load_image_range(self, start, end, thread_data = None):
|
||||
|
||||
for i in range(start, end):
|
||||
object = self.objectLibrary[i]
|
||||
print "loading: " + object.name
|
||||
pixbuf = object.get_image()
|
||||
time.sleep(self.music_player.sleep_time)
|
||||
tmpImage = clutter.Texture()
|
||||
if pixbuf == object.PENDING_DOWNLOAD:
|
||||
object.connect("image-found", self.set_image_cb, object, tmpImage)
|
||||
elif not pixbuf is None:
|
||||
#tmpImage.set_pixbuf(pixbuf)
|
||||
tmpImage = ImageFrame(pixbuf, self.image_size)
|
||||
|
||||
|
||||
self.add_texture_group(tmpImage)
|
||||
|
||||
#clutter.threads_leave()
|
||||
print "Finished threads"
|
||||
|
||||
#Just a callback function to call 'load_image_range()' in a new thread
|
||||
def load_image_range_cb(self, timeline):
|
||||
thread.start_new_thread(self.load_image_range, (self.num_columns, len(self.objectLibrary)-1))
|
||||
|
||||
#A simple callback funtion to set the image of an artist/album after it has completed a download
|
||||
def set_image_cb(self, data, music_object, tmpImage):
|
||||
#if self.glossMgr.debug:
|
||||
print "Image for music_object '%s' downloaded" % (music_object.name)
|
||||
pixbuf = music_object.get_image()
|
||||
if not pixbuf is None:
|
||||
clutter.threads_init()
|
||||
tmpImage.set_pixbuf(pixbuf)
|
||||
clutter.threads_leave()
|
|
@ -13,4 +13,12 @@ class album:
|
|||
|
||||
except IndexError, e:
|
||||
print "Music_Player: Found difference in DB structure for albums. Attempting to continue."
|
||||
|
||||
|
||||
def get_image(self):
|
||||
#First way to get an image is via the songs on this album
|
||||
songs = self.music_player.backend.get_songs_by_albumID(self.albumID)
|
||||
|
||||
for song in songs:
|
||||
pixbuf = song.get_image_from_ID3()
|
||||
if not pixbuf is None:
|
||||
return pixbuf
|
|
@ -6,7 +6,6 @@ import thread
|
|||
from modules.music_player.music_objects.music_object import MusicObject
|
||||
|
||||
class artist(MusicObject):
|
||||
PENDING_DOWNLOAD = range(1)
|
||||
|
||||
artistID = None
|
||||
name = None
|
||||
|
|
|
@ -2,6 +2,7 @@ import gobject
|
|||
|
||||
# An abstract class that simply serves to help emit a common signal
|
||||
class MusicObject(gobject.GObject):
|
||||
PENDING_DOWNLOAD = range(1)
|
||||
|
||||
#Setup signals
|
||||
__gsignals__ = {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import eyeD3
|
||||
import os
|
||||
import pygtk
|
||||
import gtk
|
||||
|
||||
class song:
|
||||
filename = None
|
||||
|
@ -46,6 +48,8 @@ class song:
|
|||
def get_image(self):
|
||||
return self.get_image_from_ID3()
|
||||
|
||||
#Tries to retrieve an image (pixbuf) from a song
|
||||
#Returns None if nothing found
|
||||
def get_image_from_ID3(self):
|
||||
#Basic check first up to make sure the filename is set
|
||||
if self.filename is None:
|
||||
|
@ -74,6 +78,9 @@ class song:
|
|||
|
||||
print "Image Mine Type: " + str(img.mimeType)
|
||||
data = img.imageData
|
||||
return data
|
||||
loader = gtk.gdk.PixbufLoader()
|
||||
loader.write(pixbuf)
|
||||
loader.close()
|
||||
return loader.get_pixbuf()
|
||||
|
||||
|
||||
|
|
|
@ -2,16 +2,15 @@ import pygtk
|
|||
import gtk
|
||||
import clutter
|
||||
import thread, time
|
||||
from modules.music_player.music_objects.song import song
|
||||
from modules.music_player.music_objects.artist import artist
|
||||
from modules.music_player.music_objects.album import album
|
||||
from modules.music_player.backends.myth_music import Backend
|
||||
from modules.music_player.lastFM_interface import lastFM_interface
|
||||
from ui_elements.image_row import ImageRow
|
||||
from ui_elements.image_frame import ImageFrame
|
||||
from modules.music_player.music_object_row import MusicObjectRow
|
||||
|
||||
|
||||
class Module:
|
||||
title = "Music"
|
||||
num_columns = 6
|
||||
sleep_time = 0.2
|
||||
|
||||
def __init__(self, glossMgr, dbMgr):
|
||||
self.stage = glossMgr.get_stage()
|
||||
|
@ -22,7 +21,9 @@ class Module:
|
|||
self.artists = []
|
||||
self.songs = []
|
||||
|
||||
self.imageRow = ImageRow(self.glossMgr, self.stage.get_width(), 200, self.num_columns)
|
||||
self.backend = Backend(self)
|
||||
|
||||
self.artistImageRow = MusicObjectRow(self.glossMgr, self.stage.get_width(), 200, self.num_columns, self)
|
||||
|
||||
self.lastFM = lastFM_interface()
|
||||
self.base_dir = self.dbMgr.get_setting("MusicLocation")
|
||||
|
@ -31,8 +32,8 @@ class Module:
|
|||
|
||||
self.is_playing = False
|
||||
#self.load_albums()
|
||||
#self.load_artists()
|
||||
thread.start_new_thread(self.load_artists, ())
|
||||
self.artists = self.backend.get_artists()
|
||||
#thread.start_new_thread(self.load_artists, ())
|
||||
|
||||
|
||||
def setup_ui(self):
|
||||
|
@ -66,7 +67,9 @@ class Module:
|
|||
clutter.main_quit()
|
||||
|
||||
if (event.keyval == clutter.keysyms.Left) or (event.keyval == clutter.keysyms.Right):
|
||||
self.imageRow.input_queue.input(event)
|
||||
#calculate a period of time the loading threads should sleep for when a timline is in progress
|
||||
self.sleep_time = float(MusicObjectRow.frames) / float(MusicObjectRow.fps)
|
||||
self.artistImageRow.input_queue.input(event)
|
||||
|
||||
def begin(self, glossMgr):
|
||||
|
||||
|
@ -81,60 +84,25 @@ class Module:
|
|||
self.alpha = clutter.Alpha(self.timeline_backdrop, clutter.ramp_inc_func)
|
||||
self.backdrop_behaviour = clutter.BehaviourOpacity(opacity_start=0, opacity_end=255, alpha=self.alpha)
|
||||
self.backdrop_behaviour.apply(self.backdrop)
|
||||
|
||||
|
||||
#Load in the initial images:
|
||||
self.load_image_range(0, self.num_columns)
|
||||
self.artistImageRow.objectLibrary = self.artists
|
||||
self.artistImageRow.load_image_range(0, self.num_columns)
|
||||
|
||||
self.stage.add(self.imageRow)
|
||||
self.imageRow.set_opacity(0)
|
||||
self.imageRow.show()
|
||||
self.backdrop_behaviour.apply(self.imageRow)
|
||||
self.stage.add(self.artistImageRow)
|
||||
self.artistImageRow.set_opacity(0)
|
||||
self.artistImageRow.show()
|
||||
self.backdrop_behaviour.apply(self.artistImageRow)
|
||||
|
||||
self.timeline_backdrop.start()
|
||||
|
||||
#Load the rest of the images
|
||||
#thread.start_new_thread(self.load_image_range, (self.num_columns, len(self.artists)-1))
|
||||
self.timeline_backdrop.connect("completed", self.load_image_range_cb)
|
||||
self.timeline_backdrop.connect("completed", self.artistImageRow.load_image_range_cb)
|
||||
#self.load_image_range(self.num_columns, len(self.artists)-1)
|
||||
self.imageRow.select_first()
|
||||
self.artistImageRow.select_first()
|
||||
|
||||
#Just a callback function to call 'load_image_range()'
|
||||
def load_image_range_cb(self, timeline):
|
||||
#self.load_image_range(self.num_columns, len(self.artists)-1)
|
||||
#clutter.threads_enter()
|
||||
thread.start_new_thread(self.load_image_range, (self.num_columns, len(self.artists)-1))
|
||||
|
||||
def load_image_range(self, start, end, thread_data = None):
|
||||
|
||||
for i in range(start, end):
|
||||
artist = self.artists[i]
|
||||
print "loading: " + artist.name
|
||||
pixbuf = artist.get_image()
|
||||
if end > 6:
|
||||
time.sleep(0.5)
|
||||
tmpImage = clutter.Texture()
|
||||
if pixbuf == artist.PENDING_DOWNLOAD:
|
||||
artist.connect("image-found", self.set_image_cb, artist, tmpImage)
|
||||
elif not pixbuf is None:
|
||||
#tmpImage.set_pixbuf(pixbuf)
|
||||
tmpImage = ImageFrame(pixbuf, self.imageRow.image_size)
|
||||
|
||||
|
||||
self.imageRow.add_texture_group(tmpImage)
|
||||
|
||||
#clutter.threads_leave()
|
||||
print "Finished threads"
|
||||
|
||||
#A simple callback funtion to set the image of an artist/album after it has completed a download
|
||||
def set_image_cb(self, data, music_object, tmpImage):
|
||||
#if self.glossMgr.debug:
|
||||
print "Image for music_object '%s' downloaded" % (music_object.name)
|
||||
pixbuf = music_object.get_image()
|
||||
if not pixbuf is None:
|
||||
clutter.threads_init()
|
||||
tmpImage.set_pixbuf(pixbuf)
|
||||
clutter.threads_leave()
|
||||
|
||||
|
||||
def stop(self):
|
||||
pass
|
||||
|
@ -145,7 +113,7 @@ class Module:
|
|||
def unpause(self):
|
||||
pass
|
||||
|
||||
def load_albums(self):
|
||||
def load_songs(self):
|
||||
#Generate some SQL to retrieve videos that were in the final_file_list
|
||||
#Load the videos into the cover viewer
|
||||
sql = "SELECT * FROM music_songs" # WHERE filename IN ("
|
||||
|
@ -179,36 +147,4 @@ class Module:
|
|||
pixbuf = loader.get_pixbuf()
|
||||
self.tmpImage = clutter.Texture()
|
||||
self.tmpImage.set_pixbuf(pixbuf)
|
||||
|
||||
def load_artists(self):
|
||||
#Generate some SQL to retrieve videos that were in the final_file_list
|
||||
#Load the videos into the cover viewer
|
||||
sql = "SELECT * FROM music_artists" # WHERE filename IN ("
|
||||
if self.glossMgr.debug: print "Music Artist SQL: " + sql
|
||||
|
||||
results = self.dbMgr.run_sql(sql)
|
||||
|
||||
#Check for null return
|
||||
if results == None:
|
||||
print "MusicPlayer: No connection to DB or no artists found in DB"
|
||||
return None
|
||||
|
||||
pixbuf = None
|
||||
#Else add the entries in
|
||||
for record in results:
|
||||
tempArtist = artist(self)
|
||||
tempArtist.import_from_mythObject(record)
|
||||
self.artists.append(tempArtist)
|
||||
|
||||
"""
|
||||
if not tempArtist.get_image()is None:
|
||||
pixbuf = tempArtist.get_image()
|
||||
break
|
||||
"""
|
||||
#print filename
|
||||
#tempSong.set_file(filename)
|
||||
"""
|
||||
if not pixbuf is None:
|
||||
self.tmpImage = clutter.Texture()
|
||||
self.tmpImage.set_pixbuf(pixbuf)
|
||||
"""
|
|
@ -16,6 +16,8 @@ class ImageRow(clutter.Group):
|
|||
inactiveOpacity = 150
|
||||
images_size_percent = 0.90 #This is the percentage of the total group size that the covers will take
|
||||
|
||||
fps = 35
|
||||
frames = 25
|
||||
|
||||
def __init__(self, glossMgr, width, height, columns):
|
||||
clutter.Group.__init__(self)
|
||||
|
@ -97,7 +99,7 @@ class ImageRow(clutter.Group):
|
|||
|
||||
|
||||
def select_item(self, incomingItem, outgoingItem):
|
||||
self.timeline = clutter.Timeline(10,35)
|
||||
self.timeline = clutter.Timeline(self.frames, self.fps)
|
||||
alpha = clutter.Alpha(self.timeline, clutter.smoothstep_inc_func)
|
||||
self.input_queue.set_timeline(self.timeline)
|
||||
|
||||
|
@ -158,7 +160,7 @@ class ImageRow(clutter.Group):
|
|||
self.timeline.start()
|
||||
|
||||
def select_first(self):
|
||||
self.timeline = clutter.Timeline(20,80)
|
||||
self.timeline = clutter.Timeline(self.frames, self.fps)
|
||||
self.input_queue.set_timeline(self.timeline)
|
||||
|
||||
incomingItem = 0
|
||||
|
@ -181,7 +183,7 @@ class ImageRow(clutter.Group):
|
|||
if self.currentSelection is None:
|
||||
return
|
||||
|
||||
self.timeline = clutter.Timeline(10,35)
|
||||
self.timeline = clutter.Timeline(self.frames, self.fps)
|
||||
alpha = clutter.Alpha(self.timeline, clutter.smoothstep_inc_func)
|
||||
|
||||
self.behaviourOld_scale = clutter.BehaviourScale(x_scale_start=self.scaleFactor, y_scale_start=self.scaleFactor, x_scale_end=1, y_scale_end=1, alpha=alpha)
|
||||
|
|
Loading…
Reference in New Issue