Save settings

master
Muges 11 years ago
parent 8376dd6ed4
commit 380e610ace
  1. 19
      ambientsounds.py
  2. 7
      readme.md
  3. 47
      sounds.py
  4. 123
      ui.py

@ -26,14 +26,17 @@ import traceback
from ui import UI
from sounds import MasterVolume
ui = UI()
if __name__ == "__main__":
ui = UI()
try:
ui.start()
try:
ui.start()
master = MasterVolume()
master = MasterVolume()
ui.run(master)
except:
ui.end()
traceback.print_exc()
ui.run(master)
except SystemExit:
pass
except:
ui.end()
traceback.print_exc()

@ -11,10 +11,11 @@ The program depends on :
- [pygame](http://www.pygame.org/news.html) to play the tracks
- [mutagen](https://bitbucket.org/lazka/mutagen) to read the ogg vorbis tags
## Manual
## Shortcuts
- `Up`/`Down` to select a track or a preset
- `Left`/`Right` to change the volume of the selected track
- `Up` and `Down` to select an item
- `Left` and `Right` to change the volume of the selected track
- `s` to save the current settings
- `q` to quit
## Sounds

@ -108,7 +108,7 @@ class Sound(Volume):
if self.sound == None:
# Load the sound and play it
self.sound = pygame.mixer.Sound(self.filename)
self.sound.play(-1)
self.sound.play(-1, 0, 2000)
# Set the volume
self.sound.set_volume((self.mastervolume.get_volume()*self.get_volume())/10000.)
@ -117,17 +117,16 @@ class Preset:
"""
Stores volumes for each track
"""
def __init__(self, filename, master):
def __init__(self, master, filename):
"""
Initialise (without reading or creating it) a preset that
Initialize (without reading or creating it) a preset that
will be stored in the file `filename`. master is a reference to
a mastervolume object.
"""
self.filename = filename
self.name = os.path.splitext(os.path.basename(filename))[0]
self.master = master
self.filename = filename
self.volumes = {}
def apply(self):
"""
Apply the preset
@ -146,7 +145,8 @@ class Preset:
for sound in self.master.get_sounds():
volume = sound.get_volume()
if volume == 0:
self.volumes.pop(sound.name)
if self.volumes.has_key(sound.name):
self.volumes.pop(sound.name)
else:
self.volumes[sound.name] = volume
@ -172,30 +172,33 @@ class MasterVolume(Volume):
"""
# Configuration directories
confdirs = [os.path.dirname(os.path.realpath(__file__)),
"/usr/share/ambientsounds/",
os.path.expanduser("~/.config/ambientsounds/")]
sounddirs = [os.path.join(os.path.dirname(os.path.realpath(__file__)), "sounds"),
"/usr/share/ambientsounds/sounds",
os.path.expanduser("~/.config/ambientsounds/sounds")]
def __init__(self):
Volume.__init__(self, "Volume", 100)
# Get the sounds
self.sounds = []
for dirname in self.confdirs:
sounddir = os.path.join(dirname, "sounds")
for sounddir in self.sounddirs:
if os.path.isdir(sounddir):
for filename in os.listdir(sounddir):
self.sounds.append(Sound(os.path.join(sounddir, filename), self))
pygame.mixer.set_num_channels(len(self.sounds))
# Get the presets
self.presets = []
for dirname in self.confdirs:
presetdir = os.path.join(dirname, "presets")
if os.path.isdir(presetdir):
for filename in os.listdir(presetdir):
self.presets.append(Preset(os.path.join(presetdir, filename), self))
# Get the preset
self.presetpath = os.path.expanduser("~/.config/ambientsounds/preset.json")
if os.path.isfile(self.presetpath):
preset = Preset(self, self.presetpath)
preset.read()
preset.apply()
def save_preset(self):
preset = Preset(self, self.presetpath)
preset.save()
preset.write()
def get_sounds(self):
"""
@ -209,12 +212,6 @@ class MasterVolume(Volume):
"""
return self.sounds[i]
def get_presets(self):
"""
Returns the list of available presets
"""
return self.presets
def _set_volume(self):
"""
Update the volume of all the sounds

123
ui.py

@ -24,6 +24,7 @@
# SOFTWARE.
import curses
import sys
class OneLineWidget:
"""
@ -48,12 +49,12 @@ class OneLineWidget:
"""
raise NotImplementedError()
def on_key(self, c):
def on_key(self, c, ui):
"""
Method called when the user types the key c and the widget is
selected.
"""
return
return False
class VolumeWidget(OneLineWidget):
"""
@ -95,14 +96,17 @@ class VolumeWidget(OneLineWidget):
self.parent.addstr(y, slidex, "#"*slidewleft)
self.parent.addstr(y, slidex+slidewleft, "-"*slidewright)
def on_key(self, c):
def on_key(self, c, ui):
if c == curses.KEY_LEFT:
# Increase the volume
self.volume.inc_volume(-1)
elif c == curses.KEY_RIGHT:
# Decrease the volume
self.volume.inc_volume(1)
else:
return False
return True
class ScrollableList:
"""
Object representing a list of OneLineWidgets that can be browsed and
@ -125,7 +129,7 @@ class ScrollableList:
def get_selection(self):
try:
return self.widgets[self.selection]
except KeyError:
except IndexError:
return None
def set_selection(self, selection):
@ -190,7 +194,7 @@ class ScrollableList:
width = sright-sleft
self.pad.clear()
self.pad.resize(self.height, width)
self.pad.resize(max(1, self.height), max(1, width))
# Draw each widget
y = 0
@ -202,7 +206,7 @@ class ScrollableList:
ptop = max(0, min(self.selection - height/2, self.height-height-1))
self.pad.refresh(ptop, 0, stop, sleft, sbottom, sright)
def on_key(self, c):
def on_key(self, c, ui):
if c == curses.KEY_DOWN:
self.select_next_widget()
elif c == curses.KEY_UP:
@ -210,7 +214,10 @@ class ScrollableList:
else:
selection = self.get_selection()
if selection != None:
selection.on_key(c)
return selection.on_key(c, ui)
else:
return False
return True
class VolumeList(ScrollableList):
"""
@ -218,7 +225,8 @@ class VolumeList(ScrollableList):
"""
def __init__(self, mastervolume):
ScrollableList.__init__(self)
self.mastervolume = mastervolume
sounds = mastervolume.get_sounds()
namesw = max(max([len(s.name) for s in sounds]), len(mastervolume.name))
@ -229,6 +237,52 @@ class VolumeList(ScrollableList):
widgets.append(VolumeWidget(self.pad, sound, namesw))
self.set_widgets(widgets, 2)
def on_key(self, c, ui):
if not ScrollableList.on_key(self, c, ui):
if c == ord("s"):
self.mastervolume.save_preset()
else:
return False
return True
class MessageView:
"""
Display a message at the center of the screen
"""
def __init__(self, message):
"""
Initialise the MessageView
- message is a string
"""
self.message = message.split("\n")
self.pad = curses.newpad(1,1)
def draw(self, stop, sleft, sbottom, sright):
"""
Draw the message in the portion of the screen delimited by the
coordinates (stop, sleft, sbottom, sright)
"""
height = sbottom-stop
width = sright-sleft
self.pad.clear()
self.pad.resize(height, width)
messageheight = len(self.message)
y = (height-messageheight)/2
for text in self.message:
x = (width-len(text))/2
self.pad.addstr(y, x, text)
y += 1
self.pad.refresh(0, 0, stop, sleft, sbottom, sright)
class LoadingView(MessageView):
def __init__(self):
MessageView.__init__(self, "Loading sounds...")
class UI:
def start(self):
@ -244,12 +298,10 @@ class UI:
self.resize()
# Display loading text
text = "Loading sounds..."
x = (self.screenw-len(text))/2
y = self.screenh/2
self.screen.addstr(y, x, text)
self.screen.refresh()
self.loadingview = LoadingView()
self.current = self.loadingview
self.update()
def end(self):
"""
@ -282,36 +334,43 @@ class UI:
"""
Update the screen
"""
self.screen.clear()
self.screen.refresh()
self.current.draw(self.vpadding, self.hpadding,
self.screenh-self.vpadding-1,
self.screenw-self.hpadding-1)
self.volumelist.draw(self.vpadding, self.hpadding,
self.screenh-self.vpadding-1,
self.screenw-self.hpadding-1)
def run(self, mastervolume):
"""
Start the main loop
"""
self.volumelist = VolumeList(mastervolume)
self.current = self.volumelist
self.resize()
self.update()
while True:
# Wait for user input and handle it
c = self.screen.getch()
if c == ord('q'):
# Quit
self.end()
break
elif c == curses.KEY_RESIZE:
# The terminal has been resized, update the display
self.resize()
self.update()
else:
# Propagate the key to the VolumeList
self.volumelist.on_key(c)
self.on_key(self.screen.getch(), self)
self.update()
def on_key(self, c, ui):
"""
Callback called when a key is pressed
"""
if c == ord('q'):
# Quit
self.end()
sys.exit(0)
elif c == curses.KEY_HOME:
self.current = self.volumelist
elif c == curses.KEY_RESIZE:
# The terminal has been resized, update the display
self.resize()
else:
# Propagate the key to the current view
self.current.on_key(c, ui)

Loading…
Cancel
Save